87 changes: 87 additions & 0 deletions clang/test/C/C2x/n3018.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// RUN: %clang_cc1 -std=c23 -verify -triple x86_64 -pedantic -Wno-conversion -Wno-constant-conversion %s

/* WG14 N3018: Full
* The constexpr specifier for object definitions
*/

#define ULLONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL)
#define UINT_MAX (__INT_MAX__ *2U +1U)

void Example0() {
constexpr unsigned int minusOne = -1;
// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned int'}}
constexpr unsigned int uint_max = -1U;
constexpr double onethird = 1.0/3.0;
constexpr double onethirdtrunc = (double)(1.0/3.0);

constexpr char string[] = { "\xFF", };
constexpr unsigned char ucstring[] = { "\xFF", };
// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
constexpr char string1[] = { -1, 0, };
constexpr unsigned char ucstring1[] = { -1, 0, };
// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}

// TODO: Make sure these work correctly once char8_t and _Decimal are supported
// constexpr char8_t u8string[] = { 255, 0, }; // ok
// constexpr char8_t u8string[] = { u8"\xFF", }; // ok
// constexpr _Decimal32 small = DEC64_TRUE_MIN * 0;// constraint violation
}

void Example1() {
constexpr int K = 47;
enum {
A = K,
};
constexpr int L = K;
static int b = K + 1;
int array[K];
_Static_assert(K == 47);
}

constexpr int K = 47;
static const int b = K + 1;

void Example2() {
constexpr int A = 42LL;
constexpr signed short B = ULLONG_MAX;
// expected-error@-1 {{constexpr initializer evaluates to 18446744073709551615 which is not exactly representable in type 'const short'}}
constexpr float C = 47u;

constexpr float D = 432000000;
constexpr float E = 1.0 / 3.0;
// expected-error@-1 {{constexpr initializer evaluates to 3.333333e-01 which is not exactly representable in type 'const float'}}
constexpr float F = 1.0f / 3.0f;
}


void Example3() {
constexpr static unsigned short array[] = {
3000,
300000,
// expected-error@-1 {{constexpr initializer evaluates to 300000 which is not exactly representable in type 'const unsigned short'}}
-1
// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned short'}}
};

constexpr static unsigned short array1[] = {
3000,
3000,
-1
// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned short'}}
};

struct S {
int x, y;
};
constexpr struct S s = {
.x = __INT_MAX__,
.y = UINT_MAX,
// expected-error@-1 {{constexpr initializer evaluates to 4294967295 which is not exactly representable in type 'int'}}
};
}

void Example4() {
struct s { void *p; };
constexpr struct s A = { nullptr };
constexpr struct s B = A;
}
61 changes: 61 additions & 0 deletions clang/test/CXX/drs/dr24xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,64 @@ template<A> struct X {};
X<1> x;
#endif
}

namespace dr2445 { // dr2445: 19
#if __cplusplus >= 202002L
template <typename> constexpr bool F = false;
template <typename T> struct A { };

template <typename T, typename U>
bool operator==(T, A<U *>);

template <typename T, typename U>
bool operator!=(A<T>, U) {
static_assert(F<T>, "Isn't this less specialized?");
return false;
}

bool f(A<int> ax, A<int *> ay) { return ay != ax; }

template<class T> concept AlwaysTrue=true;
template <class T> struct B {
template <AlwaysTrue U>
bool operator==(const B<U>&)const;
};


template <typename U>
bool operator==(const B<int>&,const B<U>&) {
static_assert(F<int>, "Isn't this less specialized?");
return false;
}

bool g(B<int> bx, B<int *> by) { return bx == by; }

struct C{
template<AlwaysTrue T>
int operator+(T){return 0;}
template<class T>
void operator-(T){}
};
template<class T>
void operator+(C&&,T){}
template<AlwaysTrue T>
int operator-(C&&,T){return 0;}

void t(int* iptr){
int x1 = C{} + iptr;
int x2 = C{} - iptr;
}

struct D{
template<AlwaysTrue T>
int operator+(T) volatile {return 1;}
};

template<class T>
void operator+(volatile D&,T) {}

int foo(volatile D& d){
return d + 1;
}
#endif
}
25 changes: 25 additions & 0 deletions clang/test/CXX/drs/dr438.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr438 { // dr438: 2.7

void f() {
long A[2];
A[0] = 0;
A[A[0]] = 1;
}

} // namespace dr438

// CHECK-LABEL: define {{.*}} void @dr438::f()()
// CHECK: [[A:%.+]] = alloca [2 x i64]
// CHECK: {{.+}} = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0
// CHECK: [[ARRAYIDX1:%.+]] = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0
// CHECK-NEXT: [[TEMPIDX:%.+]] = load i64, ptr [[ARRAYIDX1]]
// CHECK-NEXT: [[ARRAYIDX2:%.+]] = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 [[TEMPIDX]]
// CHECK-LABEL: }
30 changes: 30 additions & 0 deletions clang/test/CXX/drs/dr439.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr439 { // dr439: 2.7

void f() {
int* p1 = new int;
const int* p2 = static_cast<const int*>(static_cast<void *>(p1));
bool b = p1 == p2; // b will have the value true.
}

} // namespace dr439

// We're checking that p2 was copied from p1, and then was carried over
// to the comparison without change.

// CHECK-LABEL: define {{.*}} void @dr439::f()()
// CHECK: [[P1:%.+]] = alloca ptr, align 8
// CHECK-NEXT: [[P2:%.+]] = alloca ptr, align 8
// CHECK: [[TEMP0:%.+]] = load ptr, ptr [[P1]]
// CHECK-NEXT: store ptr [[TEMP0:%.+]], ptr [[P2]]
// CHECK-NEXT: [[TEMP1:%.+]] = load ptr, ptr [[P1]]
// CHECK-NEXT: [[TEMP2:%.+]] = load ptr, ptr [[P2]]
// CHECK-NEXT: {{.*}} = icmp eq ptr [[TEMP1]], [[TEMP2]]
// CHECK-LABEL: }
38 changes: 38 additions & 0 deletions clang/test/CXX/drs/dr441.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr441 { // dr441: 2.7

struct A {
A() {}
};

A dynamic_init;
int i;
int& ir = i;
int* ip = &i;

} // namespace dr441

// CHECK-DAG: @dr441::dynamic_init = global %"struct.dr441::A" zeroinitializer
// CHECK-DAG: @dr441::i = global i32 0
// CHECK-DAG: @dr441::ir = constant ptr @dr441::i
// CHECK-DAG: @dr441::ip = global ptr @dr441::i
// CHECK-DAG: @llvm.global_ctors = appending global [{{.+}}] [{ {{.+}} } { {{.+}}, ptr @_GLOBAL__sub_I_dr441.cpp, {{.+}} }]

// CHECK-LABEL: define {{.*}} void @__cxx_global_var_init()
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @dr441::A::A()({{.*}} @dr441::dynamic_init)
// CHECK-NEXT: ret void
// CHECK-NEXT: }

// CHECK-LABEL: define {{.*}} void @_GLOBAL__sub_I_dr441.cpp()
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @__cxx_global_var_init()
// CHECK-NEXT: ret void
// CHECK-NEXT: }
33 changes: 33 additions & 0 deletions clang/test/CXX/drs/dr462.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

#if __cplusplus == 199711L
#define NOTHROW throw()
#else
#define NOTHROW noexcept(true)
#endif

namespace dr462 { // dr462: 2.7

struct A {
~A() NOTHROW {}
};

extern void full_expr_fence() NOTHROW;

void f() {
const A& r = (3, A());
full_expr_fence();
}

} // namespace dr462

// CHECK-LABEL: define {{.*}} void @dr462::f()()
// CHECK: call void @dr462::full_expr_fence()()
// CHECK: call void @dr462::A::~A()
// CHECK-LABEL: }
37 changes: 37 additions & 0 deletions clang/test/CXX/drs/dr492.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

#if __cplusplus == 199711L
#define NOTHROW throw()
#else
#define NOTHROW noexcept(true)
#endif

namespace std {
struct type_info {
const char* name() const NOTHROW;
};
}

namespace dr492 { // dr492: 2.7

void f() {
typeid(int).name();
typeid(const int).name();
typeid(volatile int).name();
typeid(const volatile int).name();
}

} // namespace dr492

// CHECK-LABEL: define {{.*}} void @dr492::f()()
// CHECK: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
// CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
// CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
// CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
// CHECK-LABEL: }
12 changes: 6 additions & 6 deletions clang/test/CXX/drs/dr4xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,9 @@ namespace dr437 { // dr437: sup 1308
};
}

// dr438 FIXME write a codegen test
// dr439 FIXME write a codegen test
// dr441 FIXME write a codegen test
// dr438 is in dr438.cpp
// dr439 is in dr439.cpp
// dr441 is in dr441.cpp
// dr442: sup 348
// dr443: na

Expand Down Expand Up @@ -943,7 +943,7 @@ namespace dr460 { // dr460: yes
}

// dr461: na
// dr462 FIXME write a codegen test
// dr462 is in dr462.cpp
// dr463: na
// dr464: na
// dr465: na
Expand Down Expand Up @@ -1089,7 +1089,7 @@ namespace dr474 { // dr474: 3.4
}
}

// dr475 FIXME write a codegen test
// dr475 FIXME write a libc++abi test

