Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,103 @@ hidden through macros.
memcpy(dst, buf, sizeof(INT_SZ)); // sizeof(sizeof(int)) is suspicious.
}

Suspicious usages of 'sizeof(...)' in pointer arithmetic
--------------------------------------------------------

Arithmetic operators on pointers automatically scale the result with the size
of the pointed typed.
Further use of ``sizeof`` around pointer arithmetic will typically result in an
unintended result.

Scaling the result of pointer difference
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Subtracting two pointers results in an integer expression (of type
``ptrdiff_t``) which expresses the distance between the two pointed objects in
"number of objects between".
A common mistake is to think that the result is "number of bytes between", and
scale the difference with ``sizeof``, such as ``P1 - P2 == N * sizeof(T)``
(instead of ``P1 - P2 == N``) or ``(P1 - P2) / sizeof(T)`` instead of
``P1 - P2``.

.. code-block:: c++

void splitFour(const Obj* Objs, size_t N, Obj Delimiter) {
const Obj *P = Objs;
while (P < Objs + N) {
if (*P == Delimiter) {
break;
}
}
if (P - Objs != 4 * sizeof(Obj)) { // Expecting a distance multiplied by sizeof is suspicious.
error();
}
}

.. code-block:: c++

void iterateIfEvenLength(int *Begin, int *End) {
auto N = (Begin - End) / sizeof(int); // Dividing by sizeof() is suspicious.
if (N % 2)
return;
// ...
}

Stepping a pointer with a scaled integer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Conversely, when performing pointer arithmetics to add or subtract from a
pointer, the arithmetic operator implicitly scales the value actually added to
the pointer with the size of the pointee, as ``Ptr + N`` expects ``N`` to be
"number of objects to step", and not "number of bytes to step".

Seeing the calculation of a pointer where ``sizeof`` appears is suspicious,
and the result is typically unintended, often out of bounds.
``Ptr + sizeof(T)`` will offset the pointer by ``sizeof(T)`` elements,
effectively exponentiating the scaling factor to the power of 2.

This case also checks suspicious ``alignof`` and ``offsetof`` usages in
pointer arithmetic, as both return the "size" in bytes and not elements,
potentially resulting in doubly-scaled offsets.

.. code-block:: c++

void printEveryEvenIndexElement(int *Array, size_t N) {
int *P = Array;
while (P <= Array + N * sizeof(int)) { // Suspicious pointer arithmetic using sizeof()!
printf("%d ", *P);
P += 2 * sizeof(int); // Suspicious pointer arithmetic using sizeof()!
}
}

.. code-block:: c++

struct Message { /* ... */; char Flags[8]; };
void clearFlags(Message *Array, size_t N) {
const Message *End = Array + N;
while (Array < End) {
memset(Array + offsetof(Message, Flags), // Suspicious pointer arithmetic using offsetof()!
0, sizeof(Message::Flags));
++Array;
}
}
For this checked bogus pattern, `cert-arr39-c` redirects here as an alias of
this check.

This check corresponds to the CERT C Coding Standard rule
`ARR39-C. Do not add or subtract a scaled integer to a pointer
<http://wiki.sei.cmu.edu/confluence/display/c/ARR39-C.+Do+not+add+or+subtract+a+scaled+integer+to+a+pointer>`_.

