Author: Andy Kaylor
Date: 2026-06-12T09:24:38-07:00
New Revision: 484b955581d976f97a47ef621c441e21c231aa23

URL: 
https://github.com/llvm/llvm-project/commit/484b955581d976f97a47ef621c441e21c231aa23
DIFF: 
https://github.com/llvm/llvm-project/commit/484b955581d976f97a47ef621c441e21c231aa23.diff

LOG: [CIR] Implement throw within an aggregate expression (#203404)

This implements CIR support for throwing an exception from within a
branch of a ternary expression that represents an aggregate prvalue. We
previously had support for throwing an exception within a ternary
aggregate expression, but when the expression uses a prvalue, it goes
through a different code path. The new implementation is just calling an
existing function from a different place. The bulk of what's being added
here is the testing.

Added: 
    

Modified: 
    clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
    clang/test/CIR/CodeGen/ternary-throw.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 1b5654c4d0d59..44f481508cd7e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -627,9 +627,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
     emitFinalDestCopy(e->getType(), tmpLValue);
   }
 
-  void VisitCXXThrowExpr(const CXXThrowExpr *e) {
-    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCXXThrowExpr");
-  }
+  void VisitCXXThrowExpr(const CXXThrowExpr *e) { cgf.emitCXXThrowExpr(e); }
   void VisitAtomicExpr(AtomicExpr *e) {
     RValue result = cgf.emitAtomicExpr(e);
     emitFinalDestCopy(e->getType(), result);

diff  --git a/clang/test/CIR/CodeGen/ternary-throw.cpp 
b/clang/test/CIR/CodeGen/ternary-throw.cpp
index ef9f2aaea4c9f..fbafa9811d76e 100644
--- a/clang/test/CIR/CodeGen/ternary-throw.cpp
+++ b/clang/test/CIR/CodeGen/ternary-throw.cpp
@@ -521,3 +521,132 @@ const int test_agg_cond_const_false_throw_true(struct s6 
a1, struct s6 a2) {
 // OGCG: %[[F0_PTR:.*]] = getelementptr inbounds nuw %struct.s6, ptr %[[A1]], 
i32 0, i32 0
 // OGCG: %[[F0_VAL:.*]] = load i32, ptr %[[F0_PTR]]
 // OGCG: ret i32 %{{.*}}
+
+struct Agg {
+  int x;
+  int y;
+};
+
+void test_agg_throw_true(bool flag) {
+  Agg a = flag ? throw 0 : Agg{1, 2};
+}
+
+// CIR-LABEL: cir.func{{.*}} @_Z19test_agg_throw_trueb(
+// CIR:   %[[FLAG:.*]] = cir.alloca "flag"
+// CIR:   %[[A:.*]] = cir.alloca "a"
+// CIR:   %[[FLAG_VAL:.*]] = cir.load{{.*}} %[[FLAG]] : !cir.ptr<!cir.bool>, 
!cir.bool
+// CIR:   cir.if %[[FLAG_VAL]] {
+// CIR:     %[[EXC:.*]] = cir.alloc.exception{{.*}} -> !cir.ptr<!s32i>
+// CIR:     %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
+// CIR:     cir.store{{.*}} %[[ZERO]], %[[EXC]] : !s32i, !cir.ptr<!s32i>
+// CIR:     cir.throw %[[EXC]] : !cir.ptr<!s32i>, @_ZTIi
+// CIR:     cir.unreachable
+// CIR:   } else {
+// CIR:     %[[X:.*]] = cir.get_member %[[A]][0] {name = "x"} : 
!cir.ptr<!rec_Agg> -> !cir.ptr<!s32i>
+// CIR:     %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
+// CIR:     cir.store{{.*}} %[[ONE]], %[[X]] : !s32i, !cir.ptr<!s32i>
+// CIR:     %[[Y:.*]] = cir.get_member %[[A]][1] {name = "y"} : 
!cir.ptr<!rec_Agg> -> !cir.ptr<!s32i>
+// CIR:     %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
+// CIR:     cir.store{{.*}} %[[TWO]], %[[Y]] : !s32i, !cir.ptr<!s32i>
+// CIR:   }
+// CIR:   cir.return
+
+// LLVM-LABEL: define{{.*}} void @_Z19test_agg_throw_trueb(
+// LLVM:   %[[FLAG_ALLOCA:.*]] = alloca i8
+// LLVM:   %[[A_ALLOCA:.*]] = alloca %struct.Agg
+// LLVM:   %[[BOOL:.*]] = trunc i8 %{{.*}} to i1
+// LLVM:   br i1 %[[BOOL]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]
+// LLVM: [[TRUE_BB]]:
+// LLVM:   %[[EXC:.*]] = call{{.*}} ptr @__cxa_allocate_exception
+// LLVM:   store i32 0, ptr %[[EXC]]
+// LLVM:   call void @__cxa_throw(ptr %[[EXC]], ptr @_ZTIi
+// LLVM:   unreachable
+// LLVM: [[FALSE_BB]]:
+// LLVM:   %[[X:.*]] = getelementptr inbounds nuw %struct.Agg, ptr 
%[[A_ALLOCA]], i32 0, i32 0
+// LLVM:   store i32 1, ptr %[[X]]
+// LLVM:   %[[Y:.*]] = getelementptr inbounds nuw %struct.Agg, ptr 
%[[A_ALLOCA]], i32 0, i32 1
+// LLVM:   store i32 2, ptr %[[Y]]
+// LLVM:   br label %[[END:.*]]
+// LLVM: [[END]]:
+// LLVM:   ret void
+
+// OGCG-LABEL: define{{.*}} void @_Z19test_agg_throw_trueb(
+// OGCG:   %[[A:.*]] = alloca %struct.Agg
+// OGCG:   %[[FLAG:.*]] = load i8, ptr %{{.*}}
+// OGCG:   %[[BOOL:.*]] = icmp ne i8 %[[FLAG]], 0
+// OGCG:   br i1 %[[BOOL]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]
+// OGCG: [[TRUE_BB]]:
+// OGCG:   %[[EXC:.*]] = call{{.*}} ptr @__cxa_allocate_exception
+// OGCG:   store i32 0, ptr %[[EXC]]
+// OGCG:   call void @__cxa_throw(ptr %[[EXC]], ptr @_ZTIi
+// OGCG:   unreachable
+// OGCG: [[FALSE_BB]]:
+// OGCG:   %[[X:.*]] = getelementptr inbounds nuw %struct.Agg, ptr %[[A]], i32 
0, i32 0
+// OGCG:   store i32 1, ptr %[[X]]
+// OGCG:   %[[Y:.*]] = getelementptr inbounds nuw %struct.Agg, ptr %[[A]], i32 
0, i32 1
+// OGCG:   store i32 2, ptr %[[Y]]
+// OGCG:   br label %[[END:.*]]
+// OGCG: [[END]]:
+// OGCG:   ret void
+
+void test_agg_throw_false(bool flag) {
+  Agg a = flag ? Agg{1, 2} : throw 0;
+}
+
+// CIR-LABEL: cir.func{{.*}} @_Z20test_agg_throw_falseb(
+// CIR:   %[[FLAG:.*]] = cir.alloca "flag"
+// CIR:   %[[A:.*]] = cir.alloca "a"
+// CIR:   %[[FLAG_VAL:.*]] = cir.load{{.*}} %[[FLAG]] : !cir.ptr<!cir.bool>, 
!cir.bool
+// CIR:   cir.if %[[FLAG_VAL]] {
+// CIR:     %[[X:.*]] = cir.get_member %[[A]][0] {name = "x"} : 
!cir.ptr<!rec_Agg> -> !cir.ptr<!s32i>
+// CIR:     %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
+// CIR:     cir.store{{.*}} %[[ONE]], %[[X]] : !s32i, !cir.ptr<!s32i>
+// CIR:     %[[Y:.*]] = cir.get_member %[[A]][1] {name = "y"} : 
!cir.ptr<!rec_Agg> -> !cir.ptr<!s32i>
+// CIR:     %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
+// CIR:     cir.store{{.*}} %[[TWO]], %[[Y]] : !s32i, !cir.ptr<!s32i>
+// CIR:   } else {
+// CIR:     %[[EXC:.*]] = cir.alloc.exception{{.*}} -> !cir.ptr<!s32i>
+// CIR:     %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
+// CIR:     cir.store{{.*}} %[[ZERO]], %[[EXC]] : !s32i, !cir.ptr<!s32i>
+// CIR:     cir.throw %[[EXC]] : !cir.ptr<!s32i>, @_ZTIi
+// CIR:     cir.unreachable
+// CIR:   }
+// CIR:   cir.return
+
+// LLVM-LABEL: define{{.*}} void @_Z20test_agg_throw_falseb(
+// LLVM:   %[[FLAG_ALLOCA:.*]] = alloca i8
+// LLVM:   %[[A_ALLOCA:.*]] = alloca %struct.Agg
+// LLVM:   %[[BOOL:.*]] = trunc i8 %{{.*}} to i1
+// LLVM:   br i1 %[[BOOL]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]
+// LLVM: [[TRUE_BB]]:
+// LLVM:   %[[X:.*]] = getelementptr inbounds nuw %struct.Agg, ptr 
%[[A_ALLOCA]], i32 0, i32 0
+// LLVM:   store i32 1, ptr %[[X]]
+// LLVM:   %[[Y:.*]] = getelementptr inbounds nuw %struct.Agg, ptr 
%[[A_ALLOCA]], i32 0, i32 1
+// LLVM:   store i32 2, ptr %[[Y]]
+// LLVM:   br label %[[END:.*]]
+// LLVM: [[FALSE_BB]]:
+// LLVM:   %[[EXC:.*]] = call{{.*}} ptr @__cxa_allocate_exception
+// LLVM:   store i32 0, ptr %[[EXC]]
+// LLVM:   call void @__cxa_throw(ptr %[[EXC]], ptr @_ZTIi
+// LLVM:   unreachable
+// LLVM: [[END]]:
+// LLVM:   ret void
+
+// OGCG-LABEL: define{{.*}} void @_Z20test_agg_throw_falseb(
+// OGCG:   %[[A:.*]] = alloca %struct.Agg
+// OGCG:   %[[FLAG:.*]] = load i8, ptr %{{.*}}
+// OGCG:   %[[BOOL:.*]] = icmp ne i8 %[[FLAG]], 0
+// OGCG:   br i1 %[[BOOL]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]
+// OGCG: [[TRUE_BB]]:
+// OGCG:   %[[X:.*]] = getelementptr inbounds nuw %struct.Agg, ptr %[[A]], i32 
0, i32 0
+// OGCG:   store i32 1, ptr %[[X]]
+// OGCG:   %[[Y:.*]] = getelementptr inbounds nuw %struct.Agg, ptr %[[A]], i32 
0, i32 1
+// OGCG:   store i32 2, ptr %[[Y]]
+// OGCG:   br label %[[END:.*]]
+// OGCG: [[FALSE_BB]]:
+// OGCG:   %[[EXC:.*]] = call{{.*}} ptr @__cxa_allocate_exception
+// OGCG:   store i32 0, ptr %[[EXC]]
+// OGCG:   call void @__cxa_throw(ptr %[[EXC]], ptr @_ZTIi
+// OGCG:   unreachable
+// OGCG: [[END]]:
+// OGCG:   ret void


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to