247 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR3// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM5// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll6// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG7 8void rethrow() {9 throw;10}11 12// CIR: cir.throw13// CIR: cir.unreachable14 15// LLVM: call void @__cxa_rethrow()16// LLVM: unreachable17 18// OGCG: call void @__cxa_rethrow()19// OGCG: unreachable20 21int rethrow_from_block(int a, int b) {22 if (b == 0)23 throw;24 return a / b;25}26 27// CIR: %[[A_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]28// CIR: %[[B_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]29// CIR: %[[RES_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]30// CIR: cir.store %{{.*}}, %[[A_ADDR]] : !s32i, !cir.ptr<!s32i>31// CIR: cir.store %{{.*}}, %[[B_ADDR]] : !s32i, !cir.ptr<!s32i>32// CIR: cir.scope {33// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!s32i>, !s32i34// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i35// CIR: %[[IS_B_ZERO:.*]] = cir.cmp(eq, %[[TMP_B]], %[[CONST_0]]) : !s32i, !cir.bool36// CIR: cir.if %[[IS_B_ZERO]] {37// CIR: cir.throw38// CIR: cir.unreachable39// CIR: }40// CIR: }41// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!s32i>, !s32i42// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!s32i>, !s32i43// CIR: %[[DIV_A_B:.*]] = cir.binop(div, %[[TMP_A:.*]], %[[TMP_B:.*]]) : !s32i44// CIR: cir.store %[[DIV_A_B]], %[[RES_ADDR]] : !s32i, !cir.ptr<!s32i>45// CIR: %[[RESULT:.*]] = cir.load %[[RES_ADDR]] : !cir.ptr<!s32i>, !s32i46// CIR: cir.return %[[RESULT]] : !s32i47 48// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 449// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1, align 450// LLVM: %[[RES_ADDR:.*]] = alloca i32, i64 1, align 451// LLVM: store i32 %{{.*}}, ptr %[[A_ADDR]], align 452// LLVM: store i32 %{{.*}}, ptr %[[B_ADDR]], align 453// LLVM: br label %[[CHECK_COND:.*]]54// LLVM: [[CHECK_COND]]:55// LLVM: %[[TMP_B:.*]] = load i32, ptr %[[B_ADDR]], align 456// LLVM: %[[IS_B_ZERO:.*]] = icmp eq i32 %[[TMP_B]], 057// LLVM: br i1 %[[IS_B_ZERO]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]58// LLVM: [[IF_THEN]]:59// LLVM: call void @__cxa_rethrow()60// LLVM: unreachable61// LLVM: [[IF_ELSE]]:62// LLVM: br label %[[IF_END:.*]]63// LLVM: [[IF_END]]:64// LLVM: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 465// LLVM: %[[TMP_B:.*]] = load i32, ptr %[[B_ADDR]], align 466// LLVM: %[[DIV_A_B:.*]] = sdiv i32 %[[TMP_A]], %[[TMP_B]]67// LLVM: store i32 %[[DIV_A_B]], ptr %[[RES_ADDR]], align 468// LLVM: %[[RESULT:.*]] = load i32, ptr %[[RES_ADDR]], align 469// LLVM: ret i32 %[[RESULT]]70 71// OGCG: %[[A_ADDR:.*]] = alloca i32, align 472// OGCG: %[[B_ADDR:.*]] = alloca i32, align 473// OGCG: store i32 %{{.*}}, ptr %[[A_ADDR]], align 474// OGCG: store i32 %{{.*}}, ptr %[[B_ADDR]], align 475// OGCG: %[[TMP_B:.*]] = load i32, ptr %[[B_ADDR]], align 476// OGCG: %[[IS_B_ZERO:.*]] = icmp eq i32 %[[TMP_B]], 077// OGCG: br i1 %[[IS_B_ZERO]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]78// OGCG: [[IF_THEN]]:79// OGCG: call void @__cxa_rethrow()80// OGCG: unreachable81// OGCG: [[IF_END]]:82// OGCG: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 483// OGCG: %[[TMP_B:.*]] = load i32, ptr %[[B_ADDR]], align 484// OGCG: %[[DIV_A_B:.*]] = sdiv i32 %[[TMP_A]], %[[TMP_B]]85// OGCG: ret i32 %[[DIV_A_B]]86 87void throw_scalar() { 88 throw 1;89}90 91// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 4 -> !cir.ptr<!s32i>92// CIR: %[[EXCEPTION_VALUE:.*]] = cir.const #cir.int<1> : !s32i93// CIR: cir.store{{.*}} %[[EXCEPTION_VALUE]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i>94// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i>, @_ZTIi95// CIR: cir.unreachable96 97// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4)98// LLVM: store i32 1, ptr %[[EXCEPTION_ADDR]], align 1699// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIi, ptr null)100// LLVM: unreachable101 102// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4)103// OGCG: store i32 1, ptr %[[EXCEPTION_ADDR]], align 16104// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIi, ptr null)105// OGCG: unreachable106 107void paren_expr() { (throw 0, 1 + 2); }108 109// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 4 -> !cir.ptr<!s32i>110// CIR: %[[EXCEPTION_VALUE:.*]] = cir.const #cir.int<0> : !s32i111// CIR: cir.store{{.*}} %[[EXCEPTION_VALUE]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i>112// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i>, @_ZTIi113// CIR: cir.unreachable114// CIR: ^bb1:115// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i116// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i117// CIR: %[[ADD:.*]] = cir.binop(add, %[[CONST_1]], %[[CONST_2]]) nsw : !s32i118 119// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4)120// LLVM: store i32 0, ptr %[[EXCEPTION_ADDR]], align 16121// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIi, ptr null)122 123// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4)124// OGCG: store i32 0, ptr %[[EXCEPTION_ADDR]], align 16125// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIi, ptr null)126 127void throw_complex_expr() {128 throw __builtin_complex(1.1f, 2.2f);129}130 131// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 8 -> !cir.ptr<!cir.complex<!cir.float>>132// CIR: %[[EXCEPTION_VALUE:.*]] = cir.const #cir.const_complex<#cir.fp<1.100000e+00> : !cir.float, #cir.fp<2.200000e+00> : !cir.float> : !cir.complex<!cir.float>133// CIR: cir.store{{.*}} %[[EXCEPTION_VALUE]], %[[EXCEPTION_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>134// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, @_ZTICf135// CIR: cir.unreachable136 137// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 8)138// LLVM: store { float, float } { float 0x3FF19999A0000000, float 0x40019999A0000000 }, ptr %[[EXCEPTION_ADDR]], align 16139// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTICf, ptr null)140 141// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 8)142// OGCG: %[[EXCEPTION_REAL:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[EXCEPTION_ADDR]], i32 0, i32 0143// OGCG: %[[EXCEPTION_IMAG:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[EXCEPTION_ADDR]], i32 0, i32 1144// OGCG: store float 0x3FF19999A0000000, ptr %[[EXCEPTION_REAL]], align 16145// OGCG: store float 0x40019999A0000000, ptr %[[EXCEPTION_IMAG]], align 4146// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTICf, ptr null)147 148void throw_vector_type() {149 typedef int vi4 __attribute__((vector_size(16)));150 vi4 a;151 throw a;152}153 154// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]155// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 16 -> !cir.ptr<!cir.vector<4 x !s32i>>156// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>157// CIR: cir.store{{.*}} %[[TMP_A]], %[[EXCEPTION_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>158// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, @_ZTIDv4_i159// CIR: cir.unreachable160 161// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16162// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 16)163// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16164// LLVM: store <4 x i32> %[[TMP_A]], ptr %[[EXCEPTION_ADDR]], align 16165// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIDv4_i, ptr null)166 167// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16168// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 16)169// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16170// OGCG: store <4 x i32> %[[TMP_A]], ptr %[[EXCEPTION_ADDR]], align 16171// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIDv4_i, ptr null)172// OGCG: unreachable173 174void throw_ext_vector_type() {175 typedef int vi4 __attribute__((ext_vector_type(4)));176 vi4 a;177 throw a;178}179 180// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]181// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 16 -> !cir.ptr<!cir.vector<4 x !s32i>>182// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>183// CIR: cir.store{{.*}} %[[TMP_A]], %[[EXCEPTION_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>184// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, @_ZTIDv4_i185// CIR: cir.unreachable186 187// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16188// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 16)189// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16190// LLVM: store <4 x i32> %[[TMP_A]], ptr %[[EXCEPTION_ADDR]], align 16191// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIDv4_i, ptr null)192 193// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16194// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 16)195// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16196// OGCG: store <4 x i32> %[[TMP_A]], ptr %[[EXCEPTION_ADDR]], align 16197// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIDv4_i, ptr null)198// OGCG: unreachable199 200void throw_enum_expr() {201 enum Test {202 TestA,203 TestB204 };205 throw Test::TestA;206}207 208// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 4 -> !cir.ptr<!u32i>209// CIR: %[[EXCEPTION_VALUE:.*]] = cir.const #cir.int<0> : !u32i210// CIR: cir.store{{.*}} %[[EXCEPTION_VALUE]], %[[EXCEPTION_ADDR]] : !u32i, !cir.ptr<!u32i>211// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!u32i>, @_ZTIZ15throw_enum_exprvE4Test212// CIR: cir.unreachable213 214// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4)215// LLVM: store i32 0, ptr %[[EXCEPTION_ADDR]], align 16216// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIZ15throw_enum_exprvE4Test, ptr null)217// LLVM: unreachable218 219// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4)220// OGCG: store i32 0, ptr %[[EXCEPTION_ADDR]], align 16221// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIZ15throw_enum_exprvE4Test, ptr null)222// OGCG: unreachable223 224void throw_enum_class_expr() {225 enum class Test {226 TestA,227 TestB228 };229 throw Test::TestA;230}231 232// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 4 -> !cir.ptr<!s32i>233// CIR: %[[EXCEPTION_VALUE:.*]] = cir.const #cir.int<0> : !s32i234// CIR: cir.store{{.*}} %[[EXCEPTION_VALUE]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i>235// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i>, @_ZTIZ21throw_enum_class_exprvE4Test236// CIR: cir.unreachable237 238// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4)239// LLVM: store i32 0, ptr %[[EXCEPTION_ADDR]], align 16240// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIZ21throw_enum_class_exprvE4Test, ptr null)241// LLVM: unreachable242 243// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4)244// OGCG: store i32 0, ptr %[[EXCEPTION_ADDR]], align 16245// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIZ21throw_enum_class_exprvE4Test, ptr null)246// OGCG: unreachable247