Limitations
"""""""""""

Cases where the pointee type has a size of `1` byte (such as, and most
importantly, ``char``) are excluded.

Options
-------

Expand Down
10 changes: 10 additions & 0 deletions clang-tools-extra/docs/clang-tidy/checks/cert/arr39-c.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. title:: clang-tidy - cert-arr39-c
.. meta::
:http-equiv=refresh: 5;URL=../bugprone/sizeof-expression.html

cert-arr39-c
============

The `cert-arr39-c` check is an alias, please see
:doc:`bugprone-sizeof-expression <../bugprone/sizeof-expression>`
for more information.
1 change: 1 addition & 0 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ Check aliases
:header: "Name", "Redirect", "Offers fixes"

:doc:`bugprone-narrowing-conversions <bugprone/narrowing-conversions>`, :doc:`cppcoreguidelines-narrowing-conversions <cppcoreguidelines/narrowing-conversions>`,
:doc:`cert-arr39-c <cert/arr39-c>`, :doc:`bugprone-sizeof-expression <bugprone/sizeof-expression>`,
:doc:`cert-con36-c <cert/con36-c>`, :doc:`bugprone-spuriously-wake-up-functions <bugprone/spuriously-wake-up-functions>`,
:doc:`cert-con54-cpp <cert/con54-cpp>`, :doc:`bugprone-spuriously-wake-up-functions <bugprone/spuriously-wake-up-functions>`,
:doc:`cert-ctr56-cpp <cert/ctr56-cpp>`, :doc:`bugprone-pointer-arithmetic-on-polymorphic-object <bugprone/pointer-arithmetic-on-polymorphic-object>`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,9 @@ class Test11 {
Test11(const Test11 &) = default;
Test11(Test11 &&) = default;
};

template <template <class> typename T, typename U>
struct gh106333
{
gh106333(U && arg1, T<int> arg2) {}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %check_clang_tidy -std=c11-or-later %s bugprone-sizeof-expression %t

#define alignof(type_name) _Alignof(type_name)
extern void sink(const void *P);

enum { BufferSize = 1024 };

struct S {
long A, B, C;
};

void bad4d(void) {
struct S Buffer[BufferSize];

struct S *P = &Buffer[0];
struct S *Q = P;
while (Q < P + alignof(Buffer)) {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'alignof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator [bugprone-sizeof-expression]
// CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(struct S)' == {{[0-9]+}}
sink(Q++);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,372 @@
// RUN: %check_clang_tidy %s bugprone-sizeof-expression %t

#define offsetof(type, member) __builtin_offsetof(type, member)

typedef __SIZE_TYPE__ size_t;
typedef __WCHAR_TYPE__ wchar_t;

extern void *memset(void *Dest, int Ch, size_t Count);
extern size_t strlen(const char *Str);
extern size_t wcslen(const wchar_t *Str);
extern char *strcpy(char *Dest, const char *Src);
extern wchar_t *wcscpy(wchar_t *Dest, const wchar_t *Src);
extern int scanf(const char *Format, ...);
extern int wscanf(const wchar_t *Format, ...);

extern void sink(const void *P);

enum { BufferSize = 1024 };

void bad1a(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q < P + sizeof(Buffer)) {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator [bugprone-sizeof-expression]
// CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
*Q++ = 0;
}
}

void bad1b(void) {
typedef int Integer;
Integer Buffer[BufferSize];

Integer *P = &Buffer[0];
Integer *Q = P;
while (Q < P + sizeof(Buffer)) {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(Integer)' == {{[0-9]+}}
*Q++ = 0;
}
}

void good1(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q < P + BufferSize) {
*Q++ = 0;
}
}

void bad2(void) {
int Buffer[BufferSize];
int *P = Buffer;

while (P < Buffer + sizeof(Buffer)) {
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:21: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
*P++ = 0;
}
}

void good2(void) {
int Buffer[BufferSize];
int *P = Buffer;

while (P < Buffer + BufferSize) {
*P++ = 0;
}
}

struct S {
long A, B, C;
};

void bad3a(struct S *S) {
const size_t Offset = offsetof(struct S, B);
struct S *P = S;

// This is not captureable by Tidy because the size/offset expression is
// not a direct child of the pointer arithmetics.
memset(P + Offset, 0, sizeof(struct S) - Offset);
}

void good3a(struct S *S) {
const size_t Offset = offsetof(struct S, B);
char *P = (char*)S;

// This is not captureable by Tidy because the size/offset expression is
// not a direct child of the pointer arithmetics.
memset(P + Offset, 0, sizeof(struct S) - Offset);
}

void bad3b(struct S *S) {
memset(S + offsetof(struct S, B), 0,
sizeof(struct S) - offsetof(struct S, B));
// CHECK-MESSAGES: :[[@LINE-2]]:12: warning: suspicious usage of 'offsetof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-3]]:12: note: '+' in pointer arithmetic internally scales with 'sizeof(struct S)' == {{[0-9]+}}
}

void good3b(struct S *S) {
char *P = (char*)S;
memset(P + offsetof(struct S, B), 0,
sizeof(struct S) - offsetof(struct S, B));
}

void bad3c(void) {
struct S Buffer[BufferSize];

struct S *P = &Buffer[0];
struct S *Q = P;
while (Q < P + sizeof(Buffer)) {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(struct S)' == {{[0-9]+}}
sink(Q++);
}
}

void bad4(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q += sizeof(*Q);
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+=' operator
// CHECK-MESSAGES: :[[@LINE-2]]:7: note: '+=' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
}
}

void silenced4(void) {
char Buffer[BufferSize];

char *P = &Buffer[0];
char *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q += sizeof(*Q);
}
}

void good4(void) {
char Buffer[BufferSize];

char *P = &Buffer[0];
char *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q += 1;
}
}

void good5aa(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q += ( sizeof(Buffer) / sizeof(Buffer[0]) );
}
}

void good5ab(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q = Q + ( sizeof(Buffer) / sizeof(Buffer[0]) );
}
}

void good5ba(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q -= ( sizeof(Buffer) / sizeof(Buffer[0]) );
}
}

void good5bb(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q = Q - ( sizeof(Buffer) / sizeof(Buffer[0]) );
}
}

void bad6(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q = Q + sizeof(*Q);
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:11: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
}
}

void silenced6(void) {
char Buffer[BufferSize];

char *P = &Buffer[0];
char *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q = Q + sizeof(*Q);
}
}

void good6(void) {
char Buffer[BufferSize];

char *P = &Buffer[0];
char *Q = P;
while (Q < P + BufferSize) {
*Q = 0;
Q = Q + 1;
}
}

void silenced7(void) {
char Buffer[BufferSize];

char *P = &Buffer[0];
const char *Q = P;
while (Q < P + BufferSize) {
sink(Q);
Q = Q + sizeof(*Q);
}
}

void good7(void) {
char Buffer[BufferSize];

char *P = &Buffer[0];
const char *Q = P;
while (Q < P + BufferSize) {
sink(Q);
Q = Q + 1;
}
}

void bad8(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P;
while (Q >= P) {
*Q = 0;
Q = Q - sizeof(*Q);
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '-' operator
// CHECK-MESSAGES: :[[@LINE-2]]:11: note: '-' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
}
}

void silenced8(void) {
char Buffer[BufferSize];

char *P = &Buffer[0];
char *Q = P;
while (Q >= P) {
*Q = 0;
Q = Q - sizeof(*Q);
}
}

void good8(void) {
char Buffer[BufferSize];

char *P = &Buffer[0];
char *Q = P;
while (Q >= P) {
*Q = 0;
Q = Q - 1;
}
}

void good9(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = P + BufferSize;
int N = Q - P;
while (N >= 0) {
Q[N] = 0;
N = N - 1;
}
}

void good10(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = Buffer + BufferSize;
int I = sizeof(*P) - sizeof(*Q);

sink(&I);
}

void good11(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
int *Q = Buffer + BufferSize;
int I = sizeof(Q) - sizeof(*P);

sink(&I);
}

void bad12(void) {
wchar_t Message[BufferSize];
wcscpy(Message, L"Message: ");
wscanf(L"%s", Message + wcslen(Message) * sizeof(wchar_t));
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:25: note: '+' in pointer arithmetic internally scales with 'sizeof(wchar_t)' == {{[0-9]+}}
}

void silenced12(void) {
char Message[BufferSize];
strcpy(Message, "Message: ");
scanf("%s", Message + strlen(Message) * sizeof(char));
}

void nomatch12(void) {
char Message[BufferSize];
strcpy(Message, "Message: ");
scanf("%s", Message + strlen(Message));
}

void good12(void) {
wchar_t Message[BufferSize];
wcscpy(Message, L"Message: ");
wscanf(L"%s", Message + wcslen(Message));
}

void good13(void) {
int Buffer[BufferSize];

int *P = &Buffer[0];
while (P < (Buffer + sizeof(Buffer) / sizeof(int))) {
// NO-WARNING: Calculating the element count of the buffer here, which is
// safe with this idiom (as long as the types don't change).
++P;
}

while (P < (Buffer + sizeof(Buffer) / sizeof(Buffer[0]))) {
// NO-WARNING: Calculating the element count of the buffer here, which is
// safe with this idiom.
++P;
}

while (P < (Buffer + sizeof(Buffer) / sizeof(*P))) {
// NO-WARNING: Calculating the element count of the buffer here, which is
// safe with this idiom.
++P;
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,43 @@ int Test6() {
return sum;
}

static constexpr inline int BufferSize = 1024;

template <typename T>
T next(const T *&Read) {
T value = *Read;
Read += sizeof(T);
return value;
}

void Test7() {
int Buffer[BufferSize];
int *P = &Buffer[0];

const int *P2 = P;
int V1 = next(P2);
// CHECK-MESSAGES: :[[@LINE-10]]:8: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+=' operator
// CHECK-MESSAGES: :[[@LINE-11]]:8: note: '+=' in pointer arithmetic internally scales with 'sizeof(const int)' == {{[0-9]+}}
int V2 = next(P2);
(void)V1;
(void)V2;

int *Q = P;
while (Q < P + sizeof(Buffer)) {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
// CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
*Q++ = 0;
}
}

#ifdef __SIZEOF_INT128__
template <__int128_t N>
#else
template <long N> // Fallback for platforms which do not define `__int128_t`
#endif
bool Baz() { return sizeof(A) < N; }
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: suspicious comparison of 'sizeof(expr)' to a constant
bool Test7() { return Baz<-1>(); }
bool Test8() { return Baz<-1>(); }

void some_generic_function(const void *arg, int argsize);
int *IntP, **IntPP;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,9 +641,9 @@ struct S3 {
}

namespace GH82970 {
struct InitFromBingingDecl {
struct InitFromBindingDecl {
int m;
InitFromBingingDecl() {
InitFromBindingDecl() {
struct { int i; } a;
auto [n] = a;
m = n;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

int f() {
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f' defined in a header file; function definitions in header files can lead to ODR violations [misc-definitions-in-headers]
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: make as 'inline'
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: mark the definition as 'inline'
// CHECK-FIXES: inline int f() {
return 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,5 +323,11 @@ struct GH91982 {
}
};

struct GH107594 {
int foo(int a, int b, char c) {
return std::max<int>({a, b, c});
}
};

} // namespace

Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
// RUN: }}'

enum EError {
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EError' are not consistent
// CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EError' are not consistent
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EError' are not consistent
// CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 'EError' are not consistent
EError_a = 1,
EError_b,
// CHECK-FIXES: EError_b = 2,
Expand All @@ -34,8 +34,8 @@ enum EAll {

#define ENUMERATOR_1 EMacro1_b
enum EMacro1 {
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EMacro1' are not consistent
// CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EMacro1' are not consistent
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EMacro1' are not consistent
// CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 'EMacro1' are not consistent
EMacro1_a = 1,
ENUMERATOR_1,
// CHECK-FIXES: ENUMERATOR_1 = 2,
Expand All @@ -45,8 +45,8 @@ enum EMacro1 {

#define ENUMERATOR_2 EMacro2_b = 2
enum EMacro2 {
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EMacro2' are not consistent
// CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EMacro2' are not consistent
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EMacro2' are not consistent
// CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 'EMacro2' are not consistent
EMacro2_a = 1,
ENUMERATOR_2,
EMacro2_c,
Expand Down Expand Up @@ -78,3 +78,40 @@ enum EnumSequentialInitialValue {
EnumSequentialInitialValue_2 = 4,
// CHECK-FIXES-ENABLE: EnumSequentialInitialValue_2 ,
};

// gh107590
enum WithFwdDeclInconsistent : int;

enum WithFwdDeclInconsistent : int {
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'WithFwdDeclInconsistent' are not consistent
// CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 'WithFwdDeclInconsistent' are not consistent
EFI0,
// CHECK-FIXES: EFI0 = 0,
EFI1 = 1,
EFI2,
// CHECK-FIXES: EFI2 = 2,
};

enum WithFwdDeclZeroFirst : int;

enum WithFwdDeclZeroFirst : int {
// CHECK-MESSAGES-ENABLE: :[[@LINE+1]]:3: warning: zero initial value for the first enumerator in 'WithFwdDeclZeroFirst' can be disregarded
EFZ0 = 0,
// CHECK-FIXES-ENABLE: EFZ0 ,
EFZ1,
EFZ2,
};


enum WithFwdDeclSequential : int;

enum WithFwdDeclSequential : int {
// CHECK-MESSAGES-ENABLE: :[[@LINE-1]]:1: warning: sequential initial value in 'WithFwdDeclSequential' can be ignored
EFS0 = 2,
// CHECK-FIXES-ENABLE: EFS0 = 2,
EFS1 = 3,
// CHECK-FIXES-ENABLE: EFS1 ,
EFS2 = 4,
// CHECK-FIXES-ENABLE: EFS2 ,
};

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %check_clang_tidy %s readability-enum-initial-value %t

enum class EError {
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EError' are not consistent
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EError' are not consistent
EError_a = 1,
EError_b,
// CHECK-FIXES: EError_b = 2,
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,8 @@ AST Matchers
- Fixed an ordering issue with the `hasOperands` matcher occurring when setting a
binding in the first matcher and using it in the second matcher.

- Fixed a crash when traverse lambda expr with invalid captures. (#GH106444)

clang-format
------------

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/AMDGPUTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
//===----------------------------------------------------------------------===//

#ifndef AMDGPU_OPAQUE_PTR_TYPE
#define AMDGPU_OPAQUE_PTR_TYPE(Name, MangledName, AS, Width, Align, Id, SingletonId) \
#define AMDGPU_OPAQUE_PTR_TYPE(Name, AS, Width, Align, Id, SingletonId) \
AMDGPU_TYPE(Name, Id, SingletonId)
#endif

AMDGPU_OPAQUE_PTR_TYPE("__amdgpu_buffer_rsrc_t", "__amdgpu_buffer_rsrc_t", 8, 128, 128, AMDGPUBufferRsrc, AMDGPUBufferRsrcTy)
AMDGPU_OPAQUE_PTR_TYPE("__amdgpu_buffer_rsrc_t", 8, 128, 128, AMDGPUBufferRsrc, AMDGPUBufferRsrcTy)

#undef AMDGPU_TYPE
#undef AMDGPU_OPAQUE_PTR_TYPE
3 changes: 1 addition & 2 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2243,8 +2243,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Align = 8; \
break;
#include "clang/Basic/WebAssemblyReferenceTypes.def"
#define AMDGPU_OPAQUE_PTR_TYPE(NAME, MANGLEDNAME, AS, WIDTH, ALIGN, ID, \
SINGLETONID) \
#define AMDGPU_OPAQUE_PTR_TYPE(NAME, AS, WIDTH, ALIGN, ID, SINGLETONID) \
case BuiltinType::ID: \
Width = WIDTH; \
Align = ALIGN; \
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,18 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
IsStatic = false;
IsExtern = true;
}

// Register all previous declarations as well. For extern blocks, just replace
// the index with the new variable.
if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern, Init)) {
for (const Decl *P = VD; P; P = P->getPreviousDecl())
for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
if (P != VD) {
unsigned PIdx = GlobalIndices[P];
if (Globals[PIdx]->block()->isExtern())
Globals[PIdx] = Globals[*Idx];
}
GlobalIndices[P] = *Idx;
}
return *Idx;
}
return std::nullopt;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2146,7 +2146,7 @@ static bool IsLiteralLValue(const LValue &Value) {
if (Value.getLValueCallIndex())
return false;
const Expr *E = Value.Base.dyn_cast<const Expr*>();
return E && !isa<MaterializeTemporaryExpr, StringLiteral>(E);
return E && !isa<MaterializeTemporaryExpr>(E);
}

static bool IsWeakLValue(const LValue &Value) {
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/ASTMatchers/ASTMatchFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,13 @@ class MatchChildASTVisitor
ScopedIncrement ScopedDepth(&CurrentDepth);

for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
const auto *C = Node->capture_begin() + I;
const LambdaCapture *C = Node->capture_begin() + I;
if (!C->isExplicit())
continue;
if (Node->isInitCapture(C) && !match(*C->getCapturedVar()))
return false;
if (!match(*Node->capture_init_begin()[I]))
const Expr *CIE = Node->capture_init_begin()[I];
if (CIE != nullptr && !match(*CIE))
return false;
}

Expand Down
9 changes: 8 additions & 1 deletion clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,14 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__");

// ACLE predefines. Many can only have one possible value on v8 AArch64.
Builder.defineMacro("__ARM_ACLE", "200");
Builder.defineMacro("__ARM_ACLE_VERSION(year, quarter, patch)",
"(100 * (year) + 10 * (quarter) + (patch))");
#define __ARM_ACLE_VERSION(Y, Q, P) (100 * (Y) + 10 * (Q) + (P))
Builder.defineMacro("__ARM_ACLE",
std::to_string(__ARM_ACLE_VERSION(2024, 2, 0)));
Builder.defineMacro("__FUNCTION_MULTI_VERSIONING_SUPPORT_LEVEL",
std::to_string(__ARM_ACLE_VERSION(2024, 2, 0)));
#undef __ARM_ACLE_VERSION
Builder.defineMacro("__ARM_ARCH",
std::to_string(ArchInfo->Version.getMajor()));
Builder.defineMacro("__ARM_ARCH_PROFILE",
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -900,13 +900,12 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return SingletonId; \
}
#include "clang/Basic/WebAssemblyReferenceTypes.def"
#define AMDGPU_OPAQUE_PTR_TYPE(Name, MangledName, AS, Width, Align, Id, \
SingletonId) \
#define AMDGPU_OPAQUE_PTR_TYPE(Name, AS, Width, Align, Id, SingletonId) \
case BuiltinType::Id: { \
if (!SingletonId) \
SingletonId = \
DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, \
MangledName, TheCU, TheCU->getFile(), 0); \
DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name, \
TheCU, TheCU->getFile(), 0); \
return SingletonId; \
}
#include "clang/Basic/AMDGPUTypes.def"
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
llvm_unreachable("Unexpected wasm reference builtin type!"); \
} break;
#include "clang/Basic/WebAssemblyReferenceTypes.def"
#define AMDGPU_OPAQUE_PTR_TYPE(Name, MangledName, AS, Width, Align, Id, \
SingletonId) \
#define AMDGPU_OPAQUE_PTR_TYPE(Name, AS, Width, Align, Id, SingletonId) \
case BuiltinType::Id: \
return llvm::PointerType::get(getLLVMContext(), AS);
#include "clang/Basic/AMDGPUTypes.def"
Expand Down
89 changes: 53 additions & 36 deletions clang/lib/Driver/ToolChains/PS4CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ void tools::PS4cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);

if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
CmdArgs.push_back(
Args.MakeArgString("--sysroot=" + TC.getSDKLibraryRootDir()));

if (Args.hasArg(options::OPT_pie))
CmdArgs.push_back("-pie");
Expand Down Expand Up @@ -234,8 +234,8 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);

if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
CmdArgs.push_back(
Args.MakeArgString("--sysroot=" + TC.getSDKLibraryRootDir()));

// Default to PIE for non-static executables.
const bool PIE =
Expand Down Expand Up @@ -325,46 +325,63 @@ toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args, StringRef Platform,
const char *EnvVar)
: Generic_ELF(D, Triple, Args) {
// Determine where to find the PS4/PS5 libraries.
// If -isysroot was passed, use that as the SDK base path.
// If not, we use the EnvVar if it exists; otherwise use the driver's
// installation path, which should be <SDK_DIR>/host_tools/bin.
// Determine the baseline SDK directory from the environment, else
// the driver's location, which should be <SDK_DIR>/host_tools/bin.
SmallString<128> SDKRootDir;
SmallString<80> Whence;
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
SDKRootDir = A->getValue();
if (!llvm::sys::fs::exists(SDKRootDir))
D.Diag(clang::diag::warn_missing_sysroot) << SDKRootDir;
Whence = A->getSpelling();
} else if (const char *EnvValue = getenv(EnvVar)) {
if (const char *EnvValue = getenv(EnvVar)) {
SDKRootDir = EnvValue;
Whence = { "environment variable '", EnvVar, "'" };
Whence = {"environment variable '", EnvVar, "'"};
} else {
SDKRootDir = D.Dir + "/../../";
Whence = "compiler's location";
}

SmallString<512> SDKIncludeDir(SDKRootDir);
llvm::sys::path::append(SDKIncludeDir, "target/include");
if (!Args.hasArg(options::OPT_nostdinc) &&
!Args.hasArg(options::OPT_nostdlibinc) &&
!Args.hasArg(options::OPT_isysroot) &&
!Args.hasArg(options::OPT__sysroot_EQ) &&
!llvm::sys::fs::exists(SDKIncludeDir)) {
D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
<< Twine(Platform, " system headers").str() << SDKIncludeDir << Whence;
}
// Allow --sysroot= to override the root directory for header and library
// search, and -sysroot to override header search. If both are specified,
// -isysroot overrides --sysroot for header search.
auto OverrideRoot = [&](const options::ID &Opt, std::string &Root,
StringRef Default) {
if (const Arg *A = Args.getLastArg(Opt)) {
Root = A->getValue();
if (!llvm::sys::fs::exists(Root))
D.Diag(clang::diag::warn_missing_sysroot) << Root;
return true;
}
Root = Default.str();
return false;
};

SmallString<512> SDKLibDir(SDKRootDir);
llvm::sys::path::append(SDKLibDir, "target/lib");
if (!Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
!Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
!Args.hasArg(options::OPT_emit_ast) &&
!llvm::sys::fs::exists(SDKLibDir)) {
bool CustomSysroot =
OverrideRoot(options::OPT__sysroot_EQ, SDKLibraryRootDir, SDKRootDir);
bool CustomISysroot =
OverrideRoot(options::OPT_isysroot, SDKHeaderRootDir, SDKLibraryRootDir);

// Emit warnings if parts of the SDK are missing, unless the user has taken
// control of header or library search. If we're not linking, don't check
// for missing libraries.
auto CheckSDKPartExists = [&](StringRef Dir, StringRef Desc) {
if (llvm::sys::fs::exists(Dir))
return true;
D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
<< Twine(Platform, " system libraries").str() << SDKLibDir << Whence;
return;
<< (Twine(Platform) + " " + Desc).str() << Dir << Whence;
return false;
};

bool Linking = !Args.hasArg(options::OPT_E, options::OPT_c, options::OPT_S,
options::OPT_emit_ast);
if (!CustomSysroot && Linking) {
SmallString<128> Dir(SDKLibraryRootDir);
llvm::sys::path::append(Dir, "target/lib");
if (CheckSDKPartExists(Dir, "system libraries"))
getFilePaths().push_back(std::string(Dir));
}
if (!CustomSysroot && !CustomISysroot &&
!Args.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc)) {
SmallString<128> Dir(SDKHeaderRootDir);
llvm::sys::path::append(Dir, "target/include");
CheckSDKPartExists(Dir, "system headers");
}
getFilePaths().push_back(std::string(SDKLibDir));
}

void toolchains::PS4PS5Base::AddClangSystemIncludeArgs(
Expand All @@ -385,9 +402,9 @@ void toolchains::PS4PS5Base::AddClangSystemIncludeArgs(
return;

addExternCSystemInclude(DriverArgs, CC1Args,
SDKRootDir + "/target/include");
SDKHeaderRootDir + "/target/include");
addExternCSystemInclude(DriverArgs, CC1Args,
SDKRootDir + "/target/include_common");
SDKHeaderRootDir + "/target/include_common");
}

Tool *toolchains::PS4CPU::buildAssembler() const {
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/Driver/ToolChains/PS4CPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,12 @@ class LLVM_LIBRARY_VISIBILITY PS4PS5Base : public Generic_ELF {
const char *Suffix) const = 0;
virtual const char *getProfileRTLibName() const = 0;

StringRef getSDKLibraryRootDir() const { return SDKLibraryRootDir; }

private:
// We compute the SDK root dir in the ctor, and use it later.
std::string SDKRootDir;
// We compute the SDK locations in the ctor, and use them later.
std::string SDKHeaderRootDir;
std::string SDKLibraryRootDir;
};

// PS4-specific Toolchain class.
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ bool clang::CreateHLSLAttributedResourceType(
assert(AttrList.size() && "expected list of resource attributes");

QualType ContainedTy = QualType();
TypeSourceInfo *ContainedTyInfo;
TypeSourceInfo *ContainedTyInfo = nullptr;
SourceLocation LocBegin = AttrList[0]->getRange().getBegin();
SourceLocation LocEnd = AttrList[0]->getRange().getEnd();

Expand Down Expand Up @@ -641,7 +641,7 @@ bool clang::CreateHLSLAttributedResourceType(
ResType = S.getASTContext().getHLSLAttributedResourceType(
Wrapped, ContainedTy, ResAttrs);

if (LocInfo) {
if (LocInfo && ContainedTyInfo) {
LocInfo->Range = SourceRange(LocBegin, LocEnd);
LocInfo->ContainedTyInfo = ContainedTyInfo;
}
Expand Down
14 changes: 10 additions & 4 deletions clang/test/AST/ByteCode/cxx20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,16 +108,22 @@ constexpr auto p2 = "test2";
constexpr bool b1 = foo(p1) == foo(p1);
static_assert(b1);

constexpr bool b2 = foo(p1) == foo(p2);
static_assert(!b2);
constexpr bool b2 = foo(p1) == foo(p2); // ref-error {{must be initialized by a constant expression}} \
// ref-note {{comparison of addresses of literals}} \
// ref-note {{declared here}}
static_assert(!b2); // ref-error {{not an integral constant expression}} \
// ref-note {{not a constant expression}}

constexpr auto name1() { return "name1"; }
constexpr auto name2() { return "name2"; }

constexpr auto b3 = name1() == name1();
static_assert(b3);
constexpr auto b4 = name1() == name2();
static_assert(!b4);
constexpr auto b4 = name1() == name2(); // ref-error {{must be initialized by a constant expression}} \
// ref-note {{has unspecified value}} \
// ref-note {{declared here}}
static_assert(!b4); // ref-error {{not an integral constant expression}} \
// ref-note {{not a constant expression}}

namespace UninitializedFields {
class A {
Expand Down
13 changes: 13 additions & 0 deletions clang/test/AST/ByteCode/extern.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected %s
// RUN: %clang_cc1 -verify=both,ref %s


// both-no-diagnostics

extern const int E;
constexpr int getE() {
return E;
}
const int E = 10;
static_assert(getE() == 10);

9 changes: 9 additions & 0 deletions clang/test/Driver/ps4-linker.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,12 @@

// RUN: %clang --target=x86_64-scei-ps4 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-NO-LTO %s
// CHECK-NO-LTO-NOT: -lto-debug-options

// Test the driver passes a sysroot to the linker. Without --sysroot, its value
// is sourced from the SDK environment variable.

// RUN: env SCE_ORBIS_SDK_DIR=mysdk %clang --target=x64_64-scei-ps4 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-SYSROOT %s
// RUN: env SCE_ORBIS_SDK_DIR=other %clang --target=x64_64-scei-ps4 %s -### --sysroot=mysdk 2>&1 | FileCheck --check-prefixes=CHECK-SYSROOT %s

// CHECK-SYSROOT: {{ld(\.exe)?}}"
// CHECK-SYSROOT-SAME: "--sysroot=mysdk"
4 changes: 2 additions & 2 deletions clang/test/Driver/ps4-ps5-header-search.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// PS4 and PS5 use the same SDK layout, so use the same tree for both.
// RUN: env SCE_ORBIS_SDK_DIR=%S/Inputs/scei-ps4_tree %clang -target x86_64-scei-ps4 --sysroot="" -E -v %s 2>&1 | FileCheck %s --check-prefix=ENVPS4
// RUN: env SCE_PROSPERO_SDK_DIR=%S/Inputs/scei-ps4_tree %clang -target x86_64-sie-ps5 --sysroot="" -E -v %s 2>&1 | FileCheck %s --check-prefix=ENVPS4
// RUN: env SCE_ORBIS_SDK_DIR=%S/Inputs/scei-ps4_tree %clang -target x86_64-scei-ps4 -E -v %s 2>&1 | FileCheck %s --check-prefix=ENVPS4
// RUN: env SCE_PROSPERO_SDK_DIR=%S/Inputs/scei-ps4_tree %clang -target x86_64-sie-ps5 -E -v %s 2>&1 | FileCheck %s --check-prefix=ENVPS4
// ENVPS4: Inputs/scei-ps4_tree/target/include
// ENVPS4: Inputs/scei-ps4_tree/target/include_common
// ENVPS4-NOT: /usr/include
Expand Down
101 changes: 63 additions & 38 deletions clang/test/Driver/ps4-sdk-root.c
Original file line number Diff line number Diff line change
@@ -1,42 +1,67 @@
// Check that PS4 clang doesn't report a warning message when locating
// system header files (either by looking at the value of SCE_ORBIS_SDK_DIR
// or relative to the location of the compiler driver), if "-nostdinc",
// "--sysroot" or "-isysroot" option is specified on the command line.
// Otherwise, check that PS4 clang reports a warning.

// Check that PS4 clang doesn't report a warning message when locating
// system libraries (either by looking at the value of SCE_ORBIS_SDK_DIR
// or relative to the location of the compiler driver), if "-c", "-S", "-E"
// or "--sysroot" option is specified on the command line.
// Otherwise, check that PS4 clang reports a warning.

// Setting up SCE_ORBIS_SDK_DIR to existing location, which is not a PS4 SDK.
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=WARN-SYS-LIBS -check-prefix=NO-WARN %s

// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -c -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -S -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -E -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -emit-ast -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -isysroot foo -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=WARN-SYS-LIBS -check-prefix=NO-WARN %s

// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -c -nostdinc -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -S -nostdinc -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -E -nostdinc -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -emit-ast -nostdinc -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s

// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -c --sysroot=foo/ -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -S --sysroot=foo/ -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -E --sysroot=foo/ -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -emit-ast --sysroot=foo/ -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s

// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -c -isysroot foo -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -S -isysroot foo -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -E -isysroot foo -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -emit-ast -isysroot foo -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### --sysroot=foo/ -isysroot foo -target x86_64-scei-ps4 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
/// PS4 clang emits warnings when SDK headers (<SDKROOT>/target/include/) or
/// libraries (<SDKROOT>/target/lib/) are missing, unless the user takes control
/// of search paths, when corresponding existence checks are skipped.
///
/// User control of header search is assumed if `--sysroot`, `-isysroot`,
/// `-nostdinc` or `-nostdlibinc` is supplied. User control of library search
/// is assumed if `--sysroot` is supplied.
///
/// Warnings are emitted if a specified `-isysroot` or `--sysroot` does not
/// exist.
///
/// The default <SDKROOT> for both headers and libraries is taken from the
/// SCE_ORBIS_SDK_DIR environment variable.

// RUN: echo "-### -Winvalid-or-nonexistent-directory -target x86_64-scei-ps4" > %t.rsp

/// If SDK headers and/or libraries are found, associated warnings are absent.
// RUN: rm -rf %t.inconly && mkdir -p %t.inconly/target/include
// RUN: env SCE_ORBIS_SDK_DIR=%t.inconly %clang @%t.rsp %s 2>&1 | FileCheck -check-prefixes=WARN-SYS-LIBS,NO-WARN %s

// RUN: rm -rf %t.libonly && mkdir -p %t.libonly/target/lib
// RUN: env SCE_ORBIS_SDK_DIR=%t.libonly %clang @%t.rsp %s 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s

// RUN: rm -rf %t.both && mkdir -p %t.both/target/lib && mkdir %t.both/target/include
// RUN: env SCE_ORBIS_SDK_DIR=%t.both %clang @%t.rsp %s 2>&1 | FileCheck -check-prefix=NO-WARN %s

/// In the following invocations, SCE_ORBIS_SDK_DIR is set to an existing
/// location where SDK headers and libraries are absent.

/// When compiling and linking, we should see a warnings about both missing
/// headers and libraries.
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,WARN-SYS-LIBS,NO-WARN %s

/// If `-c`, `-S`, `-E` or `-emit-ast` is supplied, the existence check for SDK
/// libraries is skipped because no linking will be performed. We only expect
/// warnings about missing headers.
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -c 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -S 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -E 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -emit-ast 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s

/// If the user takes control of include paths, the existence check for headers
/// is not performed.
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -c -nostdinc 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -c -nostdlibinc 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -c -isysroot . 2>&1 | FileCheck -check-prefixes=NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -c --sysroot=. 2>&1 | FileCheck -check-prefixes=NO-WARN %s

/// --sysroot disables the existence check for libraries and headers.
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s --sysroot=. 2>&1 | FileCheck -check-prefix=NO-WARN %s

/// -isysroot overrides --sysroot for header search, but not library search.
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -isysroot . --sysroot=.. 2>&1 | FileCheck -check-prefixes=ISYSTEM,NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s --sysroot=.. -isysroot . 2>&1 | FileCheck -check-prefixes=ISYSTEM,NO-WARN %s

/// Warnings are emitted if non-existent --sysroot/-isysroot are supplied.
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s --sysroot=foo -isysroot . 2>&1 | FileCheck -check-prefixes=WARN-SYSROOT,NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s -isysroot foo --sysroot=. 2>&1 | FileCheck -check-prefixes=WARN-SYSROOT,NO-WARN %s
// RUN: env SCE_ORBIS_SDK_DIR=.. %clang @%t.rsp %s --sysroot=foo -isysroot bar 2>&1 | FileCheck -check-prefixes=WARN-SYSROOT,WARN-SYSROOT2,NO-WARN %s

// NO-WARN-NOT: {{warning:|error:}}
// WARN-SYS-HEADERS: warning: unable to find PS4 system headers directory
// WARN-ISYSROOT: warning: no such sysroot directory: 'foo'
// WARN-SYS-LIBS: warning: unable to find PS4 system libraries directory
// WARN-SYS-HEADERS: warning: unable to find PS4 system headers directory
// WARN-SYSROOT: warning: no such sysroot directory: 'foo'
// WARN-SYSROOT2: warning: no such sysroot directory: 'bar'
// NO-WARN-NOT: {{warning:|error:}}
// ISYSTEM: "-cc1"{{.*}}"-internal-externc-isystem" "./target/include"
9 changes: 9 additions & 0 deletions clang/test/Driver/ps5-linker.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@
// RUN: %clang --target=x86_64-sie-ps5 -flto -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG %s

// CHECK-DIAG: -plugin-opt=-crash-diagnostics-dir=mydumps

// Test the driver passes a sysroot to the linker. Without --sysroot, its value
// is sourced from the SDK environment variable.

// RUN: env SCE_PROSPERO_SDK_DIR=mysdk %clang --target=x64_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-SYSROOT %s
// RUN: env SCE_PROSPERO_SDK_DIR=other %clang --target=x64_64-sie-ps5 %s -### --sysroot=mysdk 2>&1 | FileCheck --check-prefixes=CHECK-SYSROOT %s

// CHECK-SYSROOT: {{ld(\.exe)?}}"
// CHECK-SYSROOT-SAME: "--sysroot=mysdk"
101 changes: 63 additions & 38 deletions clang/test/Driver/ps5-sdk-root.c
Original file line number Diff line number Diff line change
@@ -1,44 +1,69 @@
/// (Essentially identical to ps4-sdk-root.c except for the target.)

/// Check that PS5 clang doesn't report a warning message when locating
/// system header files (either by looking at the value of SCE_PROSPERO_SDK_DIR
/// or relative to the location of the compiler driver), if "-nostdinc",
/// "--sysroot" or "-isysroot" option is specified on the command line.
/// Otherwise, check that PS5 clang reports a warning.

// Check that PS5 clang doesn't report a warning message when locating
// system libraries (either by looking at the value of SCE_PROSPERO_SDK_DIR
// or relative to the location of the compiler driver), if "-c", "-S", "-E"
// or "--sysroot" option is specified on the command line.
// Otherwise, check that PS5 clang reports a warning.

// Setting up SCE_PROSPERO_SDK_DIR to existing location, which is not a PS5 SDK.
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=WARN-SYS-LIBS -check-prefix=NO-WARN %s

// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -c -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -S -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -E -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -emit-ast -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-SYS-HEADERS -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -isysroot foo -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=WARN-SYS-LIBS -check-prefix=NO-WARN %s

// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -c -nostdinc -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -S -nostdinc -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -E -nostdinc -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -emit-ast -nostdinc -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s

// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -c --sysroot=foo/ -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -S --sysroot=foo/ -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -E --sysroot=foo/ -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -emit-ast --sysroot=foo/ -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=NO-WARN %s

// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -c -isysroot foo -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -S -isysroot foo -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -E -isysroot foo -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### -emit-ast -isysroot foo -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang -Winvalid-or-nonexistent-directory -### --sysroot=foo/ -isysroot foo -target x86_64-sie-ps5 %s 2>&1 | FileCheck -check-prefix=WARN-ISYSROOT -check-prefix=NO-WARN %s
/// PS5 clang emits warnings when SDK headers (<SDKROOT>/target/include/) or
/// libraries (<SDKROOT>/target/lib/) are missing, unless the user takes control
/// of search paths, when corresponding existence checks are skipped.
///
/// User control of header search is assumed if `--sysroot`, `-isysroot`,
/// `-nostdinc` or `-nostdlibinc` is supplied. User control of library search
/// is assumed if `--sysroot` is supplied.
///
/// Warnings are emitted if a specified `-isysroot` or `--sysroot` does not
/// exist.
///
/// The default <SDKROOT> for both headers and libraries is taken from the
/// SCE_PROSPERO_SDK_DIR environment variable.

// RUN: echo "-### -Winvalid-or-nonexistent-directory -target x86_64-sie-ps5" > %t.rsp

/// If SDK headers and/or libraries are found, associated warnings are absent.
// RUN: rm -rf %t.inconly && mkdir -p %t.inconly/target/include
// RUN: env SCE_PROSPERO_SDK_DIR=%t.inconly %clang @%t.rsp %s 2>&1 | FileCheck -check-prefixes=WARN-SYS-LIBS,NO-WARN %s

// RUN: rm -rf %t.libonly && mkdir -p %t.libonly/target/lib
// RUN: env SCE_PROSPERO_SDK_DIR=%t.libonly %clang @%t.rsp %s 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s

// RUN: rm -rf %t.both && mkdir -p %t.both/target/lib && mkdir %t.both/target/include
// RUN: env SCE_PROSPERO_SDK_DIR=%t.both %clang @%t.rsp %s 2>&1 | FileCheck -check-prefix=NO-WARN %s

/// In the following invocations, SCE_PROSPERO_SDK_DIR is set to an existing
/// location where SDK headers and libraries are absent.

/// When compiling and linking, we should see a warnings about both missing
/// headers and libraries.
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,WARN-SYS-LIBS,NO-WARN %s

/// If `-c`, `-S`, `-E` or `-emit-ast` is supplied, the existence check for SDK
/// libraries is skipped because no linking will be performed. We only expect
/// warnings about missing headers.
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -c 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -S 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -E 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -emit-ast 2>&1 | FileCheck -check-prefixes=WARN-SYS-HEADERS,NO-WARN %s

/// If the user takes control of include paths, the existence check for headers
/// is not performed.
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -c -nostdinc 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -c -nostdlibinc 2>&1 | FileCheck -check-prefix=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -c -isysroot . 2>&1 | FileCheck -check-prefixes=NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -c --sysroot=. 2>&1 | FileCheck -check-prefixes=NO-WARN %s

/// --sysroot disables the existence check for libraries and headers.
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s --sysroot=. 2>&1 | FileCheck -check-prefix=NO-WARN %s

/// -isysroot overrides --sysroot for header search, but not library search.
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -isysroot . --sysroot=.. 2>&1 | FileCheck -check-prefixes=ISYSTEM,NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s --sysroot=.. -isysroot . 2>&1 | FileCheck -check-prefixes=ISYSTEM,NO-WARN %s

/// Warnings are emitted if non-existent --sysroot/-isysroot are supplied.
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s --sysroot=foo -isysroot . 2>&1 | FileCheck -check-prefixes=WARN-SYSROOT,NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s -isysroot foo --sysroot=. 2>&1 | FileCheck -check-prefixes=WARN-SYSROOT,NO-WARN %s
// RUN: env SCE_PROSPERO_SDK_DIR=.. %clang @%t.rsp %s --sysroot=foo -isysroot bar 2>&1 | FileCheck -check-prefixes=WARN-SYSROOT,WARN-SYSROOT2,NO-WARN %s

// NO-WARN-NOT: {{warning:|error:}}
// WARN-SYS-HEADERS: warning: unable to find PS5 system headers directory
// WARN-ISYSROOT: warning: no such sysroot directory: 'foo'
// WARN-SYS-LIBS: warning: unable to find PS5 system libraries directory
// WARN-SYS-HEADERS: warning: unable to find PS5 system headers directory
// WARN-SYSROOT: warning: no such sysroot directory: 'foo'
// WARN-SYSROOT2: warning: no such sysroot directory: 'bar'
// NO-WARN-NOT: {{warning:|error:}}
// ISYSTEM: "-cc1"{{.*}}"-internal-externc-isystem" "./target/include"
1 change: 0 additions & 1 deletion clang/test/Preprocessor/aarch64-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// CHECK: __AARCH64EL__ 1
// CHECK: __ARM_64BIT_STATE 1
// CHECK-NOT: __ARM_32BIT_STATE
// CHECK: __ARM_ACLE 200
// CHECK: __ARM_ALIGN_MAX_STACK_PWR 4
// CHECK: __ARM_ARCH 8
// CHECK: __ARM_ARCH_ISA_A64 1
Expand Down
15 changes: 12 additions & 3 deletions clang/test/Preprocessor/init-aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
// AARCH64_LE-NEXT: #define __AARCH64EL__ 1
// AARCH64_LE-NEXT: #define __AARCH64_CMODEL_SMALL__ 1
// AARCH64-NEXT: #define __ARM_64BIT_STATE 1
// AARCH64-NEXT: #define __ARM_ACLE 200
// AARCH64-NEXT: #define __ARM_ACLE 202420
// AARCH64-NEXT: #define __ARM_ACLE_VERSION(year,quarter,patch) (100 * (year) + 10 * (quarter) + (patch))
// AARCH64-NEXT: #define __ARM_ALIGN_MAX_STACK_PWR 4
// AARCH64-NEXT: #define __ARM_ARCH 8
// AARCH64-NEXT: #define __ARM_ARCH_ISA_A64 1
Expand Down Expand Up @@ -121,6 +122,7 @@
// AARCH64-NEXT: #define __FPCLASS_SNAN 0x0001
// AARCH64-NEXT: #define __FP_FAST_FMA 1
// AARCH64-NEXT: #define __FP_FAST_FMAF 1
// AARCH64-NEXT: #define __FUNCTION_MULTI_VERSIONING_SUPPORT_LEVEL 202420
// AARCH64-NEXT: #define __GCC_ASM_FLAG_OUTPUTS__ 1
// AARCH64-NEXT: #define __GCC_CONSTRUCTIVE_SIZE {{.+}}
// AARCH64-NEXT: #define __GCC_DESTRUCTIVE_SIZE {{.+}}
Expand Down Expand Up @@ -393,6 +395,8 @@
// AARCH64-DARWIN: #define __AARCH64EL__ 1
// AARCH64-DARWIN-NOT: #define __AARCH_BIG_ENDIAN 1
// AARCH64-DARWIN: #define __ARM_64BIT_STATE 1
// AARCH64-DARWIN: #define __ARM_ACLE 202420
// AARCH64-DARWIN: #define __ARM_ACLE_VERSION(year,quarter,patch) (100 * (year) + 10 * (quarter) + (patch))
// AARCH64-DARWIN: #define __ARM_ARCH 8
// AARCH64-DARWIN: #define __ARM_ARCH_ISA_A64 1
// AARCH64-DARWIN-NOT: #define __ARM_BIG_ENDIAN 1
Expand Down Expand Up @@ -429,6 +433,7 @@
// AARCH64-DARWIN: #define __FLT_MIN_EXP__ (-125)
// AARCH64-DARWIN: #define __FLT_MIN__ 1.17549435e-38F
// AARCH64-DARWIN: #define __FLT_RADIX__ 2
// AARCH64-DARWIN: #define __FUNCTION_MULTI_VERSIONING_SUPPORT_LEVEL 202420
// AARCH64-DARWIN: #define __INT16_C_SUFFIX__
// AARCH64-DARWIN: #define __INT16_FMTd__ "hd"
// AARCH64-DARWIN: #define __INT16_FMTi__ "hi"
Expand Down Expand Up @@ -588,7 +593,8 @@
// AARCH64-MSVC: #define _WIN64 1
// AARCH64-MSVC: #define __AARCH64EL__ 1
// AARCH64-MSVC: #define __ARM_64BIT_STATE 1
// AARCH64-MSVC: #define __ARM_ACLE 200
// AARCH64-MSVC: #define __ARM_ACLE 202420
// AARCH64-MSVC: #define __ARM_ACLE_VERSION(year,quarter,patch) (100 * (year) + 10 * (quarter) + (patch))
// AARCH64-MSVC: #define __ARM_ALIGN_MAX_STACK_PWR 4
// AARCH64-MSVC: #define __ARM_ARCH 8
// AARCH64-MSVC: #define __ARM_ARCH_ISA_A64 1
Expand Down Expand Up @@ -644,6 +650,7 @@
// AARCH64-MSVC: #define __FLT_MIN_EXP__ (-125)
// AARCH64-MSVC: #define __FLT_MIN__ 1.17549435e-38F
// AARCH64-MSVC: #define __FLT_RADIX__ 2
// AARCH64-MSVC: #define __FUNCTION_MULTI_VERSIONING_SUPPORT_LEVEL 202420
// AARCH64-MSVC: #define __INT_MAX__ 2147483647
// AARCH64-MSVC: #define __LDBL_DECIMAL_DIG__ 17
// AARCH64-MSVC: #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
Expand Down Expand Up @@ -750,7 +757,8 @@
// ARM64EC-MSVC: #define __AARCH64EL__ 1
// ARM64EC-MSVC: #define __AARCH64_CMODEL_SMALL__ 1
// ARM64EC-MSVC: #define __ARM_64BIT_STATE 1
// ARM64EC-MSVC: #define __ARM_ACLE 200
// ARM64EC-MSVC: #define __ARM_ACLE 202420
// ARM64EC-MSVC: #define __ARM_ACLE_VERSION(year,quarter,patch) (100 * (year) + 10 * (quarter) + (patch))
// ARM64EC-MSVC: #define __ARM_ALIGN_MAX_STACK_PWR 4
// ARM64EC-MSVC: #define __ARM_ARCH 8
// ARM64EC-MSVC: #define __ARM_ARCH_ISA_A64 1
Expand Down Expand Up @@ -850,6 +858,7 @@
// ARM64EC-MSVC: #define __FPCLASS_SNAN 0x0001
// ARM64EC-MSVC: #define __FP_FAST_FMA 1
// ARM64EC-MSVC: #define __FP_FAST_FMAF 1
// ARM64EC-MSVC: #define __FUNCTION_MULTI_VERSIONING_SUPPORT_LEVEL 202420
// ARM64EC-MSVC: #define __GCC_ASM_FLAG_OUTPUTS__ 1
// ARM64EC-MSVC: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// ARM64EC-MSVC: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 1
Expand Down
6 changes: 4 additions & 2 deletions clang/test/SemaCXX/constant-expression-cxx11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,9 +358,11 @@ struct Str {

extern char externalvar[];
constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL; // expected-error {{must be initialized by a constant expression}} expected-note {{reinterpret_cast}}
constexpr bool litaddress = "foo" == "foo"; // cxx20_23-warning {{comparison between two arrays is deprecated}}
constexpr bool litaddress = "foo" == "foo"; // expected-error {{must be initialized by a constant expression}}
// expected-note@-1 {{comparison of addresses of literals has unspecified value}}
// cxx20_23-warning@-2 {{comparison between two arrays is deprecated}}
static_assert(0 != "foo", "");
static_assert("foo" != "foo", "");// cxx20_23-warning {{comparison between two arrays is deprecated}}

}

namespace MaterializeTemporary {
Expand Down
13 changes: 13 additions & 0 deletions clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5052,6 +5052,19 @@ TEST(ForEachConstructorInitializer, MatchesInitializers) {
cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));
}

TEST(LambdaCapture, InvalidLambdaCapture) {
// not crash
EXPECT_FALSE(matches(
R"(int main() {
struct A { A()=default; A(A const&)=delete; };
A a; [a]() -> void {}();
return 0;
})",
traverse(TK_IgnoreUnlessSpelledInSource,
lambdaExpr(has(lambdaCapture()))),
langCxx11OrLater()));
}

TEST(ForEachLambdaCapture, MatchesCaptures) {
EXPECT_TRUE(matches(
"int main() { int x, y; auto f = [x, y]() { return x + y; }; }",
Expand Down
8 changes: 4 additions & 4 deletions clang/www/c_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>Contradiction about INFINITY macro</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2848.pdf">N2848</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Require exact-width integer type interfaces</td>
Expand Down Expand Up @@ -603,7 +603,7 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>char8_t: A type for UTF-8 characters and strings</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2653.htm">N2653</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Clarification for max exponent macros-update</td>
Expand Down Expand Up @@ -727,7 +727,7 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>constexpr for object definitions</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3018.htm">N3018</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Introduce storage class specifiers for compound literals</td>
Expand Down Expand Up @@ -757,7 +757,7 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>#embed</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm">N3017</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
</table>
</details>
Expand Down
92 changes: 73 additions & 19 deletions clang/www/cxx_dr_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/150.html">150</a></td>
<td>C++17</td>
<td>Template template parameters and default arguments</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="151">
<td><a href="https://cplusplus.github.io/CWG/issues/151.html">151</a></td>
Expand Down Expand Up @@ -1017,7 +1017,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/162.html">162</a></td>
<td>CD1</td>
<td>(<TT>&amp;C::f)()</TT> with nonstatic members</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="163">
<td><a href="https://cplusplus.github.io/CWG/issues/163.html">163</a></td>
Expand Down Expand Up @@ -7827,7 +7827,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/1334.html">1334</a></td>
<td>NAD</td>
<td>Layout compatibility and cv-qualification</td>
<td class="unreleased-superseded" align="center">Superseded by <a href="#1719">1719</a></td>
<td class="full-superseded" align="center">Superseded by <a href="#1719">1719</a></td>
</tr>
<tr id="1335">
<td><a href="https://cplusplus.github.io/CWG/issues/1335.html">1335</a></td>
Expand Down Expand Up @@ -10141,7 +10141,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/1719.html">1719</a></td>
<td>CD4</td>
<td>Layout compatibility and cv-qualification revisited</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="1720">
<td><a href="https://cplusplus.github.io/CWG/issues/1720.html">1720</a></td>
Expand Down Expand Up @@ -11809,11 +11809,11 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>Reference list-initialization ignores conversion functions</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="1997">
<tr id="1997">
<td><a href="https://cplusplus.github.io/CWG/issues/1997.html">1997</a></td>
<td>drafting</td>
<td>DRWP</td>
<td>Placement new and previous initialization</td>
<td align="center">Not resolved</td>
<td class="unknown" align="center">Unknown</td>
</tr>
<tr id="1998">
<td><a href="https://cplusplus.github.io/CWG/issues/1998.html">1998</a></td>
Expand Down Expand Up @@ -12977,7 +12977,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2191.html">2191</a></td>
<td>C++17</td>
<td>Incorrect result for <TT>noexcept(typeid(v))</TT></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr class="open" id="2192">
<td><a href="https://cplusplus.github.io/CWG/issues/2192.html">2192</a></td>
Expand Down Expand Up @@ -14403,7 +14403,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2428.html">2428</a></td>
<td>C++23</td>
<td>Deprecating a concept</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="2429">
<td><a href="https://cplusplus.github.io/CWG/issues/2429.html">2429</a></td>
Expand Down Expand Up @@ -14505,7 +14505,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2445.html">2445</a></td>
<td>C++20</td>
<td>Partial ordering with rewritten candidates</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="2446">
<td><a href="https://cplusplus.github.io/CWG/issues/2446.html">2446</a></td>
Expand Down Expand Up @@ -15345,7 +15345,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2583.html">2583</a></td>
<td>C++23</td>
<td>Common initial sequence should consider over-alignment</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr class="open" id="2584">
<td><a href="https://cplusplus.github.io/CWG/issues/2584.html">2584</a></td>
Expand Down Expand Up @@ -15573,7 +15573,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2621.html">2621</a></td>
<td>C++23</td>
<td>Kind of lookup for <TT>using enum</TT> declarations</td>
<td class="unreleased-superseded" align="center">Superseded by <a href="#2877">2877</a></td>
<td class="full-superseded" align="center">Superseded by <a href="#2877">2877</a></td>
</tr>
<tr id="2622">
<td><a href="https://cplusplus.github.io/CWG/issues/2622.html">2622</a></td>
Expand Down Expand Up @@ -15999,7 +15999,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2692.html">2692</a></td>
<td>C++23</td>
<td>Static and explicit object member functions with the same parameter-type-lists</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr class="open" id="2693">
<td><a href="https://cplusplus.github.io/CWG/issues/2693.html">2693</a></td>
Expand Down Expand Up @@ -16401,7 +16401,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2759.html">2759</a></td>
<td>DRWP</td>
<td>[[no_unique_address] and common initial sequence</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="2760">
<td><a href="https://cplusplus.github.io/CWG/issues/2760.html">2760</a></td>
Expand Down Expand Up @@ -16762,7 +16762,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2819.html">2819</a></td>
<td>accepted</td>
<td>Cast from null pointer value in a constant expression</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="2820">
<td><a href="https://cplusplus.github.io/CWG/issues/2820.html">2820</a></td>
Expand Down Expand Up @@ -17000,7 +17000,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2858.html">2858</a></td>
<td>accepted</td>
<td>Declarative <I>nested-name-specifier</I>s and <I>pack-index-specifier</I>s</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="2859">
<td><a href="https://cplusplus.github.io/CWG/issues/2859.html">2859</a></td>
Expand Down Expand Up @@ -17114,7 +17114,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2877.html">2877</a></td>
<td>DR</td>
<td>Type-only lookup for <I>using-enum-declarator</I></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr class="open" id="2878">
<td><a href="https://cplusplus.github.io/CWG/issues/2878.html">2878</a></td>
Expand All @@ -17138,7 +17138,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2881.html">2881</a></td>
<td>DR</td>
<td>Type restrictions for the explicit object parameter of a lambda</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr id="2882">
<td><a href="https://cplusplus.github.io/CWG/issues/2882.html">2882</a></td>
Expand Down Expand Up @@ -17350,7 +17350,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
</tr>
<tr class="open" id="2916">
<td><a href="https://cplusplus.github.io/CWG/issues/2916.html">2916</a></td>
<td>tentatively ready</td>
<td>review</td>
<td>Variable template partial specializations should not be declared <TT>static</TT></td>
<td align="center">Not resolved</td>
</tr>
Expand Down Expand Up @@ -17427,6 +17427,60 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>open</td>
<td>Unclear status of translation unit with <TT>module</TT> keyword</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2928">
<td><a href="https://cplusplus.github.io/CWG/issues/2928.html">2928</a></td>
<td>open</td>
<td>No ordering for initializing thread-local variables</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2929">
<td><a href="https://cplusplus.github.io/CWG/issues/2929.html">2929</a></td>
<td>open</td>
<td>Lifetime of trivially-destructible static or thread-local objects</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2930">
<td><a href="https://cplusplus.github.io/CWG/issues/2930.html">2930</a></td>
<td>open</td>
<td>Unclear term "copy/move operation" in specification of copy elision</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2931">
<td><a href="https://cplusplus.github.io/CWG/issues/2931.html">2931</a></td>
<td>open</td>
<td>Restrictions on operator functions that are explicit object member functions</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2932">
<td><a href="https://cplusplus.github.io/CWG/issues/2932.html">2932</a></td>
<td>open</td>
<td>Value range of empty enumeration</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2933">
<td><a href="https://cplusplus.github.io/CWG/issues/2933.html">2933</a></td>
<td>open</td>
<td>Dangling references</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2934">
<td><a href="https://cplusplus.github.io/CWG/issues/2934.html">2934</a></td>
<td>open</td>
<td>Unclear semantics of exception escaping from <TT>unhandled_exception</TT></td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2935">
<td><a href="https://cplusplus.github.io/CWG/issues/2935.html">2935</a></td>
<td>open</td>
<td>Destroying the coroutine state when initial-await-resume-called is false</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2936">
<td><a href="https://cplusplus.github.io/CWG/issues/2936.html">2936</a></td>
<td>open</td>
<td>Local classes of templated functions should be part of the current instantiation</td>
<td align="center">Not resolved</td>
</tr></table>

</div>
Expand Down
26 changes: 13 additions & 13 deletions clang/www/cxx_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Pack Indexing</td>
<td><a href="https://wg21.link/P2662R3">P2662R3</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Remove Deprecated Arithmetic Conversion on Enumerations</td>
Expand All @@ -167,7 +167,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Disallow Binding a Returned Glvalue to a Temporary</td>
<td><a href="https://wg21.link/P2748R5">P2748R5</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Clarifying rules for brace elision in aggregate initialization</td>
Expand All @@ -177,7 +177,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Attributes for Structured Bindings</td>
<td><a href="https://wg21.link/P0609R3">P0609R3</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Module Declarations Shouldn’t be Macros</td>
Expand All @@ -187,7 +187,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Trivial infinite loops are not Undefined Behavior</td>
<td><a href="https://wg21.link/P2809R3">P2809R3</a> (<a href="#dr">DR</a>)</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Erroneous behaviour for uninitialized reads</td>
Expand All @@ -197,7 +197,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td><tt>= delete("should have a reason");</tt></td>
<td><a href="https://wg21.link/P2573R2">P2573R2</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Variadic friends</td>
Expand All @@ -213,12 +213,12 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Deleting a Pointer to an Incomplete Type Should be Ill-formed</td>
<td><a href="https://wg21.link/P3144">P3144R2</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Ordering of constraints involving fold expressions</td>
<td><a href="https://wg21.link/P2963R3">P2963R3</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Structured binding declaration as a condition</td>
Expand Down Expand Up @@ -304,7 +304,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
</tr>
<tr>
<td><a href="https://wg21.link/P2797R0">P2797R0</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td rowspan=2>Change scope of lambda trailing-return-type</td>
Expand Down Expand Up @@ -368,7 +368,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
<tr>
<td>Type trait to determine if a reference binds to a temporary</td>
<td><a href="https://wg21.link/P2255R2">P2255R2</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<!-- July 2022 papers -->
<tr>
Expand Down Expand Up @@ -409,7 +409,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
<tr>
<td>Relaxing some constexpr restrictions</td>
<td><a href="https://wg21.link/P2448R2">P2448R2</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Using unknown pointers and references in constant expressions</td>
Expand All @@ -434,7 +434,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
<tr>
<td>Portable assumptions</td>
<td><a href="https://wg21.link/P1774R8">P1774R8</a></td>
<td class="unreleased" align="center">Clang 19</td>
<td class="full" align="center">Clang 19</td>
</tr>
<tr>
<td>Support for UTF-8 as a portable source file encoding</td>
Expand Down Expand Up @@ -564,7 +564,7 @@ <h2 id="cxx20">C++20 implementation status</h2>
</tr>
<tr> <!-- from Cologne -->
<td><a href="https://wg21.link/p0848r3">P0848R3</a></td>
<td rowspan="1" class="unreleased" align="center">Clang 19</td>
<td rowspan="1" class="full" align="center">Clang 19</td>
</tr>
<tr>
<td><a href="https://wg21.link/p1616r1">P1616R1</a></td>
Expand Down Expand Up @@ -1154,7 +1154,7 @@ <h2 id="cxx17">C++17 implementation status</h2>
<tr>
<td>Matching template template parameters to compatible arguments</td>
<td><a href="https://wg21.link/p0522r0">P0522R0</a> (<a href="#dr">DR</a>)</td>
<td class="unreleased" align="center">Clang 19 <a href="#p0522">(10)</a></td>
<td class="full" align="center">Clang 19 <a href="#p0522">(10)</a></td>
</tr>
<tr>
<td>Removing deprecated dynamic exception specifications</td>
Expand Down
2 changes: 1 addition & 1 deletion clang/www/make_cxx_dr_status
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#! /usr/bin/env python3
import sys, os, re, urllib.request

latest_release = 18
latest_release = 19

clang_www_dir = os.path.dirname(__file__)
default_issue_list_path = os.path.join(clang_www_dir, 'cwg_index.html')
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Optimizer/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ def ConstantArgumentGlobalisationOpt : Pass<"constant-argument-globalisation-opt
let dependentDialects = [ "fir::FIROpsDialect" ];
}

def StackArrays : Pass<"stack-arrays", "mlir::ModuleOp"> {
def StackArrays : Pass<"stack-arrays", "mlir::func::FuncOp"> {
let summary = "Move local array allocations from heap memory into stack memory";
let description = [{
Convert heap allocations for arrays, even those of unknown size, into stack
Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
typeGen.convertType(resTy, fileAttr, cuAttr, /*declOp=*/nullptr);
types.push_back(tyAttr);
}
// If no return type then add a null type as a place holder for that.
if (types.empty())
types.push_back(mlir::LLVM::DINullTypeAttr::get(context));
for (auto inTy : funcOp.getArgumentTypes()) {
auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr,
cuAttr, /*declOp=*/nullptr);
Expand Down
21 changes: 12 additions & 9 deletions flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,23 +213,26 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType(
convertType(seqTy.getEleTy(), fileAttr, scope, declOp);

unsigned index = 0;
auto intTy = mlir::IntegerType::get(context, 64);
for (fir::SequenceType::Extent dim : seqTy.getShape()) {
int64_t shift = 1;
if (declOp && declOp.getShift().size() > index) {
if (std::optional<std::int64_t> optint =
getIntIfConstant(declOp.getShift()[index]))
shift = *optint;
}
if (dim == seqTy.getUnknownExtent()) {
mlir::IntegerAttr lowerAttr = nullptr;
if (declOp && declOp.getShift().size() > index)
lowerAttr = mlir::IntegerAttr::get(intTy, llvm::APInt(64, shift));
// FIXME: This path is taken for assumed size arrays but also for arrays
// with non constant extent. For the latter case, the DISubrangeAttr
// should point to a variable which will have the extent at runtime.
auto subrangeTy = mlir::LLVM::DISubrangeAttr::get(
context, /*count=*/nullptr, /*lowerBound=*/nullptr,
/*upperBound*/ nullptr, /*stride*/ nullptr);
context, /*count=*/nullptr, lowerAttr, /*upperBound*/ nullptr,
/*stride*/ nullptr);
elements.push_back(subrangeTy);
} else {
auto intTy = mlir::IntegerType::get(context, 64);
int64_t shift = 1;
if (declOp && declOp.getShift().size() > index) {
if (std::optional<std::int64_t> optint =
getIntIfConstant(declOp.getShift()[index]))
shift = *optint;
}
auto countAttr = mlir::IntegerAttr::get(intTy, llvm::APInt(64, dim));
auto lowerAttr = mlir::IntegerAttr::get(intTy, llvm::APInt(64, shift));
auto subrangeTy = mlir::LLVM::DISubrangeAttr::get(
Expand Down
9 changes: 1 addition & 8 deletions flang/lib/Optimizer/Transforms/StackArrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ class StackArraysPass : public fir::impl::StackArraysBase<StackArraysPass> {
llvm::StringRef getDescription() const override;

void runOnOperation() override;
void runOnFunc(mlir::Operation *func);

private:
Statistic runCount{this, "stackArraysRunCount",
Expand Down Expand Up @@ -766,13 +765,7 @@ llvm::StringRef StackArraysPass::getDescription() const {
}

void StackArraysPass::runOnOperation() {
mlir::ModuleOp mod = getOperation();

mod.walk([this](mlir::func::FuncOp func) { runOnFunc(func); });
}

void StackArraysPass::runOnFunc(mlir::Operation *func) {
assert(mlir::isa<mlir::func::FuncOp>(func));
mlir::func::FuncOp func = getOperation();

auto &analysis = getAnalysis<StackArraysAnalysisWrapper>();
const StackArraysAnalysisWrapper::AllocMemMap *candidateOps =
Expand Down
13 changes: 10 additions & 3 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "flang/Parser/parse-tree.h"
#include "flang/Parser/tools.h"
#include "flang/Semantics/expression.h"
#include "flang/Semantics/symbol.h"
#include "flang/Semantics/tools.h"
#include <list>
#include <map>
Expand Down Expand Up @@ -717,7 +718,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
void CheckDataCopyingClause(
const parser::Name &, const Symbol &, Symbol::Flag);
void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause);
void CheckObjectInNamelist(
void CheckObjectInNamelistOrAssociate(
const parser::Name &, const Symbol &, Symbol::Flag);
void CheckSourceLabel(const parser::Label &);
void CheckLabelContext(const parser::CharBlock, const parser::CharBlock,
Expand Down Expand Up @@ -2356,7 +2357,7 @@ void OmpAttributeVisitor::ResolveOmpObject(
CheckMultipleAppearances(*name, *symbol, ompFlag);
}
if (privateDataSharingAttributeFlags.test(ompFlag)) {
CheckObjectInNamelist(*name, *symbol, ompFlag);
CheckObjectInNamelistOrAssociate(*name, *symbol, ompFlag);
}

if (ompFlag == Symbol::Flag::OmpAllocate) {
Expand Down Expand Up @@ -2713,7 +2714,7 @@ void OmpAttributeVisitor::CheckDataCopyingClause(
}
}

void OmpAttributeVisitor::CheckObjectInNamelist(
void OmpAttributeVisitor::CheckObjectInNamelistOrAssociate(
const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
const auto &ultimateSymbol{symbol.GetUltimate()};
llvm::StringRef clauseName{"PRIVATE"};
Expand All @@ -2728,6 +2729,12 @@ void OmpAttributeVisitor::CheckObjectInNamelist(
"Variable '%s' in NAMELIST cannot be in a %s clause"_err_en_US,
name.ToString(), clauseName.str());
}

if (ultimateSymbol.has<AssocEntityDetails>()) {
context_.Say(name.source,
"Variable '%s' in ASSOCIATE cannot be in a %s clause"_err_en_US,
name.ToString(), clauseName.str());
}
}

void OmpAttributeVisitor::CheckSourceLabel(const parser::Label &label) {
Expand Down
32 changes: 32 additions & 0 deletions flang/test/Semantics/OpenMP/private-assoc.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
! RUN: %python %S/../test_errors.py %s %flang -fopenmp

! The ASSOCIATE name preserves the association with the selector established
! in the associate statement. Therefore it is incorrect to change the
! data-sharing attribute of the name.

subroutine assoc_private(x)
integer :: x
associate(z => x)
!ERROR: Variable 'z' in ASSOCIATE cannot be in a PRIVATE clause
!$omp parallel private(z)
!$omp end parallel
end associate
end subroutine

subroutine assoc_firstprivate(x)
integer :: x
associate(z => x)
!ERROR: Variable 'z' in ASSOCIATE cannot be in a FIRSTPRIVATE clause
!$omp parallel firstprivate(z)
!$omp end parallel
end associate
end subroutine

subroutine assoc_lastprivate(x)
integer :: x
associate(z => x)
!ERROR: Variable 'z' in ASSOCIATE cannot be in a LASTPRIVATE clause
!$omp parallel sections lastprivate(z)
!$omp end parallel sections
end associate
end subroutine
5 changes: 3 additions & 2 deletions flang/test/Transforms/debug-assumed-size-array.fir
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
func.func @_QMhelperPfn(%arg0: !fir.ref<!fir.array<5x?xi32>> {fir.bindc_name = "a1"}, %arg1: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "a2"}, %arg2: !fir.ref<!fir.array<2x?xi32>> {fir.bindc_name = "a3"}) {
%c5 = arith.constant 5 : index
%c1 = arith.constant 1 : index
%c2 = arith.constant 2 : index
%c-1 = arith.constant -1 : index
%0 = fir.undefined !fir.dscope
%1 = fircg.ext_declare %arg0(%c5, %c-1) dummy_scope %0 {uniq_name = "_QMhelperFfnEa1"} : (!fir.ref<!fir.array<5x?xi32>>, index, index, !fir.dscope) -> !fir.ref<!fir.array<5x?xi32>> loc(#loc1)
%2 = fircg.ext_declare %arg1(%c-1) dummy_scope %0 {uniq_name = "_QMhelperFfnEa2"} : (!fir.ref<!fir.array<?xi32>>, index, !fir.dscope) -> !fir.ref<!fir.array<?xi32>> loc(#loc2)
%2 = fircg.ext_declare %arg1(%c-1) origin %c2 dummy_scope %0 {uniq_name = "_QMhelperFfnEa2"} : (!fir.ref<!fir.array<?xi32>>, index, index, !fir.dscope) -> !fir.ref<!fir.array<?xi32>> loc(#loc2)
return
} loc(#loc3)
}
Expand All @@ -16,6 +17,6 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
#loc2 = loc("test.f90":4:1)

// CHECK-DAG: #[[TY1:.*]] = #llvm.di_composite_type<tag = DW_TAG_array_type{{.*}}elements = #llvm.di_subrange<count = 5 : i64, lowerBound = 1 : i64>, #llvm.di_subrange<>>
// CHECK-DAG: #[[TY2:.*]] = #llvm.di_composite_type<tag = DW_TAG_array_type{{.*}}elements = #llvm.di_subrange<>>
// CHECK-DAG: #[[TY2:.*]] = #llvm.di_composite_type<tag = DW_TAG_array_type{{.*}}elements = #llvm.di_subrange<lowerBound = 2 : i64>>
// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "a1"{{.*}}type = #[[TY1]]>
// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "a2"{{.*}}type = #[[TY2]]>
10 changes: 9 additions & 1 deletion flang/test/Transforms/debug-fn-info.fir
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,16 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
%11 = fir.load %5 : !fir.ref<i32>
return %11 : i32
} loc(#loc3)
func.func private @_QFPfn3(%arg0: !fir.ref<i32> {fir.bindc_name = "abc"}) attributes {fir.host_symbol = @_QQmain, llvm.linkage = #llvm.linkage<internal>} {
%0 = fir.undefined !fir.dscope
%1 = fircg.ext_declare %arg0 dummy_scope %0 {uniq_name = "_QFFfn3Eabc"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
return
} loc(#loc4)
}
#loc1 = loc("test.f90":15:1)
#loc2 = loc("test.f90":26:22)
#loc3 = loc("test2.f90":43:22)
#loc4 = loc("test2.f90":53:22)


// CHECK-DAG: #[[INT8:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 64, encoding = DW_ATE_signed>
Expand All @@ -64,12 +70,14 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
// CHECK-DAG: #[[LOG1:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "logical", sizeInBits = 8, encoding = DW_ATE_boolean>
// CHECK-DAG: #[[REAL4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real", sizeInBits = 32, encoding = DW_ATE_float>
// CHECK-DAG: #[[LOG4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "logical", sizeInBits = 32, encoding = DW_ATE_boolean>
// CHECK: #[[TY0:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_program>
// CHECK: #[[TY0:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_program, types = #di_null_type>
// CHECK: #[[TY1:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #[[INT8]], #[[INT4]], #[[REAL8]], #[[LOG1]]>
// CHECK: #[[TY2:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #[[INT4]], #[[INT8]], #[[REAL4]], #[[LOG4]]>
// CHECK: #[[TY3:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #di_null_type, #[[INT4]]>

// Line numbers should match the number in corresponding loc entry.
// CHECK: #llvm.di_subprogram<{{.*}}name = "_QQmain", linkageName = "_QQmain", file = {{.*}}, line = 15, scopeLine = 15, subprogramFlags = Definition, type = #[[TY0]]>
// CHECK: #llvm.di_subprogram<{{.*}}name = "fn1", linkageName = "_QFPfn1", file = {{.*}}, line = 26, scopeLine = 26, subprogramFlags = Definition, type = #[[TY1]]>
// CHECK: #llvm.di_subprogram<{{.*}}name = "fn2", linkageName = "_QFPfn2", file = {{.*}}, line = 43, scopeLine = 43, subprogramFlags = Definition, type = #[[TY2]]>
// CHECK: #llvm.di_subprogram<{{.*}}name = "fn3", linkageName = "_QFPfn3", file = {{.*}}, line = 53, scopeLine = 53, subprogramFlags = Definition, type = #[[TY3]]>

2 changes: 1 addition & 1 deletion libc/benchmarks/MemorySizeDistributions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ getDistributionOrDie(ArrayRef<MemorySizeDistribution> Distributions,
<< "', available distributions:\n";
for (const auto &MSD : Distributions)
Stream << "'" << MSD.Name << "'\n";
report_fatal_error(Stream.str());
report_fatal_error(Message);
}

} // namespace libc_benchmarks
Expand Down
2 changes: 1 addition & 1 deletion libc/benchmarks/automemcpy/unittests/CodeGenTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ TEST(Automemcpy, Codegen) {
raw_string_ostream OutputStream(Output);
Serialize(OutputStream, kDescriptors);

EXPECT_STREQ(OutputStream.str().c_str(),
EXPECT_STREQ(Output.c_str(),
R"(// This file is auto-generated by libc/benchmarks/automemcpy.
// Functions : 6

Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ sure you don't forget anything:

- Did you add the relevant feature test macro(s) for your feature? Did you update the ``generate_feature_test_macro_components.py`` script with it?
- Did you run the ``libcxx-generate-files`` target and verify its output?
- If needed, did you add `_LIBCPP_PUSH_MACROS` and `_LIBCPP_POP_MACROS` to the relevant headers?
- If needed, did you add ``_LIBCPP_PUSH_MACROS`` and ``_LIBCPP_POP_MACROS`` to the relevant headers?

The review process
==================
Expand Down
8 changes: 4 additions & 4 deletions libcxx/include/__algorithm/mismatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) {
}

for (size_t __i = 0; __i != __unroll_count; ++__i) {
if (auto __cmp_res = __lhs[__i] == __rhs[__i]; !std::__all_of(__cmp_res)) {
if (auto __cmp_res = std::__as_mask(__lhs[__i] == __rhs[__i]); !std::__all_of(__cmp_res)) {
auto __offset = __i * __vec_size + std::__find_first_not_set(__cmp_res);
return {__first1 + __offset, __first2 + __offset};
}
Expand All @@ -91,7 +91,7 @@ __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) {

// check the remaining 0-3 vectors
while (static_cast<size_t>(__last1 - __first1) >= __vec_size) {
if (auto __cmp_res = std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2);
if (auto __cmp_res = std::__as_mask(std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2));
!std::__all_of(__cmp_res)) {
auto __offset = std::__find_first_not_set(__cmp_res);
return {__first1 + __offset, __first2 + __offset};
Expand All @@ -108,8 +108,8 @@ __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) {
if (static_cast<size_t>(__first1 - __orig_first1) >= __vec_size) {
__first1 = __last1 - __vec_size;
__first2 = __last2 - __vec_size;
auto __offset =
std::__find_first_not_set(std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2));
auto __offset = std::__find_first_not_set(
std::__as_mask(std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2)));
return {__first1 + __offset, __first2 + __offset};
} // else loop over the elements individually
}
Expand Down
77 changes: 50 additions & 27 deletions libcxx/include/__algorithm/simd_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,42 +116,65 @@ template <class _VecT, class _Iter>
}(make_index_sequence<__simd_vector_size_v<_VecT>>{});
}

template <class _Tp, size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept {
return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector<bool, _Np>));
template <size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<bool, _Np> __vec) noexcept {
return __builtin_reduce_and(__vec);
}

template <class _Tp, size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept {
using __mask_vec = __simd_vector<bool, _Np>;
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI auto __as_mask(__simd_vector<_Tp, _Np> __vec) noexcept {
static_assert(!is_same<_Tp, bool>::value, "vector type should not be a bool!");
return __builtin_convertvector(__vec, __simd_vector<bool, _Np>);
}

// This has MSan disabled du to https://github.com/llvm/llvm-project/issues/85876
auto __impl = [&]<class _MaskT>(_MaskT) _LIBCPP_NO_SANITIZE("memory") noexcept {
# if defined(_LIBCPP_BIG_ENDIAN)
return std::min<size_t>(
_Np, std::__countl_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec))));
# else
return std::min<size_t>(
_Np, std::__countr_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec))));
# endif
};

if constexpr (sizeof(__mask_vec) == sizeof(uint8_t)) {
return __impl(uint8_t{});
} else if constexpr (sizeof(__mask_vec) == sizeof(uint16_t)) {
return __impl(uint16_t{});
} else if constexpr (sizeof(__mask_vec) == sizeof(uint32_t)) {
return __impl(uint32_t{});
} else if constexpr (sizeof(__mask_vec) == sizeof(uint64_t)) {
return __impl(uint64_t{});
// This uses __builtin_convertvector around the __builtin_shufflevector to work around #107981.
template <size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI __simd_vector<bool, 8>
__extend_vector(__simd_vector<bool, _Np> __vec) noexcept {
using _VecT = __simd_vector<bool, _Np>;
if constexpr (_Np == 4) {
return __builtin_convertvector(
__builtin_shufflevector(__vec, _VecT{}, 0, 1, 2, 3, 4, 5, 6, 7), __simd_vector<bool, 8>);
} else if constexpr (_Np == 2) {
return std::__extend_vector(
__builtin_convertvector(__builtin_shufflevector(__vec, _VecT{}, 0, 1, 2, 3), __simd_vector<bool, 4>));
} else if constexpr (_Np == 1) {
return std::__extend_vector(
__builtin_convertvector(__builtin_shufflevector(__vec, _VecT{}, 0, 1), __simd_vector<bool, 2>));
} else {
static_assert(sizeof(__mask_vec) == 0, "unexpected required size for mask integer type");
static_assert(sizeof(_VecT) == 0, "Unexpected vector size");
}
}

template <size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI auto __to_int_mask(__simd_vector<bool, _Np> __vec) {
if constexpr (_Np < 8) {
return std::__bit_cast<uint8_t>(std::__extend_vector(__vec));
} else if constexpr (_Np == 8) {
return std::__bit_cast<uint8_t>(__vec);
} else if constexpr (_Np == 16) {
return std::__bit_cast<uint16_t>(__vec);
} else if constexpr (_Np == 32) {
return std::__bit_cast<uint32_t>(__vec);
} else if constexpr (_Np == 64) {
return std::__bit_cast<uint64_t>(__vec);
} else {
static_assert(sizeof(__simd_vector<bool, _Np>) == 0, "Unexpected vector size");
return 0;
}
}

template <class _Tp, size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept {
template <size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<bool, _Np> __vec) noexcept {
# if defined(_LIBCPP_BIG_ENDIAN)
return std::min<size_t>(_Np, std::__countl_zero(std::__to_int_mask(__vec)));
# else
return std::min<size_t>(_Np, std::__countr_zero(std::__to_int_mask(__vec)));
# endif
}

template <size_t _Np>
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector<bool, _Np> __vec) noexcept {
return std::__find_first_set(~__vec);
}

Expand Down
56 changes: 28 additions & 28 deletions libcxx/include/__assert
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
: _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING( \
expression) " failed: " message "\n"))

// TODO: __builtin_assume can currently inhibit optimizations. Until this has been fixed and we can add
// assumptions without a clear optimization intent, disable that to avoid worsening the code generation.
// See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a discussion.
#if 0 && __has_builtin(__builtin_assume)
// WARNING: __builtin_assume can currently inhibit optimizations. Only add assumptions with a clear
// optimization intent. See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a
// discussion.
#if __has_builtin(__builtin_assume)
# define _LIBCPP_ASSUME(expression) \
(_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume") \
__builtin_assume(static_cast<bool>(expression)) _LIBCPP_DIAGNOSTIC_POP)
Expand All @@ -44,18 +44,18 @@
# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message)
// Disabled checks.
// On most modern platforms, dereferencing a null pointer does not lead to an actual memory access.
# define _LIBCPP_ASSERT_NON_NULL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_NON_NULL(expression, message) ((void)0)
// Overlapping ranges will make algorithms produce incorrect results but don't directly lead to a security
// vulnerability.
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) ((void)0)
# define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message) ((void)0)
# define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) ((void)0)
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) ((void)0)
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) ((void)0)
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) ((void)0)
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) ((void)0)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) ((void)0)
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) ((void)0)

// Extensive hardening mode checks.

Expand All @@ -73,8 +73,8 @@
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSERT(expression, message)
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSERT(expression, message)
// Disabled checks.
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) ((void)0)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) ((void)0)

// Debug hardening mode checks.

Expand All @@ -99,18 +99,18 @@
#else

// All checks disabled.
# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_NON_NULL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression)
# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) ((void)0)
# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) ((void)0)
# define _LIBCPP_ASSERT_NON_NULL(expression, message) ((void)0)
# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) ((void)0)
# define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message) ((void)0)
# define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) ((void)0)
# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) ((void)0)
# define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message) ((void)0)
# define _LIBCPP_ASSERT_PEDANTIC(expression, message) ((void)0)
# define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message) ((void)0)
# define _LIBCPP_ASSERT_INTERNAL(expression, message) ((void)0)
# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) ((void)0)

#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST
// clang-format on
Expand Down
Loading