https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/152846
>From 946f3718f7e67966f07c962e7283d7fd11d0b329 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Sat, 9 Aug 2025 11:48:23 +0200 Subject: [PATCH 1/3] [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 <am...@programmer.net> Date: Sat, 9 Aug 2025 19:28:40 +0200 Subject: [PATCH 2/3] 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 <am...@programmer.net> Date: Sat, 9 Aug 2025 19:33:30 +0200 Subject: [PATCH 3/3] 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); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits