xref: /llvm-project/clang/test/CodeGenCXX/cxx20-consteval-crash.cpp (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
1 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -emit-llvm -o - | FileCheck %s
2 // RUN: %clang_cc1 -emit-obj -debug-info-kind=constructor -std=c++20 %s -o -
3 
4 namespace PR50787 {
5 // This code would previously cause a crash.
6 extern int x_;
7 consteval auto& X() { return x_; }
8 constexpr auto& x1 = X();
9 auto x2 = X();
10 
11 // CHECK: @_ZN7PR507872x_E = external global i32, align 4
12 // CHECK-NEXT: @_ZN7PR507872x1E = constant ptr @_ZN7PR507872x_E, align 8
13 // CHECK-NEXT: @_ZN7PR507872x2E = global i32 0, align 4
14 }
15 
16 namespace PR51484 {
17 // This code would previously cause a crash.
18 struct X { int val; };
19 consteval X g() { return {0}; }
20 void f() { g(); }
21 
22 // CHECK: define dso_local void @_ZN7PR514841fEv() #1 {
23 // CHECK: entry:
24 // CHECK-NOT: call i32 @_ZN7PR514841gEv()
25 // CHECK:  ret void
26 // CHECK: }
27 }
28 
29 namespace Issue54578 {
30 inline consteval unsigned char operator""_UC(const unsigned long long n) {
31   return static_cast<unsigned char>(n);
32 }
33 
34 inline constexpr char f1(const auto octet) {
35   return 4_UC;
36 }
37 
38 template <typename Ty>
39 inline constexpr char f2(const Ty octet) {
40   return 4_UC;
41 }
42 
43 int foo() {
44   return f1('a') + f2('a');
45 }
46 
47 // Because the consteval functions are inline (implicitly as well as
48 // explicitly), we need to defer the CHECK lines until this point to get the
49 // order correct. We want to ensure there is no definition of the consteval
50 // UDL function, and that the constexpr f1 and f2 functions both return a
51 // constant value.
52 
53 // CHECK-NOT: define{{.*}} zeroext i8 @_ZN10Issue54578li3_UCEy
54 // CHECK: define{{.*}} i32 @_ZN10Issue545783fooEv(
55 // CHECK: define{{.*}} signext i8 @_ZN10Issue545782f1IcEEcT_(
56 // CHECK: ret i8 4
57 // CHECK: define{{.*}} signext i8 @_ZN10Issue545782f2IcEEcT_(
58 // CHECK: ret i8 4
59 }
60 
61 namespace Issue55871 {
62 struct Item {
63   consteval Item(char c) :_char{c}{}
64   char _char;
65 };
66 
67 int function(const Item& item1, const Item& item2) {
68   return 0;
69 }
70 
71 int foo() {
72   return function(Item{'a'}, Item{'a'});
73 }
74 } // namespace Issue58871
75 
76 namespace Issue55065 {
77 struct Base {
78   consteval virtual int Get() const = 0;
79 };
80 
81 struct Derived : Base {
82   consteval int Get() const override {
83     return 42;
84   }
85 };
86 
87 int foo() {
88   constexpr Derived a;
89 
90   auto val = a.Get();
91   return val;
92 }
93 } // namespace Issue55065
94 
95 namespace GH60166 {
96 
97 struct Base {
98    void* one = nullptr;
99    void* two = nullptr;
100 };
101 
102 struct Derived : Base {
103    void* three = nullptr;
104    consteval Derived() = default;
105 };
106 
107 void method() {
108   // CHECK: %agg.tmp.ensured = alloca %"struct.GH60166::Derived"
109   // CHECK: %0 = getelementptr inbounds nuw { ptr, ptr, ptr }, ptr %agg.tmp.ensured, i32 0, i32 0
110   // CHECK: store ptr null, ptr %0, align 8
111   // CHECK: %1 = getelementptr inbounds nuw { ptr, ptr, ptr }, ptr %agg.tmp.ensured, i32 0, i32 1
112   // CHECK: store ptr null, ptr %1, align 8
113   // CHECK: %2 = getelementptr inbounds nuw { ptr, ptr, ptr }, ptr %agg.tmp.ensured, i32 0, i32 2
114   // CHECK: store ptr null, ptr %2, align 8
115    (void)Derived();
116 }
117 
118 } // namespace GH60166
119 
120 namespace GH61142 {
121 
122 template <typename T>
123 struct Test {
124   constexpr static void bar() {
125     foo();
126   }
127   consteval static void foo() {};
128 };
129 
130 consteval void a() {
131   Test<int>::bar();
132 }
133 
134 void b() {
135   Test<int>::bar();
136 }
137 
138 // Make sure consteval function is not emitted.
139 // CHECK-NOT: call {{.*}}foo{{.*}}()
140 // CHECK-NOT: define {{.*}}foo{{.*}}()
141 
142 } // namespace GH61142
143