https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/164849

>From 7c2568a42968e315867fceb8e5a928fc9ee157a4 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Wed, 22 Oct 2025 09:21:27 -0700
Subject: [PATCH 1/2] [CIR] Upstream trivial constructor const handling

This adds handling for records with trivial constructors in CIR's
ConstExprEmitter.
---
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp |  3 +-
 clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp  | 24 ++++++++--
 .../CIR/CodeGen/trivial-ctor-const-init.cpp   | 44 +++++++++++++++++++
 3 files changed, 66 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/trivial-ctor-const-init.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index d6d226b3f75db..8fe0d9b4a69ef 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -362,8 +362,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
     cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: 
VisitCXXTypeidExpr");
   }
   void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e) {
-    cgf.cgm.errorNYI(e->getSourceRange(),
-                     "AggExprEmitter: VisitMaterializeTemporaryExpr");
+    Visit(e->getSubExpr());
   }
   void VisitOpaqueValueExpr(OpaqueValueExpr *e) {
     cgf.cgm.errorNYI(e->getSourceRange(),
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 800262aac8fa4..c1f4fe5973d17 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1069,9 +1069,27 @@ class ConstExprEmitter
 
   mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
     if (!e->getConstructor()->isTrivial())
-      return nullptr;
-    cgm.errorNYI(e->getBeginLoc(), "trivial constructor const handling");
-    return {};
+      return {};
+
+    // Only default and copy/move constructors can be trivial.
+    if (e->getNumArgs()) {
+      assert(e->getNumArgs() == 1 && "trivial ctor with > 1 argument");
+      assert(e->getConstructor()->isCopyOrMoveConstructor() &&
+             "trivial ctor has argument but isn't a copy/move ctor");
+
+      Expr *arg = e->getArg(0);
+      assert(cgm.getASTContext().hasSameUnqualifiedType(ty, arg->getType()) &&
+             "argument to copy ctor is of wrong type");
+
+      // Look through the temporary; it's just converting the value to an 
lvalue
+      // to pass it to the constructor.
+      if (auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
+        return Visit(mte->getSubExpr(), ty);
+      // Don't try to support arbitrary lvalue-to-rvalue conversions for now.
+      return {};
+    }
+
+    return cgm.getBuilder().getZeroInitAttr(cgm.convertType(ty));
   }
 
   mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
diff --git a/clang/test/CIR/CodeGen/trivial-ctor-const-init.cpp 
b/clang/test/CIR/CodeGen/trivial-ctor-const-init.cpp
new file mode 100644
index 0000000000000..7429549100362
--- /dev/null
+++ b/clang/test/CIR/CodeGen/trivial-ctor-const-init.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++11 -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++11 -fclangir 
-emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++11 -emit-llvm %s 
-o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+struct StructWithDefaultCtor {
+  int n;
+};
+
+StructWithDefaultCtor defCtor = StructWithDefaultCtor();
+
+// CIR: cir.global {{.*}} @defCtor = #cir.zero : !rec_StructWithDefaultCtor
+// LLVM: @defCtor = global %struct.StructWithDefaultCtor zeroinitializer
+// OGCG: @defCtor = global %struct.StructWithDefaultCtor zeroinitializer
+
+struct StructWithCtorArg {
+  double value;
+  StructWithCtorArg(const double& x) : value(x) {}
+};
+
+StructWithCtorArg withArg = 0.0;
+
+// CIR: cir.global {{.*}} @withArg = #cir.zero : !rec_StructWithCtorArg
+// LLVM: @withArg = global %struct.StructWithCtorArg zeroinitializer
+// OGCG: @withArg = global %struct.StructWithCtorArg zeroinitializer
+
+// CIR: cir.func {{.*}} @__cxx_global_var_init()
+// CIR:   %[[TMP0:.*]] = cir.alloca !cir.double, !cir.ptr<!cir.double>, 
["ref.tmp0"]
+// CIR:   %[[WITH_ARG:.*]] = cir.get_global @withArg : 
!cir.ptr<!rec_StructWithCtorArg>
+// CIR:   %[[ZERO:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double
+// CIR:   cir.store{{.*}} %[[ZERO]], %[[TMP0]] : !cir.double, 
!cir.ptr<!cir.double>
+// CIR:   cir.call @_ZN17StructWithCtorArgC1ERKd(%[[WITH_ARG]], %[[TMP0]]) : 
(!cir.ptr<!rec_StructWithCtorArg>, !cir.ptr<!cir.double>) -> ()
+
+// LLVM: define {{.*}} void @__cxx_global_var_init()
+// LLVM:   %[[TMP0:.*]] = alloca double
+// LLVM:   store double 0.000000e+00, ptr %[[TMP0]]
+// LLVM:   call void @_ZN17StructWithCtorArgC1ERKd(ptr @withArg, ptr %[[TMP0]])
+
+// OGCG: define {{.*}} void @__cxx_global_var_init()
+// OGCG:   %[[TMP0:.*]] = alloca double
+// OGCG:   store double 0.000000e+00, ptr %[[TMP0]]
+// OGCG:   call void @_ZN17StructWithCtorArgC1ERKd(ptr {{.*}} @withArg, ptr 
{{.*}} %[[TMP0]])

>From 20b47cdc088a4f116729b5dfa8eff2d5eabdcdfb Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Fri, 24 Oct 2025 09:41:57 -0700
Subject: [PATCH 2/2] Add marker for future investigation

---
 clang/include/clang/CIR/MissingFeatures.h    | 1 +
 clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 598e826a473a6..d5bc5ce8d8997 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -231,6 +231,7 @@ struct MissingFeatures {
   static bool coverageMapping() { return false; }
   static bool createInvariantGroup() { return false; }
   static bool createProfileWeightsForLoop() { return false; }
+  static bool ctorConstLvalueToRvalueConversion() { return false; }
   static bool ctorMemcpyizer() { return false; }
   static bool cudaSupport() { return false; }
   static bool cxxRecordStaticMembers() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index c1f4fe5973d17..8fc36aea93a3d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1085,6 +1085,11 @@ class ConstExprEmitter
       // to pass it to the constructor.
       if (auto const *mte = dyn_cast<MaterializeTemporaryExpr>(arg))
         return Visit(mte->getSubExpr(), ty);
+
+      // TODO: Investigate whether there are cases that can fall through to 
here
+      //       that need to be handled. This is missing in classic codegen 
also.
+      assert(!cir::MissingFeatures::ctorConstLvalueToRvalueConversion());
+
       // Don't try to support arbitrary lvalue-to-rvalue conversions for now.
       return {};
     }

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

Reply via email to