summaryrefslogtreecommitdiff
path: root/clang/test/CodeGenCXX
diff options
context:
space:
mode:
authorMingming Liu <mingmingl@google.com>2025-09-10 15:25:31 -0700
committerGitHub <noreply@github.com>2025-09-10 15:25:31 -0700
commit1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch)
tree57f4b1f313c8cf74eed8819870f39c36ea263c68 /clang/test/CodeGenCXX
parent898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff)
parentb8cefcb601ddaa18482555c4ff363c01a270c2fe (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.cpp18
-rw-r--r--clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp15
-rw-r--r--clang/test/CodeGenCXX/destructor-attr.cpp23
-rw-r--r--clang/test/CodeGenCXX/dynamic-cast-exact-disabled.cpp1
-rw-r--r--clang/test/CodeGenCXX/int64_uint64.cpp8
-rw-r--r--clang/test/CodeGenCXX/labeled-break-continue.cpp221
-rw-r--r--clang/test/CodeGenCXX/mangle-ms-cxx11.cpp39
-rw-r--r--clang/test/CodeGenCXX/ptrauth-dynamic-cast-exact.cpp128
-rw-r--r--clang/test/CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp37
-rw-r--r--clang/test/CodeGenCXX/sret_cast_with_nonzero_alloca_as.cpp2
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) {