diff options
Diffstat (limited to 'clang/lib/CodeGen')
27 files changed, 170 insertions, 112 deletions
diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 13c837a..1e3ac2e 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -105,7 +105,7 @@ llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) { CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) return CXXABI.getRecordArgABI(CXXRD); if (!RD->canPassInRegisters()) @@ -136,7 +136,7 @@ bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) { if (const RecordType *UT = Ty->getAsUnionType()) { - const RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *UD = UT->getDecl()->getDefinitionOrSelf(); if (UD->hasAttr<TransparentUnionAttr>()) { assert(!UD->field_empty() && "sema created an empty transparent union"); return UD->field_begin()->getType(); @@ -274,7 +274,7 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, // according to the Itanium ABI. The exception applies only to records, // not arrays of records, so we must also check whether we stripped off an // array type above. - if (isa<CXXRecordDecl>(RT->getOriginalDecl()) && + if (isa<CXXRecordDecl>(RT->getDecl()) && (WasArray || (!AsIfNoUniqueAddr && !FD->hasAttr<NoUniqueAddressAttr>()))) return false; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index f8e8086..6020684 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1200,7 +1200,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline( } } - if (shouldEmitUnifiedLTOModueFlag()) + if (shouldEmitUnifiedLTOModueFlag() && + !TheModule->getModuleFlag("UnifiedLTO")) TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1)); } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index df28641..741fa44 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1896,7 +1896,7 @@ bool CodeGenModule::MayDropFunctionReturn(const ASTContext &Context, // complex destructor or a non-trivially copyable type. if (const RecordType *RT = ReturnType.getCanonicalType()->getAsCanonical<RecordType>()) { - if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) + if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) return ClassDecl->hasTrivialDestructor(); } return ReturnType.isTriviallyCopyableType(Context); @@ -3853,7 +3853,7 @@ static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset, SmallVectorImpl<uint64_t> &Bits) { ASTContext &Context = CGM.getContext(); int CharWidth = Context.getCharWidth(); - const RecordDecl *RD = RTy->getOriginalDecl()->getDefinition(); + const RecordDecl *RD = RTy->getDecl()->getDefinition(); const ASTRecordLayout &ASTLayout = Context.getASTRecordLayout(RD); const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(RD); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index f31f0a2..f782b0c 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2026,7 +2026,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, // Anonymous union members do not have their destructors called. const RecordType *RT = type->getAsUnionType(); - if (RT && RT->getOriginalDecl()->isAnonymousStructOrUnion()) + if (RT && RT->getDecl()->isAnonymousStructOrUnion()) continue; CleanupKind cleanupKind = getCleanupKind(dtorKind); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 9fe9a13..12e2813ef 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -647,6 +647,68 @@ StringRef CGDebugInfo::getCurrentDirname() { return CGM.getCodeGenOpts().DebugCompilationDir; } +static llvm::dwarf::SourceLanguage GetSourceLanguage(const CodeGenModule &CGM) { + const CodeGenOptions &CGO = CGM.getCodeGenOpts(); + const LangOptions &LO = CGM.getLangOpts(); + + assert(CGO.DwarfVersion <= 5); + + llvm::dwarf::SourceLanguage LangTag; + if (LO.CPlusPlus) { + if (LO.ObjC) + LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; + else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5) + LangTag = llvm::dwarf::DW_LANG_C_plus_plus; + else if (LO.CPlusPlus14) + LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14; + else if (LO.CPlusPlus11) + LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11; + else + LangTag = llvm::dwarf::DW_LANG_C_plus_plus; + } else if (LO.ObjC) { + LangTag = llvm::dwarf::DW_LANG_ObjC; + } else if (LO.OpenCL && (!CGO.DebugStrictDwarf || CGO.DwarfVersion >= 5)) { + LangTag = llvm::dwarf::DW_LANG_OpenCL; + } else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) { + LangTag = llvm::dwarf::DW_LANG_C11; + } else if (LO.C99) { + LangTag = llvm::dwarf::DW_LANG_C99; + } else { + LangTag = llvm::dwarf::DW_LANG_C89; + } + + return LangTag; +} + +static llvm::DISourceLanguageName +GetDISourceLanguageName(const CodeGenModule &CGM) { + // Emit pre-DWARFv6 language codes. + if (CGM.getCodeGenOpts().DwarfVersion < 6) + return llvm::DISourceLanguageName(GetSourceLanguage(CGM)); + + const LangOptions &LO = CGM.getLangOpts(); + + uint32_t LangVersion = 0; + llvm::dwarf::SourceLanguageName LangTag; + if (LO.CPlusPlus) { + if (LO.ObjC) { + LangTag = llvm::dwarf::DW_LNAME_ObjC_plus_plus; + } else { + LangTag = llvm::dwarf::DW_LNAME_C_plus_plus; + LangVersion = LO.getCPlusPlusLangStd().value_or(0); + } + } else if (LO.ObjC) { + LangTag = llvm::dwarf::DW_LNAME_ObjC; + } else if (LO.OpenCL) { + LangTag = llvm::dwarf::DW_LNAME_OpenCL_C; + } else { + LangTag = llvm::dwarf::DW_LNAME_C; + LangVersion = LO.getCLangStd().value_or(0); + } + + return llvm::DISourceLanguageName(LangTag, LangVersion); +} + void CGDebugInfo::CreateCompileUnit() { SmallString<64> Checksum; std::optional<llvm::DIFile::ChecksumKind> CSKind; @@ -702,31 +764,6 @@ void CGDebugInfo::CreateCompileUnit() { } } - llvm::dwarf::SourceLanguage LangTag; - if (LO.CPlusPlus) { - if (LO.ObjC) - LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; - else if (CGO.DebugStrictDwarf && CGO.DwarfVersion < 5) - LangTag = llvm::dwarf::DW_LANG_C_plus_plus; - else if (LO.CPlusPlus14) - LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14; - else if (LO.CPlusPlus11) - LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11; - else - LangTag = llvm::dwarf::DW_LANG_C_plus_plus; - } else if (LO.ObjC) { - LangTag = llvm::dwarf::DW_LANG_ObjC; - } else if (LO.OpenCL && (!CGM.getCodeGenOpts().DebugStrictDwarf || - CGM.getCodeGenOpts().DwarfVersion >= 5)) { - LangTag = llvm::dwarf::DW_LANG_OpenCL; - } else if (LO.C11 && !(CGO.DebugStrictDwarf && CGO.DwarfVersion < 5)) { - LangTag = llvm::dwarf::DW_LANG_C11; - } else if (LO.C99) { - LangTag = llvm::dwarf::DW_LANG_C99; - } else { - LangTag = llvm::dwarf::DW_LANG_C89; - } - std::string Producer = getClangFullVersion(); // Figure out which version of the ObjC runtime we have. @@ -787,7 +824,7 @@ void CGDebugInfo::CreateCompileUnit() { // Create new compile unit. TheCU = DBuilder.createCompileUnit( - llvm::DISourceLanguageName(LangTag), CUFile, + GetDISourceLanguageName(CGM), CUFile, CGOpts.EmitVersionIdentMetadata ? Producer : "", CGOpts.OptimizationLevel != 0 || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO, @@ -1234,20 +1271,46 @@ llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty, Ty->getPointeeType(), Unit); } -/// \return whether a C++ mangling exists for the type defined by TD. -static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) { - switch (TheCU->getSourceLanguage().getUnversionedName()) { +static bool hasCXXMangling(llvm::dwarf::SourceLanguage Lang, bool IsTagDecl) { + switch (Lang) { case llvm::dwarf::DW_LANG_C_plus_plus: case llvm::dwarf::DW_LANG_C_plus_plus_11: case llvm::dwarf::DW_LANG_C_plus_plus_14: return true; case llvm::dwarf::DW_LANG_ObjC_plus_plus: - return isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD); + return IsTagDecl; + default: + return false; + } +} + +static bool hasCXXMangling(llvm::dwarf::SourceLanguageName Lang, + bool IsTagDecl) { + switch (Lang) { + case llvm::dwarf::DW_LNAME_C_plus_plus: + return true; + case llvm::dwarf::DW_LNAME_ObjC_plus_plus: + return IsTagDecl; default: return false; } } +/// \return whether a C++ mangling exists for the type defined by TD. +static bool hasCXXMangling(const TagDecl *TD, llvm::DICompileUnit *TheCU) { + const bool IsTagDecl = isa<CXXRecordDecl>(TD) || isa<EnumDecl>(TD); + + if (llvm::DISourceLanguageName SourceLang = TheCU->getSourceLanguage(); + SourceLang.hasVersionedName()) + return hasCXXMangling( + static_cast<llvm::dwarf::SourceLanguageName>(SourceLang.getName()), + IsTagDecl); + else + return hasCXXMangling( + static_cast<llvm::dwarf::SourceLanguage>(SourceLang.getName()), + IsTagDecl); +} + // Determines if the debug info for this tag declaration needs a type // identifier. The purpose of the unique identifier is to deduplicate type // information for identical types across TUs. Because of the C++ one definition @@ -1290,7 +1353,7 @@ static bool needsTypeIdentifier(const TagDecl *TD, CodeGenModule &CGM, static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM, llvm::DICompileUnit *TheCU) { SmallString<256> Identifier; - const TagDecl *TD = Ty->getOriginalDecl()->getDefinitionOrSelf(); + const TagDecl *TD = Ty->getDecl()->getDefinitionOrSelf(); if (!needsTypeIdentifier(TD, CGM, TheCU)) return Identifier; @@ -1326,7 +1389,7 @@ static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { llvm::DICompositeType * CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, llvm::DIScope *Ctx) { - const RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = Ty->getDecl()->getDefinitionOrSelf(); if (llvm::DIType *T = getTypeOrNull(QualType(Ty, 0))) return cast<llvm::DICompositeType>(T); llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation()); @@ -2402,7 +2465,7 @@ void CGDebugInfo::CollectCXXBasesAux( for (const auto &BI : Bases) { const auto *Base = cast<CXXRecordDecl>( - BI.getType()->castAsCanonical<RecordType>()->getOriginalDecl()) + BI.getType()->castAsCanonical<RecordType>()->getDecl()) ->getDefinition(); if (!SeenTypes.insert(Base).second) continue; @@ -3077,7 +3140,7 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { } llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { - RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); + RecordDecl *RD = Ty->getDecl()->getDefinitionOrSelf(); llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0))); if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts())) { @@ -3105,7 +3168,7 @@ llvm::DIType *CGDebugInfo::GetPreferredNameType(const CXXRecordDecl *RD, std::pair<llvm::DIType *, llvm::DIType *> CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { - RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); + RecordDecl *RD = Ty->getDecl()->getDefinitionOrSelf(); // Get overall information about the record type for the debug info. llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation()); @@ -3748,7 +3811,7 @@ llvm::DIType *CGDebugInfo::CreateType(const HLSLInlineSpirvType *Ty, static auto getEnumInfo(CodeGenModule &CGM, llvm::DICompileUnit *TheCU, const EnumType *Ty) { - const EnumDecl *ED = Ty->getOriginalDecl()->getDefinitionOrSelf(); + const EnumDecl *ED = Ty->getDecl()->getDefinitionOrSelf(); uint64_t Size = 0; uint32_t Align = 0; @@ -4151,7 +4214,7 @@ CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) { // TODO: Currently used for context chains when limiting debug info. llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { - RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); + RecordDecl *RD = Ty->getDecl()->getDefinitionOrSelf(); // Get overall information about the record type for the debug info. StringRef RDName = getClassName(RD); @@ -4238,8 +4301,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { break; } - if (auto *CTSD = - dyn_cast<ClassTemplateSpecializationDecl>(Ty->getOriginalDecl())) { + if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Ty->getDecl())) { CXXRecordDecl *TemplateDecl = CTSD->getSpecializedTemplate()->getTemplatedDecl(); RegionMap[TemplateDecl].reset(RealDecl); @@ -5141,7 +5203,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, } else if (const auto *RT = dyn_cast<RecordType>(VD->getType())) { // If VD is an anonymous union then Storage represents value for // all union fields. - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); if (RD->isUnion() && RD->isAnonymousStructOrUnion()) { // GDB has trouble finding local variables in anonymous unions, so we emit // artificial local variables for each of the members. @@ -5691,9 +5753,8 @@ llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls( // Ignore unnamed fields, but recurse into anonymous records. if (FieldName.empty()) { if (const auto *RT = dyn_cast<RecordType>(Field->getType())) - GVE = - CollectAnonRecordDecls(RT->getOriginalDecl()->getDefinitionOrSelf(), - Unit, LineNo, LinkageName, Var, DContext); + GVE = CollectAnonRecordDecls(RT->getDecl()->getDefinitionOrSelf(), Unit, + LineNo, LinkageName, Var, DContext); continue; } // Use VarDecl's Tag, Scope and Line number. @@ -5712,7 +5773,7 @@ static bool ReferencesAnonymousEntity(RecordType *RT) { // But so long as it's not one of those, it doesn't matter if some sub-type // of the record (a template parameter) can't be reconstituted - because the // un-reconstitutable type itself will carry its own name. - const auto *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()); + const auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); if (!RD) return false; if (!RD->getIdentifier()) @@ -5774,7 +5835,7 @@ struct ReconstitutableType : public RecursiveASTVisitor<ReconstitutableType> { bool TraverseEnumType(EnumType *ET, bool = false) { // Unnamed enums can't be reconstituted due to a lack of column info we // produce in the DWARF, so we can't get Clang's full name back. - if (const auto *ED = dyn_cast<EnumDecl>(ET->getOriginalDecl())) { + if (const auto *ED = dyn_cast<EnumDecl>(ET->getDecl())) { if (!ED->getIdentifier()) { Reconstitutable = false; return false; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index e8255b0..8439ec7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2011,7 +2011,7 @@ static bool isConstantEmittableObjectType(QualType type) { // Otherwise, all object types satisfy this except C++ classes with // mutable subobjects or non-trivial copy/destroy behavior. if (const auto *RT = dyn_cast<RecordType>(type)) - if (const auto *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) { + if (const auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { RD = RD->getDefinitionOrSelf(); if (RD->hasMutableFields() || !RD->isTrivial()) return false; @@ -4564,7 +4564,7 @@ static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) { const auto *PointeeT = PtrT->getPointeeType() ->getUnqualifiedDesugaredType(); if (const auto *RecT = dyn_cast<RecordType>(PointeeT)) - return RecT->getOriginalDecl() + return RecT->getDecl() ->getMostRecentDecl() ->hasAttr<BPFPreserveAccessIndexAttr>(); return false; @@ -7008,7 +7008,7 @@ void CodeGenFunction::FlattenAccessAndTypeLValue( WorkList.emplace_back(LVal, CAT->getElementType(), IdxListCopy); } } else if (const auto *RT = dyn_cast<RecordType>(T)) { - const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *Record = RT->getDecl()->getDefinitionOrSelf(); assert(!Record->isUnion() && "Union types not supported in flat cast."); const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(Record); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 07b9aeb..eee397f 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -2080,7 +2080,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { // referencee. InitListExprs for unions and arrays can't have references. if (const RecordType *RT = E->getType()->getAsCanonical<RecordType>()) { if (!RT->isUnionType()) { - RecordDecl *SD = RT->getOriginalDecl()->getDefinitionOrSelf(); + RecordDecl *SD = RT->getDecl()->getDefinitionOrSelf(); CharUnits NumNonZeroBytes = CharUnits::Zero(); unsigned ILEElement = 0; @@ -2133,7 +2133,7 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E, if (const RecordType *RT = CGF.getContext() .getBaseElementType(E->getType()) ->getAsCanonical<RecordType>()) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getOriginalDecl()); + const auto *RD = cast<CXXRecordDecl>(RT->getDecl()); if (RD->hasUserDeclaredConstructor()) return; } diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 31ac266..14d8db3 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1236,8 +1236,8 @@ void CodeGenFunction::EmitNewArrayInitializer( if (auto *ILE = dyn_cast<InitListExpr>(Init)) { if (const RecordType *RType = ILE->getType()->getAsCanonical<RecordType>()) { - if (RType->getOriginalDecl()->isStruct()) { - const RecordDecl *RD = RType->getOriginalDecl()->getDefinitionOrSelf(); + if (RType->getDecl()->isStruct()) { + const RecordDecl *RD = RType->getDecl()->getDefinitionOrSelf(); unsigned NumElements = 0; if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) NumElements = CXXRD->getNumBases(); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 715160d..714192d 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -3583,7 +3583,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { } const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout( - CurrentType->castAsCanonical<RecordType>()->getOriginalDecl()); + CurrentType->castAsCanonical<RecordType>()->getDecl()); // Save the element type. CurrentType = ON.getBase()->getType(); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 603cef9..ecab933 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -519,6 +519,10 @@ void clang::CodeGen::CGHLSLRuntime::setHLSLEntryAttributes( if (CGM.getCodeGenOpts().OptimizationLevel == 0) Fn->addFnAttr(llvm::Attribute::OptimizeNone); Fn->addFnAttr(llvm::Attribute::NoInline); + + if (CGM.getLangOpts().HLSLSpvEnableMaximalReconvergence) { + Fn->addFnAttr("enable-maximal-reconvergence", "true"); + } } static Value *buildVectorInput(IRBuilder<> &B, Function *F, llvm::Type *Ty) { diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 2d70e4c..0a383c8 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -464,8 +464,7 @@ template <class Derived> struct GenFuncBase { if (WrongType) { std::string FuncName = std::string(F->getName()); - SourceLocation Loc = - QT->castAs<RecordType>()->getOriginalDecl()->getLocation(); + SourceLocation Loc = QT->castAs<RecordType>()->getDecl()->getLocation(); CGM.Error(Loc, "special function " + FuncName + " for non-trivial C struct has incorrect type"); return nullptr; diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index dbcce9b..c571821a 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -2495,7 +2495,7 @@ void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, CharUnits BytePos, bool &HasUnion, bool ByrefLayout) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); SmallVector<const FieldDecl *, 16> Fields(RD->fields()); llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); const llvm::StructLayout *RecLayout = @@ -5184,7 +5184,7 @@ CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, } void IvarLayoutBuilder::visitRecord(const RecordType *RT, CharUnits offset) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); // If this is a union, remember that we had one, because it might mess // up the ordering of layout entries. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 8d019d4..c5eb14e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2348,7 +2348,7 @@ static QualType GeneralizeTransparentUnion(QualType Ty) { const RecordType *UT = Ty->getAsUnionType(); if (!UT) return Ty; - const RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *UD = UT->getDecl()->getDefinitionOrSelf(); if (!UD->hasAttr<TransparentUnionAttr>()) return Ty; for (const auto *it : UD->fields()) { @@ -4230,7 +4230,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { static bool HasNonDllImportDtor(QualType T) { if (const auto *RT = T->getBaseElementTypeUnsafe()->getAsCanonical<RecordType>()) - if (auto *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) { + if (auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { RD = RD->getDefinitionOrSelf(); if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>()) return true; diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index f8c7d64..4e29d8a 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -310,7 +310,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { // This also covers anonymous structs and unions, which have a different // compatibility rule, but it doesn't matter because you can never have a // pointer to an anonymous struct or union. - if (!RT->getOriginalDecl()->getDeclName()) + if (!RT->getDecl()->getDeclName()) return getAnyPtr(PtrDepth); // For non-builtin types use the mangled name of the canonical type. @@ -332,7 +332,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { // Enum types are distinct types. In C++ they have "underlying types", // however they aren't related for TBAA. if (const EnumType *ETy = dyn_cast<EnumType>(Ty)) { - const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf(); + const EnumDecl *ED = ETy->getDecl()->getDefinitionOrSelf(); if (!Features.CPlusPlus) return getTypeInfo(ED->getIntegerType()); @@ -433,7 +433,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset, llvm::MDBuilder::TBAAStructField(BaseOffset, Size, TBAATag)); return true; } - const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition(); + const RecordDecl *RD = TTy->getDecl()->getDefinition(); if (RD->hasFlexibleArrayMember()) return false; @@ -514,7 +514,7 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) { llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) { if (auto *TTy = dyn_cast<RecordType>(Ty)) { - const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition(); + const RecordDecl *RD = TTy->getDecl()->getDefinition(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); using TBAAStructField = llvm::MDBuilder::TBAAStructField; SmallVector<TBAAStructField, 4> Fields; diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 3ffe999..ea31195 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -373,8 +373,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { } // RecordTypes are cached and processed specially. - if (const RecordType *RT = dyn_cast<RecordType>(Ty)) - return ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf()); + if (const auto *RT = dyn_cast<RecordType>(Ty)) + return ConvertRecordDeclType(RT->getDecl()->getDefinitionOrSelf()); llvm::Type *CachedType = nullptr; auto TCI = TypeCache.find(Ty); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 7dc2eaf..9e195a9 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3816,7 +3816,7 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { const CXXRecordDecl *RD = - cast<CXXRecordDecl>(RecordTy->getOriginalDecl())->getDefinitionOrSelf(); + cast<CXXRecordDecl>(RecordTy->getDecl())->getDefinitionOrSelf(); if (!RD->hasDefinition()) return false; @@ -3850,9 +3850,7 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, /// IsIncompleteClassType - Returns whether the given record type is incomplete. static bool IsIncompleteClassType(const RecordType *RecordTy) { - return !RecordTy->getOriginalDecl() - ->getDefinitionOrSelf() - ->isCompleteDefinition(); + return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition(); } /// ContainsIncompleteClassType - Returns whether the given type contains an @@ -3985,9 +3983,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty, break; case Type::Record: { - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(cast<RecordType>(Ty)->getOriginalDecl()) - ->getDefinitionOrSelf(); + const auto *RD = cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()) + ->getDefinitionOrSelf(); if (!RD->hasDefinition() || !RD->getNumBases()) { VTableName = ClassTypeInfo; @@ -4109,8 +4106,8 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, return llvm::GlobalValue::LinkOnceODRLinkage; if (const RecordType *Record = dyn_cast<RecordType>(Ty)) { - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf(); + const auto *RD = + cast<CXXRecordDecl>(Record->getDecl())->getDefinitionOrSelf(); if (RD->hasAttr<WeakAttr>()) return llvm::GlobalValue::WeakODRLinkage; if (CGM.getTriple().isWindowsItaniumEnvironment()) @@ -4273,9 +4270,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( break; case Type::Record: { - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(cast<RecordType>(Ty)->getOriginalDecl()) - ->getDefinitionOrSelf(); + const auto *RD = cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl()) + ->getDefinitionOrSelf(); if (!RD->hasDefinition() || !RD->getNumBases()) { // We don't need to emit any fields. break; @@ -4322,8 +4318,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( if (CGM.getTarget().hasPS4DLLImportExport() && GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) { if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getOriginalDecl()) - ->getDefinitionOrSelf(); + const auto *RD = + cast<CXXRecordDecl>(RecordTy->getDecl())->getDefinitionOrSelf(); if (RD->hasAttr<DLLExportAttr>() || CXXRecordNonInlineHasAttr<DLLExportAttr>(RD)) GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass; diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index 4d894fd..20965430 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -66,7 +66,7 @@ void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) { // Record types. if (auto recType = type->getAsCanonical<RecordType>()) { - addTypedData(recType->getOriginalDecl(), begin); + addTypedData(recType->getDecl(), begin); // Array types. } else if (type->isArrayType()) { @@ -814,7 +814,7 @@ static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, bool forReturn) { unsigned IndirectAS = CGM.getDataLayout().getAllocaAddrSpace(); if (auto recordType = dyn_cast<RecordType>(type)) { - auto record = recordType->getOriginalDecl(); + auto record = recordType->getDecl(); auto &layout = CGM.getContext().getASTRecordLayout(record); if (mustPassRecordIndirectly(CGM, record)) @@ -822,8 +822,7 @@ static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, /*AddrSpace=*/IndirectAS, /*byval=*/false); SwiftAggLowering lowering(CGM); - lowering.addTypedData(recordType->getOriginalDecl(), CharUnits::Zero(), - layout); + lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout); lowering.finish(); return classifyExpandedType(lowering, forReturn, layout.getAlignment(), diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 1e58c3f..342a3af 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -82,6 +82,8 @@ TargetCodeGenInfo::~TargetCodeGenInfo() = default; // If someone can figure out a general rule for this, that would be great. // It's probably just doomed to be platform-dependent, though. unsigned TargetCodeGenInfo::getSizeOfUnwindException() const { + if (getABIInfo().getCodeGenOpts().hasSEHExceptions()) + return getABIInfo().getDataLayout().getPointerSizeInBits() > 32 ? 64 : 48; // Verified for: // x86-64 FreeBSD, Linux, Darwin // x86-32 FreeBSD, Linux, Darwin diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index d7deece..bb41a14 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -743,7 +743,7 @@ bool AArch64ABIInfo::passAsPureScalableType( return false; // Pure scalable types are never unions and never contain unions. - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); if (RD->isUnion()) return false; diff --git a/clang/lib/CodeGen/Targets/ARC.cpp b/clang/lib/CodeGen/Targets/ARC.cpp index 6727587..6c9444d 100644 --- a/clang/lib/CodeGen/Targets/ARC.cpp +++ b/clang/lib/CodeGen/Targets/ARC.cpp @@ -112,8 +112,7 @@ ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty, if (isAggregateTypeForABI(Ty)) { // Structures with flexible arrays are always indirect. - if (RT && - RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) + if (RT && RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return getIndirectByValue(Ty); // Ignore empty structs/unions. diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp index c84c9f2..4d05217 100644 --- a/clang/lib/CodeGen/Targets/ARM.cpp +++ b/clang/lib/CodeGen/Targets/ARM.cpp @@ -516,7 +516,7 @@ static bool isIntegerLikeType(QualType Ty, ASTContext &Context, if (!RT) return false; // Ignore records with flexible arrays. - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return false; diff --git a/clang/lib/CodeGen/Targets/Lanai.cpp b/clang/lib/CodeGen/Targets/Lanai.cpp index e76431a..871a135 100644 --- a/clang/lib/CodeGen/Targets/Lanai.cpp +++ b/clang/lib/CodeGen/Targets/Lanai.cpp @@ -102,8 +102,7 @@ ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, if (isAggregateTypeForABI(Ty)) { // Structures with flexible arrays are always indirect. - if (RT && - RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) + if (RT && RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return getIndirectResult(Ty, /*ByVal=*/true, State); // Ignore empty structs/unions. diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 1f344d6..878723d 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -150,7 +150,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( // Non-zero-length arrays of empty records make the struct ineligible to be // passed via FARs in C++. if (const auto *RTy = EltTy->getAsCanonical<RecordType>()) { - if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getOriginalDecl()) && + if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) && isEmptyRecord(getContext(), EltTy, true, true)) return false; } @@ -169,7 +169,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( // copy constructor are not eligible for the FP calling convention. if (getRecordArgABI(Ty, CGT.getCXXABI())) return false; - const RecordDecl *RD = RTy->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RTy->getDecl()->getDefinitionOrSelf(); if (isEmptyRecord(getContext(), Ty, true, true) && (!RD->isUnion() || !isa<CXXRecordDecl>(RD))) return true; diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp index f26ab97..22fdcd9 100644 --- a/clang/lib/CodeGen/Targets/Mips.cpp +++ b/clang/lib/CodeGen/Targets/Mips.cpp @@ -161,7 +161,7 @@ llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const { return llvm::StructType::get(getVMContext(), ArgList); } - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); assert(!(TySize % 8) && "Size of structure must be multiple of 8."); @@ -265,7 +265,7 @@ MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const { SmallVector<llvm::Type*, 8> RTList; if (RT && RT->isStructureOrClassType()) { - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); unsigned FieldCnt = Layout.getFieldCount(); diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index 0d0941e..d134589 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -234,7 +234,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, // Non-zero-length arrays of empty records make the struct ineligible for // the FP calling convention in C++. if (const auto *RTy = EltTy->getAsCanonical<RecordType>()) { - if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getOriginalDecl()) && + if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) && isEmptyRecord(getContext(), EltTy, true, true)) return false; } @@ -256,7 +256,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, return false; if (isEmptyRecord(getContext(), Ty, true, true)) return true; - const RecordDecl *RD = RTy->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RTy->getDecl()->getDefinitionOrSelf(); // Unions aren't eligible unless they're empty (which is caught above). if (RD->isUnion()) return false; diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index fb78948..8daf8eb 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -795,8 +795,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, if (isAggregateTypeForABI(Ty)) { // Structures with flexible arrays are always indirect. // FIXME: This should not be byval! - if (RT && - RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) + if (RT && RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return getIndirectResult(Ty, true, State); // Ignore empty structs/unions on non-Windows. @@ -831,7 +830,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, unsigned AlignInBits = 0; if (RT) { const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(RT->getOriginalDecl()); + getContext().getASTRecordLayout(RT->getDecl()); AlignInBits = getContext().toBits(Layout.getRequiredAlignment()); } else if (TI.isAlignRequired()) { AlignInBits = TI.Align; @@ -2042,7 +2041,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, if (getRecordArgABI(RT, getCXXABI())) return; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf(); // Assume variable sized types are passed in memory. if (RD->hasFlexibleArrayMember()) @@ -2851,9 +2850,8 @@ ABIArgInfo X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, unsigned &NeededSSE, unsigned &MaxVectorWidth) const { - auto *RD = cast<RecordType>(Ty.getCanonicalType()) - ->getOriginalDecl() - ->getDefinitionOrSelf(); + auto *RD = + cast<RecordType>(Ty.getCanonicalType())->getDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return getIndirectReturnResult(Ty); @@ -3313,7 +3311,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, RAA == CGCXXABI::RAA_DirectInMemory); } - if (RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) + if (RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); } diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index ab01154..f9726ec 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -380,7 +380,7 @@ static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT, // We collect all encoded fields and order as necessary. bool IsRecursive = false; - const RecordDecl *RD = RT->getOriginalDecl()->getDefinition(); + const RecordDecl *RD = RT->getDecl()->getDefinition(); if (RD && !RD->field_empty()) { // An incomplete TypeString stub is placed in the cache for this RecordType // so that recursive calls to this RecordType will use it whilst building a @@ -429,7 +429,7 @@ static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET, Enc += "){"; // We collect all encoded enumerations and order them alphanumerically. - if (const EnumDecl *ED = ET->getOriginalDecl()->getDefinition()) { + if (const EnumDecl *ED = ET->getDecl()->getDefinition()) { SmallVector<FieldEncoding, 16> FE; for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; ++I) { |