[clang] b9329fe - [CIR] Upstream support for calling constructors (#143579)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 10 16:50:32 PDT 2025
Author: Andy Kaylor
Date: 2025-06-10T16:50:29-07:00
New Revision: b9329fe88e47741d9c20ab92f892ac52457e6195
URL: https://github.com/llvm/llvm-project/commit/b9329fe88e47741d9c20ab92f892ac52457e6195
DIFF: https://github.com/llvm/llvm-project/commit/b9329fe88e47741d9c20ab92f892ac52457e6195.diff
LOG: [CIR] Upstream support for calling constructors (#143579)
This change adds support for calling C++ constructors. The support for
actually defining a constructor is still missing and will be added in a
later change.
Added:
clang/test/CIR/CodeGen/ctor.cpp
Modified:
clang/include/clang/CIR/MissingFeatures.h
clang/lib/CIR/CodeGen/CIRGenCall.cpp
clang/lib/CIR/CodeGen/CIRGenClass.cpp
clang/lib/CIR/CodeGen/CIRGenExpr.cpp
clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
clang/lib/CIR/CodeGen/CIRGenFunction.h
clang/lib/CIR/CodeGen/CIRGenModule.cpp
clang/lib/CIR/CodeGen/CIRGenModule.h
clang/lib/CIR/CodeGen/CIRGenTypes.h
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 72d882beb2244..f89d386378e51 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -222,6 +222,9 @@ struct MissingFeatures {
static bool instrumentation() { return false; }
static bool cleanupAfterErrorDiags() { return false; }
static bool cxxRecordStaticMembers() { return false; }
+ static bool isMemcpyEquivalentSpecialMember() { return false; }
+ static bool isTrivialCtorOrDtor() { return false; }
+ static bool implicitConstructorArgs() { return false; }
// Missing types
static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index b194a8670bfb9..9d25eea9e413d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -60,6 +60,13 @@ CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
return *this;
}
+/// Returns the canonical formal type of the given C++ method.
+static CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *md) {
+ return md->getType()
+ ->getCanonicalTypeUnqualified()
+ .getAs<FunctionProtoType>();
+}
+
/// Adds the formal parameters in FPT to the given prefix. If any parameter in
/// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
/// TODO(cir): this should be shared with LLVM codegen
@@ -76,6 +83,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
}
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+ auto *md = cast<CXXMethodDecl>(gd.getDecl());
+
+ llvm::SmallVector<CanQualType, 16> argTypes;
+ argTypes.push_back(deriveThisType(md->getParent(), md));
+
+ bool passParams = true;
+
+ if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
+ // A base class inheriting constructor doesn't get forwarded arguments
+ // needed to construct a virtual base (or base class thereof)
+ if (cd->getInheritedConstructor())
+ cgm.errorNYI(cd->getSourceRange(),
+ "arrangeCXXStructorDeclaration: inheriting constructor");
+ }
+
+ CanQual<FunctionProtoType> fpt = getFormalType(md);
+
+ if (passParams)
+ appendParameterTypes(*this, argTypes, fpt);
+
+ assert(!cir::MissingFeatures::implicitConstructorArgs());
+
+ RequiredArgs required =
+ (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
+ : RequiredArgs::All);
+
+ CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
+ : theCXXABI.hasMostDerivedReturn(gd)
+ ? astContext.VoidPtrTy
+ : astContext.VoidTy;
+
+ assert(!theCXXABI.hasThisReturn(gd) &&
+ "Please send PR with a test and remove this");
+
+ assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+ assert(!cir::MissingFeatures::opCallFnInfoOpts());
+
+ return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
/// indicates that there is no meaningful 'this' type, and a null `md` can occur
@@ -103,13 +152,13 @@ CanQualType CIRGenTypes::deriveThisType(const CXXRecordDecl *rd,
/// top of any implicit parameters already stored.
static const CIRGenFunctionInfo &
arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl<CanQualType> &prefix,
- CanQual<FunctionProtoType> ftp) {
+ CanQual<FunctionProtoType> fpt) {
assert(!cir::MissingFeatures::opCallFnInfoOpts());
RequiredArgs required =
- RequiredArgs::getFromProtoWithExtraSlots(ftp, prefix.size());
+ RequiredArgs::getFromProtoWithExtraSlots(fpt, prefix.size());
assert(!cir::MissingFeatures::opCallExtParameterInfo());
- appendParameterTypes(cgt, prefix, ftp);
- CanQualType resultType = ftp->getReturnType().getUnqualifiedType();
+ appendParameterTypes(cgt, prefix, fpt);
+ CanQualType resultType = fpt->getReturnType().getUnqualifiedType();
return cgt.arrangeCIRFunctionInfo(resultType, prefix, required);
}
@@ -141,6 +190,44 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule &cgm,
return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
}
+/// Arrange a call to a C++ method, passing the given arguments.
+///
+/// passProtoArgs indicates whether `args` has args for the parameters in the
+/// given CXXConstructorDecl.
+const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(
+ const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
+ bool passProtoArgs) {
+
+ // FIXME: Kill copy.
+ llvm::SmallVector<CanQualType, 16> argTypes;
+ for (const auto &arg : args)
+ argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
+
+ assert(!cir::MissingFeatures::implicitConstructorArgs());
+ // +1 for implicit this, which should always be args[0]
+ unsigned totalPrefixArgs = 1;
+
+ CanQual<FunctionProtoType> fpt = getFormalType(d);
+ RequiredArgs required =
+ passProtoArgs
+ ? RequiredArgs::getFromProtoWithExtraSlots(fpt, totalPrefixArgs)
+ : RequiredArgs::All;
+
+ GlobalDecl gd(d, ctorKind);
+ if (theCXXABI.hasThisReturn(gd))
+ cgm.errorNYI(d->getSourceRange(),
+ "arrangeCXXConstructorCall: hasThisReturn");
+ if (theCXXABI.hasMostDerivedReturn(gd))
+ cgm.errorNYI(d->getSourceRange(),
+ "arrangeCXXConstructorCall: hasMostDerivedReturn");
+ CanQualType resultType = astContext.VoidTy;
+
+ assert(!cir::MissingFeatures::opCallFnInfoOpts());
+ assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+
+ return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
/// Arrange a call to a C++ method, passing the given arguments.
///
/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. It
@@ -198,7 +285,7 @@ CIRGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *md) {
/// constructor or destructor.
const CIRGenFunctionInfo &
CIRGenTypes::arrangeCXXMethodType(const CXXRecordDecl *rd,
- const FunctionProtoType *ftp,
+ const FunctionProtoType *fpt,
const CXXMethodDecl *md) {
llvm::SmallVector<CanQualType, 16> argTypes;
@@ -208,7 +295,7 @@ CIRGenTypes::arrangeCXXMethodType(const CXXRecordDecl *rd,
assert(!cir::MissingFeatures::opCallFnInfoOpts());
return ::arrangeCIRFunctionInfo(
*this, argTypes,
- ftp->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
+ fpt->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
}
/// Arrange the argument and result information for the declaration or
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 4cdaa480121dd..8491a66ea6cb4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -10,9 +10,12 @@
//
//===----------------------------------------------------------------------===//
+#include "CIRGenCXXABI.h"
#include "CIRGenFunction.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
#include "clang/CIR/MissingFeatures.h"
using namespace clang;
@@ -63,3 +66,74 @@ Address CIRGenFunction::getAddressOfBaseClass(
return value;
}
+
+void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
+ clang::CXXCtorType type,
+ bool forVirtualBase,
+ bool delegating,
+ AggValueSlot thisAVS,
+ const clang::CXXConstructExpr *e) {
+ CallArgList args;
+ Address thisAddr = thisAVS.getAddress();
+ QualType thisType = d->getThisType();
+ mlir::Value thisPtr = thisAddr.getPointer();
+
+ assert(!cir::MissingFeatures::addressSpace());
+
+ args.add(RValue::get(thisPtr), thisType);
+
+ // In LLVM Codegen: If this is a trivial constructor, just emit what's needed.
+ // If this is a union copy constructor, we must emit a memcpy, because the AST
+ // does not model that copy.
+ assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+ const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
+
+ assert(!cir::MissingFeatures::opCallArgEvaluationOrder());
+
+ emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
+ /*ParamsToSkip=*/0);
+
+ assert(!cir::MissingFeatures::sanitizers());
+ emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
+ e->getExprLoc());
+}
+
+void CIRGenFunction::emitCXXConstructorCall(
+ const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
+ bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
+
+ const CXXRecordDecl *crd = d->getParent();
+
+ // If this is a call to a trivial default constructor:
+ // In LLVM: do nothing.
+ // In CIR: emit as a regular call, other later passes should lower the
+ // ctor call into trivial initialization.
+ assert(!cir::MissingFeatures::isTrivialCtorOrDtor());
+
+ assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+ bool passPrototypeArgs = true;
+
+ // Check whether we can actually emit the constructor before trying to do so.
+ if (d->getInheritedConstructor()) {
+ cgm.errorNYI(d->getSourceRange(),
+ "emitCXXConstructorCall: inherited constructor");
+ return;
+ }
+
+ // Insert any ABI-specific implicit constructor arguments.
+ assert(!cir::MissingFeatures::implicitConstructorArgs());
+
+ // Emit the call.
+ auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
+ const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
+ args, d, type, passPrototypeArgs);
+ CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
+ cir::CIRCallOpInterface c;
+ emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));
+
+ if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
+ type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
+ cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 8129fe0ad7db7..f2c2de7a4f59d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1393,6 +1393,57 @@ RValue CIRGenFunction::emitCXXMemberCallExpr(const CXXMemberCallExpr *ce,
ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
}
+void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e,
+ AggValueSlot dest) {
+ assert(!dest.isIgnored() && "Must have a destination!");
+ const CXXConstructorDecl *cd = e->getConstructor();
+
+ // If we require zero initialization before (or instead of) calling the
+ // constructor, as can be the case with a non-user-provided default
+ // constructor, emit the zero initialization now, unless destination is
+ // already zeroed.
+ if (e->requiresZeroInitialization() && !dest.isZeroed()) {
+ cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: requires initialization");
+ return;
+ }
+
+ // If this is a call to a trivial default constructor:
+ // In LLVM: do nothing.
+ // In CIR: emit as a regular call, other later passes should lower the
+ // ctor call into trivial initialization.
+
+ // Elide the constructor if we're constructing from a temporary
+ if (getLangOpts().ElideConstructors && e->isElidable()) {
+ cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: elidable constructor");
+ return;
+ }
+
+ if (getContext().getAsArrayType(e->getType())) {
+ cgm.errorNYI(e->getSourceRange(), "emitCXXConstructExpr: array type");
+ return;
+ }
+
+ clang::CXXCtorType type = Ctor_Complete;
+ bool forVirtualBase = false;
+ bool delegating = false;
+
+ switch (e->getConstructionKind()) {
+ case CXXConstructionKind::Complete:
+ type = Ctor_Complete;
+ break;
+ case CXXConstructionKind::Delegating:
+ case CXXConstructionKind::VirtualBase:
+ case CXXConstructionKind::NonVirtualBase:
+ cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: other construction kind");
+ return;
+ }
+
+ emitCXXConstructorCall(cd, type, forVirtualBase, delegating, dest, e);
+}
+
RValue CIRGenFunction::emitReferenceBindingToExpr(const Expr *e) {
// Emit the expression as an lvalue.
LValue lv = emitLValue(e);
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 56d7ea3884ba7..f1df1b79fc48e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -51,6 +51,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
void VisitInitListExpr(InitListExpr *e);
+ void VisitCXXConstructExpr(const CXXConstructExpr *e);
void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
FieldDecl *initializedFieldInUnion,
@@ -213,6 +214,11 @@ void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
}
}
+void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *e) {
+ AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
+ cgf.emitCXXConstructExpr(e, slot);
+}
+
void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
LValue lv) {
const QualType type = lv.getType();
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index d6002c3e4d4d9..7db7f6928fd8f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -744,6 +744,19 @@ class CIRGenFunction : public CIRGenTypeCache {
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
+ void emitCXXConstructExpr(const clang::CXXConstructExpr *e,
+ AggValueSlot dest);
+
+ void emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
+ clang::CXXCtorType type, bool forVirtualBase,
+ bool delegating, AggValueSlot thisAVS,
+ const clang::CXXConstructExpr *e);
+
+ void emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
+ clang::CXXCtorType type, bool forVirtualBase,
+ bool delegating, Address thisAddr,
+ CallArgList &args, clang::SourceLocation loc);
+
mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
llvm::ArrayRef<const Attr *> attrs);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 3d46c44b4f1ec..8407f8fad06ba 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -103,6 +103,25 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
CIRGenModule::~CIRGenModule() = default;
+/// FIXME: this could likely be a common helper and not necessarily related
+/// with codegen.
+/// Return the best known alignment for an unknown pointer to a
+/// particular class.
+CharUnits CIRGenModule::getClassPointerAlignment(const CXXRecordDecl *rd) {
+ if (!rd->hasDefinition())
+ return CharUnits::One(); // Hopefully won't be used anywhere.
+
+ auto &layout = astContext.getASTRecordLayout(rd);
+
+ // If the class is final, then we know that the pointer points to an
+ // object of that type and can use the full alignment.
+ if (rd->isEffectivelyFinal())
+ return layout.getAlignment();
+
+ // Otherwise, we have to assume it could be a subclass.
+ return layout.getNonVirtualAlignment();
+}
+
CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
LValueBaseInfo *baseInfo) {
assert(!cir::MissingFeatures::opTBAA());
@@ -1174,6 +1193,34 @@ void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
assert(!cir::MissingFeatures::opGlobalVisibility());
}
+std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
+ GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
+ bool dontDefer, ForDefinition_t isForDefinition) {
+ auto *md = cast<CXXMethodDecl>(gd.getDecl());
+
+ if (isa<CXXDestructorDecl>(md)) {
+ // Always alias equivalent complete destructors to base destructors in the
+ // MS ABI.
+ if (getTarget().getCXXABI().isMicrosoft() &&
+ gd.getDtorType() == Dtor_Complete &&
+ md->getParent()->getNumVBases() == 0)
+ errorNYI(md->getSourceRange(),
+ "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
+ }
+
+ if (!fnType) {
+ if (!fnInfo)
+ fnInfo = &getTypes().arrangeCXXStructorDeclaration(gd);
+ fnType = getTypes().getFunctionType(*fnInfo);
+ }
+
+ auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
+ /*ForVtable=*/false, dontDefer,
+ /*IsThunk=*/false, isForDefinition);
+
+ return {fnType, fn};
+}
+
cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
mlir::Type funcType, bool forVTable,
bool dontDefer,
@@ -1248,8 +1295,11 @@ StringRef CIRGenModule::getMangledName(GlobalDecl gd) {
// Some ABIs don't have constructor variants. Make sure that base and complete
// constructors get mangled the same.
if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
- errorNYI(cd->getSourceRange(), "getMangledName: C++ constructor");
- return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
+ if (!getTarget().getCXXABI().hasConstructorVariants()) {
+ errorNYI(cd->getSourceRange(),
+ "getMangledName: C++ constructor without variants");
+ return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
+ }
}
// Keep the first result in the case of a mangling collision.
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 24ec9ca6403bc..9748c0b3ed43a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -166,11 +166,30 @@ class CIRGenModule : public CIRGenTypeCache {
mlir::Location getLoc(clang::SourceLocation cLoc);
mlir::Location getLoc(clang::SourceRange cRange);
+ /// Return the best known alignment for an unknown pointer to a
+ /// particular class.
+ clang::CharUnits getClassPointerAlignment(const clang::CXXRecordDecl *rd);
+
/// FIXME: this could likely be a common helper and not necessarily related
/// with codegen.
clang::CharUnits getNaturalTypeAlignment(clang::QualType t,
LValueBaseInfo *baseInfo);
+ cir::FuncOp
+ getAddrOfCXXStructor(clang::GlobalDecl gd,
+ const CIRGenFunctionInfo *fnInfo = nullptr,
+ cir::FuncType fnType = nullptr, bool dontDefer = false,
+ ForDefinition_t isForDefinition = NotForDefinition) {
+ return getAddrAndTypeOfCXXStructor(gd, fnInfo, fnType, dontDefer,
+ isForDefinition)
+ .second;
+ }
+
+ std::pair<cir::FuncType, cir::FuncOp> getAddrAndTypeOfCXXStructor(
+ clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo = nullptr,
+ cir::FuncType fnType = nullptr, bool dontDefer = false,
+ ForDefinition_t isForDefinition = NotForDefinition);
+
/// This contains all the decls which have definitions but which are deferred
/// for emission and therefore should only be output if they are actually
/// used. If a decl is in this, then it is known to have not been referenced
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index 48d474beeddec..c2813d79bf63b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -19,6 +19,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/ABI.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -165,6 +166,10 @@ class CIRGenTypes {
bool isZeroInitializable(clang::QualType ty);
bool isZeroInitializable(const RecordDecl *rd);
+ const CIRGenFunctionInfo &arrangeCXXConstructorCall(
+ const CallArgList &args, const clang::CXXConstructorDecl *d,
+ clang::CXXCtorType ctorKind, bool passProtoArgs = true);
+
const CIRGenFunctionInfo &
arrangeCXXMethodCall(const CallArgList &args,
const clang::FunctionProtoType *type,
@@ -173,6 +178,7 @@ class CIRGenTypes {
/// C++ methods have some special rules and also have implicit parameters.
const CIRGenFunctionInfo &
arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md);
+ const CIRGenFunctionInfo &arrangeCXXStructorDeclaration(clang::GlobalDecl gd);
const CIRGenFunctionInfo &
arrangeCXXMethodType(const clang::CXXRecordDecl *rd,
diff --git a/clang/test/CIR/CodeGen/ctor.cpp b/clang/test/CIR/CodeGen/ctor.cpp
new file mode 100644
index 0000000000000..3a1e82e338c1c
--- /dev/null
+++ b/clang/test/CIR/CodeGen/ctor.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+struct Struk {
+ int a;
+ Struk();
+};
+
+void baz() {
+ Struk s;
+}
+
+// CHECK: !rec_Struk = !cir.record<struct "Struk" {!s32i}>
+
+// CHECK: cir.func @_ZN5StrukC1Ev(!cir.ptr<!rec_Struk>)
+// CHECK: cir.func @_Z3bazv()
+// CHECK-NEXT: %[[S_ADDR:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["s", init] {alignment = 4 : i64}
+// CHECK-NEXT: cir.call @_ZN5StrukC1Ev(%[[S_ADDR]]) : (!cir.ptr<!rec_Struk>) -> ()
+// CHECK-NEXT: cir.return
More information about the cfe-commits
mailing list