diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /clang/test/CodeGenCXX | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'clang/test/CodeGenCXX')
| -rw-r--r-- | clang/test/CodeGenCXX/constructor-attr.cpp | 18 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp | 15 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/destructor-attr.cpp | 23 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp | 1 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/int64_uint64.cpp | 8 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/labeled-break-continue.cpp | 221 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/mangle-ms-cxx11.cpp | 39 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/ptrauth-dynamic-cast-exact.cpp | 128 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp | 37 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/sret_cast_with_nonzero_alloca_as.cpp | 2 |
10 files changed, 482 insertions, 10 deletions
diff --git a/clang/test/CodeGenCXX/constructor-attr.cpp b/clang/test/CodeGenCXX/constructor-attr.cpp index ec27ed210ce7..d73b661f1ec4 100644 --- a/clang/test/CodeGenCXX/constructor-attr.cpp +++ b/clang/test/CodeGenCXX/constructor-attr.cpp @@ -1,6 +1,11 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // CHECK: @llvm.global_ctors +// CHECK-SAME: i32 65535, ptr @_ZN3Foo3fooEv +// CHECK-SAME: i32 101, ptr @_Z22template_dependent_cxxILi101EEvv +// CHECK-SAME: i32 102, ptr @_Z22template_dependent_gnuILi102EEvv +// CHECK-SAME: i32 103, ptr @_Z1fv +// CHECK-SAME: i32 104, ptr @_Z23template_dependent_nttpIiLi104EEvv // PR6521 void bar(); @@ -10,3 +15,16 @@ struct Foo { bar(); } }; + + +template <int P> +[[gnu::constructor(P)]] void template_dependent_cxx() {} +template <int P> +__attribute__((constructor(P))) void template_dependent_gnu() {} +template <typename T, int P = sizeof(T) * 26> +[[gnu::constructor(P)]] void template_dependent_nttp() {} + +template void template_dependent_cxx<101>(); +template void template_dependent_gnu<102>(); +[[gnu::constructor(103)]] void f() {} +template void template_dependent_nttp<int>(); diff --git a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp index a29f4d720c1d..007b47c441b2 100644 --- a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp +++ b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp @@ -32,4 +32,19 @@ void foo(int a) { f({a}); } +constexpr int gh151716() { + int(&&g)[]{0,1,2}; + return g[2]; +} +// CHECK-LABEL: @_ZN3One10gh151716_fEv +// CHECK-NEXT: entry: +// CHECK-NEXT: %v = alloca i32, align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull %v) +// CHECK-NEXT: store volatile i32 2, ptr %v, align 4 +// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull %v) +// CHECK-NEXT: ret void +void gh151716_f() { + volatile const int v = gh151716(); +} + } // namespace One diff --git a/clang/test/CodeGenCXX/destructor-attr.cpp b/clang/test/CodeGenCXX/destructor-attr.cpp new file mode 100644 index 000000000000..f0500caed3cc --- /dev/null +++ b/clang/test/CodeGenCXX/destructor-attr.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s + +// CHECK: @llvm.global_dtors +// CHECK-SAME: i32 65535, ptr @_ZN3Foo3fooEv +// CHECK-SAME: i32 101, ptr @_Z22template_dependent_cxxILi101EEvv +// CHECK-SAME: i32 104, ptr @_Z23template_dependent_nttpIiLi104EEvv + +// PR6521 +void bar(); +struct Foo { + // CHECK-LABEL: define linkonce_odr {{.*}}void @_ZN3Foo3fooEv + static void foo() __attribute__((destructor)) { + bar(); + } +}; + +template <int P> +[[gnu::destructor(P)]] void template_dependent_cxx() {} +template <typename T, int P = sizeof(T) * 26> +[[gnu::destructor(P)]] void template_dependent_nttp() {} + +template void template_dependent_cxx<101>(); +template void template_dependent_nttp<int>(); diff --git a/clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp b/clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp index 3156e1bb21b1..bf202d14c339 100644 --- a/clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp +++ b/clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp @@ -3,7 +3,6 @@ // RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -O1 -fvisibility=hidden -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK,INEXACT // RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -O1 -fapple-kext -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK,INEXACT // RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -O1 -fno-assume-unique-vtables -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK,INEXACT -// RUN: %clang_cc1 -I%S %s -triple arm64e-apple-darwin10 -O1 -fptrauth-calls -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK,INEXACT struct A { virtual ~A(); }; struct B final : A { }; diff --git a/clang/test/CodeGenCXX/int64_uint64.cpp b/clang/test/CodeGenCXX/int64_uint64.cpp index f4fd9ea76147..8046ea9376d9 100644 --- a/clang/test/CodeGenCXX/int64_uint64.cpp +++ b/clang/test/CodeGenCXX/int64_uint64.cpp @@ -6,6 +6,14 @@ // RUN: -target-feature +neon \ // RUN: -emit-llvm -w -O1 -o - %s | FileCheck --check-prefix=CHECK-AARCH64 %s +// RUN: %clang_cc1 -triple arm-linux-guneabi \ +// RUN: -target-cpu cortex-a8 -fexperimental-new-constant-interpreter \ +// RUN: -emit-llvm -w -O1 -o - %s | FileCheck --check-prefix=CHECK-ARM %s + +// RUN: %clang_cc1 -triple arm64-linux-gnueabi \ +// RUN: -target-feature +neon -fexperimental-new-constant-interpreter \ +// RUN: -emit-llvm -w -O1 -o - %s | FileCheck --check-prefix=CHECK-AARCH64 %s + // REQUIRES: aarch64-registered-target || arm-registered-target // Test if int64_t and uint64_t can be correctly mangled. diff --git a/clang/test/CodeGenCXX/labeled-break-continue.cpp b/clang/test/CodeGenCXX/labeled-break-continue.cpp new file mode 100644 index 000000000000..4bdb5369aa8f --- /dev/null +++ b/clang/test/CodeGenCXX/labeled-break-continue.cpp @@ -0,0 +1,221 @@ +// RUN: %clang_cc1 -fnamed-loops -triple x86_64-unknown-linux -std=c++20 -emit-llvm -o - %s | FileCheck %s + +static int a[10]{}; +struct NonTrivialDestructor { + ~NonTrivialDestructor(); +}; + +bool g(int); +bool h(); + +// CHECK-LABEL: define {{.*}} void @_Z2f1v() +// CHECK: entry: +// CHECK: %__range1 = alloca ptr, align 8 +// CHECK: %__begin1 = alloca ptr, align 8 +// CHECK: %__end1 = alloca ptr, align 8 +// CHECK: %i = alloca i32, align 4 +// CHECK: br label %x +// CHECK: x: +// CHECK: store ptr @_ZL1a, ptr %__range1, align 8 +// CHECK: store ptr @_ZL1a, ptr %__begin1, align 8 +// CHECK: store ptr getelementptr inbounds (i32, ptr @_ZL1a, i64 10), ptr %__end1, align 8 +// CHECK: br label %for.cond +// CHECK: for.cond: +// CHECK: %0 = load ptr, ptr %__begin1, align 8 +// CHECK: %1 = load ptr, ptr %__end1, align 8 +// CHECK: %cmp = icmp ne ptr %0, %1 +// CHECK: br i1 %cmp, label %for.body, label %for.end +// CHECK: for.body: +// CHECK: %2 = load ptr, ptr %__begin1, align 8 +// CHECK: %3 = load i32, ptr %2, align 4 +// CHECK: store i32 %3, ptr %i, align 4 +// CHECK: %4 = load i32, ptr %i, align 4 +// CHECK: %call = call {{.*}} i1 @_Z1gi(i32 {{.*}} %4) +// CHECK: br i1 %call, label %if.then, label %if.end +// CHECK: if.then: +// CHECK: br label %for.end +// CHECK: if.end: +// CHECK: %5 = load i32, ptr %i, align 4 +// CHECK: %call1 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %5) +// CHECK: br i1 %call1, label %if.then2, label %if.end3 +// CHECK: if.then2: +// CHECK: br label %for.inc +// CHECK: if.end3: +// CHECK: br label %for.inc +// CHECK: for.inc: +// CHECK: %6 = load ptr, ptr %__begin1, align 8 +// CHECK: %incdec.ptr = getelementptr inbounds nuw i32, ptr %6, i32 1 +// CHECK: store ptr %incdec.ptr, ptr %__begin1, align 8 +// CHECK: br label %for.cond +// CHECK: for.end: +// CHECK: ret void +void f1() { + x: for (int i : a) { + if (g(i)) break x; + if (g(i)) continue x; + } +} + +// CHECK-LABEL: define {{.*}} void @_Z2f2v() +// CHECK: entry: +// CHECK: %n1 = alloca %struct.NonTrivialDestructor, align 1 +// CHECK: %__range2 = alloca ptr, align 8 +// CHECK: %__begin2 = alloca ptr, align 8 +// CHECK: %__end2 = alloca ptr, align 8 +// CHECK: %i = alloca i32, align 4 +// CHECK: %n2 = alloca %struct.NonTrivialDestructor, align 1 +// CHECK: %cleanup.dest.slot = alloca i32, align 4 +// CHECK: %n3 = alloca %struct.NonTrivialDestructor, align 1 +// CHECK: %n4 = alloca %struct.NonTrivialDestructor, align 1 +// CHECK: br label %l1 +// CHECK: l1: +// CHECK: br label %while.cond +// CHECK: while.cond: +// CHECK: %call = call {{.*}} i1 @_Z1gi(i32 {{.*}} 0) +// CHECK: br i1 %call, label %while.body, label %while.end +// CHECK: while.body: +// CHECK: br label %l2 +// CHECK: l2: +// CHECK: store ptr @_ZL1a, ptr %__range2, align 8 +// CHECK: store ptr @_ZL1a, ptr %__begin2, align 8 +// CHECK: store ptr getelementptr inbounds (i32, ptr @_ZL1a, i64 10), ptr %__end2, align 8 +// CHECK: br label %for.cond +// CHECK: for.cond: +// CHECK: %0 = load ptr, ptr %__begin2, align 8 +// CHECK: %1 = load ptr, ptr %__end2, align 8 +// CHECK: %cmp = icmp ne ptr %0, %1 +// CHECK: br i1 %cmp, label %for.body, label %for.end +// CHECK: for.body: +// CHECK: %2 = load ptr, ptr %__begin2, align 8 +// CHECK: %3 = load i32, ptr %2, align 4 +// CHECK: store i32 %3, ptr %i, align 4 +// CHECK: %4 = load i32, ptr %i, align 4 +// CHECK: %call1 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %4) +// CHECK: br i1 %call1, label %if.then, label %if.end +// CHECK: if.then: +// CHECK: store i32 4, ptr %cleanup.dest.slot, align 4 +// CHECK: br label %cleanup +// CHECK: if.end: +// CHECK: %5 = load i32, ptr %i, align 4 +// CHECK: %call2 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %5) +// CHECK: br i1 %call2, label %if.then3, label %if.end4 +// CHECK: if.then3: +// CHECK: store i32 3, ptr %cleanup.dest.slot, align 4 +// CHECK: br label %cleanup +// CHECK: if.end4: +// CHECK: %6 = load i32, ptr %i, align 4 +// CHECK: %call5 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %6) +// CHECK: br i1 %call5, label %if.then6, label %if.end7 +// CHECK: if.then6: +// CHECK: store i32 6, ptr %cleanup.dest.slot, align 4 +// CHECK: br label %cleanup +// CHECK: if.end7: +// CHECK: %7 = load i32, ptr %i, align 4 +// CHECK: %call8 = call {{.*}} i1 @_Z1gi(i32 {{.*}} %7) +// CHECK: br i1 %call8, label %if.then9, label %if.end10 +// CHECK: if.then9: +// CHECK: store i32 7, ptr %cleanup.dest.slot, align 4 +// CHECK: br label %cleanup +// CHECK: if.end10: +// CHECK: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}} %n3) +// CHECK: store i32 0, ptr %cleanup.dest.slot, align 4 +// CHECK: br label %cleanup +// CHECK: cleanup: +// CHECK: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}} %n2) +// CHECK: %cleanup.dest = load i32, ptr %cleanup.dest.slot, align 4 +// CHECK: switch i32 %cleanup.dest, label %cleanup11 [ +// CHECK: i32 0, label %cleanup.cont +// CHECK: i32 6, label %for.end +// CHECK: i32 7, label %for.inc +// CHECK: ] +// CHECK: cleanup.cont: +// CHECK: br label %for.inc +// CHECK: for.inc: +// CHECK: %8 = load ptr, ptr %__begin2, align 8 +// CHECK: %incdec.ptr = getelementptr inbounds nuw i32, ptr %8, i32 1 +// CHECK: store ptr %incdec.ptr, ptr %__begin2, align 8 +// CHECK: br label %for.cond +// CHECK: for.end: +// CHECK: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}} %n4) +// CHECK: store i32 0, ptr %cleanup.dest.slot, align 4 +// CHECK: br label %cleanup11 +// CHECK: cleanup11: +// CHECK: call void @_ZN20NonTrivialDestructorD1Ev(ptr {{.*}} %n1) +// CHECK: %cleanup.dest12 = load i32, ptr %cleanup.dest.slot, align 4 +// CHECK: switch i32 %cleanup.dest12, label %unreachable [ +// CHECK: i32 0, label %cleanup.cont13 +// CHECK: i32 4, label %while.end +// CHECK: i32 3, label %while.cond +// CHECK: ] +// CHECK: cleanup.cont13: +// CHECK: br label %while.cond +// CHECK: while.end: +// CHECK: ret void +// CHECK: unreachable: +// CHECK: unreachable +void f2() { + l1: while (g(0)) { + NonTrivialDestructor n1; + l2: for (int i : a) { + NonTrivialDestructor n2; + if (g(i)) break l1; + if (g(i)) continue l1; + if (g(i)) break l2; + if (g(i)) continue l2; + NonTrivialDestructor n3; + } + NonTrivialDestructor n4; + } +} + +template <bool Continue> +void f3() { + l1: while (g(1)) { + for (;g(2);) { + if constexpr (Continue) continue l1; + else break l1; + } + } +} + +// CHECK-LABEL: define {{.*}} void @_Z2f3ILb1EEvv() +// CHECK: entry: +// CHECK: br label %l1 +// CHECK: l1: +// CHECK: br label %while.cond +// CHECK: while.cond: +// CHECK: %call = call {{.*}} i1 @_Z1gi(i32 {{.*}} 1) +// CHECK: br i1 %call, label %while.body, label %while.end +// CHECK: while.body: +// CHECK: br label %for.cond +// CHECK: for.cond: +// CHECK: %call1 = call {{.*}} i1 @_Z1gi(i32 {{.*}} 2) +// CHECK: br i1 %call1, label %for.body, label %for.end +// CHECK: for.body: +// CHECK: br label %while.cond +// CHECK: for.end: +// CHECK: br label %while.cond +// CHECK: while.end: +// CHECK: ret void +template void f3<true>(); + +// CHECK-LABEL: define {{.*}} void @_Z2f3ILb0EEvv() +// CHECK: entry: +// CHECK: br label %l1 +// CHECK: l1: +// CHECK: br label %while.cond +// CHECK: while.cond: +// CHECK: %call = call {{.*}} i1 @_Z1gi(i32 {{.*}} 1) +// CHECK: br i1 %call, label %while.body, label %while.end +// CHECK: while.body: +// CHECK: br label %for.cond +// CHECK: for.cond: +// CHECK: %call1 = call {{.*}} i1 @_Z1gi(i32 {{.*}} 2) +// CHECK: br i1 %call1, label %for.body, label %for.end +// CHECK: for.body: +// CHECK: br label %while.end +// CHECK: for.end: +// CHECK: br label %while.cond +// CHECK: while.end: +// CHECK: ret void +template void f3<false>(); diff --git a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp index 312c70cc740e..44f4436328a7 100644 --- a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -358,3 +358,42 @@ struct s { enum {}; enum {}; }; // DBG-DAG: DW_TAG_enumeration_type{{.*}}identifier: ".?AW4<unnamed-type-$S3>@s@pr37723@@" s x; } + +namespace InconsistentTagKinds { + namespace t1 { + class A; + struct A; + void f(A*) {} + // CHECK-DAG: @"?f@t1@InconsistentTagKinds@@YAXPAVA@12@@Z" + } // namespace t1 + namespace t2 { + struct A; + class A; + void f(A*) {} + // CHECK-DAG: @"?f@t2@InconsistentTagKinds@@YAXPAUA@12@@Z" + } // namespace t2 + namespace t3 { + class A {}; + struct A; + void f(A*) {} + // CHECK-DAG: @"?f@t3@InconsistentTagKinds@@YAXPAVA@12@@Z" + } // namespace t3 + namespace t4 { + struct A {}; + class A; + void f(A*) {} + // CHECK-DAG: @"?f@t4@InconsistentTagKinds@@YAXPAUA@12@@Z" + } // namespace t4 + namespace t5 { + class A; + struct A {}; + void f(A*) {} + // CHECK-DAG: @"?f@t5@InconsistentTagKinds@@YAXPAUA@12@@Z" + } // namespace t5 + namespace t6 { + struct A; + class A {}; + void f(A*) {} + // CHECK-DAG: @"?f@t6@InconsistentTagKinds@@YAXPAVA@12@@Z" + } // namespace t6 +} // namespace InconsistentTagKinds diff --git a/clang/test/CodeGenCXX/ptrauth-dynamic-cast-exact.cpp b/clang/test/CodeGenCXX/ptrauth-dynamic-cast-exact.cpp new file mode 100644 index 000000000000..1710ca556338 --- /dev/null +++ b/clang/test/CodeGenCXX/ptrauth-dynamic-cast-exact.cpp @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 -I%S %s -triple arm64e-apple-darwin10 -O1 -fptrauth-calls -fptrauth-vtable-pointer-address-discrimination -fptrauth-vtable-pointer-type-discrimination -emit-llvm -std=c++11 -o - | FileCheck %s --check-prefixes=CHECK + +struct A { + virtual ~A(); +}; +struct B { + int foo; + virtual ~B(); +}; +struct C final : A, B { + virtual void f(){}; +}; +struct D final : B, A { + virtual void f(){}; +}; + +struct Offset { + virtual ~Offset(); +}; +struct E { + virtual ~E(); +}; +struct F final : Offset, E { +}; +struct G { + virtual ~G(); + int g; +}; +struct H : E { + int h; +}; +struct I : E { + int i; +}; +struct J : virtual E { + int j; +}; +struct K : virtual E { + int k; +}; +struct L final : G, H, I, J, K { + int l; +}; +struct M final: G, private H { int m; }; + +// CHECK-LABEL: @_Z10exact_to_CP1A +C *exact_to_C(A *a) { + // CHECK: [[UNAUTHED_VPTR:%.*]] = load ptr, ptr %a, align 8 + // CHECK: [[VPTR_ADDRI:%.*]] = ptrtoint ptr %a to i64 + // CHECK: [[VPTR_ADDR_DISC:%.*]] = tail call i64 @llvm.ptrauth.blend(i64 [[VPTR_ADDRI]], i64 62866) + // CHECK: [[UNAUTHED_VPTRI:%.*]] = ptrtoint ptr [[UNAUTHED_VPTR]] to i64 + // CHECK: [[AUTHED_VPTRI:%.*]] = tail call i64 @llvm.ptrauth.auth(i64 [[UNAUTHED_VPTRI]], i32 2, i64 [[VPTR_ADDR_DISC]]) + // CHECK: [[IS_EXPECTED:%.*]] = icmp eq i64 [[AUTHED_VPTRI]], ptrtoint (ptr getelementptr inbounds nuw inrange(-16, 24) (i8, ptr @_ZTV1C, i64 16) to i64) + // CHECK: br i1 [[IS_EXPECTED]], label %dynamic_cast.end, label %dynamic_cast.null + // CHECK: [[NULL_CHECKED_RESULT:%.*]] = phi ptr [ %a, %dynamic_cast.notnull ], [ null, %dynamic_cast.null ] + // CHECK: ret ptr [[NULL_CHECKED_RESULT]] + return dynamic_cast<C*>(a); +} + +// CHECK-LABEL: @_Z9exact_t_DP1A +D *exact_t_D(A *a) { + // CHECK: dynamic_cast.notnull: + // CHECK: [[SRC_UNAUTHED_VPTR:%.*]] = load ptr, ptr %a + // CHECK: [[SRC_VPTR_ADDRI:%.*]] = ptrtoint ptr %a to i64 + // CHECK: [[SRC_VPTR_DISC:%.*]] = tail call i64 @llvm.ptrauth.blend(i64 [[SRC_VPTR_ADDRI]], i64 62866) + // CHECK: [[SRC_UNAUTHED_VPTRI:%.*]] = ptrtoint ptr [[SRC_UNAUTHED_VPTR]] to i64 + // CHECK: [[SRC_AUTHED_VPTRI:%.*]] = tail call i64 @llvm.ptrauth.auth(i64 [[SRC_UNAUTHED_VPTRI]], i32 2, i64 [[SRC_VPTR_DISC]]) + // CHECK: [[SUCCESS:%.*]] = icmp eq i64 [[SRC_AUTHED_VPTRI]], ptrtoint (ptr getelementptr inbounds nuw inrange(-16, 16) (i8, ptr @_ZTV1D, i64 56) to i64) + // CHECK: br i1 [[SUCCESS]], label %dynamic_cast.postauth.success, label %dynamic_cast.postauth.complete + // CHECK: dynamic_cast.postauth.success: + // CHECK: [[ADJUSTED_THIS:%.*]] = getelementptr inbounds i8, ptr %a, i64 -16 + // CHECK: [[ADJUSTED_UNAUTHED_VPTR:%.*]] = load ptr, ptr [[ADJUSTED_THIS]] + // CHECK: [[ADJUSTED_VPTR_ADDRI:%.*]] = ptrtoint ptr [[ADJUSTED_THIS]] to i64 + // CHECK: [[ADJUSTED_VPTR_DISC:%.*]] = tail call i64 @llvm.ptrauth.blend(i64 [[ADJUSTED_VPTR_ADDRI]], i64 28965) + // CHECK: [[ADJUSTED_UNAUTHED_VPTRI:%.*]] = ptrtoint ptr [[ADJUSTED_UNAUTHED_VPTR]] to i64 + // CHECK: [[ADJUSTED_AUTHED_VPTRI:%.*]] = tail call i64 @llvm.ptrauth.auth(i64 [[ADJUSTED_UNAUTHED_VPTRI]], i32 2, i64 [[ADJUSTED_VPTR_DISC]]) + // CHECK: [[ADJUSTED_AUTHED_VPTR:%.*]] = inttoptr i64 [[ADJUSTED_AUTHED_VPTRI]] to ptr + // CHECK: br label %dynamic_cast.postauth.complete + // CHECK: dynamic_cast.postauth.complete: + // CHECK: [[AUTHED_ADJUSTED_THIS:%.*]] = phi ptr [ [[ADJUSTED_THIS]], %dynamic_cast.postauth.success ], [ null, %dynamic_cast.notnull ] + // CHECK: br i1 [[SUCCESS]], label %dynamic_cast.end, label %dynamic_cast.null + // CHECK: dynamic_cast.null: + // CHECK: br label %dynamic_cast.end + // CHECK: dynamic_cast.end: + // CHECK: [[RESULT:%.*]] = phi ptr [ [[AUTHED_ADJUSTED_THIS]], %dynamic_cast.postauth.complete ], [ null, %dynamic_cast.null ] + // CHECK: ret ptr [[RESULT]] + return dynamic_cast<D*>(a); +} + +// CHECK-LABEL: @_Z11exact_multiP1E +L *exact_multi(E *e) { + // CHECK: dynamic_cast.notnull: + // CHECK: [[VTABLE_ADDR:%.*]] = load ptr, ptr %e, align 8 + // CHECK: [[THIS_ADDRI:%.*]] = ptrtoint ptr %e to i64 + // CHECK: [[VTABLE_DISC:%.*]] = tail call i64 @llvm.ptrauth.blend(i64 [[THIS_ADDRI]], i64 12810) + // CHECK: [[VTABLE_ADDRI:%.*]] = ptrtoint ptr [[VTABLE_ADDR]] to i64 + // CHECK: [[AUTHED_VTABLEI:%.*]] = tail call i64 @llvm.ptrauth.auth(i64 [[VTABLE_ADDRI]], i32 2, i64 [[VTABLE_DISC]]) + // CHECK: [[AUTHED_VTABLE:%.*]] = inttoptr i64 [[AUTHED_VTABLEI]] to ptr + // CHECK: [[PRIMARY_BASE_OFFSET:%.*]] = getelementptr inbounds i8, ptr [[AUTHED_VTABLE]], i64 -16 + // CHECK: %offset.to.top = load i64, ptr [[PRIMARY_BASE_OFFSET]] + // CHECK: [[ADJUSTED_THIS:%.*]] = getelementptr inbounds i8, ptr %e, i64 %offset.to.top + // CHECK: [[ADJUSTED_THIS_VTABLE:%.*]] = load ptr, ptr [[ADJUSTED_THIS]] + // CHECK: [[ADJUSTED_THIS_VTABLEI:%.*]] = ptrtoint ptr [[ADJUSTED_THIS_VTABLE]] to i64 + // CHECK: [[ADJUSTED_THIS_STRIPPED_VTABLEI:%.*]] = tail call i64 @llvm.ptrauth.strip(i64 [[ADJUSTED_THIS_VTABLEI]], i32 0) + // CHECK: [[SUCCESS:%.*]] = icmp eq i64 [[ADJUSTED_THIS_STRIPPED_VTABLEI]], ptrtoint (ptr getelementptr inbounds nuw inrange(-24, 16) (i8, ptr @_ZTV1L, i64 24) to i64) + // CHECK: br i1 [[SUCCESS]], label %dynamic_cast.postauth.success, label %dynamic_cast.postauth.complete + // CHECK: dynamic_cast.postauth.success: + // CHECK: [[ADJUSTED_THISI:%.*]] = ptrtoint ptr [[ADJUSTED_THIS]] to i64 + // CHECK: [[DEST_DISC:%.*]] = tail call i64 @llvm.ptrauth.blend(i64 [[ADJUSTED_THISI]], i64 41434) + // CHECK: tail call i64 @llvm.ptrauth.auth(i64 [[ADJUSTED_THIS_VTABLEI]], i32 2, i64 [[DEST_DISC]]) + // CHECK: br label %dynamic_cast.postauth.complete + // CHECK: dynamic_cast.postauth.complete: + // CHECK: [[AUTHED_ADJUSTED_THIS:%.*]] = phi ptr [ [[ADJUSTED_THIS]], %dynamic_cast.postauth.success ], [ null, %dynamic_cast.notnull ] + // CHECK: br i1 [[SUCCESS]], label %dynamic_cast.end, label %dynamic_cast.null + // CHECK: dynamic_cast.null: + // CHECK: br label %dynamic_cast.end + // CHECK: dynamic_cast.end: + // CHECK: [[RESULT:%.*]] = phi ptr [ [[AUTHED_ADJUSTED_THIS]], %dynamic_cast.postauth.complete ], [ null, %dynamic_cast.null ] + // CHECK: ret ptr [[RESULT]] + return dynamic_cast<L*>(e); +} + +// CHECK-LABEL: @_Z19exact_invalid_multiP1H +M *exact_invalid_multi(H* d) { + // CHECK: entry: + // CHECK-NEXT: ret ptr null + return dynamic_cast<M*>(d); +} diff --git a/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp b/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp index 1b103719fbe4..e33525c1ec0f 100644 --- a/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp +++ b/clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp @@ -1,31 +1,31 @@ -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s -// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: %clang_cc1 %s -x c++ -std=c++20 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s @@ -78,6 +78,27 @@ struct authenticated(default_key, default_address_discrimination, custom_discrim virtual void g(); }; +// CHECK: @_ZTVN5test19ConstEvalE = external unnamed_addr constant { [3 x ptr] }, align 8 +// CHECK: @_ZN5test12ceE = global %{{.*}} { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test19ConstEvalE, i32 0, i32 0, i32 2), i32 2, i64 0, ptr @_ZN5test12ceE) }, align 8 +// CHECK: @_ZTVN5test116ConstEvalDerivedE = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTIN5test116ConstEvalDerivedE, ptr ptrauth (ptr @_ZN5test19ConstEval1fEv, i32 0, i64 26259, ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test116ConstEvalDerivedE, i32 0, i32 0, i32 2))] },{{.*}}align 8 +// CHECK: @_ZN5test13cedE = global { ptr } { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test116ConstEvalDerivedE, i32 0, i32 0, i32 2), i32 2, i64 0, ptr @_ZN5test13cedE) }, align 8 + +struct authenticated(default_key, address_discrimination, no_extra_discrimination) ConstEval { + consteval ConstEval() {} + virtual void f(); +}; + +// clang used to bail out with error message "could not emit constant value abstractly". +ConstEval ce; + +struct ConstEvalDerived : public ConstEval { +public: + consteval ConstEvalDerived() {} +}; + +// clang used to emit an undef initializer. +ConstEvalDerived ced; + template <typename T> struct SubClass : T { virtual void g(); diff --git a/clang/test/CodeGenCXX/sret_cast_with_nonzero_alloca_as.cpp b/clang/test/CodeGenCXX/sret_cast_with_nonzero_alloca_as.cpp index a0ee54dc16ba..a1a6ada4f3fd 100644 --- a/clang/test/CodeGenCXX/sret_cast_with_nonzero_alloca_as.cpp +++ b/clang/test/CodeGenCXX/sret_cast_with_nonzero_alloca_as.cpp @@ -18,7 +18,7 @@ struct X { int z[17]; }; // CHECK-NEXT: store i8 [[TMP0]], ptr [[ADD_PTR]], align 1 // CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[Y_ADDR_ASCAST]], align 1 // CHECK-NEXT: [[ADD_PTR1:%.*]] = getelementptr inbounds i8, ptr [[AGG_RESULT_ASCAST]], i64 2 -// CHECK-NEXT: store i8 [[TMP1]], ptr [[ADD_PTR1]], align 1 +// CHECK-NEXT: store i8 [[TMP1]], ptr [[ADD_PTR1]], align 2 // CHECK-NEXT: ret void // X foo(char x, char y) { |