namespace dr477 { // dr477: 3.5
struct A {
Expand Down Expand Up @@ -1437,7 +1437,7 @@ namespace dr491 { // dr491: dup 413
// expected-error@-1 {{excess elements in array initializer}}
}

// dr492 FIXME write a codegen test
// dr492 is in dr492.cpp

namespace dr493 { // dr493: dup 976
struct X {
Expand Down
56 changes: 28 additions & 28 deletions clang/test/CodeGen/attr-target-version.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,16 @@ int hoo(void) {
// CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one
// CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two
// CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e
// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
// CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline
// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d
// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
// CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver
// CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver
// CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
// CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
// CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
//.
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng
Expand Down Expand Up @@ -238,11 +238,18 @@ int hoo(void) {
// CHECK-NEXT: ret i32 111
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
// CHECK-SAME: () #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
// CHECK: resolver_else:
// CHECK-NEXT: ret ptr @fmv_c.default
//
//
// CHECK: Function Attrs: noinline nounwind optnone
Expand Down Expand Up @@ -405,20 +412,6 @@ int hoo(void) {
// CHECK-NEXT: ret ptr @fmv_d.default
//
//
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
// CHECK: resolver_else:
// CHECK-NEXT: ret ptr @fmv_c.default
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@recur
// CHECK-SAME: () #[[ATTR2]] {
Expand Down Expand Up @@ -568,6 +561,20 @@ int hoo(void) {
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
// CHECK-SAME: () #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
// CHECK-SAME: () #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1
// CHECK-SAME: () #[[ATTR12:[0-9]+]] {
// CHECK-NEXT: entry:
Expand Down Expand Up @@ -700,13 +707,6 @@ int hoo(void) {
// CHECK-NEXT: ret i32 1
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
// CHECK-SAME: () #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
//
//
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv
// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] {
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CodeGenCUDA/amdgpu-code-object-version-linking.cu
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
// LINKED4: [[GEP_4_Z:%.*]] = getelementptr i8, ptr addrspace(4) %{{.*}}, i32 8
// LINKED4: select i1 false, ptr addrspace(4) [[GEP_5_Z]], ptr addrspace(4) [[GEP_4_Z]]
// LINKED4: load i16, ptr addrspace(4) %{{.*}}, align 2, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
// LINKED4: "amdgpu_code_object_version", i32 400
// LINKED4: "amdhsa_code_object_version", i32 400

// LINKED5: __oclc_ABI_version = weak_odr hidden local_unnamed_addr addrspace(4) constant i32 500
// LINKED5-LABEL: bar
Expand Down Expand Up @@ -82,7 +82,7 @@
// LINKED5: [[GEP_4_Z:%.*]] = getelementptr i8, ptr addrspace(4) %{{.*}}, i32 8
// LINKED5: select i1 true, ptr addrspace(4) [[GEP_5_Z]], ptr addrspace(4) [[GEP_4_Z]]
// LINKED5: load i16, ptr addrspace(4) %{{.*}}, align 2, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
// LINKED5: "amdgpu_code_object_version", i32 500
// LINKED5: "amdhsa_code_object_version", i32 500

// LINKED6: __oclc_ABI_version = weak_odr hidden local_unnamed_addr addrspace(4) constant i32 600
// LINKED6-LABEL: bar
Expand Down Expand Up @@ -112,7 +112,7 @@
// LINKED6: [[GEP_4_Z:%.*]] = getelementptr i8, ptr addrspace(4) %{{.*}}, i32 8
// LINKED6: select i1 true, ptr addrspace(4) [[GEP_5_Z]], ptr addrspace(4) [[GEP_4_Z]]
// LINKED6: load i16, ptr addrspace(4) %{{.*}}, align 2, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
// LINKED6: "amdgpu_code_object_version", i32 600
// LINKED6: "amdhsa_code_object_version", i32 600

#ifdef DEVICELIB
__device__ void bar(int *x, int *y, int *z)
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGenCUDA/amdgpu-code-object-version.cu
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
// RUN: not %clang_cc1 -fcuda-is-device -triple amdgcn-amd-amdhsa -emit-llvm \
// RUN: -mcode-object-version=4.1 -o - %s 2>&1| FileCheck %s -check-prefix=INV

// V4: !{{.*}} = !{i32 1, !"amdgpu_code_object_version", i32 400}
// V5: !{{.*}} = !{i32 1, !"amdgpu_code_object_version", i32 500}
// V6: !{{.*}} = !{i32 1, !"amdgpu_code_object_version", i32 600}
// NONE-NOT: !{{.*}} = !{i32 1, !"amdgpu_code_object_version",
// V4: !{{.*}} = !{i32 1, !"amdhsa_code_object_version", i32 400}
// V5: !{{.*}} = !{i32 1, !"amdhsa_code_object_version", i32 500}
// V6: !{{.*}} = !{i32 1, !"amdhsa_code_object_version", i32 600}
// NONE-NOT: !{{.*}} = !{i32 1, !"amdhsa_code_object_version",
// INV: error: invalid value '4.1' in '-mcode-object-version=4.1'
4 changes: 2 additions & 2 deletions clang/test/CodeGenHIP/default-attributes.hip
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ __global__ void kernel() {
// OPT: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
// OPT: attributes #1 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "amdgpu-flat-work-group-size"="1,1024" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="true" }
//.
// OPTNONE: !0 = !{i32 1, !"amdgpu_code_object_version", i32 500}
// OPTNONE: !0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
// OPTNONE: !1 = !{i32 1, !"amdgpu_printf_kind", !"hostcall"}
// OPTNONE: !2 = !{i32 1, !"wchar_size", i32 4}
//.
// OPT: !0 = !{i32 1, !"amdgpu_code_object_version", i32 500}
// OPT: !0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
// OPT: !1 = !{i32 1, !"amdgpu_printf_kind", !"hostcall"}
// OPT: !2 = !{i32 1, !"wchar_size", i32 4}
//.
4 changes: 2 additions & 2 deletions clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ kernel void test_target_features_kernel(global int *i) {
// GFX900: attributes #8 = { nounwind }
// GFX900: attributes #9 = { convergent nounwind }
//.
// NOCPU: !0 = !{i32 1, !"amdgpu_code_object_version", i32 500}
// NOCPU: !0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
// NOCPU: !1 = !{i32 1, !"wchar_size", i32 4}
// NOCPU: !2 = !{i32 2, i32 0}
// NOCPU: !3 = !{i32 1, i32 0, i32 1, i32 0}
Expand All @@ -721,7 +721,7 @@ kernel void test_target_features_kernel(global int *i) {
// NOCPU: !15 = !{i32 1}
// NOCPU: !16 = !{!"int*"}
//.
// GFX900: !0 = !{i32 1, !"amdgpu_code_object_version", i32 500}
// GFX900: !0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
// GFX900: !1 = !{i32 1, !"wchar_size", i32 4}
// GFX900: !2 = !{i32 2, i32 0}
// GFX900: !3 = !{!4, !4, i64 0}
Expand Down
12 changes: 12 additions & 0 deletions clang/test/CodeGenOpenCL/builtins-amdgcn.cl
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,18 @@ unsigned test_wavefrontsize() {
return __builtin_amdgcn_wavefrontsize();
}

// CHECK-LABEL test_get_fpenv(
unsigned long test_get_fpenv() {
// CHECK: call i64 @llvm.get.fpenv.i64()
return __builtin_amdgcn_get_fpenv();
}

// CHECK-LABEL test_set_fpenv(
void test_set_fpenv(unsigned long env) {
// CHECK: call void @llvm.set.fpenv.i64(i64 %[[ENV:.+]])
__builtin_amdgcn_set_fpenv(env);
}

// CHECK-DAG: [[$WI_RANGE]] = !{i32 0, i32 1024}
// CHECK-DAG: [[$WS_RANGE]] = !{i16 1, i16 1025}
// CHECK-DAG: attributes #[[$NOUNWIND_READONLY]] = { convergent mustprogress nocallback nofree nounwind willreturn memory(none) }
109 changes: 109 additions & 0 deletions clang/test/Modules/transitive-import.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: split-file %s %t
//
// RUN: %clang_cc1 -std=c++20 %t/Invisible.cppm -emit-module-interface -o %t/Invisible.pcm
// RUN: %clang_cc1 -std=c++20 %t/Other.cppm -emit-module-interface -fprebuilt-module-path=%t \
// RUN: -o %t/Other.pcm
// RUN: %clang_cc1 -std=c++20 %t/Another.cppm -emit-module-interface -o %t/Another.pcm
// RUN: %clang_cc1 -std=c++20 %t/A-interface.cppm -emit-module-interface \
// RUN: -fprebuilt-module-path=%t -o %t/A-interface.pcm
// RUN: %clang_cc1 -std=c++20 %t/A-interface2.cppm -emit-module-interface \
// RUN: -fprebuilt-module-path=%t -o %t/A-interface2.pcm
// RUN: %clang_cc1 -std=c++20 %t/A-interface3.cppm -emit-module-interface \
// RUN: -fprebuilt-module-path=%t -o %t/A-interface3.pcm
// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface \
// RUN: -fprebuilt-module-path=%t -o %t/A.pcm

// RUN: %clang_cc1 -std=c++20 %t/A.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
// RUN: %clang_cc1 -std=c++20 %t/A-impl.cppm -fprebuilt-module-path=%t -fsyntax-only -verify

// RUN: %clang_cc1 -std=c++20 %t/A-impl2.cppm -fprebuilt-module-path=%t -fsyntax-only -verify

//--- Invisible.cppm
export module Invisible;
export void invisible() {}

//--- Other.cppm
export module Other;
import Invisible;
export void other() {}

//--- Another.cppm
export module Another;
export void another() {}

//--- A-interface.cppm
export module A:interface;
import Other;
export void a_interface() {}

//--- A-interface2.cppm
export module A:interface2;
import Another;
export void a_interface2() {}

//--- A-interface3.cppm
export module A:interface3;
import :interface;
import :interface2;
export void a_interface3() {}

//--- A.cppm
export module A;
import Another;
import :interface;
import :interface2;
import :interface3;

export void a() {}
export void impl();

//--- A.cpp
module A;
void impl() {
a_interface();
a_interface2();
a_interface3();

other();
another();

invisible(); // expected-error {{declaration of 'invisible' must be imported from module 'Invisible' before it is required}}
// expected-note@* {{declaration here is not visible}}
}

//--- A-impl.cppm
module A:impl;
import :interface3;

void impl_part() {
a_interface();
a_interface2();
a_interface3();

other();
another();

invisible(); // expected-error {{declaration of 'invisible' must be imported from module 'Invisible' before it is required}}
// expected-note@* {{declaration here is not visible}}
}

//--- A-impl2.cppm
module A:impl2;
import A;

void impl_part2() {
a();
impl();

a_interface();
a_interface2();
a_interface3();

other();
another();

invisible(); // expected-error {{declaration of 'invisible' must be imported from module 'Invisible' before it is required}}
// expected-note@* {{declaration here is not visible}}
}
19 changes: 19 additions & 0 deletions clang/test/OpenMP/declare_target_ast_print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,13 +360,32 @@ int inner_link;
// CHECK-NEXT: int inner_link;
// CHECK-NEXT: #pragma omp end declare target

void foo2() { return ;}
// CHECK: #pragma omp declare target
// CHECK-NEXT: void foo2() {
// CHECK-NEXT: return;
// CHECK-NEXT: }

int x;
// CHECK: #pragma omp declare target link
// CHECK-NEXT: int x;
// CHECK-NEXT: #pragma omp end declare target

int main (int argc, char **argv) {
foo();
foo_c();
foo_cpp();
test1();
baz<float>();
baz<int>();

#if _OPENMP == 202111
#pragma omp declare target enter(foo2)
#else
#pragma omp declare target to (foo2)
#endif

#pragma omp declare target link(x)
return (0);
}

Expand Down
9 changes: 9 additions & 0 deletions clang/test/OpenMP/declare_target_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,20 @@ struct S {
#pragma omp end declare target
};

void foo3() {
return;
}

int *y;
int **w = &y;
int main (int argc, char **argv) {
int a = 2;
#pragma omp declare target // expected-error {{unexpected OpenMP directive '#pragma omp declare target'}}
int v;
#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
foo(v);
#pragma omp declare target to(foo3) link(w) // omp52-error {{unexpected 'to' clause, use 'enter' instead}} omp52-error {{expected at least one 'enter', 'link' or 'indirect' clause}}
#pragma omp declare target to(a) //omp45-error {{local variable 'a' should not be used in 'declare target' directive}} omp5-error {{local variable 'a' should not be used in 'declare target' directive}} omp51-error {{local variable 'a' should not be used in 'declare target' directive}} omp52-error {{unexpected 'to' clause, use 'enter' instead}} omp52-error {{expected at least one 'enter', 'link' or 'indirect' clause}}
return (0);
}

Expand Down
15 changes: 15 additions & 0 deletions clang/test/Parser/c23-constexpr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %s -Wpre-c2x-compat
// RUN: %clang_cc1 -fsyntax-only -verify=c17 -std=c17 %s

constexpr int a = 0; // c17-error {{unknown type name 'constexpr'}} \
c23-warning {{'constexpr' is incompatible with C standards before C23}}

void func(int array[constexpr]); // c23-error {{expected expression}} \
// c17-error {{use of undeclared}}

_Atomic constexpr int b = 0; // c23-error {{constexpr variable cannot have type 'const _Atomic(int)'}} \
// c23-warning {{'constexpr' is incompatible with C standards before C23}} \
// c17-error {{unknown type name 'constexpr'}}

int static constexpr c = 1; // c17-error {{expected ';' after top level declarator}} \
// c23-warning {{'constexpr' is incompatible with C standards before C23}}
2 changes: 1 addition & 1 deletion clang/test/Rewriter/rewrite-modern-class.mm
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ @interface class_has_no_ivar : root_with_ivars @end

@implementation class_has_no_ivar @end

//============================class needs to be synthesized here=====================
//===================== class needs to be synthesized here =====================
@interface SUPER {
@public
double divar;
Expand Down
25 changes: 19 additions & 6 deletions clang/test/Sema/attr-target-version.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,25 @@ void __attribute__((target_version("ssbs+fp16fml"))) two(void) {}
//expected-error@+1 {{'main' cannot be a multiversioned function}}
int __attribute__((target_version("lse"))) main(void) { return 1; }

//expected-note@+1 {{previous definition is here}}
int hoo(void) { return 1; }
//expected-note@-1 {{previous definition is here}}
//expected-warning@+2 {{attribute declaration must precede definition}}
//expected-error@+1 {{redefinition of 'hoo'}}
int __attribute__((target_version("dit"))) hoo(void) { return 2; }
// It is ok for the default version to appear first.
int default_first(void) { return 1; }
int __attribute__((target_version("dit"))) default_first(void) { return 2; }
int __attribute__((target_version("mops"))) default_first(void) { return 3; }

// It is ok if the default version is between other versions.
int __attribute__((target_version("simd"))) default_middle(void) {return 0; }
int __attribute__((target_version("default"))) default_middle(void) { return 1; }
int __attribute__((target_version("aes"))) default_middle(void) { return 2; }

// It is ok for the default version to be the last one.
int __attribute__((target_version("rdm"))) default_last(void) {return 0; }
int __attribute__((target_version("lse+aes"))) default_last(void) { return 1; }
int __attribute__((target_version("default"))) default_last(void) { return 2; }

// It is also ok to forward declare the default.
int __attribute__((target_version("default"))) default_fwd_declare(void);
int __attribute__((target_version("sve"))) default_fwd_declare(void) { return 0; }
int default_fwd_declare(void) { return 1; }

//expected-warning@+1 {{unsupported '' in the 'target_version' attribute string; 'target_version' attribute ignored}}
int __attribute__((target_version(""))) unsup1(void) { return 1; }
Expand Down
359 changes: 359 additions & 0 deletions clang/test/Sema/constexpr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,359 @@
// RUN: %clang_cc1 -std=c23 -verify -triple x86_64 -pedantic -Wno-conversion -Wno-constant-conversion -Wno-div-by-zero %s

// Check that constexpr only applies to variables.
constexpr void f0() {} // expected-error {{'constexpr' can only be used in variable declarations}}
constexpr const int f1() { return 0; } // expected-error {{'constexpr' can only be used in variable declarations}}

constexpr struct S1 { int f; }; //expected-error {{struct cannot be marked constexpr}}
constexpr struct S2 ; // expected-error {{struct cannot be marked constexpr}}
constexpr union U1; // expected-error {{union cannot be marked constexpr}}
constexpr union U2 {int a; float b;}; // expected-error {{union cannot be marked constexpr}}
constexpr enum E1 {A = 1, B = 2} ; // expected-error {{enum cannot be marked constexpr}}
struct S3 {
static constexpr int f = 0; // expected-error {{type name does not allow storage class}}
// expected-error@-1 {{type name does not allow constexpr}}
// expected-error@-2 {{expected ';' at end}}
constexpr int f1 = 0;
// expected-error@-1 {{type name does not allow constexpr}}
// expected-error@-2 {{expected ';' at end}}
};

constexpr; // expected-error {{'constexpr' can only be used in variable declarations}}
constexpr int V1 = 3;
constexpr float V2 = 7.0;
int V3 = (constexpr)3; // expected-error {{expected expression}}

void f2() {
constexpr int a = 0;
constexpr float b = 1.7f;
}

// Check how constexpr works with other storage-class specifiers.
constexpr auto V4 = 1;
constexpr static auto V5 = 1;
constexpr static const auto V6 = 1;
constexpr static const int V7 = 1;
constexpr static int V8 = 1;
constexpr auto Ulong = 1L;
constexpr auto CompoundLiteral = (int){13};
constexpr auto DoubleCast = (double)(1 / 3);
constexpr auto String = "this is a string"; // expected-error {{constexpr pointer initializer is not null}}
constexpr signed auto Long = 1L; // expected-error {{'auto' cannot be signed or unsigned}}
_Static_assert(_Generic(Ulong, long : 1));
_Static_assert(_Generic(CompoundLiteral, int : 1));
_Static_assert(_Generic(DoubleCast, double : 1));
_Static_assert(_Generic(String, char* : 1));

typedef constexpr int Foo; // expected-error {{typedef cannot be constexpr}}
constexpr typedef int Bar; // expected-error {{typedef cannot be constexpr}}

void f3(constexpr register int P1) { // expected-error {{function parameter cannot be constexpr}}
constexpr register int V9 = 0;
constexpr register auto V10 = 0.0;
}

constexpr thread_local int V11 = 38; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}
constexpr static thread_local double V12 = 38; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}
constexpr extern thread_local char V13; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}
// expected-error@-1 {{cannot combine with previous 'extern' declaration specifier}}
// expected-error@-2 {{constexpr variable declaration must be a definition}}
constexpr thread_local short V14 = 38; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}

// Check how constexpr works with qualifiers.
constexpr _Atomic int V15 = 0; // expected-error {{constexpr variable cannot have type 'const _Atomic(int)'}}
constexpr _Atomic(int) V16 = 0; // expected-error {{constexpr variable cannot have type 'const _Atomic(int)'}}

constexpr volatile int V17 = 0; // expected-error {{constexpr variable cannot have type 'const volatile int'}}

constexpr int * restrict V18 = 0; // expected-error {{constexpr variable cannot have type 'int *const restrict'}}

constexpr extern char Oops = 1; // expected-error {{cannot combine with previous 'extern' declaration specifier}} \
// expected-warning {{'extern' variable has an initializer}}

constexpr int * restrict * Oops1 = 0;

typedef _Atomic(int) TheA;
typedef volatile short TheV;
typedef float * restrict TheR;

constexpr TheA V19[3] = {};
// expected-error@-1 {{constexpr variable cannot have type 'const TheA[3]' (aka 'const _Atomic(int)[3]')}}
constexpr TheV V20[3] = {};
// expected-error@-1 {{constexpr variable cannot have type 'const TheV[3]' (aka 'const volatile short[3]')}}
constexpr TheR V21[3] = {};
// expected-error@-1 {{constexpr variable cannot have type 'const TheR[3]' (aka 'float *restrict const[3]')}}

struct HasA {
TheA f;
int b;
};

struct HasV {
float b;
TheV f;
};

struct HasR {
short b;
int a;
TheR f;
};

constexpr struct HasA V22[2] = {};
// expected-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
constexpr struct HasV V23[2] = {};
// expected-error@-1 {{constexpr variable cannot have type 'TheV' (aka 'volatile short')}}
constexpr struct HasR V24[2] = {};
// expected-error@-1 {{constexpr variable cannot have type 'TheR' (aka 'float *restrict')}}

union U3 {
float a;
union {
struct HasA f;
struct HasR f1;
};
};

constexpr union U3 V25 = {};
// expected-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
constexpr union U3 V26[8] = {};
// expected-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}

struct S4 {
union U3 f[3];
};

constexpr struct S4 V27 = {};
// expected-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
constexpr const int V28 = 28;

struct S {
union {
volatile int i;
};
int j;
};

constexpr struct S s = {}; // expected-error {{constexpr variable cannot have type 'volatile int'}}

// Check that constexpr variable must have a valid initializer which is a
// constant expression.
constexpr int V29;
// expected-error@-1 {{constexpr variable 'V29' must be initialized by a constant expression}}

struct S5 {
int f;
};

constexpr struct S5 V30;
// expected-error@-1 {{constexpr variable 'V30' must be initialized by a constant expression}}
constexpr struct S5 V31 = {};

int randomFoo() { return 7; }

constexpr float V32 = randomFoo();
// expected-error@-1 {{constexpr variable 'V32' must be initialized by a constant expression}}

const int V33 = 4;
const int V34 = 0;
const int V35 = 2;

constexpr int V36 = V33 / V34;
// expected-error@-1 {{constexpr variable 'V36' must be initialized by a constant expression}}
constexpr int V37 = V33 / V35;
// expected-error@-1 {{constexpr variable 'V37' must be initialized by a constant expression}}
constexpr int V38 = 3;
constexpr int V39 = V38 / V38;
constexpr int V40 = V38 / 2;
constexpr int V41 = V38 / 0;
// expected-error@-1 {{constexpr variable 'V41' must be initialized by a constant expression}}
// expected-note@-2 {{division by zero}}
constexpr int V42 = V38 & 0;

constexpr struct S5 V43 = { randomFoo() };
// expected-error@-1 {{constexpr variable 'V43' must be initialized by a constant expression}}
constexpr struct S5 V44 = { 0 };
constexpr struct S5 V45 = { V38 / 0 };
// expected-error@-1 {{constexpr variable 'V45' must be initialized by a constant expression}}
// expected-note@-2 {{division by zero}}

constexpr float V46[3] = {randomFoo() };
// expected-error@-1 {{constexpr variable 'V46' must be initialized by a constant expression}}
constexpr struct S5 V47[3] = {randomFoo() };
// expected-error@-1 {{constexpr variable 'V47' must be initialized by a constant expression}}

const static int V48 = V38;
constexpr static int V49 = V48;
// expected-error@-1 {{constexpr variable 'V49' must be initialized by a constant expression}}

void f4(const int P1) {
constexpr int V = P1;
// expected-error@-1 {{constexpr variable 'V' must be initialized by a constant expression}}

constexpr int V1 = 12;
constexpr const int *V2 = &V1;
// expected-error@-1 {{constexpr variable 'V2' must be initialized by a constant expression}}
}

// Check that initializer for constexpr variable should match the type of the
// variable and is exactly representable int the variable's type.

struct S6 {
unsigned char a;
};

struct S7 {
union {
float a;
};
unsigned int b;
};

struct S8 {
unsigned char a[3];
unsigned int b[3];
};

constexpr struct S8 DesigInit = {.b = {299, 7, 8}, .a = {-1, 7, 8}};
// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned char'}}

void f5() {
constexpr char V50 = 300;
// expected-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'const char'}}
constexpr float V51 = 1.0 / 3.0;
// expected-error@-1 {{constexpr initializer evaluates to 3.333333e-01 which is not exactly representable in type 'const float'}}
constexpr float V52 = 0.7;
// expected-error@-1 {{constexpr initializer evaluates to 7.000000e-01 which is not exactly representable in type 'const float'}}
constexpr float V53 = 1.0f / 3.0f;
constexpr float V54 = 432000000000;
// expected-error@-1 {{constexpr initializer evaluates to 432000000000 which is not exactly representable in type 'const float'}}
constexpr unsigned char V55[] = {
"\xAF",
// expected-error@-1 {{constexpr initializer evaluates to -81 which is not exactly representable in type 'const unsigned char'}}
};

constexpr unsigned char V56[] = {
u8"\xAF",
};
constexpr struct S6 V57 = {299};
// expected-error@-1 {{constexpr initializer evaluates to 299 which is not exactly representable in type 'unsigned char'}}
constexpr struct S6 V58 = {-299};
// expected-error@-1 {{constexpr initializer evaluates to -299 which is not exactly representable in type 'unsigned char'}}
constexpr double V59 = 0.5;
constexpr double V60 = 1.0;
constexpr float V61 = V59 / V60;
constexpr double V62 = 1.7;
constexpr float V63 = V59 / V62;
// expected-error@-1 {{constexpr initializer evaluates to 2.941176e-01 which is not exactly representable in type 'const float'}}

constexpr unsigned char V64 = '\xAF';
// expected-error@-1 {{constexpr initializer evaluates to -81 which is not exactly representable in type 'const unsigned char'}}
constexpr unsigned char V65 = u8'\xAF';

constexpr char V66[3] = {300};
// expected-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'const char'}}
constexpr struct S6 V67[3] = {300};
// expected-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'unsigned char'}}

constexpr struct S7 V68 = {0.3, -1 };
// expected-error@-1 {{constexpr initializer evaluates to 3.000000e-01 which is not exactly representable in type 'float'}}
// expected-error@-2 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned int'}}
constexpr struct S7 V69 = {0.5, -1 };
// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned int'}}
constexpr struct S7 V70[3] = {{123456789}};
// expected-error@-1 {{constexpr initializer evaluates to 123456789 which is not exactly representable in type 'float'}}

constexpr int V71 = 0.3;
// expected-error@-1 {{constexpr initializer for type 'const int' is of type 'double'}}
constexpr int V72 = V59;
// expected-error@-1 {{constexpr initializer for type 'const int' is of type 'const double'}}
constexpr struct S6 V73 = {V59};
// expected-error@-1 {{constexpr initializer for type 'unsigned char' is of type 'const double'}}

constexpr float V74 = 1;
constexpr float V75 = V59;
constexpr unsigned int V76[3] = {0.5};
// expected-error@-1 {{constexpr initializer for type 'const unsigned int' is of type 'double'}}

constexpr _Complex float V77 = 0;
constexpr float V78 = V77;
// expected-error@-1 {{constexpr initializer for type 'const float' is of type 'const _Complex float'}}
constexpr int V79 = V77;
// expected-error@-1 {{constexpr initializer for type 'const int' is of type 'const _Complex float'}}

}

constexpr char string[] = "test""ing this out\xFF";
constexpr unsigned char ustring[] = "test""ing this out\xFF";
// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
constexpr char u8string[] = u8"test"u8"ing this out\xFF";
// expected-error@-1 {{constexpr initializer evaluates to 255 which is not exactly representable in type 'const char'}}
constexpr unsigned char u8ustring[] = u8"test"u8"ing this out\xFF";
constexpr unsigned short uustring[] = u"test"u"ing this out\xFF";
constexpr unsigned int Ustring[] = U"test"U"ing this out\xFF";
constexpr unsigned char Arr2[6][6] = {
{"ek\xFF"}, {"ek\xFF"}
// expected-error@-1 2{{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
};

constexpr int i = (12);
constexpr int j = (i);
constexpr unsigned jneg = (-i);
// expected-error@-1 {{constexpr initializer evaluates to -12 which is not exactly representable in type 'const unsigned int'}}

// Check that initializer for pointer constexpr variable should be null.
constexpr int V80 = 3;
constexpr const int *V81 = &V80;
// expected-error@-1 {{constexpr pointer initializer is not null}}
constexpr int *V82 = 0;
constexpr int *V83 = V82;
constexpr int *V84 = 42;
// expected-error@-1 {{constexpr variable 'V84' must be initialized by a constant expression}}
// expected-note@-2 {{this conversion is not allowed in a constant expression}}
// expected-error@-3 {{constexpr pointer initializer is not null}}
constexpr int *V85 = nullptr;

// Check that constexpr variables should not be VLAs.
void f6(const int P1) {
constexpr int V86[P1] = {};
// expected-error@-1 {{constexpr variable cannot have type 'const int[P1]'}}
const int V87 = 3;
constexpr int V88[V87] = {};
// expected-warning@-1 {{variable length array folded to constant array as an extension}}
int V89 = 7;
constexpr int V90[V89] = {};
// expected-error@-1 {{constexpr variable cannot have type 'const int[V89]'}}
}

void f7(int n, int array[n]) {
constexpr typeof(array) foo = 0; // Accepted because array is a pointer type, not a VLA type
int (*(*fp)(int n))[n];
constexpr typeof(fp) bar = 0; // expected-error {{constexpr variable cannot have type 'const typeof (fp)' (aka 'int (*(*const)(int))[n]')}}
}

// Check how constexpr works with NaNs and infinities.
#define FLT_NAN __builtin_nanf("1")
#define DBL_NAN __builtin_nan("1")
#define LD_NAN __builtin_nanf("1")
#define FLT_SNAN __builtin_nansf("1")
#define DBL_SNAN __builtin_nans("1")
#define LD_SNAN __builtin_nansl("1")
#define INF __builtin_inf()
void infsNaNs() {
// Inf and quiet NaN is always fine, signaling NaN must have the same type.
constexpr float fl0 = INF;
constexpr float fl1 = (long double)INF;
constexpr float fl2 = (long double)FLT_NAN;
constexpr float fl3 = FLT_NAN;
constexpr float fl5 = DBL_NAN;
constexpr float fl6 = LD_NAN;
constexpr float fl7 = DBL_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const float'}}
constexpr float fl8 = LD_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const float'}}

constexpr double db0 = FLT_NAN;
constexpr double db2 = DBL_NAN;
constexpr double db3 = DBL_SNAN;
constexpr double db4 = FLT_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
constexpr double db5 = LD_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
constexpr double db6 = INF;
}
25 changes: 25 additions & 0 deletions clang/test/SemaCXX/overload-template.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -std=c++23 -verify -fsyntax-only %s

enum copy_traits { movable = 1 };

Expand Down Expand Up @@ -33,3 +34,27 @@ void ReproducesBugSimply() {
InsertRow(3, B{}); // expected-error {{no matching function for call to 'InsertRow'}}
}

#if __cplusplus >= 202302L
namespace overloadCheck{
template<typename T>
concept AlwaysTrue = true;

struct S {
int f(AlwaysTrue auto) { return 1; }
void f(this S&&, auto) {}

void g(auto) {}
int g(this S&&,AlwaysTrue auto) {return 1;}

int h(AlwaysTrue auto) { return 1; } //expected-note {{previous definition is here}}
int h(this S&&,AlwaysTrue auto) { // expected-error {{class member cannot be redeclared}}
return 1;
}
};

int main() {
int x = S{}.f(0);
int y = S{}.g(0);
}
}
#endif
37 changes: 37 additions & 0 deletions clang/test/SemaCXX/overloaded-operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,3 +645,40 @@ class b {


}

#if __cplusplus >= 202002L
namespace nw{
template<class T>
concept AlwaysTrue=true;

struct S{
template<class T>
void operator+(const T&)const{}

template<AlwaysTrue T>
int operator-(const T&)const{return 0;}

template<AlwaysTrue T>
int operator*(const T&)const{ // expected-note {{candidate function}}
return 0;
}
};

template<AlwaysTrue T>
int operator+(const S&, const T&){return 0;}

template<class T>
void operator-(const S&, const T&){}

template<AlwaysTrue T>
int operator*(const S&, const T&){ // expected-note {{candidate function}}
return 0;
}

void foo(){
int a = S{} + 1;
int b = S{} - 1;
int c = S{} * 1; // expected-error {{use of overloaded operator '*' is ambiguous (with operand types 'S' and 'int')}}
}
}
#endif
15 changes: 15 additions & 0 deletions clang/test/SemaCXX/warn-self-move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ void int_test() {
x = std::move(x); // expected-warning{{explicitly moving}}
(x) = std::move(x); // expected-warning{{explicitly moving}}

x = static_cast<int&&>(x); // expected-warning{{explicitly moving}}
(x) = static_cast<int&&>(x); // expected-warning{{explicitly moving}}

using std::move;
x = move(x); // expected-warning{{explicitly moving}} \
expected-warning {{unqualified call to 'std::move}}
Expand All @@ -26,6 +29,9 @@ void global_int_test() {
global = std::move(global); // expected-warning{{explicitly moving}}
(global) = std::move(global); // expected-warning{{explicitly moving}}

global = static_cast<int&&>(global); // expected-warning{{explicitly moving}}
(global) = static_cast<int&&>(global); // expected-warning{{explicitly moving}}

using std::move;
global = move(global); // expected-warning{{explicitly moving}} \
expected-warning {{unqualified call to 'std::move}}
Expand All @@ -35,11 +41,16 @@ class field_test {
int x;
field_test(field_test&& other) {
x = std::move(x); // expected-warning{{explicitly moving}}
x = static_cast<int&&>(x); // expected-warning{{explicitly moving}}
x = std::move(other.x);
x = static_cast<int&&>(other.x);
other.x = std::move(x);
other.x = static_cast<int&&>(x);
other.x = std::move(other.x); // expected-warning{{explicitly moving}}
other.x = static_cast<int&&>(other.x); // expected-warning{{explicitly moving}}
}
void withSuggest(int x) {
x = static_cast<int&&>(x); // expected-warning{{explicitly moving variable of type 'int' to itself; did you mean to move to member 'x'?}}
x = std::move(x); // expected-warning{{explicitly moving variable of type 'int' to itself; did you mean to move to member 'x'?}}
}
};
Expand All @@ -50,11 +61,15 @@ struct C { C() {}; ~C() {} };
void struct_test() {
A a;
a = std::move(a); // expected-warning{{explicitly moving}}
a = static_cast<A&&>(a); // expected-warning{{explicitly moving}}

B b;
b = std::move(b); // expected-warning{{explicitly moving}}
b = static_cast<B&&>(b); // expected-warning{{explicitly moving}}
b.a = std::move(b.a); // expected-warning{{explicitly moving}}
b.a = static_cast<A&&>(b.a); // expected-warning{{explicitly moving}}

C c;
c = std::move(c); // expected-warning{{explicitly moving}}
c = static_cast<C&&>(c); // expected-warning{{explicitly moving}}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//==-- loop_proto_to_llvm.h - Protobuf-C++ conversion ----------------------------==//
//===- loop_proto_to_llvm.h - Protobuf-C++ conversion -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
2 changes: 1 addition & 1 deletion clang/tools/diagtool/DiagTool.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- DiagTool.cpp - Classes for defining diagtool tools -------------------===//
//===- DiagTool.cpp - Classes for defining diagtool tools -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
2 changes: 1 addition & 1 deletion clang/unittests/AST/ASTImporterODRStrategiesTest.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- unittest/AST/ASTImporterODRStrategiesTest.cpp -----------------------===//
//===- ASTImporterODRStrategiesTest.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
4 changes: 2 additions & 2 deletions clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
//===- RegistryTest.cpp - Registry unit tests -----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===-----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//

#include "../ASTMatchersTest.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
Expand Down
4 changes: 2 additions & 2 deletions clang/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//===- unittest/ASTMatchers/Dynamic/VariantValueTest.cpp - VariantValue unit tests -===//
//===- VariantValueTest.cpp - VariantValue unit tests ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===-----------------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//

#include "../ASTMatchersTest.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp -===//
//===- CXXOperatorCallExprTraverser.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- unittests/Tooling/RecursiveASTVisitorTests/CallbacksBinaryOperator.cpp -===//
//===- CallbacksBinaryOperator.cpp ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- unittests/Tooling/RecursiveASTVisitorTests/CallbacksCompoundAssignOperator.cpp -===//
//===- CallbacksCompoundAssignOperator.cpp --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- unittests/Tooling/RecursiveASTVisitorTests/CallbacksUnaryOperator.cpp -===//
//===- CallbacksUnaryOperator.cpp -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp -===//
//===- InitListExprPostOrderNoQueue.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp -===//
//===- InitListExprPreOrderNoQueue.cpp ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- unittest/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp -===//
//===- TemplateArgumentLocTraverser.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
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 @@ -784,7 +784,7 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>Free positioning of labels inside compound statements</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf">N2508</a></td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr>
<td>Clarification request for C17 example of undefined behavior</td>
Expand Down Expand Up @@ -1156,7 +1156,7 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>Remove trigraphs??!</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2940.pdf">N2940</a></td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr>
<td>Improved normal enumerations</td>
Expand Down Expand Up @@ -1196,12 +1196,12 @@ <h2 id="c2x">C23 implementation status</h2>
<tr>
<td>Type inference for object declarations</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3007.htm">N3007</a></td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<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="none" align="center">No</td>
<td class="unreleased" align="center">Clang 19</td>
</tr>
<tr>
<td>Introduce storage class specifiers for compound literals</td>
Expand Down
26 changes: 13 additions & 13 deletions clang/www/cxx_dr_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -2668,13 +2668,13 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/438.html">438</a></td>
<td>CD2</td>
<td>Possible flaw in wording for multiple accesses to object between sequence points</td>
<td class="unknown" align="center">Unknown</td>
<td class="full" align="center">Clang 2.7</td>
</tr>
<tr id="439">
<td><a href="https://cplusplus.github.io/CWG/issues/439.html">439</a></td>
<td>CD1</td>
<td>Guarantees on casting pointer back to cv-qualified version of original type</td>
<td class="unknown" align="center">Unknown</td>
<td class="full" align="center">Clang 2.7</td>
</tr>
<tr id="440">
<td><a href="https://cplusplus.github.io/CWG/issues/440.html">440</a></td>
Expand All @@ -2686,7 +2686,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/441.html">441</a></td>
<td>CD1</td>
<td>Ordering of static reference initialization</td>
<td class="unknown" align="center">Unknown</td>
<td class="full" align="center">Clang 2.7</td>
</tr>
<tr id="442">
<td><a href="https://cplusplus.github.io/CWG/issues/442.html">442</a></td>
Expand Down Expand Up @@ -2812,7 +2812,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/462.html">462</a></td>
<td>CD3</td>
<td>Lifetime of temporaries bound to comma expressions</td>
<td class="unknown" align="center">Unknown</td>
<td class="full" align="center">Clang 2.7</td>
</tr>
<tr id="463">
<td><a href="https://cplusplus.github.io/CWG/issues/463.html">463</a></td>
Expand Down Expand Up @@ -2992,7 +2992,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/492.html">492</a></td>
<td>CD1</td>
<td><TT>typeid</TT> constness inconsistent with example</td>
<td class="unknown" align="center">Unknown</td>
<td class="full" align="center">Clang 2.7</td>
</tr>
<tr id="493">
<td><a href="https://cplusplus.github.io/CWG/issues/493.html">493</a></td>
Expand Down Expand Up @@ -11076,7 +11076,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/1878.html">1878</a></td>
<td>CD4</td>
<td><TT>operator auto</TT> template</td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr id="1879">
<td><a href="https://cplusplus.github.io/CWG/issues/1879.html">1879</a></td>
Expand Down Expand Up @@ -12384,7 +12384,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2096.html">2096</a></td>
<td>CD4</td>
<td>Constraints on literal unions</td>
<td class="unreleased" align="center">Duplicate of <a href="#2598">2598</a></td>
<td class="full" align="center">Duplicate of <a href="#2598">2598</a></td>
</tr>
<tr class="open" id="2097">
<td><a href="https://cplusplus.github.io/CWG/issues/2097.html">2097</a></td>
Expand Down Expand Up @@ -14478,7 +14478,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="unknown" align="center">Unknown</td>
<td class="unreleased" 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 @@ -15396,7 +15396,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2598.html">2598</a></td>
<td>C++23</td>
<td>Unions should not require a non-static data member of literal type</td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr id="2599">
<td><a href="https://cplusplus.github.io/CWG/issues/2599.html">2599</a></td>
Expand Down Expand Up @@ -15726,7 +15726,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2653.html">2653</a></td>
<td>C++23</td>
<td>Can an explicit object parameter have a default argument?</td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr id="2654">
<td><a href="https://cplusplus.github.io/CWG/issues/2654.html">2654</a></td>
Expand Down Expand Up @@ -15840,7 +15840,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2672.html">2672</a></td>
<td>DR</td>
<td>Lambda body SFINAE is still required, contrary to intent and note</td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr id="2673">
<td><a href="https://cplusplus.github.io/CWG/issues/2673.html">2673</a></td>
Expand Down Expand Up @@ -15930,7 +15930,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2687.html">2687</a></td>
<td>C++23</td>
<td>Calling an explicit object member function via an address-of-overload-set</td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr class="open" id="2688">
<td><a href="https://cplusplus.github.io/CWG/issues/2688.html">2688</a></td>
Expand Down Expand Up @@ -16542,7 +16542,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2789.html">2789</a></td>
<td>DR</td>
<td>Overload resolution with implicit and explicit object member functions</td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr class="open" id="2790">
<td><a href="https://cplusplus.github.io/CWG/issues/2790.html">2790</a></td>
Expand Down
10 changes: 5 additions & 5 deletions clang/www/cxx_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Unevaluated strings</td>
<td><a href="https://wg21.link/P2361R6">P2361R6</a></td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr>
<td>Add @, $, and ` to the basic character set</td>
Expand Down Expand Up @@ -145,13 +145,13 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Placeholder variables with no name</td>
<td><a href="https://wg21.link/P2169R4">P2169R4</a></td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<!-- Fall 2023 papers (Kona) -->
<tr>
<td>Template parameter initialization</td>
<td><a href="https://wg21.link/P2308R1">P2308R1</a> (<a href="#dr">DR</a>)</td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr>
<td>Pack Indexing</td>
Expand All @@ -161,7 +161,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Remove Deprecated Arithmetic Conversion on Enumerations</td>
<td><a href="https://wg21.link/P2864R2">P2864R2</a></td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>

</table>
Expand Down Expand Up @@ -239,7 +239,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
<tr>
<td rowspan=2>Deducing this</td>
<td><a href="https://wg21.link/P0847R7">P0847R7</a></td>
<td class="unreleased" align="center">Clang 18</td>
<td class="full" align="center">Clang 18</td>
</tr>
<tr>
<td><a href="https://wg21.link/P2797R0">P2797R0</a></td>
Expand Down
3 changes: 1 addition & 2 deletions clang/www/make_cxx_dr_status
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#! /usr/bin/env python3
import sys, os, re, urllib.request

latest_release = 18

clang_www_dir = os.path.dirname(__file__)
default_issue_list_path = os.path.join(clang_www_dir, 'cwg_index.html')
Expand Down Expand Up @@ -127,8 +128,6 @@ out_file.write('''\
<th>Available in Clang?</th>
</tr>''')

latest_release = 17

class AvailabilityError(RuntimeError):
pass

Expand Down
5 changes: 3 additions & 2 deletions compiler-rt/lib/profile/InstrProfilingPlatformWindows.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ ValueProfNode *EndVNode = &VNodesEnd;
/* lld-link provides __buildid symbol which ponits to the 16 bytes build id when
* using /build-id flag. https://lld.llvm.org/windows_support.html#lld-flags */
#define BUILD_ID_LEN 16
COMPILER_RT_WEAK uint8_t __buildid[BUILD_ID_LEN];
COMPILER_RT_WEAK uint8_t __buildid[BUILD_ID_LEN] = {0};
COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
if (*__buildid) {
static const uint8_t zeros[BUILD_ID_LEN] = {0};
if (memcmp(__buildid, zeros, BUILD_ID_LEN) != 0) {
if (Writer &&
lprofWriteOneBinaryId(Writer, BUILD_ID_LEN, __buildid, 0) == -1)
return -1;
Expand Down
24 changes: 15 additions & 9 deletions flang/include/flang/Evaluate/traverse.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
#include <type_traits>

namespace Fortran::evaluate {
template <typename Visitor, typename Result> class Traverse {
template <typename Visitor, typename Result,
bool TraverseAssocEntityDetails = true>
class Traverse {
public:
explicit Traverse(Visitor &v) : visitor_{v} {}

Expand Down Expand Up @@ -108,12 +110,13 @@ template <typename Visitor, typename Result> class Traverse {
}
Result operator()(const Symbol &symbol) const {
const Symbol &ultimate{symbol.GetUltimate()};
if (const auto *assoc{
ultimate.detailsIf<semantics::AssocEntityDetails>()}) {
return visitor_(assoc->expr());
} else {
return visitor_.Default();
if constexpr (TraverseAssocEntityDetails) {
if (const auto *assoc{
ultimate.detailsIf<semantics::AssocEntityDetails>()}) {
return visitor_(assoc->expr());
}
}
return visitor_.Default();
}
Result operator()(const StaticDataObject &) const {
return visitor_.Default();
Expand Down Expand Up @@ -284,7 +287,8 @@ template <typename Visitor, typename Result> class Traverse {
// For validity checks across an expression: if any operator() result is
// false, so is the overall result.
template <typename Visitor, bool DefaultValue,
typename Base = Traverse<Visitor, bool>>
bool TraverseAssocEntityDetails = true,
typename Base = Traverse<Visitor, bool, TraverseAssocEntityDetails>>
struct AllTraverse : public Base {
explicit AllTraverse(Visitor &v) : Base{v} {}
using Base::operator();
Expand All @@ -296,7 +300,8 @@ struct AllTraverse : public Base {
// is truthful is the final result. Works for Booleans, pointers,
// and std::optional<>.
template <typename Visitor, typename Result = bool,
typename Base = Traverse<Visitor, Result>>
bool TraverseAssocEntityDetails = true,
typename Base = Traverse<Visitor, Result, TraverseAssocEntityDetails>>
class AnyTraverse : public Base {
public:
explicit AnyTraverse(Visitor &v) : Base{v} {}
Expand All @@ -315,7 +320,8 @@ class AnyTraverse : public Base {
};

template <typename Visitor, typename Set,
typename Base = Traverse<Visitor, Set>>
bool TraverseAssocEntityDetails = true,
typename Base = Traverse<Visitor, Set, TraverseAssocEntityDetails>>
struct SetTraverse : public Base {
explicit SetTraverse(Visitor &v) : Base{v} {}
using Base::operator();
Expand Down
11 changes: 7 additions & 4 deletions flang/lib/Evaluate/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,8 +995,10 @@ template semantics::UnorderedSymbolSet CollectSymbols(
const Expr<SubscriptInteger> &);

// HasVectorSubscript()
struct HasVectorSubscriptHelper : public AnyTraverse<HasVectorSubscriptHelper> {
using Base = AnyTraverse<HasVectorSubscriptHelper>;
struct HasVectorSubscriptHelper
: public AnyTraverse<HasVectorSubscriptHelper, bool,
/*TraverseAssocEntityDetails=*/false> {
using Base = AnyTraverse<HasVectorSubscriptHelper, bool, false>;
HasVectorSubscriptHelper() : Base{*this} {}
using Base::operator();
bool operator()(const Subscript &ss) const {
Expand Down Expand Up @@ -1045,9 +1047,10 @@ parser::Message *AttachDeclaration(
}

class FindImpureCallHelper
: public AnyTraverse<FindImpureCallHelper, std::optional<std::string>> {
: public AnyTraverse<FindImpureCallHelper, std::optional<std::string>,
/*TraverseAssocEntityDetails=*/false> {
using Result = std::optional<std::string>;
using Base = AnyTraverse<FindImpureCallHelper, Result>;
using Base = AnyTraverse<FindImpureCallHelper, Result, false>;

public:
explicit FindImpureCallHelper(FoldingContext &c) : Base{*this}, context_{c} {}
Expand Down
8 changes: 8 additions & 0 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,10 @@ constexpr auto FuncTypeComplex16Complex16 =
genFuncType<Ty::Complex<16>, Ty::Complex<16>>;
constexpr auto FuncTypeComplex16Complex16Complex16 =
genFuncType<Ty::Complex<16>, Ty::Complex<16>, Ty::Complex<16>>;
constexpr auto FuncTypeComplex16Complex16Integer4 =
genFuncType<Ty::Complex<16>, Ty::Complex<16>, Ty::Integer<4>>;
constexpr auto FuncTypeComplex16Complex16Integer8 =
genFuncType<Ty::Complex<16>, Ty::Complex<16>, Ty::Integer<8>>;

static constexpr MathOperation mathOperations[] = {
{"abs", "fabsf", genFuncType<Ty::Real<4>, Ty::Real<4>>,
Expand Down Expand Up @@ -1226,10 +1230,14 @@ static constexpr MathOperation mathOperations[] = {
genFuncType<Ty::Complex<4>, Ty::Complex<4>, Ty::Integer<4>>, genLibCall},
{"pow", RTNAME_STRING(zpowi),
genFuncType<Ty::Complex<8>, Ty::Complex<8>, Ty::Integer<4>>, genLibCall},
{"pow", RTNAME_STRING(cqpowi), FuncTypeComplex16Complex16Integer4,
genLibF128Call},
{"pow", RTNAME_STRING(cpowk),
genFuncType<Ty::Complex<4>, Ty::Complex<4>, Ty::Integer<8>>, genLibCall},
{"pow", RTNAME_STRING(zpowk),
genFuncType<Ty::Complex<8>, Ty::Complex<8>, Ty::Integer<8>>, genLibCall},
{"pow", RTNAME_STRING(cqpowk), FuncTypeComplex16Complex16Integer8,
genLibF128Call},
{"sign", "copysignf", genFuncType<Ty::Real<4>, Ty::Real<4>, Ty::Real<4>>,
genMathOp<mlir::math::CopySignOp>},
{"sign", "copysign", genFuncType<Ty::Real<8>, Ty::Real<8>, Ty::Real<8>>,
Expand Down
45 changes: 44 additions & 1 deletion flang/runtime/complex-powi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*
* ===-----------------------------------------------------------------------===
*/
#include "flang/Common/float128.h"
#include "flang/Runtime/entry-names.h"
#include <cstdint>
#include <cstdio>
Expand Down Expand Up @@ -79,6 +80,30 @@ extern "C" double _Complex RTNAME(zpowk)(
double _Complex base, std::int64_t exp) {
return tgpowi(base, exp);
}

#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
// Duplicate CFloat128ComplexType definition from flang/Common/float128.h.
// float128.h does not define it for C++, because _Complex triggers
// c99-extension warnings. We decided to disable warnings for this
// particular file, so we can use _Complex here.
#if LDBL_MANT_DIG == 113
typedef long double _Complex Qcomplex;
#elif HAS_FLOAT128
#if !defined(_ARCH_PPC) || defined(__LONG_DOUBLE_IEEE128__)
typedef _Complex float __attribute__((mode(TC))) Qcomplex;
#else
typedef _Complex float __attribute__((mode(KC))) Qcomplex;
#endif
#endif

extern "C" Qcomplex RTNAME(cqpowi)(Qcomplex base, std::int32_t exp) {
return tgpowi(base, exp);
}
extern "C" Qcomplex RTNAME(cqpowk)(Qcomplex base, std::int64_t exp) {
return tgpowi(base, exp);
}
#endif

#else
// on MSVC, C complex is always just a struct of two members as it is not
// supported as a builtin type. So we use C++ complex here as that has the
Expand Down Expand Up @@ -116,10 +141,28 @@ extern "C" Fcomplex RTNAME(cpowk)(Fcomplex base, std::int64_t exp) {
return *(Fcomplex *)(&cppres);
}

extern "C" Dcomplex RTNAME(zpowk)(Dcomplex base, std::int32_t exp) {
extern "C" Dcomplex RTNAME(zpowk)(Dcomplex base, std::int64_t exp) {
auto cppbase = *(std::complex<double> *)(&base);
auto cppres = tgpowi(cppbase, exp);
return *(Dcomplex *)(&cppres);
}

#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
struct Qcomplex {
CFloat128Type re;
CFloat128Type im;
};

extern "C" Dcomplex RTNAME(cqpowi)(Qcomplex base, std::int32_t exp) {
auto cppbase = *(std::complex<CFloat128Type> *)(&base);
auto cppres = tgpowi(cppbase, exp);
return *(Qcomplex *)(&cppres);
}

extern "C" Dcomplex RTNAME(cqpowk)(Qcomplex base, std::int64_t exp) {
auto cppbase = *(std::complex<CFloat128Type> *)(&base);
auto cppres = tgpowi(cppbase, exp);
return *(Qcomplex *)(&cppres);
}
#endif
#endif
9 changes: 9 additions & 0 deletions flang/test/Lower/Intrinsics/pow_complex16i.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s

! CHECK: fir.call @_FortranAcqpowi({{.*}}){{.*}}: (!fir.complex<16>, i32) -> !fir.complex<16>
complex(16) :: a
integer(4) :: b
b = a ** b
end
9 changes: 9 additions & 0 deletions flang/test/Lower/Intrinsics/pow_complex16k.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s

! CHECK: fir.call @_FortranAcqpowk({{.*}}){{.*}}: (!fir.complex<16>, i64) -> !fir.complex<16>
complex(16) :: a
integer(8) :: b
b = a ** b
end
11 changes: 11 additions & 0 deletions flang/test/Semantics/forall01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,14 @@ subroutine forall7(x)
end forall
end select
end subroutine

subroutine forall8(x)
real :: x(10)
real, external :: foo
!ERROR: Impure procedure 'foo' may not be referenced in a FORALL
forall(i=1:10) x(i) = foo() + i
!OK
associate(y => foo())
forall (i=1:10) x(i) = y + i
end associate
end subroutine
2 changes: 1 addition & 1 deletion flang/test/Semantics/selecttype03.f90
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
b%i = 1 !VDC
type is (t2)
!ERROR: Actual argument associated with INTENT(IN OUT) dummy argument 'z=' is not definable
!BECAUSE: Variable 'b' has a vector subscript
!BECAUSE: Construct association 'b' has a vector subscript
call sub_with_in_and_inout_param_vector(b,b) !VDC
end select
select type(b => foo(1) )
Expand Down
11 changes: 11 additions & 0 deletions libc/docs/full_cross_build.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ The above ``ninja`` command will build the libc static archives ``libc.a`` and
``libm.a`` for the target specified with ``-DLIBC_TARGET_TRIPLE`` in the CMake
configure step.

.. _runtimes_cross_build:

Runtimes cross build
====================

Expand Down Expand Up @@ -230,3 +232,12 @@ component of the target triple as ``none``. For example, to build for a
32-bit arm target on bare metal, one can use a target triple like
``arm-none-eabi``. Other than that, the libc for a bare metal target can be
built using any of the three recipes described above.

Building for the GPU
====================

To build for a GPU architecture, it should only be necessary to specify the
target triple as one of the supported GPU targets. Currently, this is either
``nvptx64-nvidia-cuda`` for NVIDIA GPUs or ``amdgcn-amd-amdhsa`` for AMD GPUs.
More detailed information is provided in the :ref:`GPU
documentation<libc_gpu_building>`.
246 changes: 246 additions & 0 deletions libc/docs/gpu/building.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
.. _libc_gpu_building:

======================
Building libs for GPUs
======================

.. contents:: Table of Contents
:depth: 4
:local:

Building the GPU C library
==========================

This document will present recipes to build the LLVM C library targeting a GPU
architecture. The GPU build uses the same :ref:`cross build<full_cross_build>`
support as the other targets. However, the GPU target has the restriction that
it *must* be built with an up-to-date ``clang`` compiler. This is because the
GPU target uses several compiler extensions to target GPU architectures.

The LLVM C library currently supports two GPU targets. This is either
``nvptx64-nvidia-cuda`` for NVIDIA GPUs or ``amdgcn-amd-amdhsa`` for AMD GPUs.
Targeting these architectures is done through ``clang``'s cross-compiling
support using the ``--target=<triple>`` flag. The following sections will
describe how to build the GPU support specifically.

Once you have finished building, refer to :ref:`libc_gpu_usage` to get started
with the newly built C library.

Standard runtimes build
-----------------------

The simplest way to build the GPU libc is to use the existing LLVM runtimes
support. This will automatically handle bootstrapping an up-to-date ``clang``
compiler and using it to build the C library. The following CMake invocation
will instruct it to build the ``libc`` runtime targeting both AMD and NVIDIA
GPUs.

.. code-block:: sh
$> cd llvm-project # The llvm-project checkout
$> mkdir build
$> cd build
$> cmake ../llvm -G Ninja \
-DLLVM_ENABLE_PROJECTS="clang;lld" \
-DLLVM_ENABLE_RUNTIMES="openmp" \
-DCMAKE_BUILD_TYPE=<Debug|Release> \ # Select build type
-DCMAKE_INSTALL_PREFIX=<PATH> \ # Where the libraries will live
-DRUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES=libc \
-DRUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES=libc \
-DLLVM_RUNTIME_TARGETS="default;amdgcn-amd-amdhsa;nvptx64-nvidia-cuda"
$> ninja install
We need ``clang`` to build the GPU C library and ``lld`` to link AMDGPU
executables, so we enable them in ``LLVM_ENABLE_PROJECTS``. We add ``openmp`` to
``LLVM_ENABLED_RUNTIMES`` so it is built for the default target and provides
OpenMP support. We then set ``RUNTIMES_<triple>_LLVM_ENABLE_RUNTIMES`` to enable
``libc`` for the GPU targets. The ``LLVM_RUNTIME_TARGETS`` sets the enabled
targets to build, in this case we want the default target and the GPU targets.
Note that if ``libc`` were included in ``LLVM_ENABLE_RUNTIMES`` it would build
targeting the default host environment as well.

Runtimes cross build
--------------------

For users wanting more direct control over the build process, the build steps
can be done manually instead. This build closely follows the instructions in the
:ref:`main documentation<runtimes_cross_build>` but is specialized for the GPU
build. We follow the same steps to first build the libc tools and a suitable
compiler. These tools must all be up-to-date with the libc source.

.. code-block:: sh
$> cd llvm-project # The llvm-project checkout
$> mkdir build-libc-tools # A different build directory for the build tools
$> cd build-libc-tools
$> HOST_C_COMPILER=<C compiler for the host> # For example "clang"
$> HOST_CXX_COMPILER=<C++ compiler for the host> # For example "clang++"
$> cmake ../llvm \
-G Ninja \
-DLLVM_ENABLE_PROJECTS="clang;libc" \
-DCMAKE_C_COMPILER=$HOST_C_COMPILER \
-DCMAKE_CXX_COMPILER=$HOST_CXX_COMPILER \
-DLLVM_LIBC_FULL_BUILD=ON \
-DLIBC_HDRGEN_ONLY=ON \ # Only build the 'libc-hdrgen' tool
-DCMAKE_BUILD_TYPE=Release # Release suggested to make "clang" fast
$> ninja # Build the 'clang' compiler
$> ninja libc-hdrgen # Build the 'libc-hdrgen' tool
Once this has finished the build directory should contain the ``clang`` compiler
and the ``libc-hdrgen`` executable. We will use the ``clang`` compiler to build
the GPU code and the ``libc-hdrgen`` tool to create the necessary headers. We
use these tools to bootstrap the build out of the runtimes directory targeting a
GPU architecture.

.. code-block:: sh
$> cd llvm-project # The llvm-project checkout
$> mkdir build # A different build directory for the build tools
$> cd build
$> TARGET_TRIPLE=<amdgcn-amd-amdhsa or nvptx64-nvidia-cuda>
$> TARGET_C_COMPILER=</path/to/clang>
$> TARGET_CXX_COMPILER=</path/to/clang++>
$> HDRGEN=</path/to/libc-hdrgen>
$> cmake ../runtimes \ # Point to the runtimes build
-G Ninja \
-DLLVM_ENABLE_RUNTIMES=libc \
-DCMAKE_C_COMPILER=$TARGET_C_COMPILER \
-DCMAKE_CXX_COMPILER=$TARGET_CXX_COMPILER \
-DLLVM_LIBC_FULL_BUILD=ON \
-DLLVM_RUNTIMES_TARGET=$TARGET_TRIPLE \
-DLIBC_HDRGEN_EXE=$HDRGEN \
-DCMAKE_BUILD_TYPE=Release
$> ninja install
The above steps will result in a build targeting one of the supported GPU
architectures. Building for multiple targets requires separate CMake
invocations.

Standalone cross build
----------------------

The GPU build can also be targeted directly as long as the compiler used is a
supported ``clang`` compiler. This method is generally not recommended as it can
only target a single GPU architecture.

.. code-block:: sh
$> cd llvm-project # The llvm-project checkout
$> mkdir build # A different build directory for the build tools
$> cd build
$> CLANG_C_COMPILER=</path/to/clang> # Must be a trunk build
$> CLANG_CXX_COMPILER=</path/to/clang++> # Must be a trunk build
$> TARGET_TRIPLE=<amdgcn-amd-amdhsa or nvptx64-nvidia-cuda>
$> cmake ../llvm \ # Point to the llvm directory
-G Ninja \
-DLLVM_ENABLE_PROJECTS=libc \
-DCMAKE_C_COMPILER=$CLANG_C_COMPILER \
-DCMAKE_CXX_COMPILER=$CLANG_CXX_COMPILER \
-DLLVM_LIBC_FULL_BUILD=ON \
-DLIBC_TARGET_TRIPLE=$TARGET_TRIPLE \
-DCMAKE_BUILD_TYPE=Release
$> ninja install
This will build and install the GPU C library along with all the other LLVM
libraries.

Build overview
==============

Once installed, the GPU build will create several files used for different
targets. This section will briefly describe their purpose.

**lib/<host-triple>/libcgpu-amdgpu.a or lib/libcgpu-amdgpu.a**
A static library containing fat binaries supporting AMD GPUs. These are built
using the support described in the `clang documentation
<https://clang.llvm.org/docs/OffloadingDesign.html>`_. These are intended to
be static libraries included natively for offloading languages like CUDA, HIP,
or OpenMP. This implements the standard C library.

**lib/<host-triple>/libmgpu-amdgpu.a or lib/libmgpu-amdgpu.a**
A static library containing fat binaries that implements the standard math
library for AMD GPUs.

**lib/<host-triple>/libcgpu-nvptx.a or lib/libcgpu-nvptx.a**
A static library containing fat binaries that implement the standard C library
for NVIDIA GPUs.

**lib/<host-triple>/libmgpu-nvptx.a or lib/libmgpu-nvptx.a**
A static library containing fat binaries that implement the standard math
library for NVIDIA GPUs.

**include/<target-triple>**
The include directory where all of the generated headers for the target will
go. These definitions are strictly for the GPU when being targeted directly.

**lib/clang/<llvm-major-version>/include/llvm-libc-wrappers/llvm-libc-decls**
These are wrapper headers created for offloading languages like CUDA, HIP, or
OpenMP. They contain functions supported in the GPU libc along with attributes
and metadata that declare them on the target device and make them compatible
with the host headers.

**lib/<target-triple>/libc.a**
The main C library static archive containing LLVM-IR targeting the given GPU.
It can be linked directly or inspected depending on the target support.

**lib/<target-triple>/libm.a**
The C library static archive providing implementations of the standard math
functions.

**lib/<target-triple>/libc.bc**
An alternate form of the library provided as a single LLVM-IR bitcode blob.
This can be used similarly to NVIDIA's or AMD's device libraries.

**lib/<target-triple>/libm.bc**
An alternate form of the library provided as a single LLVM-IR bitcode blob
containing the standard math functions.

**lib/<target-triple>/crt1.o**
An LLVM-IR file containing startup code to call the ``main`` function on the
GPU. This is used similarly to the standard C library startup object.

**bin/amdhsa-loader**
A binary utility used to launch executables compiled targeting the AMD GPU.
This will be included if the build system found the ``hsa-runtime64`` library
either in ``/opt/rocm`` or the current CMake installation directory. This is
required to build the GPU tests .See the :ref:`libc GPU usage<libc_gpu_usage>`
for more information.

**bin/nvptx-loader**
A binary utility used to launch executables compiled targeting the NVIDIA GPU.
This will be included if the build system found the CUDA driver API. This is
required for building tests.

**include/llvm-libc-rpc-server.h**
A header file containing definitions that can be used to interface with the
:ref:`RPC server<libc_gpu_rpc>`.

**lib/libllvmlibc_rpc_server.a**
The static library containing the implementation of the RPC server. This can
be used to enable host services for anyone looking to interface with the
:ref:`RPC client<libc_gpu_rpc>`.

CMake options
=============

This section briefly lists a few of the CMake variables that specifically
control the GPU build of the C library.

**LLVM_LIBC_FULL_BUILD**:BOOL
This flag controls whether or not the libc build will generate its own
headers. This must always be on when targeting the GPU.

**LIBC_GPU_TEST_ARCHITECTURE**:STRING
Sets the architecture used to build the GPU tests for, such as ``gfx90a`` or
``sm_80`` for AMD and NVIDIA GPUs respectively. The default behavior is to
detect the system's GPU architecture using the ``native`` option. If this
option is not set and a GPU was not detected the tests will not be built.

**LIBC_GPU_TEST_JOBS**:STRING
Sets the number of threads used to run GPU tests. The GPU test suite will
commonly run out of resources if this is not constrained so it is recommended
to keep it low. The default value is a single thread.

**LIBC_GPU_LOADER_EXECUTABLE**:STRING
Overrides the default loader used for running GPU tests. If this is not
provided the standard one will be built.
3 changes: 2 additions & 1 deletion libc/docs/gpu/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ learn more about this project.

.. toctree::

building
using
support
testing
rpc
testing
motivation
2 changes: 2 additions & 0 deletions libc/docs/gpu/rpc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ in the GPU executable as an indicator for whether or not the server can be
checked. These details should ideally be handled by the GPU language runtime,
but the following example shows how it can be used by a standard user.

.. _libc_gpu_cuda_server:

.. code-block:: cuda
#include <cstdio>
Expand Down
261 changes: 212 additions & 49 deletions libc/docs/gpu/using.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.. _libc_gpu_usage:


===================
Using libc for GPUs
===================
Expand All @@ -9,80 +8,244 @@ Using libc for GPUs
:depth: 4
:local:

Building the GPU library
========================

LLVM's libc GPU support *must* be built with an up-to-date ``clang`` compiler
due to heavy reliance on ``clang``'s GPU support. This can be done automatically
using the LLVM runtimes support. The GPU build is done using cross-compilation
to the GPU architecture. This project currently supports AMD and NVIDIA GPUs
which can be targeted using the appropriate target name. The following
invocation will enable a cross-compiling build for the GPU architecture and
enable the ``libc`` project only for them.
Using the GPU C library
=======================

Once you have finished :ref:`building<libc_gpu_building>` the GPU C library it
can be used to run libc or libm functions directly on the GPU. Currently, not
all C standard functions are supported on the GPU. Consult the :ref:`list of
supported functions<libc_gpu_support>` for a comprehensive list.

The GPU C library supports two main usage modes. The first is as a supplementary
library for offloading languages such as OpenMP, CUDA, or HIP. These aim to
provide standard system utilities similarly to existing vendor libraries. The
second method treats the GPU as a hosted target by compiling C or C++ for it
directly. This is more similar to targeting OpenCL and is primarily used for
exported functions on the GPU and testing.

Offloading usage
----------------

Offloading languages like CUDA, HIP, or OpenMP work by compiling a single source
file for both the host target and a list of offloading devices. In order to
support standard compilation flows, the ``clang`` driver uses fat binaries,
described in the `clang documentation
<https://clang.llvm.org/docs/OffloadingDesign.html>`_. This linking mode is used
by the OpenMP toolchain, but is currently opt-in for the CUDA and HIP toolchains
through the ``--offload-new-driver``` and ``-fgpu-rdc`` flags.

The installation should contain a static library called ``libcgpu-amdgpu.a`` or
``libcgpu-nvptx.a`` depending on which GPU architectures your build targeted.
These contain fat binaries compatible with the offloading toolchain such that
they can be used directly.

.. code-block:: sh
$> cd llvm-project # The llvm-project checkout
$> mkdir build
$> cd build
$> cmake ../llvm -G Ninja \
-DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" \
-DLLVM_ENABLE_RUNTIMES="openmp" \
-DCMAKE_BUILD_TYPE=<Debug|Release> \ # Select build type
-DCMAKE_INSTALL_PREFIX=<PATH> \ # Where 'libcgpu.a' will live
-DRUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES=libc \
-DRUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES=libc \
-DLLVM_RUNTIME_TARGETS=default;amdgcn-amd-amdhsa;nvptx64-nvidia-cuda
$> ninja install
Since we want to include ``clang``, ``lld`` and ``compiler-rt`` in our
toolchain, we list them in ``LLVM_ENABLE_PROJECTS``. To ensure ``libc`` is built
using a compatible compiler and to support ``openmp`` offloading, we list them
in ``LLVM_ENABLE_RUNTIMES`` to build them after the enabled projects using the
newly built compiler. ``CMAKE_INSTALL_PREFIX`` specifies the installation
directory in which to install the ``libcgpu-nvptx.a`` and ``libcgpu-amdgpu.a``
libraries and headers along with LLVM. The generated headers will be placed in
``include/<gpu-triple>``.

Usage
=====

Once the static archive has been built it can be linked directly
with offloading applications as a standard library. This process is described in
the `clang documentation <https://clang.llvm.org/docs/OffloadingDesign.html>`_.
This linking mode is used by the OpenMP toolchain, but is currently opt-in for
the CUDA and HIP toolchains through the ``--offload-new-driver``` and
``-fgpu-rdc`` flags. A typical usage will look this this:
$> clang opnemp.c -fopenmp --offload-arch=gfx90a -lcgpu-amdgpu
$> clang cuda.cu --offload-arch=sm_80 --offload-new-driver -fgpu-rdc -lcgpu-nvptx
$> clang hip.hip --offload-arch=gfx940 --offload-new-driver -fgpu-rdc -lcgpu-amdgpu
This will automatically link in the needed function definitions if they were
required by the user's application. Normally using the ``-fgpu-rdc`` option
results in sub-par performance due to ABA linking. However, the offloading
toolchain supports the ``--foffload-lto`` option to support LTO on the target
device.

Offloading languages require that functions present on the device be declared as
such. This is done with the ``__device__`` keyword in CUDA and HIP or the
``declare target`` pragma in OpenMP. This requires that the LLVM C library
exposes its implemented functions to the compiler when it is used to build. We
support this by providing wrapper headers in the compiler's resource directory.
These are located in ``<clang-resource-dir>/include/llvm-libc-wrappers`` in your
installation.

The support for HIP and CUDA is more experimental, requiring manual intervention
to link and use the facilities. An example of this is shown in the :ref:`CUDA
server example<libc_gpu_cuda_server>`. The OpenMP Offloading toolchain is
completely integrated with the LLVM C library however. It will automatically
handle including the necessary libraries, define device-side interfaces, and run
the RPC server.

OpenMP Offloading example
^^^^^^^^^^^^^^^^^^^^^^^^^

This section provides a simple example of compiling an OpenMP program with the
GPU C library.

.. code-block:: c++

#include <stdio.h>

int main() {
FILE *file = stderr;
#pragma omp target teams num_teams(2) thread_limit(2)
#pragma omp parallel num_threads(2)
{ fputs("Hello from OpenMP!\n", file); }
}
This can simply be compiled like any other OpenMP application to print from two
threads and two blocks.

.. code-block:: sh
$> clang foo.c -fopenmp --offload-arch=gfx90a -lcgpu
$> clang openmp.c -fopenmp --offload-arch=gfx90a
$> ./a.out
Hello from OpenMP!
Hello from OpenMP!
Hello from OpenMP!
Hello from OpenMP!
Including the wrapper headers, linking the C library, and running the :ref:`RPC
server<libc_gpu_rpc>` are all handled automatically by the compiler and runtime.

Binary format
^^^^^^^^^^^^^

The ``libcgpu.a`` static archive is a fat-binary containing LLVM-IR for each
supported target device. The supported architectures can be seen using LLVM's
``llvm-objdump`` with the ``--offloading`` flag:

.. code-block:: sh
$> llvm-objdump --offloading libcgpu.a
libcgpu.a(strcmp.cpp.o): file format elf64-x86-64
$> llvm-objdump --offloading libcgpu-amdgpu.a
libcgpu-amdgpu.a(strcmp.cpp.o): file format elf64-x86-64
OFFLOADING IMAGE [0]:
kind llvm ir
arch generic
triple amdgcn-amd-amdhsa
producer none
...
Because the device code is stored inside a fat binary, it can be difficult to
inspect the resulting code. This can be done using the following utilities:

.. code-block:: sh
$> llvm-ar x libcgpu.a strcmp.cpp.o
$> clang-offload-packager strcmp.cpp.o --image=arch=gfx90a,file=gfx90a.bc
$> opt -S out.bc
...
$> llvm-ar x libcgpu.a strcmp.cpp.o
$> clang-offload-packager strcmp.cpp.o --image=arch=generic,file=strcmp.bc
$> opt -S out.bc
...
Please note that this fat binary format is provided for compatibility with
existing offloading toolchains. The implementation in ``libc`` does not depend
on any existing offloading languages and is completely freestanding.

Direct compilation
------------------

Instead of using standard offloading languages, we can also target the CPU
directly using C and C++ to create a GPU executable similarly to OpenCL. This is
done by targeting the GPU architecture using `clang's cross compilation
support <https://clang.llvm.org/docs/CrossCompilation.html>`_. This is the
method that the GPU C library uses both to build the library and to run tests.

This allows us to easily define GPU specific libraries and programs that fit
well into existing tools. In order to target the GPU effectively we rely heavily
on the compiler's intrinsic and built-in functions. For example, the following
function gets the thread identifier in the 'x' dimension on both GPUs supported
GPUs.

.. code-block:: c++

uint32_t get_thread_id_x() {
#if defined(__AMDGPU__)
return __builtin_amdgcn_workitem_id_x();
#elif defined(__NVPTX__)
return __nvvm_read_ptx_sreg_tid_x();
#else
#error "Unsupported platform"
#endif
}

We can then compile this for both NVPTX and AMDGPU into LLVM-IR using the
following commands.

.. code-block:: sh
$> clang id.c --target=amdgcn-amd-amdhsa -mcpu=native -nogpulib -flto -c
$> clang id.c --target=nvptx64-nvidia-cuda -march=native -nogpulib -flto -c
We use this support to treat the GPU as a hosted environment by providing a C
library and startup object just like a standard C library running on the host
machine. Then, in order to execute these programs, we provide a loader utility
to launch the executable on the GPU similar to a cross-compiling emulator.

Building for AMDGPU targets
^^^^^^^^^^^^^^^^^^^^^^^^^^^

The AMDGPU target supports several features natively by virtue of using ``lld``
as its linker. The installation will include the ``include/amdgcn-amd-amdhsa``
and ``lib/amdgcn-amd-amdha`` directories that contain the necessary code to use
the library. We can directly link against ``libc.a`` and use LTO to generate the
final executable.

.. code-block:: c++

#include <stdio.h>

int main() { fputs("Hello from AMDGPU!\n", stdout); }

This program can then be compiled using the ``clang`` compiler. Note that
``-flto`` and ``-mcpu=`` should be defined. This is because the GPU
sub-architectures do not have strict backwards compatibility. Use ``-mcpu=help``
for accepted arguments or ``-mcpu=native`` to target the system's installed GPUs
if present. Additionally, the AMDGPU target always uses ``-flto`` because we
currently do not fully support ELF linking in ``lld``. Once built, we use the
``amdhsa-loader`` utility to launch execution on the GPU. This will be built if
the ``hsa_runtime64`` library was found during build time.

.. code-block:: sh
$> clang hello.c --target=amdgcn-amd-amdhsa -mcpu=native -flto -lc <install>/lib/amdgcn-amd-amdhsa/crt1.o
$> amdhsa-loader --threads 2 --blocks 2 a.out
Hello from AMDGPU!
Hello from AMDGPU!
Hello from AMDGPU!
Hello from AMDGPU!
This will include the ``stdio.h`` header, which is found in the
``include/amdgcn-amd-amdhsa`` directory. We define out ``main`` function like a
standard application. The startup utility in ``lib/amdgcn-amd-amdhsa/crt1.o``
will handle the necessary steps to execute the ``main`` function along with
global initializers and command line arguments. Finally, we link in the
``libc.a`` library stored in ``lib/amdgcn-amd-amdhsa`` to define the standard C
functions.

The search paths for the include directories and libraries are automatically
handled by the compiler. We use this support internally to run unit tests on the
GPU directly. See :ref:`libc_gpu_testing` for more information. The installation
also provides ``libc.bc`` which is a single LLVM-IR bitcode blob that can be
used instead of the static library.

Building for NVPTX targets
^^^^^^^^^^^^^^^^^^^^^^^^^^

The infrastructure is the same as the AMDGPU example. However, the NVPTX binary
utilities are very limited and must be targeted directly. There is no linker
support for static libraries so we need to link in the ``libc.bc`` bitcode and
inform the compiler driver of the file's contents.

.. code-block:: c++

#include <stdio.h>

int main(int argc, char **argv, char **envp) {
fputs("Hello from NVPTX!\n", stdout);
}
Additionally, the NVPTX ABI requires that every function signature matches. This
requires us to pass the full prototype from ``main``. The installation will
contain the ``nvptx-loader`` utility if the CUDA driver was found during
compilation.

.. code-block:: sh
$> clang hello.c --target=nvptx64-nvidia-cuda -march=native \
-x ir <install>/lib/nvptx64-nvidia-cuda/libc.bc \
-x ir <install>/lib/nvptx64-nvidia-cuda/crt1.o
$> nvptx-loader --threads 2 --blocks 2 a.out
Hello from NVPTX!
Hello from NVPTX!
Hello from NVPTX!
Hello from NVPTX!
2 changes: 1 addition & 1 deletion libcxx/docs/ReleaseNotes/19.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Implemented Papers
- P2637R3 - Member ``visit``
- P2652R2 - Disallow User Specialization of ``allocator_traits``
- P2819R2 - Add ``tuple`` protocol to ``complex``
- P2495R3 - Interfacing ``stringstream``s with ``string_view``
- P2495R3 - Interfacing ``stringstream``\s with ``string_view``
- P2302R4 - ``std::ranges::contains``
- P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``

Expand Down
Loading