[clang] [CIR] Make ClangIR compatible with latest nested name specifier AST representation (PR #152846)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 9 10:43:55 PDT 2025
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/152846
>From 946f3718f7e67966f07c962e7283d7fd11d0b329 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sat, 9 Aug 2025 11:48:23 +0200
Subject: [PATCH 1/4] [CIR] Make ClangIR compatible after AST representation
modifications
---
clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp | 4 +--
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 11 ++++---
clang/lib/CIR/CodeGen/CIRGenClass.cpp | 10 +++----
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 7 +++--
clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 2 +-
clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 2 +-
clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 9 ++----
clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 +-
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 4 +--
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 30 +++++++++++--------
clang/lib/CIR/CodeGen/TargetInfo.cpp | 10 +++----
11 files changed, 48 insertions(+), 43 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
index 67d8988a5fbbd..bc30c7bd130af 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
@@ -75,7 +75,7 @@ static MemberCallInfo commonBuildCXXMemberOrOperatorCall(
RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
const CallExpr *ce, const CXXMethodDecl *md, ReturnValueSlot returnValue,
- bool hasQualifier, NestedNameSpecifier *qualifier, bool isArrow,
+ bool hasQualifier, NestedNameSpecifier qualifier, bool isArrow,
const Expr *base) {
assert(isa<CXXMemberCallExpr>(ce) || isa<CXXOperatorCallExpr>(ce));
@@ -169,7 +169,7 @@ CIRGenFunction::emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e,
assert(md->isInstance() &&
"Trying to emit a member call expr on a static method!");
return emitCXXMemberOrOperatorMemberCallExpr(
- e, md, returnValue, /*HasQualifier=*/false, /*Qualifier=*/nullptr,
+ e, md, returnValue, /*HasQualifier=*/false, /*Qualifier=*/std::nullopt,
/*IsArrow=*/false, e->getArg(0));
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index fc208fffe216f..8fac6fd6c6aca 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -205,7 +205,7 @@ CanQualType CIRGenTypes::deriveThisType(const CXXRecordDecl *rd,
const CXXMethodDecl *md) {
QualType recTy;
if (rd) {
- recTy = getASTContext().getTagDeclType(rd)->getCanonicalTypeInternal();
+ recTy = getASTContext().getCanonicalTagType(rd);
} else {
// This can happen with the MS ABI. It shouldn't need anything more than
// setting recTy to VoidTy here, but we're flagging it for now because we
@@ -267,7 +267,9 @@ void CIRGenFunction::emitDelegateCallArg(CallArgList &args,
// Deactivate the cleanup for the callee-destructed param that was pushed.
assert(!cir::MissingFeatures::thunks());
if (type->isRecordType() &&
- type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee() &&
+ type->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->isParamDestroyedInCallee() &&
param->needsDestruction(getContext())) {
cgm.errorNYI(param->getSourceRange(),
"emitDelegateCallArg: callee-destructed param");
@@ -667,8 +669,9 @@ void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
// In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
// However, we still have to push an EH-only cleanup in case we unwind before
// we make it to the call.
- if (argType->isRecordType() &&
- argType->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
+ if (argType->isRecordType() && argType->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->isParamDestroyedInCallee()) {
assert(!cir::MissingFeatures::msabi());
cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 72b9d177e4c63..27e798f2280b3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -86,7 +86,7 @@ static void emitMemberInitializer(CIRGenFunction &cgf,
QualType fieldType = field->getType();
mlir::Value thisPtr = cgf.loadCXXThis();
- QualType recordTy = cgf.getContext().getTypeDeclType(classDecl);
+ QualType recordTy = cgf.getContext().getCanonicalTypeDeclType(classDecl);
// If a base constructor is being emitted, create an LValue that has the
// non-virtual alignment.
@@ -121,7 +121,7 @@ static void emitMemberInitializer(CIRGenFunction &cgf,
static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit) {
const Type *baseType = baseInit->getBaseClass();
const auto *baseClassDecl =
- cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getOriginalDecl());
return baseClassDecl->isDynamicClass();
}
@@ -161,7 +161,7 @@ void CIRGenFunction::emitBaseInitializer(mlir::Location loc,
const Type *baseType = baseInit->getBaseClass();
const auto *baseClassDecl =
- cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getOriginalDecl());
bool isBaseVirtual = baseInit->isBaseVirtual();
@@ -377,7 +377,7 @@ void CIRGenFunction::emitCXXAggrConstructorCall(
//
// Note that these are complete objects and so we don't need to
// use the non-virtual size or alignment.
- QualType type = getContext().getTypeDeclType(ctor->getParent());
+ QualType type = getContext().getCanonicalTypeDeclType(ctor->getParent());
CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
getContext().getTypeSizeInChars(type));
@@ -484,7 +484,7 @@ void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {
void CIRGenFunction::destroyCXXObject(CIRGenFunction &cgf, Address addr,
QualType type) {
const RecordType *rtype = type->castAs<RecordType>();
- const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getDecl());
+ const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getOriginalDecl());
const CXXDestructorDecl *dtor = record->getDestructor();
// TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
// dtors which shall be removed on later CIR passes. However, only remove this
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index a0ff08ea3de3a..6114f4ff75d01 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1013,7 +1013,8 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
case CK_DerivedToBase: {
const auto *derivedClassTy =
e->getSubExpr()->getType()->castAs<clang::RecordType>();
- auto *derivedClassDecl = cast<CXXRecordDecl>(derivedClassTy->getDecl());
+ auto *derivedClassDecl =
+ cast<CXXRecordDecl>(derivedClassTy->getOriginalDecl());
LValue lv = emitLValue(e->getSubExpr());
Address thisAddr = lv.getAddress();
@@ -1167,7 +1168,7 @@ static void pushTemporaryCleanup(CIRGenFunction &cgf,
->getBaseElementTypeUnsafe()
->getAs<clang::RecordType>()) {
// Get the destructor for the reference temporary.
- auto *classDecl = cast<CXXRecordDecl>(rt->getDecl());
+ auto *classDecl = cast<CXXRecordDecl>(rt->getOriginalDecl());
if (!classDecl->hasTrivialDestructor())
referenceTemporaryDtor = classDecl->getDestructor();
}
@@ -1831,7 +1832,7 @@ RValue CIRGenFunction::emitCXXMemberCallExpr(const CXXMemberCallExpr *ce,
}
bool hasQualifier = me->hasQualifier();
- NestedNameSpecifier *qualifier = hasQualifier ? me->getQualifier() : nullptr;
+ NestedNameSpecifier qualifier = me->getQualifier();
bool isArrow = me->isArrow();
const Expr *base = me->getBase();
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 51aab95e02e66..e2c4e13ab6773 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -376,7 +376,7 @@ void AggExprEmitter::visitCXXParenListOrInitListExpr(
// the disadvantage is that the generated code is more difficult for
// the optimizer, especially with bitfields.
unsigned numInitElements = args.size();
- RecordDecl *record = e->getType()->castAs<RecordType>()->getDecl();
+ RecordDecl *record = e->getType()->castAs<RecordType>()->getOriginalDecl();
// We'll need to enter cleanup scopes in case any of the element
// initializers throws an exception.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 5b3bf85cefbb0..3d46af91773ea 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -591,7 +591,7 @@ mlir::Attribute ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &d) {
// be a problem for the near future.
if (cd->isTrivial() && cd->isDefaultConstructor()) {
const auto *cxxrd =
- cast<CXXRecordDecl>(ty->getAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(ty->getAs<RecordType>()->getOriginalDecl());
if (cxxrd->getNumBases() != 0) {
// There may not be anything additional to do here, but this will
// force us to pause and test this path when it is supported.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index dedd01ce5e685..a4d4d210cf876 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -356,7 +356,8 @@ static bool mayDropFunctionReturn(const ASTContext &astContext,
// destructor or a non-trivially copyable type.
if (const RecordType *recordType =
returnType.getCanonicalType()->getAs<RecordType>()) {
- if (const auto *classDecl = dyn_cast<CXXRecordDecl>(recordType->getDecl()))
+ if (const auto *classDecl =
+ dyn_cast<CXXRecordDecl>(recordType->getOriginalDecl()))
return classDecl->hasTrivialDestructor();
}
return returnType.isTriviallyCopyableType(astContext);
@@ -827,7 +828,7 @@ void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
// Ignore empty classes in C++.
if (getLangOpts().CPlusPlus) {
if (const RecordType *rt = ty->getAs<RecordType>()) {
- if (cast<CXXRecordDecl>(rt->getDecl())->isEmpty())
+ if (cast<CXXRecordDecl>(rt->getOriginalDecl())->isEmpty())
return;
}
}
@@ -978,10 +979,6 @@ void CIRGenFunction::emitVariablyModifiedType(QualType type) {
case Type::BitInt:
llvm_unreachable("type class is never variably-modified!");
- case Type::Elaborated:
- type = cast<clang::ElaboratedType>(ty)->getNamedType();
- break;
-
case Type::Adjusted:
type = cast<clang::AdjustedType>(ty)->getAdjustedType();
break;
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index bdbc77c0a7c4a..68447082a5a1f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1011,7 +1011,7 @@ class CIRGenFunction : public CIRGenTypeCache {
RValue emitCXXMemberOrOperatorMemberCallExpr(
const clang::CallExpr *ce, const clang::CXXMethodDecl *md,
ReturnValueSlot returnValue, bool hasQualifier,
- clang::NestedNameSpecifier *qualifier, bool isArrow,
+ clang::NestedNameSpecifier qualifier, bool isArrow,
const clang::Expr *base);
mlir::Value emitCXXNewExpr(const CXXNewExpr *e);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index ff6d293aae229..d6b0278ab0b6f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -997,7 +997,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &astContext,
return true;
if (const auto *rt = varType->getAs<RecordType>()) {
- const RecordDecl *rd = rt->getDecl();
+ const RecordDecl *rd = rt->getOriginalDecl();
for (const FieldDecl *fd : rd->fields()) {
if (fd->isBitField())
continue;
@@ -2067,7 +2067,7 @@ CharUnits CIRGenModule::computeNonVirtualBaseClassOffset(
const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
const auto *baseDecl = cast<CXXRecordDecl>(
- base->getType()->castAs<clang::RecordType>()->getDecl());
+ base->getType()->castAs<clang::RecordType>()->getOriginalDecl());
// Add the offset.
offset += layout.getBaseClassOffset(baseDecl);
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 3e07f6d3e54cc..34c74da351262 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -103,7 +103,8 @@ std::string CIRGenTypes::getRecordTypeName(const clang::RecordDecl *recordDecl,
policy.SuppressTagKeyword = true;
if (recordDecl->getIdentifier())
- astContext.getRecordType(recordDecl).print(outStream, policy);
+ QualType(astContext.getCanonicalTagType(recordDecl))
+ .print(outStream, policy);
else if (auto *typedefNameDecl = recordDecl->getTypedefNameForAnonDecl())
typedefNameDecl->printQualifiedName(outStream, policy);
else
@@ -138,7 +139,7 @@ isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt,
if (!alreadyChecked.insert(rd).second)
return true;
- const Type *key = cgt.getASTContext().getTagDeclType(rd).getTypePtr();
+ const Type *key = cgt.getASTContext().getCanonicalTagType(rd).getTypePtr();
// If this type is already laid out, converting it is a noop.
if (cgt.isRecordLayoutComplete(key))
@@ -182,7 +183,7 @@ isSafeToConvert(QualType qt, CIRGenTypes &cgt,
// If this is a record, check it.
if (const auto *rt = qt->getAs<RecordType>())
- return isSafeToConvert(rt->getDecl(), cgt, alreadyChecked);
+ return isSafeToConvert(rt->getOriginalDecl(), cgt, alreadyChecked);
// If this is an array, check the elements, which are embedded inline.
if (const auto *at = cgt.getASTContext().getAsArrayType(qt))
@@ -210,7 +211,7 @@ static bool isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt) {
mlir::Type CIRGenTypes::convertRecordDeclType(const clang::RecordDecl *rd) {
// TagDecl's are not necessarily unique, instead use the (clang) type
// connected to the decl.
- const Type *key = astContext.getTagDeclType(rd).getTypePtr();
+ const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
cir::RecordType entry = recordDeclTypes[key];
// If we don't have an entry for this record yet, create one.
@@ -242,7 +243,8 @@ mlir::Type CIRGenTypes::convertRecordDeclType(const clang::RecordDecl *rd) {
for (const auto &base : cxxRecordDecl->bases()) {
if (base.isVirtual())
continue;
- convertRecordDeclType(base.getType()->castAs<RecordType>()->getDecl());
+ convertRecordDeclType(
+ base.getType()->castAs<RecordType>()->getOriginalDecl());
}
}
@@ -275,7 +277,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
// Process record types before the type cache lookup.
if (const auto *recordType = dyn_cast<RecordType>(type))
- return convertRecordDeclType(recordType->getDecl());
+ return convertRecordDeclType(recordType->getOriginalDecl());
// Has the type already been processed?
TypeCacheTy::iterator tci = typeCache.find(ty);
@@ -457,7 +459,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
}
case Type::Enum: {
- const EnumDecl *ed = cast<EnumType>(ty)->getDecl();
+ const EnumDecl *ed = cast<EnumType>(ty)->getOriginalDecl();
if (auto integerType = ed->getIntegerType(); !integerType.isNull())
return convertType(integerType);
// Return a placeholder 'i32' type. This can be changed later when the
@@ -516,7 +518,7 @@ mlir::Type CIRGenTypes::convertTypeForMem(clang::QualType qualType,
/// Return record layout info for the given record decl.
const CIRGenRecordLayout &
CIRGenTypes::getCIRGenRecordLayout(const RecordDecl *rd) {
- const auto *key = astContext.getTagDeclType(rd).getTypePtr();
+ const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
// If we have already computed the layout, return it.
auto it = cirGenRecordLayouts.find(key);
@@ -548,7 +550,7 @@ bool CIRGenTypes::isZeroInitializable(clang::QualType t) {
}
if (const RecordType *rt = t->getAs<RecordType>()) {
- const RecordDecl *rd = rt->getDecl();
+ const RecordDecl *rd = rt->getOriginalDecl();
return isZeroInitializable(rd);
}
@@ -622,9 +624,11 @@ void CIRGenTypes::updateCompletedType(const TagDecl *td) {
// a test case that meets that condition. C++ doesn't allow forward
// declaration of enums, and C doesn't allow an incomplete forward
// declaration with a non-default type.
- assert(
- !typeCache.count(ed->getTypeForDecl()) ||
- (convertType(ed->getIntegerType()) == typeCache[ed->getTypeForDecl()]));
+
+ CanQualType t = astContext.getCanonicalTagType(td);
+ assert(!typeCache.count(t->getTypePtr()) ||
+ (convertType(ed->getIntegerType()) == typeCache[t->getTypePtr()]));
+
// If necessary, provide the full definition of a type only used with a
// declaration so far.
assert(!cir::MissingFeatures::generateDebugInfo());
@@ -639,7 +643,7 @@ void CIRGenTypes::updateCompletedType(const TagDecl *td) {
// Only complete if we converted it already. If we haven't converted it yet,
// we'll just do it lazily.
- if (recordDeclTypes.count(astContext.getTagDeclType(rd).getTypePtr()))
+ if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
convertRecordDeclType(rd);
// If necessary, provide the full definition of a type only used with a
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index d2d32bbd9403c..dd20183b69b91 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -10,20 +10,20 @@ bool clang::CIRGen::isEmptyRecordForLayout(const ASTContext &context,
if (!rt)
return false;
- const RecordDecl *rd = rt->getDecl();
+ const RecordDecl *rd = rt->getOriginalDecl();
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
if (cxxrd->isDynamicClass())
return false;
- for (const auto &I : cxxrd->bases())
- if (!isEmptyRecordForLayout(context, I.getType()))
+ for (const auto &i : cxxrd->bases())
+ if (!isEmptyRecordForLayout(context, i.getType()))
return false;
}
- for (const auto *I : rd->fields())
- if (!isEmptyFieldForLayout(context, I))
+ for (const auto *i : rd->fields())
+ if (!isEmptyFieldForLayout(context, i))
return false;
return true;
>From 295489fb71ebdf109da1d089e1bf50dd3bc7be7e Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sat, 9 Aug 2025 19:28:40 +0200
Subject: [PATCH 2/4] Address code review comments
---
clang/lib/CIR/CodeGen/CIRGenCall.cpp | 12 +++++++-----
clang/lib/CIR/CodeGen/CIRGenClass.cpp | 13 ++++++++-----
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 7 ++++---
clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 5 ++++-
clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 5 +++--
clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 7 ++++---
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 8 +++++---
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 11 ++++++++---
clang/lib/CIR/CodeGen/TargetInfo.cpp | 2 +-
9 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 8fac6fd6c6aca..35ee52bb20ff2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -42,17 +42,17 @@ CIRGenFunctionInfo::create(CanQualType resultType,
return fi;
}
-cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &fi) {
- mlir::Type resultType = convertType(fi.getReturnType());
+cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &info) {
+ mlir::Type resultType = convertType(info.getReturnType());
SmallVector<mlir::Type, 8> argTypes;
- argTypes.reserve(fi.getNumRequiredArgs());
+ argTypes.reserve(info.getNumRequiredArgs());
- for (const CanQualType &argType : fi.requiredArguments())
+ for (const CanQualType &argType : info.requiredArguments())
argTypes.push_back(convertType(argType));
return cir::FuncType::get(argTypes,
(resultType ? resultType : builder.getVoidTy()),
- fi.isVariadic());
+ info.isVariadic());
}
CIRGenCallee CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
@@ -269,6 +269,7 @@ void CIRGenFunction::emitDelegateCallArg(CallArgList &args,
if (type->isRecordType() &&
type->castAs<RecordType>()
->getOriginalDecl()
+ ->getDefinitionOrSelf()
->isParamDestroyedInCallee() &&
param->needsDestruction(getContext())) {
cgm.errorNYI(param->getSourceRange(),
@@ -671,6 +672,7 @@ void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e,
// we make it to the call.
if (argType->isRecordType() && argType->castAs<RecordType>()
->getOriginalDecl()
+ ->getDefinitionOrSelf()
->isParamDestroyedInCallee()) {
assert(!cir::MissingFeatures::msabi());
cgm.errorNYI(e->getSourceRange(), "emitCallArg: msabi is NYI");
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 27e798f2280b3..13a1c35e8abf4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -120,8 +120,10 @@ static void emitMemberInitializer(CIRGenFunction &cgf,
static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit) {
const Type *baseType = baseInit->getBaseClass();
- const auto *baseClassDecl =
- cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getOriginalDecl());
+ const auto *baseClassDecl = cast<CXXRecordDecl>(baseType->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->getDefinitionOrSelf());
return baseClassDecl->isDynamicClass();
}
@@ -160,8 +162,8 @@ void CIRGenFunction::emitBaseInitializer(mlir::Location loc,
Address thisPtr = loadCXXThisAddress();
const Type *baseType = baseInit->getBaseClass();
- const auto *baseClassDecl =
- cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getOriginalDecl());
+ const auto *baseClassDecl = cast<CXXRecordDecl>(
+ baseType->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf());
bool isBaseVirtual = baseInit->isBaseVirtual();
@@ -484,7 +486,8 @@ void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {
void CIRGenFunction::destroyCXXObject(CIRGenFunction &cgf, Address addr,
QualType type) {
const RecordType *rtype = type->castAs<RecordType>();
- const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getOriginalDecl());
+ const CXXRecordDecl *record =
+ cast<CXXRecordDecl>(rtype->getOriginalDecl()->getDefinitionOrSelf());
const CXXDestructorDecl *dtor = record->getDestructor();
// TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
// dtors which shall be removed on later CIR passes. However, only remove this
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 6114f4ff75d01..7dc660a8be2cc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1013,8 +1013,8 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
case CK_DerivedToBase: {
const auto *derivedClassTy =
e->getSubExpr()->getType()->castAs<clang::RecordType>();
- auto *derivedClassDecl =
- cast<CXXRecordDecl>(derivedClassTy->getOriginalDecl());
+ auto *derivedClassDecl = cast<CXXRecordDecl>(
+ derivedClassTy->getOriginalDecl()->getDefinitionOrSelf());
LValue lv = emitLValue(e->getSubExpr());
Address thisAddr = lv.getAddress();
@@ -1168,7 +1168,8 @@ static void pushTemporaryCleanup(CIRGenFunction &cgf,
->getBaseElementTypeUnsafe()
->getAs<clang::RecordType>()) {
// Get the destructor for the reference temporary.
- auto *classDecl = cast<CXXRecordDecl>(rt->getOriginalDecl());
+ auto *classDecl =
+ cast<CXXRecordDecl>(rt->getOriginalDecl()->getDefinitionOrSelf());
if (!classDecl->hasTrivialDestructor())
referenceTemporaryDtor = classDecl->getDestructor();
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index e2c4e13ab6773..1fda8487796a9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -376,7 +376,10 @@ void AggExprEmitter::visitCXXParenListOrInitListExpr(
// the disadvantage is that the generated code is more difficult for
// the optimizer, especially with bitfields.
unsigned numInitElements = args.size();
- RecordDecl *record = e->getType()->castAs<RecordType>()->getOriginalDecl();
+ RecordDecl *record = e->getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf();
// We'll need to enter cleanup scopes in case any of the element
// initializers throws an exception.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 3d46af91773ea..48024a5223cda 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -590,8 +590,9 @@ mlir::Attribute ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &d) {
// assignments and whatnots). Since this is for globals shouldn't
// be a problem for the near future.
if (cd->isTrivial() && cd->isDefaultConstructor()) {
- const auto *cxxrd =
- cast<CXXRecordDecl>(ty->getAs<RecordType>()->getOriginalDecl());
+ const auto *cxxrd = cast<CXXRecordDecl>(ty->getAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf());
if (cxxrd->getNumBases() != 0) {
// There may not be anything additional to do here, but this will
// force us to pause and test this path when it is supported.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index a4d4d210cf876..6e8d1385bb5b2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -356,8 +356,8 @@ static bool mayDropFunctionReturn(const ASTContext &astContext,
// destructor or a non-trivially copyable type.
if (const RecordType *recordType =
returnType.getCanonicalType()->getAs<RecordType>()) {
- if (const auto *classDecl =
- dyn_cast<CXXRecordDecl>(recordType->getOriginalDecl()))
+ if (const auto *classDecl = dyn_cast<CXXRecordDecl>(
+ recordType->getOriginalDecl()->getDefinitionOrSelf()))
return classDecl->hasTrivialDestructor();
}
return returnType.isTriviallyCopyableType(astContext);
@@ -828,7 +828,8 @@ void CIRGenFunction::emitNullInitialization(mlir::Location loc, Address destPtr,
// Ignore empty classes in C++.
if (getLangOpts().CPlusPlus) {
if (const RecordType *rt = ty->getAs<RecordType>()) {
- if (cast<CXXRecordDecl>(rt->getOriginalDecl())->isEmpty())
+ if (cast<CXXRecordDecl>(rt->getOriginalDecl()->getDefinitionOrSelf())
+ ->isEmpty())
return;
}
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index d6b0278ab0b6f..e8892c566a5f9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -997,7 +997,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &astContext,
return true;
if (const auto *rt = varType->getAs<RecordType>()) {
- const RecordDecl *rd = rt->getOriginalDecl();
+ const RecordDecl *rd = rt->getOriginalDecl()->getDefinitionOrSelf();
for (const FieldDecl *fd : rd->fields()) {
if (fd->isBitField())
continue;
@@ -2066,8 +2066,10 @@ CharUnits CIRGenModule::computeNonVirtualBaseClassOffset(
// Get the layout.
const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
- const auto *baseDecl = cast<CXXRecordDecl>(
- base->getType()->castAs<clang::RecordType>()->getOriginalDecl());
+ const auto *baseDecl = cast<CXXRecordDecl>(base->getType()
+ ->castAs<clang::RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf());
// Add the offset.
offset += layout.getBaseClassOffset(baseDecl);
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 34c74da351262..aef2003c575af 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -139,6 +139,8 @@ isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt,
if (!alreadyChecked.insert(rd).second)
return true;
+ assert(rd->isCompleteDefinition() &&
+ "Expect RecordDecl to be CompleteDefinition");
const Type *key = cgt.getASTContext().getCanonicalTagType(rd).getTypePtr();
// If this type is already laid out, converting it is a noop.
@@ -243,8 +245,10 @@ mlir::Type CIRGenTypes::convertRecordDeclType(const clang::RecordDecl *rd) {
for (const auto &base : cxxRecordDecl->bases()) {
if (base.isVirtual())
continue;
- convertRecordDeclType(
- base.getType()->castAs<RecordType>()->getOriginalDecl());
+ convertRecordDeclType(base.getType()
+ ->castAs<RecordType>()
+ ->getOriginalDecl()
+ ->getDefinitionOrSelf());
}
}
@@ -277,7 +281,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
// Process record types before the type cache lookup.
if (const auto *recordType = dyn_cast<RecordType>(type))
- return convertRecordDeclType(recordType->getOriginalDecl());
+ return convertRecordDeclType(
+ recordType->getOriginalDecl()->getDefinitionOrSelf());
// Has the type already been processed?
TypeCacheTy::iterator tci = typeCache.find(ty);
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index dd20183b69b91..7b6259b04122d 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -10,7 +10,7 @@ bool clang::CIRGen::isEmptyRecordForLayout(const ASTContext &context,
if (!rt)
return false;
- const RecordDecl *rd = rt->getOriginalDecl();
+ const RecordDecl *rd = rt->getOriginalDecl()->getDefinitionOrSelf();
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *cxxrd = dyn_cast<CXXRecordDecl>(rd)) {
>From 9203e214832542fb3532b54b73c66a366e9787cb Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sat, 9 Aug 2025 19:33:30 +0200
Subject: [PATCH 3/4] Use getDefinitionOrSelf in CIRGenTypes
---
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index aef2003c575af..a54d02eb6c7e0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -185,7 +185,8 @@ isSafeToConvert(QualType qt, CIRGenTypes &cgt,
// If this is a record, check it.
if (const auto *rt = qt->getAs<RecordType>())
- return isSafeToConvert(rt->getOriginalDecl(), cgt, alreadyChecked);
+ return isSafeToConvert(rt->getOriginalDecl()->getDefinitionOrSelf(), cgt,
+ alreadyChecked);
// If this is an array, check the elements, which are embedded inline.
if (const auto *at = cgt.getASTContext().getAsArrayType(qt))
@@ -464,7 +465,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
}
case Type::Enum: {
- const EnumDecl *ed = cast<EnumType>(ty)->getOriginalDecl();
+ const EnumDecl *ed =
+ cast<EnumType>(ty)->getOriginalDecl()->getDefinitionOrSelf();
if (auto integerType = ed->getIntegerType(); !integerType.isNull())
return convertType(integerType);
// Return a placeholder 'i32' type. This can be changed later when the
@@ -555,7 +557,7 @@ bool CIRGenTypes::isZeroInitializable(clang::QualType t) {
}
if (const RecordType *rt = t->getAs<RecordType>()) {
- const RecordDecl *rd = rt->getOriginalDecl();
+ const RecordDecl *rd = rt->getOriginalDecl()->getDefinitionOrSelf();
return isZeroInitializable(rd);
}
>From 0b222a684fcd28880690302997c6056ff0556250 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sat, 9 Aug 2025 19:37:52 +0200
Subject: [PATCH 4/4] Fix calling function twice
---
clang/lib/CIR/CodeGen/CIRGenClass.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 13a1c35e8abf4..ec3b7d81ac5c8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -120,10 +120,8 @@ static void emitMemberInitializer(CIRGenFunction &cgf,
static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit) {
const Type *baseType = baseInit->getBaseClass();
- const auto *baseClassDecl = cast<CXXRecordDecl>(baseType->castAs<RecordType>()
- ->getOriginalDecl()
- ->getDefinitionOrSelf()
- ->getDefinitionOrSelf());
+ const auto *baseClassDecl = cast<CXXRecordDecl>(
+ baseType->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf());
return baseClassDecl->isDynamicClass();
}
More information about the cfe-commits
mailing list