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 @@ -43,7 +43,7 @@ Options
extern std::string strprintf(const char *format, ...);
int i = -42;
unsigned int u = 0xffffffff;
return strprintf("%d %u\n", i, u);
return strprintf("%u %d\n", i, u);
would be converted to

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Options

int i = -42;
unsigned int u = 0xffffffff;
printf("%d %u\n", i, u);
printf("%u %d\n", i, u);

would be converted to:

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
35 changes: 19 additions & 16 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,10 @@ bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func,
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
const CallExpr *CE);

enum class ShiftDir { Left, Right };

/// Checks if the shift operation is legal.
template <typename LT, typename RT>
template <ShiftDir Dir, typename LT, typename RT>
bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
unsigned Bits) {
if (RHS.isNegative()) {
Expand All @@ -181,19 +183,21 @@ bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
return false;
}

if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {
const Expr *E = S.Current->getExpr(OpPC);
// C++11 [expr.shift]p2: A signed left shift must have a non-negative
// operand, and must not overflow the corresponding unsigned type.
if (LHS.isNegative()) {
S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
if (!S.noteUndefinedBehavior())
return false;
} else if (LHS.toUnsigned().countLeadingZeros() <
static_cast<unsigned>(RHS)) {
S.CCEDiag(E, diag::note_constexpr_lshift_discards);
if (!S.noteUndefinedBehavior())
return false;
if constexpr (Dir == ShiftDir::Left) {
if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {
const Expr *E = S.Current->getExpr(OpPC);
// C++11 [expr.shift]p2: A signed left shift must have a non-negative
// operand, and must not overflow the corresponding unsigned type.
if (LHS.isNegative()) {
S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
if (!S.noteUndefinedBehavior())
return false;
} else if (LHS.toUnsigned().countLeadingZeros() <
static_cast<unsigned>(RHS)) {
S.CCEDiag(E, diag::note_constexpr_lshift_discards);
if (!S.noteUndefinedBehavior())
return false;
}
}
}

Expand Down Expand Up @@ -2394,7 +2398,6 @@ inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
//===----------------------------------------------------------------------===//
// Shr, Shl
//===----------------------------------------------------------------------===//
enum class ShiftDir { Left, Right };

template <class LT, class RT, ShiftDir Dir>
inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
Expand Down Expand Up @@ -2431,7 +2434,7 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
}
}

if (!CheckShift(S, OpPC, LHS, RHS, Bits))
if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits))
return false;

// Limit the shift amount to Bits - 1. If this happened,
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
8 changes: 7 additions & 1 deletion clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,13 @@ 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", Twine(ARM_ACLE_VERSION(2024, 2, 0)));
Builder.defineMacro("__FUNCTION_MULTI_VERSIONING_SUPPORT_LEVEL",
Twine(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
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ void clang::CodeGen::CGHLSLRuntime::setHLSLEntryAttributes(
NumThreadsAttr->getZ());
Fn->addFnAttr(NumThreadsKindStr, NumThreadsStr);
}
Fn->addFnAttr(llvm::Attribute::NoInline);
}

static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) {
Expand Down
20 changes: 14 additions & 6 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2473,11 +2473,14 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
B.addAttribute(llvm::Attribute::StackProtectReq);

if (!D) {
// Non-entry HLSL functions must always be inlined.
if (getLangOpts().HLSL && !F->hasFnAttribute(llvm::Attribute::NoInline))
B.addAttribute(llvm::Attribute::AlwaysInline);
// If we don't have a declaration to control inlining, the function isn't
// explicitly marked as alwaysinline for semantic reasons, and inlining is
// disabled, mark the function as noinline.
if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)
else if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)
B.addAttribute(llvm::Attribute::NoInline);

F->addFnAttrs(B);
Expand All @@ -2504,9 +2507,13 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
ShouldAddOptNone &= !D->hasAttr<MinSizeAttr>();
ShouldAddOptNone &= !D->hasAttr<AlwaysInlineAttr>();

