[clang] ab1765d - [CIR] Upstream trivial constructor const handling (#164849)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 24 10:33:29 PDT 2025
Author: Andy Kaylor
Date: 2025-10-24T10:33:25-07:00
New Revision: ab1765d76502707c8c3082039775bcaf3c25f280
URL: https://github.com/llvm/llvm-project/commit/ab1765d76502707c8c3082039775bcaf3c25f280
DIFF: https://github.com/llvm/llvm-project/commit/ab1765d76502707c8c3082039775bcaf3c25f280.diff
LOG: [CIR] Upstream trivial constructor const handling (#164849)
This adds handling for records with trivial constructors in CIR's
ConstExprEmitter.
Added:
clang/test/CIR/CodeGen/trivial-ctor-const-init.cpp
Modified:
clang/include/clang/CIR/MissingFeatures.h
clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
Removed:
################################################################################
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/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 95905cee1094e..928e5aa821bb5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1078,9 +1078,32 @@ 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);
+
+ // 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 {};
+ }
+
+ 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]])
More information about the cfe-commits
mailing list