// Add optnone, but do so only if the function isn't always_inline.
if ((ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) &&
!F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
// Non-entry HLSL functions must always be inlined.
if (getLangOpts().HLSL && !F->hasFnAttribute(llvm::Attribute::NoInline) &&
!D->hasAttr<NoInlineAttr>()) {
B.addAttribute(llvm::Attribute::AlwaysInline);
} else if ((ShouldAddOptNone || D->hasAttr<OptimizeNoneAttr>()) &&
!F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
// Add optnone, but do so only if the function isn't always_inline.
B.addAttribute(llvm::Attribute::OptimizeNone);

// OptimizeNone implies noinline; we should not be inlining such functions.
Expand All @@ -2526,7 +2533,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
B.addAttribute(llvm::Attribute::NoInline);
} else if (D->hasAttr<NoDuplicateAttr>()) {
B.addAttribute(llvm::Attribute::NoDuplicate);
} else if (D->hasAttr<NoInlineAttr>() && !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
} else if (D->hasAttr<NoInlineAttr>() &&
!F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
// Add noinline if the function isn't always_inline.
B.addAttribute(llvm::Attribute::NoInline);
} else if (D->hasAttr<AlwaysInlineAttr>() &&
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);

1 change: 1 addition & 0 deletions clang/test/AST/ByteCode/shifts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#define INT_MIN (~__INT_MAX__)

constexpr int a = -1 >> 3;

namespace shifts {
constexpr void test() { // ref-error {{constexpr function never produces a constant expression}} \
Expand Down
31 changes: 21 additions & 10 deletions clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE

int i;

Expand All @@ -7,7 +8,7 @@ __attribute__((constructor)) void call_me_first(void) {
}

__attribute__((constructor)) void then_call_me(void) {
i = 12;
i = 13;
}

__attribute__((destructor)) void call_me_last(void) {
Expand All @@ -21,11 +22,21 @@ void main(unsigned GI : SV_GroupIndex) {}
// CHECK-NOT:@llvm.global_ctors
// CHECK-NOT:@llvm.global_dtors

//CHECK: define void @main()
//CHECK-NEXT: entry:
//CHECK-NEXT: call void @"?call_me_first@@YAXXZ"()
//CHECK-NEXT: call void @"?then_call_me@@YAXXZ"()
//CHECK-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
//CHECK-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
//CHECK-NEXT: call void @"?call_me_last@@YAXXZ"(
//CHECK-NEXT: ret void
// CHECK: define void @main()
// CHECK-NEXT: entry:
// Verify function constructors are emitted
// NOINLINE-NEXT: call void @"?call_me_first@@YAXXZ"()
// NOINLINE-NEXT: call void @"?then_call_me@@YAXXZ"()
// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
// NOINLINE-NEXT: call void @"?call_me_last@@YAXXZ"(
// NOINLINE-NEXT: ret void

// Verify constructor calls are inlined when AlwaysInline is run
// INLINE-NEXT: alloca
// INLINE-NEXT: store i32 12
// INLINE-NEXT: store i32 13
// INLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
// INLINE-NEXT: store i32 %
// INLINE-NEXT: store i32 0
// INLINE: ret void
23 changes: 19 additions & 4 deletions clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE

// Make sure global variable for ctors exist for lib profile.
// CHECK:@llvm.global_ctors
Expand All @@ -11,13 +12,27 @@ void FirstEntry() {}

// CHECK: define void @FirstEntry()
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
// NOINLINE-NEXT: call void @"?FirstEntry@@YAXXZ"()
// Verify inlining leaves only calls to "llvm." intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void

[shader("compute")]
[numthreads(1,1,1)]
void SecondEntry() {}

// CHECK: define void @SecondEntry()
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
// CHECK-NEXT: call void @"?SecondEntry@@YAXXZ"()
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
// NOINLINE-NEXT: call void @"?SecondEntry@@YAXXZ"()
// Verify inlining leaves only calls to "llvm." intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void


// Verify the constructor is alwaysinline
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[IntAttr:\#[0-9]+]]

// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
51 changes: 31 additions & 20 deletions clang/test/CodeGenHLSL/GlobalDestructors.hlsl
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,CHECK
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,CHECK
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE,CHECK
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE,CHECK
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK

// Make sure global variable for dtors exist for lib profile.
// Tests that constructors and destructors are appropriately generated for globals
// and that their calls are inlined when AlwaysInline is run
// but global variables are retained for the library profiles

// Make sure global variable for ctors/dtors exist for lib profile.
// LIB:@llvm.global_ctors
// LIB:@llvm.global_dtors
// Make sure global variable for dtors removed for compute profile.
// CS-NOT:llvm.global_dtors
// Make sure global variable for ctors/dtors removed for compute profile.
// CS-NOT:@llvm.global_ctors
// CS-NOT:@llvm.global_dtors

struct Tail {
Tail() {
Expand Down Expand Up @@ -46,22 +54,25 @@ void main(unsigned GI : SV_GroupIndex) {
Wag();
}

// Make sure global variable for ctors/dtors removed.
// CHECK-NOT:@llvm.global_ctors
// CHECK-NOT:@llvm.global_dtors
//CHECK: define void @main()
//CHECK-NEXT: entry:
//CHECK-NEXT: call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
//CHECK-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
//CHECK-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
//CHECK-NEXT: call void @_GLOBAL__D_a()
//CHECK-NEXT: ret void
// CHECK: define void @main()
// CHECK-NEXT: entry:
// Verify destructor is emitted
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
// NOINLINE-NEXT: call void @_GLOBAL__D_a()
// NOINLINE-NEXT: ret void
// Verify inlining leaves only calls to "llvm." intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// INLINE: ret void

// This is really just a sanity check I needed for myself to verify that
// function scope static variables also get destroyed properly.

//CHECK: define internal void @_GLOBAL__D_a()
//CHECK-NEXT: entry:
//CHECK-NEXT: call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
//CHECK-NEXT: call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
//CHECK-NEXT: ret void
// NOINLINE: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
// NOINLINE-NEXT: entry:
// NOINLINE-NEXT: call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
// NOINLINE-NEXT: call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
// NOINLINE-NEXT: ret void

// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
1 change: 1 addition & 0 deletions clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV

RWBuffer<float> Buf;
Expand Down
5 changes: 3 additions & 2 deletions clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ void main(unsigned GI : SV_GroupIndex) {
// Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy
// and confusing to follow so the match here is pretty weak.

// CHECK: define internal void @"?main@@YAXI@Z"
// CHECK-NOT: call
// CHECK: define void @main()
// Verify inlining leaves only calls to "llvm." intrinsics
// CHECK-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ void main(unsigned GI : SV_GroupIndex) {
// Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy
// and confusing to follow so the match here is pretty weak.

// CHECK: define internal void @"?main@@YAXI@Z"
// CHECK-NOT: call
// CHECK: define void @main()
// Verify inlining leaves only calls to "llvm." intrinsics
// CHECK-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void
76 changes: 76 additions & 0 deletions clang/test/CodeGenHLSL/inline-constructors.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -O1 %s | FileCheck %s --check-prefixes=CHECK,INLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -O1 %s | FileCheck %s --check-prefixes=CHECK,INLINE

// Tests that implicit constructor calls for user classes will always be inlined.

struct Weed {
Weed() {Count += 1;}
[[maybe_unused]] void pull() {Count--;}
static int weedCount() { return Count; }
private:
static int Count;

} YardWeeds;

int Weed::Count = 1; // It begins. . .

struct Kitty {
unsigned burrsInFur;

Kitty() {
burrsInFur = 0;
}

void wanderInYard(int hours) {
burrsInFur = hours*Weed::weedCount()/8;
}

void lick() {
if(burrsInFur) {
burrsInFur--;
Weed w;
}
}

} Nion;

void NionsDay(int hours) {
static Kitty Nion;
Nion.wanderInYard(hours);
while(Nion.burrsInFur) Nion.lick();
}

// CHECK: define void @main()
// CHECK-NEXT: entry:
// Verify constructor is emitted
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_inline_constructors.hlsl()
// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
// Verify inlining leaves only calls to "llvm." intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void
[shader("compute")]
[numthreads(1,1,1)]
void main(unsigned GI : SV_GroupIndex) {
NionsDay(10);
}


// CHECK: define void @rainyMain()
// CHECK-NEXT: entry:
// Verify constructor is emitted
// NOINLINE-NEXT: call void @_GLOBAL__sub_I_inline_constructors.hlsl()
// NOINLINE-NEXT: call void @"?rainyMain@@YAXXZ"()
// Verify inlining leaves only calls to "llvm." intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void
[shader("compute")]
[numthreads(1,1,1)]
void rainyMain() {
NionsDay(1);
}

116 changes: 116 additions & 0 deletions clang/test/CodeGenHLSL/inline-functions.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute %s -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK,INLINE

// Tests that user functions will always be inlined.
// This includes exported functions and mangled entry point implementation functions.
// The unmangled entry functions must not be alwaysinlined.

#define MAX 100

float nums[MAX];

// Verify that all functions have the alwaysinline attribute
// NOINLINE: Function Attrs: alwaysinline
// NOINLINE: define void @"?swap@@YAXY0GE@III@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %ix1, i32 noundef %ix2) [[IntAttr:\#[0-9]+]]
// NOINLINE: ret void
// Swap the values of Buf at indices ix1 and ix2
void swap(unsigned Buf[MAX], unsigned ix1, unsigned ix2) {
float tmp = Buf[ix1];
Buf[ix1] = Buf[ix2];
Buf[ix2] = tmp;
}

// NOINLINE: Function Attrs: alwaysinline
// NOINLINE: define void @"?BubbleSort@@YAXY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[IntAttr]]
// NOINLINE: ret void
// Inefficiently sort Buf in place
void BubbleSort(unsigned Buf[MAX], unsigned size) {
bool swapped = true;
while (swapped) {
swapped = false;
for (unsigned i = 1; i < size; i++) {
if (Buf[i] < Buf[i-1]) {
swap(Buf, i, i-1);
swapped = true;
}
}
}
}

// Note ExtAttr is the inlined export set of attribs
// CHECK: Function Attrs: alwaysinline
// CHECK: define noundef i32 @"?RemoveDupes@@YAIY0GE@II@Z"(ptr {{[a-z_ ]*}}noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) {{[a-z_ ]*}}[[ExtAttr:\#[0-9]+]]
// CHECK: ret i32
// Sort Buf and remove any duplicate values
// returns the number of values left
export
unsigned RemoveDupes(unsigned Buf[MAX], unsigned size) {
BubbleSort(Buf, size);
unsigned insertPt = 0;
for (unsigned i = 1; i < size; i++) {
if (Buf[i] == Buf[i-1])
insertPt++;
else
Buf[insertPt] = Buf[i];
}
return insertPt;
}


RWBuffer<unsigned> Indices;

// The mangled version of main only remains without inlining
// because it has internal linkage from the start
// Note main functions get the norecurse attrib, which IntAttr reflects
// NOINLINE: Function Attrs: alwaysinline
// NOINLINE: define internal void @"?main@@YAXI@Z"(i32 noundef %GI) [[IntAttr]]
// NOINLINE: ret void

// The unmangled version is not inlined, EntryAttr reflects that
// CHECK: Function Attrs: {{.*}}noinline
// CHECK: define void @main() {{[a-z_ ]*}}[[EntryAttr:\#[0-9]+]]
// Make sure function calls are inlined when AlwaysInline is run
// This only leaves calls to llvm. intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void

[numthreads(1,1,1)]
[shader("compute")]
void main(unsigned int GI : SV_GroupIndex) {
unsigned tmpIndices[MAX];
if (GI > MAX) return;
for (unsigned i = 1; i < GI; i++)
tmpIndices[i] = Indices[i];
RemoveDupes(tmpIndices, GI);
for (unsigned i = 1; i < GI; i++)
tmpIndices[i] = Indices[i];
}

// The mangled version of main only remains without inlining
// because it has internal linkage from the start
// Note main functions get the norecurse attrib, which IntAttr reflects
// NOINLINE: Function Attrs: alwaysinline
// NOINLINE: define internal void @"?main10@@YAXXZ"() [[IntAttr]]
// NOINLINE: ret void

// The unmangled version is not inlined, EntryAttr reflects that
// CHECK: Function Attrs: {{.*}}noinline
// CHECK: define void @main10() {{[a-z_ ]*}}[[EntryAttr]]
// Make sure function calls are inlined when AlwaysInline is run
// This only leaves calls to llvm. intrinsics
// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
// CHECK: ret void

[numthreads(1,1,1)]
[shader("compute")]
void main10() {
main(10);
}

// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
// CHECK: attributes [[ExtAttr]] = {{.*}} alwaysinline
// CHECK: attributes [[EntryAttr]] = {{.*}} noinline
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
Loading