diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-11 18:37:24 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-08 17:35:11 +0000 |
commit | 8a4dda33d67586ca2624f2a38417baa03a533a7f (patch) | |
tree | ea87f69d4341b5a653c3747ebbdbedd7b41da233 /contrib/llvm-project/clang/lib | |
parent | 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (diff) | |
parent | 8092e001bcd76c0b9fec2311f3a515aa60d2ed07 (diff) | |
download | src-8a4dda33d67586ca2624f2a38417baa03a533a7f.tar.gz src-8a4dda33d67586ca2624f2a38417baa03a533a7f.zip |
Diffstat (limited to 'contrib/llvm-project/clang/lib')
63 files changed, 993 insertions, 449 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/ASTContext.cpp b/contrib/llvm-project/clang/lib/AST/ASTContext.cpp index 7acacd7bf4f5..76000156fece 100644 --- a/contrib/llvm-project/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm-project/clang/lib/AST/ASTContext.cpp @@ -9612,9 +9612,8 @@ bool ASTContext::areLaxCompatibleRVVTypes(QualType FirstType, const LangOptions::LaxVectorConversionKind LVCKind = getLangOpts().getLaxVectorConversions(); - // If __riscv_v_fixed_vlen != N do not allow GNU vector lax conversion. - if (VecTy->getVectorKind() == VectorType::GenericVector && - getTypeSize(SecondType) != getRVVTypeSize(*this, BT)) + // If __riscv_v_fixed_vlen != N do not allow vector lax conversion. + if (getTypeSize(SecondType) != getRVVTypeSize(*this, BT)) return false; // If -flax-vector-conversions=all is specified, the types are diff --git a/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp b/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp index f1c842e26199..f1bad0c7f7f2 100644 --- a/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp @@ -2418,9 +2418,16 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) { unsigned BaseIndex = 0; for (const CXXBaseSpecifier &BS : CD->bases()) { - if (!CheckEvaluationResult(CERK, Info, DiagLoc, BS.getType(), - Value.getStructBase(BaseIndex), Kind, - /*SubobjectDecl=*/nullptr, CheckedTemps)) + const APValue &BaseValue = Value.getStructBase(BaseIndex); + if (!BaseValue.hasValue()) { + SourceLocation TypeBeginLoc = BS.getBaseTypeLoc(); + Info.FFDiag(TypeBeginLoc, diag::note_constexpr_uninitialized_base) + << BS.getType() << SourceRange(TypeBeginLoc, BS.getEndLoc()); + return false; + } + if (!CheckEvaluationResult(CERK, Info, DiagLoc, BS.getType(), BaseValue, + Kind, /*SubobjectDecl=*/nullptr, + CheckedTemps)) return false; ++BaseIndex; } @@ -15218,14 +15225,6 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, return true; } - // FIXME: Evaluating values of large array and record types can cause - // performance problems. Only do so in C++11 for now. - if (Exp->isPRValue() && - (Exp->getType()->isArrayType() || Exp->getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus11) { - IsConst = false; - return true; - } return false; } @@ -15467,12 +15466,6 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, return Name; }); - // FIXME: Evaluating initializers for large array and record types can cause - // performance problems. Only do so in C++11 for now. - if (isPRValue() && (getType()->isArrayType() || getType()->isRecordType()) && - !Ctx.getLangOpts().CPlusPlus11) - return false; - Expr::EvalStatus EStatus; EStatus.Diag = &Notes; diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.cpp b/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.cpp index 6958479cd7c4..4448a2ae10a1 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.cpp +++ b/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.cpp @@ -15,7 +15,7 @@ #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/TargetBuiltins.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/TargetParser/TargetParser.h" +#include "llvm/TargetParser/LoongArchTargetParser.h" using namespace clang; using namespace clang::targets; @@ -198,7 +198,15 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts, else Builder.defineMacro("__loongarch_frlen", "0"); - // TODO: define __loongarch_arch and __loongarch_tune. + // Define __loongarch_arch. + StringRef ArchName = getCPU(); + Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"')); + + // Define __loongarch_tune. + StringRef TuneCPU = getTargetOpts().TuneCPU; + if (TuneCPU.empty()) + TuneCPU = ArchName; + Builder.defineMacro("__loongarch_tune", Twine('"') + TuneCPU + Twine('"')); StringRef ABI = getABI(); if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s") @@ -270,3 +278,12 @@ bool LoongArchTargetInfo::handleTargetFeatures( } return true; } + +bool LoongArchTargetInfo::isValidCPUName(StringRef Name) const { + return llvm::LoongArch::isValidCPUName(Name); +} + +void LoongArchTargetInfo::fillValidCPUList( + SmallVectorImpl<StringRef> &Values) const { + llvm::LoongArch::fillValidCPUList(Values); +} diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.h b/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.h index 52c4ce425368..34143f462a24 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.h +++ b/contrib/llvm-project/clang/lib/Basic/Targets/LoongArch.h @@ -24,6 +24,7 @@ namespace targets { class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { protected: std::string ABI; + std::string CPU; bool HasFeatureD; bool HasFeatureF; @@ -40,6 +41,15 @@ public: WIntType = UnsignedInt; } + bool setCPU(const std::string &Name) override { + if (!isValidCPUName(Name)) + return false; + CPU = Name; + return true; + } + + StringRef getCPU() const { return CPU; } + StringRef getABI() const override { return ABI; } void getTargetDefines(const LangOptions &Opts, @@ -80,6 +90,9 @@ public: const std::vector<std::string> &FeaturesVec) const override; bool hasFeature(StringRef Feature) const override; + + bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; }; class LLVM_LIBRARY_VISIBILITY LoongArch32TargetInfo diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp b/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp index 94c894dfec0b..d55ab76395c8 100644 --- a/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp +++ b/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp @@ -196,8 +196,8 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, if (ISAInfo->hasExtension("zve32x")) { Builder.defineMacro("__riscv_vector"); - // Currently we support the v0.11 RISC-V V intrinsics. - Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(0, 11))); + // Currently we support the v0.12 RISC-V V intrinsics. + Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(0, 12))); } auto VScale = getVScaleRange(Opts); diff --git a/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.cpp b/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.cpp index 7c30cecfdb9b..2b20d5a13346 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -246,7 +246,7 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1, } bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, - bool AllowArrays) { + bool AllowArrays, bool AsIfNoUniqueAddr) { if (FD->isUnnamedBitfield()) return true; @@ -280,13 +280,14 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, // not arrays of records, so we must also check whether we stripped off an // array type above. if (isa<CXXRecordDecl>(RT->getDecl()) && - (WasArray || !FD->hasAttr<NoUniqueAddressAttr>())) + (WasArray || (!AsIfNoUniqueAddr && !FD->hasAttr<NoUniqueAddressAttr>()))) return false; - return isEmptyRecord(Context, FT, AllowArrays); + return isEmptyRecord(Context, FT, AllowArrays, AsIfNoUniqueAddr); } -bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) { +bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, + bool AsIfNoUniqueAddr) { const RecordType *RT = T->getAs<RecordType>(); if (!RT) return false; @@ -297,11 +298,11 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) { // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) for (const auto &I : CXXRD->bases()) - if (!isEmptyRecord(Context, I.getType(), true)) + if (!isEmptyRecord(Context, I.getType(), true, AsIfNoUniqueAddr)) return false; for (const auto *I : RD->fields()) - if (!isEmptyField(Context, I, AllowArrays)) + if (!isEmptyField(Context, I, AllowArrays, AsIfNoUniqueAddr)) return false; return true; } diff --git a/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.h b/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.h index 5f0cc289af68..afde08ba100c 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.h +++ b/contrib/llvm-project/clang/lib/CodeGen/ABIInfoImpl.h @@ -122,13 +122,19 @@ Address emitMergePHI(CodeGenFunction &CGF, Address Addr1, llvm::BasicBlock *Block2, const llvm::Twine &Name = ""); /// isEmptyField - Return true iff a the field is "empty", that is it -/// is an unnamed bit-field or an (array of) empty record(s). -bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays); +/// is an unnamed bit-field or an (array of) empty record(s). If +/// AsIfNoUniqueAddr is true, then C++ record fields are considered empty if +/// the [[no_unique_address]] attribute would have made them empty. +bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays, + bool AsIfNoUniqueAddr = false); /// isEmptyRecord - Return true iff a structure contains only empty /// fields. Note that a structure with a flexible array member is not -/// considered empty. -bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays); +/// considered empty. If AsIfNoUniqueAddr is true, then C++ record fields are +/// considered empty if the [[no_unique_address]] attribute would have made +/// them empty. +bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, + bool AsIfNoUniqueAddr = false); /// isSingleElementStruct - Determine if a structure is a "single /// element struct", i.e. it has exactly one non-empty field or diff --git a/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp b/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp index cda03d69522d..483f3e787a78 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp @@ -55,7 +55,6 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/TargetParser/SubtargetFeature.h" #include "llvm/TargetParser/Triple.h" -#include "llvm/Transforms/IPO/EmbedBitcodePass.h" #include "llvm/Transforms/IPO/LowerTypeTests.h" #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/InstCombine/InstCombine.h" @@ -1016,12 +1015,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( }); } - bool IsThinOrUnifiedLTO = IsThinLTO || (IsLTO && CodeGenOpts.UnifiedLTO); - if (CodeGenOpts.FatLTO) { - MPM = PB.buildFatLTODefaultPipeline(Level, IsThinOrUnifiedLTO, - IsThinOrUnifiedLTO || - shouldEmitRegularLTOSummary()); - } else if (IsThinOrUnifiedLTO) { + if (IsThinLTO || (IsLTO && CodeGenOpts.UnifiedLTO)) { MPM = PB.buildThinLTOPreLinkDefaultPipeline(Level); } else if (IsLTO) { MPM = PB.buildLTOPreLinkDefaultPipeline(Level); @@ -1077,21 +1071,6 @@ void EmitAssemblyHelper::RunOptimizationPipeline( EmitLTOSummary)); } } - if (CodeGenOpts.FatLTO) { - // Set module flags, like EnableSplitLTOUnit and UnifiedLTO, since FatLTO - // uses a different action than Backend_EmitBC or Backend_EmitLL. - bool IsThinOrUnifiedLTO = - CodeGenOpts.PrepareForThinLTO || - (CodeGenOpts.PrepareForLTO && CodeGenOpts.UnifiedLTO); - if (!TheModule->getModuleFlag("ThinLTO")) - TheModule->addModuleFlag(Module::Error, "ThinLTO", - uint32_t(IsThinOrUnifiedLTO)); - if (!TheModule->getModuleFlag("EnableSplitLTOUnit")) - TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", - uint32_t(CodeGenOpts.EnableSplitLTOUnit)); - if (CodeGenOpts.UnifiedLTO && !TheModule->getModuleFlag("UnifiedLTO")) - TheModule->addModuleFlag(Module::Error, "UnifiedLTO", uint32_t(1)); - } // Now that we have all of the passes ready, run them. { diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.cpp index 7b77dd7875bc..4df6f6505ef6 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGCXXABI.cpp @@ -312,8 +312,7 @@ void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { // Delegate back to CGM by default. - return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, - /*IsConstantVariable=*/false); + return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage); } bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp index bd272e016e92..0d1e9ad439b7 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGCall.cpp @@ -13,6 +13,7 @@ #include "CGCall.h" #include "ABIInfo.h" +#include "ABIInfoImpl.h" #include "CGBlocks.h" #include "CGCXXABI.h" #include "CGCleanup.h" @@ -112,8 +113,7 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) { // When translating an unprototyped function type, always use a // variadic type. return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(), - /*instanceMethod=*/false, - /*chainCall=*/false, std::nullopt, + FnInfoOpts::None, std::nullopt, FTNP->getExtInfo(), {}, RequiredArgs(0)); } @@ -189,10 +189,10 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod, appendParameterTypes(CGT, prefix, paramInfos, FTP); CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); - return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod, - /*chainCall=*/false, prefix, - FTP->getExtInfo(), paramInfos, - Required); + FnInfoOpts opts = + instanceMethod ? FnInfoOpts::IsInstanceMethod : FnInfoOpts::None; + return CGT.arrangeLLVMFunctionInfo(resultType, opts, prefix, + FTP->getExtInfo(), paramInfos, Required); } /// Arrange the argument and result information for a value of the @@ -271,7 +271,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, argTypes.push_back(DeriveThisType(RD, MD)); return ::arrangeLLVMFunctionInfo( - *this, true, argTypes, + *this, /*instanceMethod=*/true, argTypes, FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>()); } @@ -363,9 +363,8 @@ CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) { : TheCXXABI.hasMostDerivedReturn(GD) ? CGM.getContext().VoidPtrTy : Context.VoidTy; - return arrangeLLVMFunctionInfo(resultType, /*instanceMethod=*/true, - /*chainCall=*/false, argTypes, extInfo, - paramInfos, required); + return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::IsInstanceMethod, + argTypes, extInfo, paramInfos, required); } static SmallVector<CanQualType, 16> @@ -439,9 +438,9 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args, addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs, ArgTypes.size()); } - return arrangeLLVMFunctionInfo(ResultType, /*instanceMethod=*/true, - /*chainCall=*/false, ArgTypes, Info, - ParamInfos, Required); + + return arrangeLLVMFunctionInfo(ResultType, FnInfoOpts::IsInstanceMethod, + ArgTypes, Info, ParamInfos, Required); } /// Arrange the argument and result information for the declaration or @@ -460,10 +459,9 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { // When declaring a function without a prototype, always use a // non-variadic type. if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) { - return arrangeLLVMFunctionInfo( - noProto->getReturnType(), /*instanceMethod=*/false, - /*chainCall=*/false, std::nullopt, noProto->getExtInfo(), {}, - RequiredArgs::All); + return arrangeLLVMFunctionInfo(noProto->getReturnType(), FnInfoOpts::None, + std::nullopt, noProto->getExtInfo(), {}, + RequiredArgs::All); } return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>()); @@ -512,9 +510,9 @@ CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, RequiredArgs required = (MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All); - return arrangeLLVMFunctionInfo( - GetReturnType(MD->getReturnType()), /*instanceMethod=*/false, - /*chainCall=*/false, argTys, einfo, extParamInfos, required); + return arrangeLLVMFunctionInfo(GetReturnType(MD->getReturnType()), + FnInfoOpts::None, argTys, einfo, extParamInfos, + required); } const CGFunctionInfo & @@ -523,9 +521,8 @@ CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType, auto argTypes = getArgTypesForCall(Context, args); FunctionType::ExtInfo einfo; - return arrangeLLVMFunctionInfo( - GetReturnType(returnType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, einfo, {}, RequiredArgs::All); + return arrangeLLVMFunctionInfo(GetReturnType(returnType), FnInfoOpts::None, + argTypes, einfo, {}, RequiredArgs::All); } const CGFunctionInfo & @@ -550,8 +547,7 @@ CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) { assert(MD->isVirtual() && "only methods have thunks"); CanQual<FunctionProtoType> FTP = GetFormalType(MD); CanQualType ArgTys[] = {DeriveThisType(MD->getParent(), MD)}; - return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false, - /*chainCall=*/false, ArgTys, + return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::None, ArgTys, FTP->getExtInfo(), {}, RequiredArgs(1)); } @@ -570,9 +566,8 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD, ArgTys.push_back(Context.IntTy); CallingConv CC = Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true); - return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true, - /*chainCall=*/false, ArgTys, - FunctionType::ExtInfo(CC), {}, + return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::IsInstanceMethod, + ArgTys, FunctionType::ExtInfo(CC), {}, RequiredArgs::All); } @@ -616,10 +611,10 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, SmallVector<CanQualType, 16> argTypes; for (const auto &arg : args) argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty)); + FnInfoOpts opts = chainCall ? FnInfoOpts::IsChainCall : FnInfoOpts::None; return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()), - /*instanceMethod=*/false, chainCall, - argTypes, fnType->getExtInfo(), paramInfos, - required); + opts, argTypes, fnType->getExtInfo(), + paramInfos, required); } /// Figure out the rules for calling a function with the given formal @@ -650,8 +645,8 @@ CodeGenTypes::arrangeBlockFunctionDeclaration(const FunctionProtoType *proto, auto argTypes = getArgTypesForDeclaration(Context, params); return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()), - /*instanceMethod*/ false, /*chainCall*/ false, - argTypes, proto->getExtInfo(), paramInfos, + FnInfoOpts::None, argTypes, + proto->getExtInfo(), paramInfos, RequiredArgs::forPrototypePlus(proto, 1)); } @@ -662,10 +657,9 @@ CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType, SmallVector<CanQualType, 16> argTypes; for (const auto &Arg : args) argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); - return arrangeLLVMFunctionInfo( - GetReturnType(resultType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, FunctionType::ExtInfo(), - /*paramInfos=*/ {}, RequiredArgs::All); + return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None, + argTypes, FunctionType::ExtInfo(), + /*paramInfos=*/{}, RequiredArgs::All); } const CGFunctionInfo & @@ -673,17 +667,17 @@ CodeGenTypes::arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args) { auto argTypes = getArgTypesForDeclaration(Context, args); - return arrangeLLVMFunctionInfo( - GetReturnType(resultType), /*instanceMethod=*/false, /*chainCall=*/false, - argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); + return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None, + argTypes, FunctionType::ExtInfo(), {}, + RequiredArgs::All); } const CGFunctionInfo & CodeGenTypes::arrangeBuiltinFunctionDeclaration(CanQualType resultType, ArrayRef<CanQualType> argTypes) { - return arrangeLLVMFunctionInfo( - resultType, /*instanceMethod=*/false, /*chainCall=*/false, - argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); + return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::None, argTypes, + FunctionType::ExtInfo(), {}, + RequiredArgs::All); } /// Arrange a call to a C++ method, passing the given arguments. @@ -706,15 +700,15 @@ CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args, auto argTypes = getArgTypesForCall(Context, args); FunctionType::ExtInfo info = proto->getExtInfo(); - return arrangeLLVMFunctionInfo( - GetReturnType(proto->getReturnType()), /*instanceMethod=*/true, - /*chainCall=*/false, argTypes, info, paramInfos, required); + return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()), + FnInfoOpts::IsInstanceMethod, argTypes, info, + paramInfos, required); } const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { - return arrangeLLVMFunctionInfo( - getContext().VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, - std::nullopt, FunctionType::ExtInfo(), {}, RequiredArgs::All); + return arrangeLLVMFunctionInfo(getContext().VoidTy, FnInfoOpts::None, + std::nullopt, FunctionType::ExtInfo(), {}, + RequiredArgs::All); } const CGFunctionInfo & @@ -734,12 +728,15 @@ CodeGenTypes::arrangeCall(const CGFunctionInfo &signature, auto argTypes = getArgTypesForCall(Context, args); assert(signature.getRequiredArgs().allowsOptionalArgs()); - return arrangeLLVMFunctionInfo(signature.getReturnType(), - signature.isInstanceMethod(), - signature.isChainCall(), - argTypes, - signature.getExtInfo(), - paramInfos, + FnInfoOpts opts = FnInfoOpts::None; + if (signature.isInstanceMethod()) + opts |= FnInfoOpts::IsInstanceMethod; + if (signature.isChainCall()) + opts |= FnInfoOpts::IsChainCall; + if (signature.isDelegateCall()) + opts |= FnInfoOpts::IsDelegateCall; + return arrangeLLVMFunctionInfo(signature.getReturnType(), opts, argTypes, + signature.getExtInfo(), paramInfos, signature.getRequiredArgs()); } @@ -752,21 +749,24 @@ void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); /// Arrange the argument and result information for an abstract value /// of a given function type. This is the method which all of the /// above functions ultimately defer to. -const CGFunctionInfo & -CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType, - bool instanceMethod, - bool chainCall, - ArrayRef<CanQualType> argTypes, - FunctionType::ExtInfo info, - ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, - RequiredArgs required) { +const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo( + CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes, + FunctionType::ExtInfo info, + ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, + RequiredArgs required) { assert(llvm::all_of(argTypes, [](CanQualType T) { return T.isCanonicalAsParam(); })); // Lookup or create unique function info. llvm::FoldingSetNodeID ID; - CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, paramInfos, - required, resultType, argTypes); + bool isInstanceMethod = + (opts & FnInfoOpts::IsInstanceMethod) == FnInfoOpts::IsInstanceMethod; + bool isChainCall = + (opts & FnInfoOpts::IsChainCall) == FnInfoOpts::IsChainCall; + bool isDelegateCall = + (opts & FnInfoOpts::IsDelegateCall) == FnInfoOpts::IsDelegateCall; + CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall, + info, paramInfos, required, resultType, argTypes); void *insertPos = nullptr; CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos); @@ -776,8 +776,8 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType, unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); // Construct the function info. We co-allocate the ArgInfos. - FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info, - paramInfos, resultType, argTypes, required); + FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall, + info, paramInfos, resultType, argTypes, required); FunctionInfos.InsertNode(FI, insertPos); bool inserted = FunctionsBeingProcessed.insert(FI).second; @@ -812,9 +812,8 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType, return *FI; } -CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, - bool instanceMethod, - bool chainCall, +CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod, + bool chainCall, bool delegateCall, const FunctionType::ExtInfo &info, ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType, @@ -834,6 +833,7 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, FI->ASTCallingConvention = info.getCC(); FI->InstanceMethod = instanceMethod; FI->ChainCall = chainCall; + FI->DelegateCall = delegateCall; FI->CmseNSCall = info.getCmseNSCall(); FI->NoReturn = info.getNoReturn(); FI->ReturnsRetained = info.getProducesResult(); @@ -3989,10 +3989,6 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, QualType type = param->getType(); - if (isInAllocaArgument(CGM.getCXXABI(), type)) { - CGM.ErrorUnsupported(param, "forwarded non-trivially copyable parameter"); - } - // GetAddrOfLocalVar returns a pointer-to-pointer for references, // but the argument needs to be the original pointer. if (type->isReferenceType()) { @@ -5105,7 +5101,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, "indirect argument must be in alloca address space"); bool NeedCopy = false; - if (Addr.getAlignment() < Align && llvm::getOrEnforceKnownAlignment(V, Align.getAsAlign(), *TD) < Align.getAsAlign()) { @@ -5244,30 +5239,50 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType()); if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) { llvm::Type *SrcTy = Src.getElementType(); - uint64_t SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy); - uint64_t DstSize = CGM.getDataLayout().getTypeAllocSize(STy); - - // If the source type is smaller than the destination type of the - // coerce-to logic, copy the source value into a temp alloca the size - // of the destination type to allow loading all of it. The bits past - // the source value are left undef. - if (SrcSize < DstSize) { - Address TempAlloca - = CreateTempAlloca(STy, Src.getAlignment(), - Src.getName() + ".coerce"); - Builder.CreateMemCpy(TempAlloca, Src, SrcSize); - Src = TempAlloca; + llvm::TypeSize SrcTypeSize = + CGM.getDataLayout().getTypeAllocSize(SrcTy); + llvm::TypeSize DstTypeSize = CGM.getDataLayout().getTypeAllocSize(STy); + if (SrcTypeSize.isScalable()) { + assert(STy->containsHomogeneousScalableVectorTypes() && + "ABI only supports structure with homogeneous scalable vector " + "type"); + assert(SrcTypeSize == DstTypeSize && + "Only allow non-fractional movement of structure with " + "homogeneous scalable vector type"); + assert(NumIRArgs == STy->getNumElements()); + + llvm::Value *StoredStructValue = + Builder.CreateLoad(Src, Src.getName() + ".tuple"); + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + llvm::Value *Extract = Builder.CreateExtractValue( + StoredStructValue, i, Src.getName() + ".extract" + Twine(i)); + IRCallArgs[FirstIRArg + i] = Extract; + } } else { - Src = Src.withElementType(STy); - } + uint64_t SrcSize = SrcTypeSize.getFixedValue(); + uint64_t DstSize = DstTypeSize.getFixedValue(); + + // If the source type is smaller than the destination type of the + // coerce-to logic, copy the source value into a temp alloca the size + // of the destination type to allow loading all of it. The bits past + // the source value are left undef. + if (SrcSize < DstSize) { + Address TempAlloca = CreateTempAlloca(STy, Src.getAlignment(), + Src.getName() + ".coerce"); + Builder.CreateMemCpy(TempAlloca, Src, SrcSize); + Src = TempAlloca; + } else { + Src = Src.withElementType(STy); + } - assert(NumIRArgs == STy->getNumElements()); - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - Address EltPtr = Builder.CreateStructGEP(Src, i); - llvm::Value *LI = Builder.CreateLoad(EltPtr); - if (ArgHasMaybeUndefAttr) - LI = Builder.CreateFreeze(LI); - IRCallArgs[FirstIRArg + i] = LI; + assert(NumIRArgs == STy->getNumElements()); + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + Address EltPtr = Builder.CreateStructGEP(Src, i); + llvm::Value *LI = Builder.CreateLoad(EltPtr); + if (ArgHasMaybeUndefAttr) + LI = Builder.CreateFreeze(LI); + IRCallArgs[FirstIRArg + i] = LI; + } } } else { // In the simple case, just pass the coerced loaded value. @@ -5472,6 +5487,30 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::AlwaysInline); } + // The await_suspend call performed by co_await is essentially asynchronous + // to the execution of the coroutine. Inlining it normally into an unsplit + // coroutine can cause miscompilation because the coroutine CFG misrepresents + // the true control flow of the program: things that happen in the + // await_suspend are not guaranteed to happen prior to the resumption of the + // coroutine, and things that happen after the resumption of the coroutine + // (including its exit and the potential deallocation of the coroutine frame) + // are not guaranteed to happen only after the end of await_suspend. + // + // The short-term solution to this problem is to mark the call as uninlinable. + // But we don't want to do this if the call is known to be trivial, which is + // very common. + // + // The long-term solution may introduce patterns like: + // + // call @llvm.coro.await_suspend(ptr %awaiter, ptr %handle, + // ptr @awaitSuspendFn) + // + // Then it is much easier to perform the safety analysis in the middle end. + // If it is safe to inline the call to awaitSuspend, we can replace it in the + // CoroEarly pass. Otherwise we could replace it in the CoroSplit pass. + if (inSuspendBlock() && mayCoroHandleEscape()) + Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoInline); + // Disable inlining inside SEH __try blocks. if (isSEHTryScope()) { Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoInline); @@ -5765,9 +5804,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, DestIsVolatile = false; } - // If the value is offset in memory, apply the offset now. - Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI); - CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); + // An empty record can overlap other data (if declared with + // no_unique_address); omit the store for such types - as there is no + // actual data to store. + if (!isEmptyRecord(getContext(), RetTy, true)) { + // If the value is offset in memory, apply the offset now. + Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI); + CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); + } return convertTempToRValue(DestPtr, RetTy, SourceLocation()); } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCall.h b/contrib/llvm-project/clang/lib/CodeGen/CGCall.h index eaaf10c4eec6..65a7d8e83288 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGCall.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CGCall.h @@ -383,6 +383,35 @@ void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F, const TargetOptions &TargetOpts, bool WillInternalize); +enum class FnInfoOpts { + None = 0, + IsInstanceMethod = 1 << 0, + IsChainCall = 1 << 1, + IsDelegateCall = 1 << 2, +}; + +inline FnInfoOpts operator|(FnInfoOpts A, FnInfoOpts B) { + return static_cast<FnInfoOpts>( + static_cast<std::underlying_type_t<FnInfoOpts>>(A) | + static_cast<std::underlying_type_t<FnInfoOpts>>(B)); +} + +inline FnInfoOpts operator&(FnInfoOpts A, FnInfoOpts B) { + return static_cast<FnInfoOpts>( + static_cast<std::underlying_type_t<FnInfoOpts>>(A) & + static_cast<std::underlying_type_t<FnInfoOpts>>(B)); +} + +inline FnInfoOpts operator|=(FnInfoOpts A, FnInfoOpts B) { + A = A | B; + return A; +} + +inline FnInfoOpts operator&=(FnInfoOpts A, FnInfoOpts B) { + A = A & B; + return A; +} + } // end namespace CodeGen } // end namespace clang diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGClass.cpp index 93e7b54fca04..6ef7d12372d0 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGClass.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGClass.cpp @@ -2927,14 +2927,16 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad( } void CodeGenFunction::EmitForwardingCallToLambda( - const CXXMethodDecl *callOperator, - CallArgList &callArgs) { + const CXXMethodDecl *callOperator, CallArgList &callArgs, + const CGFunctionInfo *calleeFnInfo, llvm::Constant *calleePtr) { // Get the address of the call operator. - const CGFunctionInfo &calleeFnInfo = - CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); - llvm::Constant *calleePtr = - CGM.GetAddrOfFunction(GlobalDecl(callOperator), - CGM.getTypes().GetFunctionType(calleeFnInfo)); + if (!calleeFnInfo) + calleeFnInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); + + if (!calleePtr) + calleePtr = + CGM.GetAddrOfFunction(GlobalDecl(callOperator), + CGM.getTypes().GetFunctionType(*calleeFnInfo)); // Prepare the return slot. const FunctionProtoType *FPT = @@ -2942,8 +2944,8 @@ void CodeGenFunction::EmitForwardingCallToLambda( QualType resultType = FPT->getReturnType(); ReturnValueSlot returnSlot; if (!resultType->isVoidType() && - calleeFnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect && - !hasScalarEvaluationKind(calleeFnInfo.getReturnType())) + calleeFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && + !hasScalarEvaluationKind(calleeFnInfo->getReturnType())) returnSlot = ReturnValueSlot(ReturnValue, resultType.isVolatileQualified(), /*IsUnused=*/false, /*IsExternallyDestructed=*/true); @@ -2954,7 +2956,7 @@ void CodeGenFunction::EmitForwardingCallToLambda( // Now emit our call. auto callee = CGCallee::forDirect(calleePtr, GlobalDecl(callOperator)); - RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs); + RValue RV = EmitCall(*calleeFnInfo, callee, returnSlot, callArgs); // If necessary, copy the returned value into the slot. if (!resultType->isVoidType() && returnSlot.isNull()) { @@ -2996,7 +2998,15 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { EmitForwardingCallToLambda(CallOp, CallArgs); } -void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { +void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { + if (MD->isVariadic()) { + // FIXME: Making this work correctly is nasty because it requires either + // cloning the body of the call operator or making the call operator + // forward. + CGM.ErrorUnsupported(MD, "lambda conversion to variadic function"); + return; + } + const CXXRecordDecl *Lambda = MD->getParent(); // Start building arguments for forwarding call @@ -3007,10 +3017,16 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture"); CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); - // Add the rest of the parameters. + EmitLambdaDelegatingInvokeBody(MD, CallArgs); +} + +void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD, + CallArgList &CallArgs) { + // Add the rest of the forwarded parameters. for (auto *Param : MD->parameters()) EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc()); + const CXXRecordDecl *Lambda = MD->getParent(); const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); // For a generic lambda, find the corresponding call operator specialization // to which the call to the static-invoker shall be forwarded. @@ -3024,10 +3040,21 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { assert(CorrespondingCallOpSpecialization); CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization); } + + // Special lambda forwarding when there are inalloca parameters. + if (hasInAllocaArg(MD)) { + const CGFunctionInfo *ImplFnInfo = nullptr; + llvm::Function *ImplFn = nullptr; + EmitLambdaInAllocaImplFn(CallOp, &ImplFnInfo, &ImplFn); + + EmitForwardingCallToLambda(CallOp, CallArgs, ImplFnInfo, ImplFn); + return; + } + EmitForwardingCallToLambda(CallOp, CallArgs); } -void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { +void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) { if (MD->isVariadic()) { // FIXME: Making this work correctly is nasty because it requires either // cloning the body of the call operator or making the call operator forward. @@ -3035,5 +3062,56 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { return; } - EmitLambdaDelegatingInvokeBody(MD); + // Forward %this argument. + CallArgList CallArgs; + QualType LambdaType = getContext().getRecordType(MD->getParent()); + QualType ThisType = getContext().getPointerType(LambdaType); + llvm::Value *ThisArg = CurFn->getArg(0); + CallArgs.add(RValue::get(ThisArg), ThisType); + + EmitLambdaDelegatingInvokeBody(MD, CallArgs); +} + +void CodeGenFunction::EmitLambdaInAllocaImplFn( + const CXXMethodDecl *CallOp, const CGFunctionInfo **ImplFnInfo, + llvm::Function **ImplFn) { + const CGFunctionInfo &FnInfo = + CGM.getTypes().arrangeCXXMethodDeclaration(CallOp); + llvm::Function *CallOpFn = + cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(CallOp))); + + // Emit function containing the original call op body. __invoke will delegate + // to this function. + SmallVector<CanQualType, 4> ArgTypes; + for (auto I = FnInfo.arg_begin(); I != FnInfo.arg_end(); ++I) + ArgTypes.push_back(I->type); + *ImplFnInfo = &CGM.getTypes().arrangeLLVMFunctionInfo( + FnInfo.getReturnType(), FnInfoOpts::IsDelegateCall, ArgTypes, + FnInfo.getExtInfo(), {}, FnInfo.getRequiredArgs()); + + // Create mangled name as if this was a method named __impl. If for some + // reason the name doesn't look as expected then just tack __impl to the + // front. + // TODO: Use the name mangler to produce the right name instead of using + // string replacement. + StringRef CallOpName = CallOpFn->getName(); + std::string ImplName; + if (size_t Pos = CallOpName.find_first_of("<lambda")) + ImplName = ("?__impl@" + CallOpName.drop_front(Pos)).str(); + else + ImplName = ("__impl" + CallOpName).str(); + + llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName); + if (!Fn) { + Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(**ImplFnInfo), + llvm::GlobalValue::InternalLinkage, ImplName, + CGM.getModule()); + CGM.SetInternalFunctionAttributes(CallOp, Fn, **ImplFnInfo); + + const GlobalDecl &GD = GlobalDecl(CallOp); + const auto *D = cast<FunctionDecl>(GD.getDecl()); + CodeGenFunction(CGM).GenerateCode(GD, Fn, **ImplFnInfo); + CGM.SetLLVMFunctionAttributesForDefinition(D, Fn); + } + *ImplFn = Fn; } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCoroutine.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGCoroutine.cpp index 8437cda79beb..810ae7d51ec1 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGCoroutine.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGCoroutine.cpp @@ -139,6 +139,36 @@ static bool memberCallExpressionCanThrow(const Expr *E) { return true; } +/// Return true when the coroutine handle may escape from the await-suspend +/// (`awaiter.await_suspend(std::coroutine_handle)` expression). +/// Return false only when the coroutine wouldn't escape in the await-suspend +/// for sure. +/// +/// While it is always safe to return true, return falses can bring better +/// performances. +/// +/// See https://github.com/llvm/llvm-project/issues/56301 and +/// https://reviews.llvm.org/D157070 for the example and the full discussion. +/// +/// FIXME: It will be much better to perform such analysis in the middle end. +/// See the comments in `CodeGenFunction::EmitCall` for example. +static bool MayCoroHandleEscape(CoroutineSuspendExpr const &S) { + CXXRecordDecl *Awaiter = + S.getCommonExpr()->getType().getNonReferenceType()->getAsCXXRecordDecl(); + + // Return true conservatively if the awaiter type is not a record type. + if (!Awaiter) + return true; + + // In case the awaiter type is empty, the suspend wouldn't leak the coroutine + // handle. + // + // TODO: We can improve this by looking into the implementation of + // await-suspend and see if the coroutine handle is passed to foreign + // functions. + return !Awaiter->field_empty(); +} + // Emit suspend expression which roughly looks like: // // auto && x = CommonExpr(); @@ -199,8 +229,11 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr}); CGF.CurCoro.InSuspendBlock = true; + CGF.CurCoro.MayCoroHandleEscape = MayCoroHandleEscape(S); auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr()); CGF.CurCoro.InSuspendBlock = false; + CGF.CurCoro.MayCoroHandleEscape = false; + if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) { // Veto suspension if requested by bool returning await_suspend. BasicBlock *RealSuspendBlock = diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp index f049a682cfed..d8eb2aecb87a 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp @@ -391,12 +391,14 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { SourceManager &SM = CGM.getContext().getSourceManager(); StringRef FileName; FileID FID; + std::optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo; if (Loc.isInvalid()) { // The DIFile used by the CU is distinct from the main source file. Call // createFile() below for canonicalization if the source file was specified // with an absolute path. FileName = TheCU->getFile()->getFilename(); + CSInfo = TheCU->getFile()->getChecksum(); } else { PresumedLoc PLoc = SM.getPresumedLoc(Loc); FileName = PLoc.getFilename(); @@ -417,13 +419,14 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { return cast<llvm::DIFile>(V); } + // Put Checksum at a scope where it will persist past the createFile call. SmallString<64> Checksum; - - std::optional<llvm::DIFile::ChecksumKind> CSKind = + if (!CSInfo) { + std::optional<llvm::DIFile::ChecksumKind> CSKind = computeChecksum(FID, Checksum); - std::optional<llvm::DIFile::ChecksumInfo<StringRef>> CSInfo; - if (CSKind) - CSInfo.emplace(*CSKind, Checksum); + if (CSKind) + CSInfo.emplace(*CSKind, Checksum); + } return createFile(FileName, CSInfo, getSource(SM, SM.getFileID(Loc))); } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.h index 1fd08626358b..58ee6dd64c4f 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CGDebugInfo.h @@ -148,7 +148,7 @@ class CGDebugInfo { llvm::BumpPtrAllocator DebugInfoNames; StringRef CWDName; - llvm::StringMap<llvm::TrackingMDRef> DIFileCache; + llvm::DenseMap<const char *, llvm::TrackingMDRef> DIFileCache; llvm::DenseMap<const FunctionDecl *, llvm::TrackingMDRef> SPCache; /// Cache declarations relevant to DW_TAG_imported_declarations (C++ /// using declarations and global alias variables) that aren't covered diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp index b0d6eb05acc2..d99dcdba8e43 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGDecl.cpp @@ -202,7 +202,7 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) { return; llvm::GlobalValue::LinkageTypes Linkage = - CGM.getLLVMLinkageVarDefinition(&D, /*IsConstant=*/false); + CGM.getLLVMLinkageVarDefinition(&D); // FIXME: We need to force the emission/use of a guard variable for // some variables even if we can constant-evaluate them because diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp index be8fb6c274db..a9c88110d6f0 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp @@ -279,8 +279,8 @@ llvm::Function *CodeGenFunction::createTLSAtExitStub( } const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo( - getContext().IntTy, /*instanceMethod=*/false, /*chainCall=*/false, - {getContext().IntTy}, FunctionType::ExtInfo(), {}, RequiredArgs::All); + getContext().IntTy, FnInfoOpts::None, {getContext().IntTy}, + FunctionType::ExtInfo(), {}, RequiredArgs::All); // Get the stub function type, int(*)(int,...). llvm::FunctionType *StubTy = diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp index ed6095f7cfeb..fc16b3133f73 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp @@ -2692,8 +2692,7 @@ static LValue EmitGlobalNamedRegister(const VarDecl *VD, CodeGenModule &CGM) { /// this context. static bool canEmitSpuriousReferenceToVariable(CodeGenFunction &CGF, const DeclRefExpr *E, - const VarDecl *VD, - bool IsConstant) { + const VarDecl *VD) { // For a variable declared in an enclosing scope, do not emit a spurious // reference even if we have a capture, as that will emit an unwarranted // reference to our capture state, and will likely generate worse code than @@ -2726,7 +2725,7 @@ static bool canEmitSpuriousReferenceToVariable(CodeGenFunction &CGF, // We can emit a spurious reference only if the linkage implies that we'll // be emitting a non-interposable symbol that will be retained until link // time. - switch (CGF.CGM.getLLVMLinkageVarDefinition(VD, IsConstant)) { + switch (CGF.CGM.getLLVMLinkageVarDefinition(VD)) { case llvm::GlobalValue::ExternalLinkage: case llvm::GlobalValue::LinkOnceODRLinkage: case llvm::GlobalValue::WeakODRLinkage: @@ -2757,7 +2756,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // constant value directly instead. if (E->isNonOdrUse() == NOUR_Constant && (VD->getType()->isReferenceType() || - !canEmitSpuriousReferenceToVariable(*this, E, VD, true))) { + !canEmitSpuriousReferenceToVariable(*this, E, VD))) { VD->getAnyInitializer(VD); llvm::Constant *Val = ConstantEmitter(*this).emitAbstract( E->getLocation(), *VD->evaluateValue(), VD->getType()); @@ -2859,7 +2858,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // some reason; most likely, because it's in an outer function. } else if (VD->isStaticLocal()) { llvm::Constant *var = CGM.getOrCreateStaticVarDecl( - *VD, CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false)); + *VD, CGM.getLLVMLinkageVarDefinition(VD)); addr = Address( var, ConvertTypeForMem(VD->getType()), getContext().getDeclAlign(VD)); diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp index 353ee56839f3..942daa4aa577 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp @@ -1918,7 +1918,7 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { if (VD->isLocalVarDecl()) { return CGM.getOrCreateStaticVarDecl( - *VD, CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false)); + *VD, CGM.getLLVMLinkageVarDefinition(VD)); } } } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp index a52ec8909b12..124eade4617f 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1667,7 +1667,7 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; auto LinkageForVariable = [&VD, this]() { - return CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); + return CGM.getLLVMLinkageVarDefinition(VD); }; std::vector<llvm::GlobalVariable *> GeneratedRefs; @@ -10151,6 +10151,13 @@ void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); + + // If this is an 'extern' declaration we defer to the canonical definition and + // do not emit an offloading entry. + if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link && + VD->hasExternalStorage()) + return; + if (!Res) { if (CGM.getLangOpts().OpenMPIsTargetDevice) { // Register non-target variables being emitted in device code (debug info @@ -10163,7 +10170,7 @@ void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; auto LinkageForVariable = [&VD, this]() { - return CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); + return CGM.getLLVMLinkageVarDefinition(VD); }; std::vector<llvm::GlobalVariable *> GeneratedRefs; diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenABITypes.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenABITypes.cpp index d3a16a1d5acc..a6073e1188d6 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenABITypes.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenABITypes.cpp @@ -65,9 +65,8 @@ CodeGen::arrangeFreeFunctionCall(CodeGenModule &CGM, ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info, RequiredArgs args) { - return CGM.getTypes().arrangeLLVMFunctionInfo( - returnType, /*instanceMethod=*/false, /*chainCall=*/false, argTypes, - info, {}, args); + return CGM.getTypes().arrangeLLVMFunctionInfo(returnType, FnInfoOpts::None, + argTypes, info, {}, args); } ImplicitCXXConstructorArgs diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp index fab70b66d1d9..7ef893cb1a2d 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp @@ -572,7 +572,7 @@ llvm::ConstantInt * CodeGenFunction::getUBSanFunctionTypeHash(QualType Ty) const { // Remove any (C++17) exception specifications, to allow calling e.g. a // noexcept function through a non-noexcept pointer. - if (!isa<FunctionNoProtoType>(Ty)) + if (!Ty->isFunctionNoProtoType()) Ty = getContext().getFunctionTypeWithExceptionSpec(Ty, EST_None); std::string Mangled; llvm::raw_string_ostream Out(Mangled); @@ -683,6 +683,19 @@ static bool matchesStlAllocatorFn(const Decl *D, const ASTContext &Ctx) { return true; } +bool CodeGenFunction::isInAllocaArgument(CGCXXABI &ABI, QualType Ty) { + const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; +} + +bool CodeGenFunction::hasInAllocaArg(const CXXMethodDecl *MD) { + return getTarget().getTriple().getArch() == llvm::Triple::x86 && + getTarget().getCXXABI().isMicrosoft() && + llvm::any_of(MD->parameters(), [&](ParmVarDecl *P) { + return isInAllocaArgument(CGM.getCXXABI(), P->getType()); + }); +} + /// Return the UBSan prologue signature for \p FD if one is available. static llvm::Constant *getPrologueSignature(CodeGenModule &CGM, const FunctionDecl *FD) { @@ -1447,6 +1460,17 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, // The lambda static invoker function is special, because it forwards or // clones the body of the function call operator (but is actually static). EmitLambdaStaticInvokeBody(cast<CXXMethodDecl>(FD)); + } else if (isa<CXXMethodDecl>(FD) && + isLambdaCallOperator(cast<CXXMethodDecl>(FD)) && + !FnInfo.isDelegateCall() && + cast<CXXMethodDecl>(FD)->getParent()->getLambdaStaticInvoker() && + hasInAllocaArg(cast<CXXMethodDecl>(FD))) { + // If emitting a lambda with static invoker on X86 Windows, change + // the call operator body. + // Make sure that this is a call operator with an inalloca arg and check + // for delegate call to make sure this is the original call op and not the + // new forwarding function for the static invoker. + EmitLambdaInAllocaCallOpBody(cast<CXXMethodDecl>(FD)); } else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) && (cast<CXXMethodDecl>(FD)->isCopyAssignmentOperator() || cast<CXXMethodDecl>(FD)->isMoveAssignmentOperator())) { diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.h index 409f48a04906..28ec2b970072 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.h @@ -334,6 +334,7 @@ public: struct CGCoroInfo { std::unique_ptr<CGCoroData> Data; bool InSuspendBlock = false; + bool MayCoroHandleEscape = false; CGCoroInfo(); ~CGCoroInfo(); }; @@ -347,6 +348,10 @@ public: return isCoroutine() && CurCoro.InSuspendBlock; } + bool mayCoroHandleEscape() const { + return isCoroutine() && CurCoro.MayCoroHandleEscape; + } + /// CurGD - The GlobalDecl for the current function being compiled. GlobalDecl CurGD; @@ -1963,6 +1968,9 @@ private: /// Check if the return value of this function requires sanitization. bool requiresReturnValueCheck() const; + bool isInAllocaArgument(CGCXXABI &ABI, QualType Ty); + bool hasInAllocaArg(const CXXMethodDecl *MD); + llvm::BasicBlock *TerminateLandingPad = nullptr; llvm::BasicBlock *TerminateHandler = nullptr; llvm::SmallVector<llvm::BasicBlock *, 2> TrapBBs; @@ -2227,10 +2235,17 @@ public: void EmitBlockWithFallThrough(llvm::BasicBlock *BB, const Stmt *S); void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator, - CallArgList &CallArgs); + CallArgList &CallArgs, + const CGFunctionInfo *CallOpFnInfo = nullptr, + llvm::Constant *CallOpFn = nullptr); void EmitLambdaBlockInvokeBody(); - void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD); void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD); + void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD, + CallArgList &CallArgs); + void EmitLambdaInAllocaImplFn(const CXXMethodDecl *CallOp, + const CGFunctionInfo **ImplFnInfo, + llvm::Function **ImplFn); + void EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD); void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) { EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV); } diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp index 07a9dec12f6f..f09d1129b128 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp @@ -1974,7 +1974,7 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) { return llvm::GlobalValue::InternalLinkage; } - return getLLVMLinkageForDeclarator(D, Linkage, /*IsConstantVariable=*/false); + return getLLVMLinkageForDeclarator(D, Linkage); } llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) { @@ -2386,7 +2386,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, // functions. If the current target's C++ ABI requires this and this is a // member function, set its alignment accordingly. if (getTarget().getCXXABI().areMemberFunctionsAligned()) { - if (F->getPointerAlignment(getDataLayout()) < 2 && isa<CXXMethodDecl>(D)) + if (isa<CXXMethodDecl>(D) && F->getPointerAlignment(getDataLayout()) < 2) F->setAlignment(std::max(llvm::Align(2), F->getAlign().valueOrOne())); } @@ -3605,6 +3605,13 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Emit declaration of the must-be-emitted declare target variable. if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { + + // If this variable has external storage and doesn't require special + // link handling we defer to its canonical definition. + if (VD->hasExternalStorage() && + Res != OMPDeclareTargetDeclAttr::MT_Link) + return; + bool UnifiedMemoryEnabled = getOpenMPRuntime().hasRequiresUnifiedSharedMemory(); if ((*Res == OMPDeclareTargetDeclAttr::MT_To || @@ -3638,6 +3645,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { if (MustBeEmitted(Global) && MayBeEmittedEagerly(Global)) { // Emit the definition if it can't be deferred. EmitGlobalDefinition(GD); + addEmittedDeferredDecl(GD); return; } @@ -3657,7 +3665,6 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // The value must be emitted, but cannot be emitted eagerly. assert(!MayBeEmittedEagerly(Global)); addDeferredDeclToEmit(GD); - EmittedDeferredDecls[MangledName] = GD; } else { // Otherwise, remember that we saw a deferred decl with this name. The // first use of the mangled name will cause it to move into @@ -4397,7 +4404,6 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we // don't need it anymore). addDeferredDeclToEmit(DDI->second); - EmittedDeferredDecls[DDI->first] = DDI->second; DeferredDecls.erase(DDI); // Otherwise, there are cases we have to worry about where we're @@ -4678,7 +4684,6 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, // Move the potentially referenced deferred decl to the DeferredDeclsToEmit // list, and remove it from DeferredDecls (since we don't need it anymore). addDeferredDeclToEmit(DDI->second); - EmittedDeferredDecls[DDI->first] = DDI->second; DeferredDecls.erase(DDI); } @@ -5221,8 +5226,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, AddGlobalAnnotations(D, GV); // Set the llvm linkage type as appropriate. - llvm::GlobalValue::LinkageTypes Linkage = - getLLVMLinkageVarDefinition(D, GV->isConstant()); + llvm::GlobalValue::LinkageTypes Linkage = getLLVMLinkageVarDefinition(D); // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on // the device. [...]" @@ -5415,8 +5419,9 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context, return false; } -llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( - const DeclaratorDecl *D, GVALinkage Linkage, bool IsConstantVariable) { +llvm::GlobalValue::LinkageTypes +CodeGenModule::getLLVMLinkageForDeclarator(const DeclaratorDecl *D, + GVALinkage Linkage) { if (Linkage == GVA_Internal) return llvm::Function::InternalLinkage; @@ -5486,10 +5491,10 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator( return llvm::GlobalVariable::ExternalLinkage; } -llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageVarDefinition( - const VarDecl *VD, bool IsConstant) { +llvm::GlobalValue::LinkageTypes +CodeGenModule::getLLVMLinkageVarDefinition(const VarDecl *VD) { GVALinkage Linkage = getContext().GetGVALinkageForVariable(VD); - return getLLVMLinkageForDeclarator(VD, Linkage, IsConstant); + return getLLVMLinkageForDeclarator(VD, Linkage); } /// Replace the uses of a function that was declared with a non-proto type. @@ -5701,7 +5706,7 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), DeclTy, LangAS::Default, /*D=*/nullptr); if (const auto *VD = dyn_cast<VarDecl>(GD.getDecl())) - LT = getLLVMLinkageVarDefinition(VD, D->getType().isConstQualified()); + LT = getLLVMLinkageVarDefinition(VD); else LT = getFunctionLinkage(GD); } @@ -6332,8 +6337,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( } // Create a global variable for this lifetime-extended temporary. - llvm::GlobalValue::LinkageTypes Linkage = - getLLVMLinkageVarDefinition(VD, Constant); + llvm::GlobalValue::LinkageTypes Linkage = getLLVMLinkageVarDefinition(VD); if (Linkage == llvm::GlobalVariable::ExternalLinkage) { const VarDecl *InitVD; if (VD->isStaticDataMember() && VD->getAnyInitializer(InitVD) && diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h index 05cb217e2bee..dd97808c7775 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h @@ -361,10 +361,19 @@ private: llvm::DenseMap<llvm::StringRef, GlobalDecl> EmittedDeferredDecls; void addEmittedDeferredDecl(GlobalDecl GD) { - if (!llvm::isa<FunctionDecl>(GD.getDecl())) + // Reemission is only needed in incremental mode. + if (!Context.getLangOpts().IncrementalExtensions) return; - llvm::GlobalVariable::LinkageTypes L = getFunctionLinkage(GD); - if (llvm::GlobalValue::isLinkOnceLinkage(L) || + + // Assume a linkage by default that does not need reemission. + auto L = llvm::GlobalValue::ExternalLinkage; + if (llvm::isa<FunctionDecl>(GD.getDecl())) + L = getFunctionLinkage(GD); + else if (auto *VD = llvm::dyn_cast<VarDecl>(GD.getDecl())) + L = getLLVMLinkageVarDefinition(VD); + + if (llvm::GlobalValue::isInternalLinkage(L) || + llvm::GlobalValue::isLinkOnceLinkage(L) || llvm::GlobalValue::isWeakLinkage(L)) { EmittedDeferredDecls[getMangledName(GD)] = GD; } @@ -1321,12 +1330,11 @@ public: /// Returns LLVM linkage for a declarator. llvm::GlobalValue::LinkageTypes - getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage, - bool IsConstantVariable); + getLLVMLinkageForDeclarator(const DeclaratorDecl *D, GVALinkage Linkage); /// Returns LLVM linkage for a declarator. llvm::GlobalValue::LinkageTypes - getLLVMLinkageVarDefinition(const VarDecl *VD, bool IsConstant); + getLLVMLinkageVarDefinition(const VarDecl *VD); /// Emit all the global annotations. void EmitGlobalAnnotations(); diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenTypes.h b/contrib/llvm-project/clang/lib/CodeGen/CodeGenTypes.h index 9088f77b95c3..a0e846d9a751 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenTypes.h +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenTypes.h @@ -252,13 +252,11 @@ public: /// this. /// /// \param argTypes - must all actually be canonical as params - const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType, - bool instanceMethod, - bool chainCall, - ArrayRef<CanQualType> argTypes, - FunctionType::ExtInfo info, - ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, - RequiredArgs args); + const CGFunctionInfo &arrangeLLVMFunctionInfo( + CanQualType returnType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes, + FunctionType::ExtInfo info, + ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, + RequiredArgs args); /// Compute a new LLVM record layout object for the given record. std::unique_ptr<CGRecordLayout> ComputeRecordLayout(const RecordDecl *D, diff --git a/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp b/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp index 79a926cb9edd..ede9efb019ce 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -2839,7 +2839,7 @@ static bool isThreadWrapperReplaceable(const VarDecl *VD, static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) { llvm::GlobalValue::LinkageTypes VarLinkage = - CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); + CGM.getLLVMLinkageVarDefinition(VD); // For internal linkage variables, we don't need an external or weak wrapper. if (llvm::GlobalValue::isLocalLinkage(VarLinkage)) diff --git a/contrib/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/contrib/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp index a692abaf3b75..a14efbdba76b 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1379,8 +1379,7 @@ llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage( case Dtor_Base: // The base destructor most closely tracks the user-declared constructor, so // we delegate back to the normal declarator case. - return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, - /*IsConstantVariable=*/false); + return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage); case Dtor_Complete: // The complete destructor is like an inline function, but it may be // imported and therefore must be exported as well. This requires changing diff --git a/contrib/llvm-project/clang/lib/CodeGen/Targets/LoongArch.cpp b/contrib/llvm-project/clang/lib/CodeGen/Targets/LoongArch.cpp index 6391a8aeaa67..7483bf6d6d1e 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -148,6 +148,13 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { uint64_t ArraySize = ATy->getSize().getZExtValue(); QualType EltTy = ATy->getElementType(); + // Non-zero-length arrays of empty records make the struct ineligible to be + // passed via FARs in C++. + if (const auto *RTy = EltTy->getAs<RecordType>()) { + if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) && + isEmptyRecord(getContext(), EltTy, true, true)) + return false; + } CharUnits EltSize = getContext().getTypeSizeInChars(EltTy); for (uint64_t i = 0; i < ArraySize; ++i) { if (!detectFARsEligibleStructHelper(EltTy, CurOff, Field1Ty, Field1Off, @@ -163,7 +170,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( // copy constructor are not eligible for the FP calling convention. if (getRecordArgABI(Ty, CGT.getCXXABI())) return false; - if (isEmptyRecord(getContext(), Ty, true)) + if (isEmptyRecord(getContext(), Ty, true, true)) return true; const RecordDecl *RD = RTy->getDecl(); // Unions aren't eligible unless they're empty (which is caught above). @@ -222,6 +229,8 @@ bool LoongArchABIInfo::detectFARsEligibleStruct( if (!detectFARsEligibleStructHelper(Ty, CharUnits::Zero(), Field1Ty, Field1Off, Field2Ty, Field2Off)) return false; + if (!Field1Ty) + return false; // Not really a candidate if we have a single int but no float. if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy()) return false; diff --git a/contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp b/contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp index b6d8ae462675..b12c3025f607 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/Targets/RISCV.cpp @@ -8,7 +8,6 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" -#include "llvm/TargetParser/RISCVTargetParser.h" using namespace clang; using namespace clang::CodeGen; @@ -152,6 +151,13 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { uint64_t ArraySize = ATy->getSize().getZExtValue(); QualType EltTy = ATy->getElementType(); + // Non-zero-length arrays of empty records make the struct ineligible for + // the FP calling convention in C++. + if (const auto *RTy = EltTy->getAs<RecordType>()) { + if (ArraySize != 0 && isa<CXXRecordDecl>(RTy->getDecl()) && + isEmptyRecord(getContext(), EltTy, true, true)) + return false; + } CharUnits EltSize = getContext().getTypeSizeInChars(EltTy); for (uint64_t i = 0; i < ArraySize; ++i) { bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty, @@ -168,7 +174,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, // copy constructor are not eligible for the FP calling convention. if (getRecordArgABI(Ty, CGT.getCXXABI())) return false; - if (isEmptyRecord(getContext(), Ty, true)) + if (isEmptyRecord(getContext(), Ty, true, true)) return true; const RecordDecl *RD = RTy->getDecl(); // Unions aren't eligible unless they're empty (which is caught above). @@ -238,6 +244,8 @@ bool RISCVABIInfo::detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty, NeededArgFPRs = 0; bool IsCandidate = detectFPCCEligibleStructHelper( Ty, CharUnits::Zero(), Field1Ty, Field1Off, Field2Ty, Field2Off); + if (!Field1Ty) + return false; // Not really a candidate if we have a single int but no float. if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy()) return false; @@ -315,11 +323,15 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty) const { assert(VT->getElementType()->isBuiltinType() && "expected builtin type!"); - const auto *BT = VT->getElementType()->castAs<BuiltinType>(); - unsigned EltSize = getContext().getTypeSize(BT); + auto VScale = + getContext().getTargetInfo().getVScaleRange(getContext().getLangOpts()); + // The MinNumElts is simplified from equation: + // NumElts / VScale = + // (EltSize * NumElts / (VScale * RVVBitsPerBlock)) + // * (RVVBitsPerBlock / EltSize) llvm::ScalableVectorType *ResType = - llvm::ScalableVectorType::get(CGT.ConvertType(VT->getElementType()), - llvm::RISCV::RVVBitsPerBlock / EltSize); + llvm::ScalableVectorType::get(CGT.ConvertType(VT->getElementType()), + VT->getNumElements() / VScale->first); return ABIArgInfo::getDirect(ResType); } diff --git a/contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp b/contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp index 31679d899a44..9f5c3258d65c 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/Targets/X86.cpp @@ -140,7 +140,8 @@ class X86_32ABIInfo : public ABIInfo { Class classify(QualType Ty) const; ABIArgInfo classifyReturnType(QualType RetTy, CCState &State) const; - ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const; + ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State, + bool isDelegateCall) const; /// Updates the number of available free registers, returns /// true if any registers were allocated. @@ -737,8 +738,8 @@ void X86_32ABIInfo::runVectorCallFirstPass(CGFunctionInfo &FI, CCState &State) c } } -ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, - CCState &State) const { +ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, + bool isDelegateCall) const { // FIXME: Set alignment on indirect arguments. bool IsFastCall = State.CC == llvm::CallingConv::X86_FastCall; bool IsRegCall = State.CC == llvm::CallingConv::X86_RegCall; @@ -753,6 +754,12 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); if (RAA == CGCXXABI::RAA_Indirect) { return getIndirectResult(Ty, false, State); + } else if (isDelegateCall) { + // Avoid having different alignments on delegate call args by always + // setting the alignment to 4, which is what we do for inallocas. + ABIArgInfo Res = getIndirectResult(Ty, false, State); + Res.setIndirectAlign(CharUnits::fromQuantity(4)); + return Res; } else if (RAA == CGCXXABI::RAA_DirectInMemory) { // The field index doesn't matter, we'll fix it up later. return ABIArgInfo::getInAlloca(/*FieldIndex=*/0); @@ -940,7 +947,8 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const { if (State.IsPreassigned.test(I)) continue; - Args[I].info = classifyArgumentType(Args[I].type, State); + Args[I].info = + classifyArgumentType(Args[I].type, State, FI.isDelegateCall()); UsedInAlloca |= (Args[I].info.getKind() == ABIArgInfo::InAlloca); } diff --git a/contrib/llvm-project/clang/lib/Driver/Driver.cpp b/contrib/llvm-project/clang/lib/Driver/Driver.cpp index 488350169efa..bdbdad9362e1 100644 --- a/contrib/llvm-project/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm-project/clang/lib/Driver/Driver.cpp @@ -4741,13 +4741,8 @@ Action *Driver::ConstructPhaseAction( } case phases::Backend: { if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) { - types::ID Output; - if (Args.hasArg(options::OPT_S)) - Output = types::TY_LTO_IR; - else if (Args.hasArg(options::OPT_ffat_lto_objects)) - Output = types::TY_PP_Asm; - else - Output = types::TY_LTO_BC; + types::ID Output = + Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; return C.MakeAction<BackendJobAction>(Input, Output); } if (isUsingLTO(/* IsOffload */ true) && @@ -4941,6 +4936,12 @@ void Driver::BuildJobs(Compilation &C) const { (void)C.getArgs().hasArg(options::OPT_driver_mode); (void)C.getArgs().hasArg(options::OPT_rsp_quoting); + bool HasAssembleJob = llvm::any_of(C.getJobs(), [](auto &J) { + // Match ClangAs and other derived assemblers of Tool. ClangAs uses a + // longer ShortName "clang integrated assembler" while other assemblers just + // use "assembler". + return strstr(J.getCreator().getShortName(), "assembler"); + }); for (Arg *A : C.getArgs()) { // FIXME: It would be nice to be able to send the argument to the // DiagnosticsEngine, so that extra values, position, and so on could be @@ -4970,7 +4971,7 @@ void Driver::BuildJobs(Compilation &C) const { // already been warned about. if (!IsCLMode() || !A->getOption().matches(options::OPT_UNKNOWN)) { if (A->getOption().hasFlag(options::TargetSpecific) && - !A->isIgnoredTargetSpecific()) { + !A->isIgnoredTargetSpecific() && !HasAssembleJob) { Diag(diag::err_drv_unsupported_opt_for_target) << A->getSpelling() << getTargetTriple(); } else { diff --git a/contrib/llvm-project/clang/lib/Driver/SanitizerArgs.cpp b/contrib/llvm-project/clang/lib/Driver/SanitizerArgs.cpp index c3ce13f93464..12fe55be9113 100644 --- a/contrib/llvm-project/clang/lib/Driver/SanitizerArgs.cpp +++ b/contrib/llvm-project/clang/lib/Driver/SanitizerArgs.cpp @@ -37,6 +37,8 @@ static const SanitizerMask NeedsUbsanCxxRt = SanitizerKind::Vptr | SanitizerKind::CFI; static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr; static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr; +static const SanitizerMask NotAllowedWithExecuteOnly = + SanitizerKind::Function | SanitizerKind::KCFI; static const SanitizerMask RequiresPIE = SanitizerKind::DataFlow | SanitizerKind::Scudo; static const SanitizerMask NeedsUnwindTables = @@ -141,6 +143,16 @@ static std::string describeSanitizeArg(const llvm::opt::Arg *A, /// Sanitizers set. static std::string toString(const clang::SanitizerSet &Sanitizers); +/// Return true if an execute-only target disallows data access to code +/// sections. +static bool isExecuteOnlyTarget(const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) { + if (Triple.isPS5()) + return true; + return Args.hasFlagNoClaim(options::OPT_mexecute_only, + options::OPT_mno_execute_only, false); +} + static void validateSpecialCaseListFormat(const Driver &D, std::vector<std::string> &SCLFiles, unsigned MalformedSCLErrorDiagID, @@ -395,6 +407,22 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, DiagnosedKinds |= SanitizerKind::Function; } } + // -fsanitize=function and -fsanitize=kcfi instrument indirect function + // calls to load a type hash before the function label. Therefore, an + // execute-only target doesn't support the function and kcfi sanitizers. + const llvm::Triple &Triple = TC.getTriple(); + if (isExecuteOnlyTarget(Triple, Args)) { + if (SanitizerMask KindsToDiagnose = + Add & NotAllowedWithExecuteOnly & ~DiagnosedKinds) { + if (DiagnoseErrors) { + std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose); + D.Diag(diag::err_drv_argument_not_allowed_with) + << Desc << Triple.str(); + } + DiagnosedKinds |= KindsToDiagnose; + } + Add &= ~NotAllowedWithExecuteOnly; + } // FIXME: Make CFI on member function calls compatible with cross-DSO CFI. // There are currently two problems: @@ -457,6 +485,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, if (MinimalRuntime) { Add &= ~NotAllowedWithMinimalRuntime; } + // NotAllowedWithExecuteOnly is silently discarded on an execute-only + // target if implicitly enabled through group expansion. + if (isExecuteOnlyTarget(Triple, Args)) + Add &= ~NotAllowedWithExecuteOnly; if (CfiCrossDso) Add &= ~SanitizerKind::CFIMFCall; Add &= Supported; diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp index d60fdbc17968..8dafc3d481c2 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp @@ -427,6 +427,12 @@ ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const { return UnwindTableLevel::None; } +unsigned ToolChain::GetDefaultDwarfVersion() const { + // TODO: Remove the RISC-V special case when R_RISCV_SET_ULEB128 linker + // support becomes more widely available. + return getTriple().isRISCV() ? 4 : 5; +} + Tool *ToolChain::getClang() const { if (!Clang) Clang.reset(new tools::Clang(*this, useIntegratedBackend())); diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp index 97217eba9ca0..bfc86d9f3471 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp @@ -30,6 +30,7 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit(); @@ -38,6 +39,11 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, if (!IsArch32Bit && !IsArch64Bit) llvm_unreachable("Unsupported bit width value."); + if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getSpelling() << D.getTargetTriple(); + } + // Specify the mode in which the as(1) command operates. if (IsArch32Bit) { CmdArgs.push_back("-a32"); diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp index 856ad58f3bd9..65925e9ed610 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" +#include "llvm/TargetParser/Host.h" #include "llvm/TargetParser/LoongArchTargetParser.h" using namespace clang::driver; @@ -126,23 +127,11 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, std::vector<StringRef> &Features) { - StringRef ArchName; - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - if (!llvm::LoongArch::isValidArchName(A->getValue())) { - D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args); - return; - } + std::string ArchName; + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) ArchName = A->getValue(); - } - - // TODO: handle -march=native and -mtune=xx. - - // Select a default arch name. - if (ArchName.empty() && Triple.isLoongArch64()) - ArchName = "loongarch64"; - - if (!ArchName.empty()) - llvm::LoongArch::getArchFeatures(ArchName, Features); + ArchName = postProcessTargetCPUString(ArchName, Triple); + llvm::LoongArch::getArchFeatures(ArchName, Features); // Select floating-point features determined by -mdouble-float, // -msingle-float, -msoft-float and -mfpu. @@ -187,3 +176,25 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, if (Arg *A = Args.getLastArgNoClaim(options::OPT_mfpu_EQ)) A->ignoreTargetSpecific(); } + +std::string loongarch::postProcessTargetCPUString(const std::string &CPU, + const llvm::Triple &Triple) { + std::string CPUString = CPU; + if (CPUString == "native") { + CPUString = llvm::sys::getHostCPUName(); + if (CPUString == "generic") + CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64()); + } + if (CPUString.empty()) + CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64()); + return CPUString; +} + +std::string loongarch::getLoongArchTargetCPU(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple) { + std::string CPU; + // If we have -march, use that. + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + CPU = A->getValue(); + return postProcessTargetCPUString(CPU, Triple); +} diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.h index 0084474e7ed3..d8280cd836f8 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.h +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.h @@ -23,6 +23,12 @@ void getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple, StringRef getLoongArchABI(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple); + +std::string postProcessTargetCPUString(const std::string &CPU, + const llvm::Triple &Triple); + +std::string getLoongArchTargetCPU(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); } // end namespace loongarch } // end namespace tools } // end namespace driver diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp index 286bac2e7a2b..cf2bc63d74ad 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp @@ -267,4 +267,10 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, << A->getSpelling() << Scope; } } + + // -mno-gather, -mno-scatter support + if (Args.hasArg(options::OPT_mno_gather)) + Features.push_back("+prefer-no-gather"); + if (Args.hasArg(options::OPT_mno_scatter)) + Features.push_back("+prefer-no-scatter"); } diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp index adb550d9c5da..47ec36b3a8ff 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp @@ -56,6 +56,7 @@ #include "llvm/Support/YAMLParser.h" #include "llvm/TargetParser/ARMTargetParserCommon.h" #include "llvm/TargetParser/Host.h" +#include "llvm/TargetParser/LoongArchTargetParser.h" #include "llvm/TargetParser/RISCVTargetParser.h" #include <cctype> @@ -1853,10 +1854,20 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, void Clang::AddLoongArchTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + const llvm::Triple &Triple = getToolChain().getTriple(); + CmdArgs.push_back("-target-abi"); - CmdArgs.push_back(loongarch::getLoongArchABI(getToolChain().getDriver(), Args, - getToolChain().getTriple()) - .data()); + CmdArgs.push_back( + loongarch::getLoongArchABI(getToolChain().getDriver(), Args, Triple) + .data()); + + // Handle -mtune. + if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) { + std::string TuneCPU = A->getValue(); + TuneCPU = loongarch::postProcessTargetCPUString(TuneCPU, Triple); + CmdArgs.push_back("-tune-cpu"); + CmdArgs.push_back(Args.MakeArgString(TuneCPU)); + } } void Clang::AddMIPSTargetArgs(const ArgList &Args, @@ -2052,6 +2063,12 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, } else if (V == "vec-extabi") { VecExtabi = true; A->claim(); + } else if (V == "elfv1") { + ABIName = "elfv1"; + A->claim(); + } else if (V == "elfv2") { + ABIName = "elfv2"; + A->claim(); } else if (V != "altivec") // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore // the option if given as we don't have backend support for any targets @@ -7359,22 +7376,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (SplitLTOUnit) CmdArgs.push_back("-fsplit-lto-unit"); - if (Arg *A = Args.getLastArg(options::OPT_ffat_lto_objects, - options::OPT_fno_fat_lto_objects)) { - if (IsUsingLTO && A->getOption().matches(options::OPT_ffat_lto_objects)) { - assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin); - if (!Triple.isOSBinFormatELF()) { - D.Diag(diag::err_drv_unsupported_opt_for_target) - << A->getAsString(Args) << TC.getTripleString(); - } - CmdArgs.push_back(Args.MakeArgString( - Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full"))); - CmdArgs.push_back("-flto-unit"); - CmdArgs.push_back("-ffat-lto-objects"); - A->render(Args, CmdArgs); - } - } - if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel, options::OPT_fno_global_isel)) { CmdArgs.push_back("-mllvm"); diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp index 358d7565f47c..0d6907b8e5c7 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -474,6 +474,10 @@ std::string tools::getCPUName(const Driver &D, const ArgList &Args, case llvm::Triple::wasm32: case llvm::Triple::wasm64: return std::string(getWebAssemblyTargetCPU(Args)); + + case llvm::Triple::loongarch32: + case llvm::Triple::loongarch64: + return loongarch::getLoongArchTargetCPU(Args, T); } } @@ -617,11 +621,6 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, PluginName + Suffix, Plugin); CmdArgs.push_back(Args.MakeArgString(Twine(PluginPrefix) + Plugin)); - } else { - // Tell LLD to find and use .llvm.lto section in regular relocatable object - // files - if (Args.hasArg(options::OPT_ffat_lto_objects)) - CmdArgs.push_back("--fat-lto-objects"); } const char *PluginOptPrefix = IsOSAIX ? "-bplugin_opt:" : "-plugin-opt="; diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp index b64fff8b14be..40038dce47d8 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp @@ -1874,6 +1874,12 @@ static bool findBiarchMultilibs(const Driver &D, .flag("-m64", /*Disallow=*/true) .flag("-mx32") .makeMultilib(); + Multilib Alt32sparc = MultilibBuilder() + .gccSuffix("/sparcv8plus") + .includeSuffix("/sparcv8plus") + .flag("-m32") + .flag("-m64", /*Disallow=*/true) + .makeMultilib(); // GCC toolchain for IAMCU doesn't have crtbegin.o, so look for libgcc.a. FilterNonExistent NonExistent( @@ -1885,10 +1891,14 @@ static bool findBiarchMultilibs(const Driver &D, const bool IsX32 = TargetTriple.isX32(); if (TargetTriple.isArch32Bit() && !NonExistent(Alt32)) Want = WANT64; + if (TargetTriple.isArch32Bit() && !NonExistent(Alt32sparc)) + Want = WANT64; else if (TargetTriple.isArch64Bit() && IsX32 && !NonExistent(Altx32)) Want = WANT64; else if (TargetTriple.isArch64Bit() && !IsX32 && !NonExistent(Alt64)) Want = WANT32; + else if (TargetTriple.isArch64Bit() && !NonExistent(Alt32sparc)) + Want = WANT64; else { if (TargetTriple.isArch32Bit()) Want = NeedsBiarchSuffix ? WANT64 : WANT32; @@ -1919,6 +1929,7 @@ static bool findBiarchMultilibs(const Driver &D, Result.Multilibs.push_back(Alt64); Result.Multilibs.push_back(Alt32); Result.Multilibs.push_back(Altx32); + Result.Multilibs.push_back(Alt32sparc); Result.Multilibs.FilterOut(NonExistent); @@ -1932,7 +1943,8 @@ static bool findBiarchMultilibs(const Driver &D, if (Result.SelectedMultilibs.back() == Alt64 || Result.SelectedMultilibs.back() == Alt32 || - Result.SelectedMultilibs.back() == Altx32) + Result.SelectedMultilibs.back() == Altx32 || + Result.SelectedMultilibs.back() == Alt32sparc) Result.BiarchSibling = Default; return true; @@ -2215,6 +2227,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( // so we need to find those /usr/gcc/*/lib/gcc libdirs and go with // /usr/gcc/<version> as a prefix. + SmallVector<std::pair<GCCVersion, std::string>, 8> SolarisPrefixes; std::string PrefixDir = concat(SysRoot, "/usr/gcc"); std::error_code EC; for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), @@ -2232,8 +2245,13 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( if (!D.getVFS().exists(CandidateLibPath)) continue; - Prefixes.push_back(CandidatePrefix); + SolarisPrefixes.emplace_back( + std::make_pair(CandidateVersion, CandidatePrefix)); } + // Sort in reverse order so GCCInstallationDetector::init picks the latest. + std::sort(SolarisPrefixes.rbegin(), SolarisPrefixes.rend()); + for (auto p : SolarisPrefixes) + Prefixes.emplace_back(p.second); return; } diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp index 7acc600a6aa4..aed4ab1955b4 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp @@ -383,6 +383,10 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA, if (HTC.ShouldLinkCXXStdlib(Args)) HTC.AddCXXStdlibLibArgs(Args, CmdArgs); } + const ToolChain::path_list &LibPaths = HTC.getFilePaths(); + for (const auto &LibPath : LibPaths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); + Args.ClaimAllArgs(options::OPT_L); return; } @@ -441,6 +445,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA, const ToolChain::path_list &LibPaths = HTC.getFilePaths(); for (const auto &LibPath : LibPaths) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); + Args.ClaimAllArgs(options::OPT_L); //---------------------------------------------------------------------------- // diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp index 335a5a88cdfa..de5a69e4ca3f 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp @@ -47,11 +47,24 @@ void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA, Exec, CmdArgs, Inputs, Output)); } +static bool getPIE(const ArgList &Args, const ToolChain &TC) { + if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static) || + Args.hasArg(options::OPT_r)) + return false; + + Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie, + options::OPT_nopie); + if (!A) + return TC.isPIEDefault(Args); + return A->getOption().matches(options::OPT_pie); +} + void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + const bool IsPIE = getPIE(Args, getToolChain()); ArgStringList CmdArgs; // Demangle C++ names in errors @@ -62,6 +75,11 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("_start"); } + if (IsPIE) { + CmdArgs.push_back("-z"); + CmdArgs.push_back("type=pie"); + } + if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); CmdArgs.push_back("-dn"); @@ -113,8 +131,13 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, values_xpg = "values-xpg4.o"; CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath(values_xpg))); - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); + + const char *crtbegin = nullptr; + if (Args.hasArg(options::OPT_shared) || IsPIE) + crtbegin = "crtbeginS.o"; + else + crtbegin = "crtbegin.o"; + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(crtbegin))); // Add crtfastmath.o if available and fast math is enabled. getToolChain().addFastMathRuntimeIfAvailable(Args, CmdArgs); } @@ -151,24 +174,32 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lgcc"); CmdArgs.push_back("-lm"); } + const SanitizerArgs &SA = getToolChain().getSanitizerArgs(Args); if (NeedsSanitizerDeps) { linkSanitizerRuntimeDeps(getToolChain(), CmdArgs); // Work around Solaris/amd64 ld bug when calling __tls_get_addr directly. // However, ld -z relax=transtls is available since Solaris 11.2, but not // in Illumos. - const SanitizerArgs &SA = getToolChain().getSanitizerArgs(Args); if (getToolChain().getTriple().getArch() == llvm::Triple::x86_64 && (SA.needsAsanRt() || SA.needsStatsRt() || (SA.needsUbsanRt() && !SA.requiresMinimalRuntime()))) CmdArgs.push_back("-zrelax=transtls"); } + // Avoid AsanInitInternal cycle, Issue #64126. + if (getToolChain().getTriple().isX86() && SA.needsSharedRt() && + SA.needsAsanRt()) + CmdArgs.push_back("-znow"); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, options::OPT_r)) { - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); + if (Args.hasArg(options::OPT_shared) || IsPIE) + CmdArgs.push_back( + Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); + else + CmdArgs.push_back( + Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); } diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp index 32619bc56f7a..852437b9390f 100644 --- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp +++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp @@ -581,7 +581,8 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { ProbablyBracedList = ProbablyBracedList || (NextTok->is(tok::l_brace) && LBraceStack.back().PrevTok && - LBraceStack.back().PrevTok->is(tok::identifier)); + LBraceStack.back().PrevTok->isOneOf(tok::identifier, + tok::greater)); ProbablyBracedList = ProbablyBracedList || @@ -2464,7 +2465,7 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { const auto *PrevPrev = Prev ? Prev->getPreviousNonComment() : nullptr; const bool Blacklisted = PrevPrev && - (PrevPrev->is(tok::kw___attribute) || + (PrevPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) || (SeenEqual && (PrevPrev->isOneOf(tok::kw_if, tok::kw_while) || PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if)))); diff --git a/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp index c6f958a6077b..0bd4b01ff79d 100644 --- a/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp +++ b/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp @@ -15,6 +15,7 @@ #include "clang/Basic/FileEntry.h" #include "clang/Basic/LangStandard.h" #include "clang/Basic/Sarif.h" +#include "clang/Basic/Stack.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" @@ -1150,6 +1151,10 @@ void ASTFrontendAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); if (!CI.hasPreprocessor()) return; + // This is a fallback: If the client forgets to invoke this, we mark the + // current stack as the bottom. Though not optimal, this could help prevent + // stack overflow during deep recursion. + clang::noteBottomOfStack(); // FIXME: Move the truncation aspect of this into Sema, we delayed this till // here so the source manager would be initialized. diff --git a/contrib/llvm-project/clang/lib/Headers/__clang_cuda_math.h b/contrib/llvm-project/clang/lib/Headers/__clang_cuda_math.h index e447590393ec..6166317f8f9d 100644 --- a/contrib/llvm-project/clang/lib/Headers/__clang_cuda_math.h +++ b/contrib/llvm-project/clang/lib/Headers/__clang_cuda_math.h @@ -36,7 +36,7 @@ // because the OpenMP overlay requires constexpr functions here but prior to // c++14 void return functions could not be constexpr. #pragma push_macro("__DEVICE_VOID__") -#ifdef __OPENMP_NVPTX__ && defined(__cplusplus) && __cplusplus < 201402L +#if defined(__OPENMP_NVPTX__) && defined(__cplusplus) && __cplusplus < 201402L #define __DEVICE_VOID__ static __attribute__((always_inline, nothrow)) #else #define __DEVICE_VOID__ __DEVICE__ diff --git a/contrib/llvm-project/clang/lib/Headers/__clang_hip_libdevice_declares.h b/contrib/llvm-project/clang/lib/Headers/__clang_hip_libdevice_declares.h index ed576027cb5e..f15198b3d9f9 100644 --- a/contrib/llvm-project/clang/lib/Headers/__clang_hip_libdevice_declares.h +++ b/contrib/llvm-project/clang/lib/Headers/__clang_hip_libdevice_declares.h @@ -317,7 +317,7 @@ __device__ __attribute__((pure)) __2f16 __ocml_log_2f16(__2f16); __device__ __attribute__((pure)) __2f16 __ocml_log10_2f16(__2f16); __device__ __attribute__((pure)) __2f16 __ocml_log2_2f16(__2f16); -#if HIP_VERSION_MAJOR * 100 + HIP_VERSION_MINOR >= 560 || 1 +#if HIP_VERSION_MAJOR * 100 + HIP_VERSION_MINOR >= 560 #define __DEPRECATED_SINCE_HIP_560(X) __attribute__((deprecated(X))) #else #define __DEPRECATED_SINCE_HIP_560(X) diff --git a/contrib/llvm-project/clang/lib/Headers/cpuid.h b/contrib/llvm-project/clang/lib/Headers/cpuid.h index 454f74e92f85..1ad6853a97c9 100644 --- a/contrib/llvm-project/clang/lib/Headers/cpuid.h +++ b/contrib/llvm-project/clang/lib/Headers/cpuid.h @@ -328,14 +328,4 @@ static __inline int __get_cpuid_count (unsigned int __leaf, return 1; } -// If MS extensions are enabled, __cpuidex is defined as a builtin which will -// conflict with the __cpuidex definition below. -#ifndef _MSC_EXTENSIONS -static __inline void __cpuidex (int __cpu_info[4], int __leaf, int __subleaf) -{ - __cpuid_count(__leaf, __subleaf, __cpu_info[0], __cpu_info[1], __cpu_info[2], - __cpu_info[3]); -} -#endif - #endif /* __CPUID_H */ diff --git a/contrib/llvm-project/clang/lib/Interpreter/IncrementalExecutor.cpp b/contrib/llvm-project/clang/lib/Interpreter/IncrementalExecutor.cpp index 3f8d60630de4..2c4dfc9a611e 100644 --- a/contrib/llvm-project/clang/lib/Interpreter/IncrementalExecutor.cpp +++ b/contrib/llvm-project/clang/lib/Interpreter/IncrementalExecutor.cpp @@ -92,12 +92,19 @@ llvm::Error IncrementalExecutor::runCtors() const { llvm::Expected<llvm::orc::ExecutorAddr> IncrementalExecutor::getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const { - auto Sym = (NameKind == LinkerName) ? Jit->lookupLinkerMangled(Name) - : Jit->lookup(Name); - - if (!Sym) - return Sym.takeError(); - return Sym; + using namespace llvm::orc; + auto SO = makeJITDylibSearchOrder({&Jit->getMainJITDylib(), + Jit->getPlatformJITDylib().get(), + Jit->getProcessSymbolsJITDylib().get()}); + + ExecutionSession &ES = Jit->getExecutionSession(); + + auto SymOrErr = + ES.lookup(SO, (NameKind == LinkerName) ? ES.intern(Name) + : Jit->mangleAndIntern(Name)); + if (auto Err = SymOrErr.takeError()) + return std::move(Err); + return SymOrErr->getAddress(); } } // end namespace clang diff --git a/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp b/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp index 3b9913ac8ba4..a6f50832950c 100644 --- a/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp +++ b/contrib/llvm-project/clang/lib/Lex/LiteralSupport.cpp @@ -57,6 +57,26 @@ static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target) { } } +static unsigned getEncodingPrefixLen(tok::TokenKind kind) { + switch (kind) { + default: + llvm_unreachable("Unknown token type!"); + case tok::char_constant: + case tok::string_literal: + return 0; + case tok::utf8_char_constant: + case tok::utf8_string_literal: + return 2; + case tok::wide_char_constant: + case tok::wide_string_literal: + case tok::utf16_char_constant: + case tok::utf16_string_literal: + case tok::utf32_char_constant: + case tok::utf32_string_literal: + return 1; + } +} + static CharSourceRange MakeCharSourceRange(const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, @@ -343,7 +363,9 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin, Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf, diag::err_unevaluated_string_invalid_escape_sequence) << StringRef(EscapeBegin, ThisTokBuf - EscapeBegin); + HadError = true; } + return ResultChar; } @@ -1917,9 +1939,22 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){ // Remember if we see any wide or utf-8/16/32 strings. // Also check for illegal concatenations. if (isUnevaluated() && Tok.getKind() != tok::string_literal) { - if (Diags) - Diags->Report(Tok.getLocation(), diag::err_unevaluated_string_prefix); - hadError = true; + if (Diags) { + SourceLocation PrefixEndLoc = Lexer::AdvanceToTokenCharacter( + Tok.getLocation(), getEncodingPrefixLen(Tok.getKind()), SM, + Features); + CharSourceRange Range = + CharSourceRange::getCharRange({Tok.getLocation(), PrefixEndLoc}); + StringRef Prefix(SM.getCharacterData(Tok.getLocation()), + getEncodingPrefixLen(Tok.getKind())); + Diags->Report(Tok.getLocation(), + Features.CPlusPlus26 + ? diag::err_unevaluated_string_prefix + : diag::warn_unevaluated_string_prefix) + << Prefix << Features.CPlusPlus << FixItHint::CreateRemoval(Range); + } + if (Features.CPlusPlus26) + hadError = true; } else if (Tok.isNot(Kind) && Tok.isNot(tok::string_literal)) { if (isOrdinary()) { Kind = Tok.getKind(); diff --git a/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp index c1e09db2b3ee..d9ff6c42c502 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp @@ -1016,10 +1016,23 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) { return nullptr; } - if (isTokenStringLiteral()) - AssertMessage = ParseUnevaluatedStringLiteralExpression(); - else if (getLangOpts().CPlusPlus26) + bool ParseAsExpression = false; + if (getLangOpts().CPlusPlus26) { + for (unsigned I = 0;; ++I) { + const Token &T = GetLookAheadToken(I); + if (T.is(tok::r_paren)) + break; + if (!tok::isStringLiteral(Tok.getKind())) { + ParseAsExpression = true; + break; + } + } + } + + if (ParseAsExpression) AssertMessage = ParseConstantExpressionInExprEvalContext(); + else if (tok::isStringLiteral(Tok.getKind())) + AssertMessage = ParseUnevaluatedStringLiteralExpression(); else { Diag(Tok, diag::err_expected_string_literal) << /*Source='static_assert'*/ 1; diff --git a/contrib/llvm-project/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm-project/clang/lib/Parse/ParseTentative.cpp index b7c83bbeb82e..664337052500 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseTentative.cpp @@ -62,6 +62,7 @@ bool Parser::isCXXDeclarationStatement( case tok::kw_static_assert: case tok::kw__Static_assert: return true; + case tok::coloncolon: case tok::identifier: { if (DisambiguatingWithExpression) { RevertingTentativeParsingAction TPA(*this); diff --git a/contrib/llvm-project/clang/lib/Sema/SemaAvailability.cpp b/contrib/llvm-project/clang/lib/Sema/SemaAvailability.cpp index 05ad42780e50..84c06566387c 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaAvailability.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaAvailability.cpp @@ -123,6 +123,18 @@ ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, const NamedDecl *OffendingDecl) { assert(K != AR_Available && "Expected an unavailable declaration here!"); + // If this was defined using CF_OPTIONS, etc. then ignore the diagnostic. + auto DeclLoc = Ctx->getBeginLoc(); + // This is only a problem in Foundation's C++ implementation for CF_OPTIONS. + if (DeclLoc.isMacroID() && S.getLangOpts().CPlusPlus && + isa<TypedefDecl>(OffendingDecl)) { + StringRef MacroName = S.getPreprocessor().getImmediateMacroName(DeclLoc); + if (MacroName == "CF_OPTIONS" || MacroName == "OBJC_OPTIONS" || + MacroName == "SWIFT_OPTIONS" || MacroName == "NS_OPTIONS") { + return false; + } + } + // Checks if we should emit the availability diagnostic in the context of C. auto CheckContext = [&](const Decl *C) { if (K == AR_NotYetIntroduced) { diff --git a/contrib/llvm-project/clang/lib/Sema/SemaCast.cpp b/contrib/llvm-project/clang/lib/Sema/SemaCast.cpp index d65ecf52c523..b338d601db73 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaCast.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaCast.cpp @@ -935,6 +935,14 @@ void CastOperation::CheckDynamicCast() { << isClangCL; } + // For a dynamic_cast to a final type, IR generation might emit a reference + // to the vtable. + if (DestRecord) { + auto *DestDecl = DestRecord->getAsCXXRecordDecl(); + if (DestDecl->isEffectivelyFinal()) + Self.MarkVTableUsed(OpRange.getBegin(), DestDecl); + } + // Done. Everything else is run-time checks. Kind = CK_Dynamic; } diff --git a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp index a4bf57928470..21b5781a71cd 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp @@ -9154,7 +9154,8 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, bool HasPrototype = (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (D.getDeclSpec().isTypeRep() && - D.getDeclSpec().getRepAsType().get()->isFunctionProtoType()) || + SemaRef.GetTypeFromParser(D.getDeclSpec().getRepAsType(), nullptr) + ->isFunctionProtoType()) || (!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType()); assert( (HasPrototype || !SemaRef.getLangOpts().requiresStrictPrototypes()) && diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp index 2716b6677105..3a5e302cc03a 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp @@ -13880,56 +13880,6 @@ inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS, return InvalidOperands(Loc, LHS, RHS); } -// Diagnose cases where the user write a logical and/or but probably meant a -// bitwise one. We do this when one of the operands is a non-bool integer and -// the other is a constant. -void Sema::diagnoseLogicalInsteadOfBitwise(Expr *Op1, Expr *Op2, - SourceLocation Loc, - BinaryOperatorKind Opc) { - if (Op1->getType()->isIntegerType() && !Op1->getType()->isBooleanType() && - Op2->getType()->isIntegerType() && !Op2->isValueDependent() && - // Don't warn in macros or template instantiations. - !Loc.isMacroID() && !inTemplateInstantiation() && - !Op2->getExprLoc().isMacroID() && - !Op1->getExprLoc().isMacroID()) { - bool IsOp1InMacro = Op1->getExprLoc().isMacroID(); - bool IsOp2InMacro = Op2->getExprLoc().isMacroID(); - - // Exclude the specific expression from triggering the warning. - if (!(IsOp1InMacro && IsOp2InMacro && Op1->getSourceRange() == Op2->getSourceRange())) { - // If the RHS can be constant folded, and if it constant folds to something - // that isn't 0 or 1 (which indicate a potential logical operation that - // happened to fold to true/false) then warn. - // Parens on the RHS are ignored. - // If the RHS can be constant folded, and if it constant folds to something - // that isn't 0 or 1 (which indicate a potential logical operation that - // happened to fold to true/false) then warn. - // Parens on the RHS are ignored. - Expr::EvalResult EVResult; - if (Op2->EvaluateAsInt(EVResult, Context)) { - llvm::APSInt Result = EVResult.Val.getInt(); - if ((getLangOpts().Bool && !Op2->getType()->isBooleanType() && - !Op2->getExprLoc().isMacroID()) || - (Result != 0 && Result != 1)) { - Diag(Loc, diag::warn_logical_instead_of_bitwise) - << Op2->getSourceRange() << (Opc == BO_LAnd ? "&&" : "||"); - // Suggest replacing the logical operator with the bitwise version - Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator) - << (Opc == BO_LAnd ? "&" : "|") - << FixItHint::CreateReplacement( - SourceRange(Loc, getLocForEndOfToken(Loc)), - Opc == BO_LAnd ? "&" : "|"); - if (Opc == BO_LAnd) - // Suggest replacing "Foo() && kNonZero" with "Foo()" - Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant) - << FixItHint::CreateRemoval(SourceRange( - getLocForEndOfToken(Op1->getEndLoc()), Op2->getEndLoc())); - } - } - } - } -} - // C99 6.5.[13,14] inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, @@ -13948,6 +13898,9 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS, } } + if (EnumConstantInBoolContext) + Diag(Loc, diag::warn_enum_constant_in_bool_context); + // WebAssembly tables can't be used with logical operators. QualType LHSTy = LHS.get()->getType(); QualType RHSTy = RHS.get()->getType(); @@ -13958,14 +13911,40 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS, return InvalidOperands(Loc, LHS, RHS); } - if (EnumConstantInBoolContext) { - // Warn when converting the enum constant to a boolean - Diag(Loc, diag::warn_enum_constant_in_bool_context); - } else { - // Diagnose cases where the user write a logical and/or but probably meant a - // bitwise one. - diagnoseLogicalInsteadOfBitwise(LHS.get(), RHS.get(), Loc, Opc); - diagnoseLogicalInsteadOfBitwise(RHS.get(), LHS.get(), Loc, Opc); + // Diagnose cases where the user write a logical and/or but probably meant a + // bitwise one. We do this when the LHS is a non-bool integer and the RHS + // is a constant. + if (!EnumConstantInBoolContext && LHS.get()->getType()->isIntegerType() && + !LHS.get()->getType()->isBooleanType() && + RHS.get()->getType()->isIntegerType() && !RHS.get()->isValueDependent() && + // Don't warn in macros or template instantiations. + !Loc.isMacroID() && !inTemplateInstantiation()) { + // If the RHS can be constant folded, and if it constant folds to something + // that isn't 0 or 1 (which indicate a potential logical operation that + // happened to fold to true/false) then warn. + // Parens on the RHS are ignored. + Expr::EvalResult EVResult; + if (RHS.get()->EvaluateAsInt(EVResult, Context)) { + llvm::APSInt Result = EVResult.Val.getInt(); + if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType() && + !RHS.get()->getExprLoc().isMacroID()) || + (Result != 0 && Result != 1)) { + Diag(Loc, diag::warn_logical_instead_of_bitwise) + << RHS.get()->getSourceRange() << (Opc == BO_LAnd ? "&&" : "||"); + // Suggest replacing the logical operator with the bitwise version + Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator) + << (Opc == BO_LAnd ? "&" : "|") + << FixItHint::CreateReplacement( + SourceRange(Loc, getLocForEndOfToken(Loc)), + Opc == BO_LAnd ? "&" : "|"); + if (Opc == BO_LAnd) + // Suggest replacing "Foo() && kNonZero" with "Foo()" + Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant) + << FixItHint::CreateRemoval( + SourceRange(getLocForEndOfToken(LHS.get()->getEndLoc()), + RHS.get()->getEndLoc())); + } + } } if (!Context.getLangOpts().CPlusPlus) { diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp index 423d5372a6f6..1cff4a75790e 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp @@ -19,6 +19,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" @@ -9072,16 +9073,24 @@ Sema::BuildExprRequirement( MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray(), /*Final=*/false); MLTAL.addOuterRetainedLevels(TPL->getDepth()); - Expr *IDC = Param->getTypeConstraint()->getImmediatelyDeclaredConstraint(); + const TypeConstraint *TC = Param->getTypeConstraint(); + assert(TC && "Type Constraint cannot be null here"); + auto *IDC = TC->getImmediatelyDeclaredConstraint(); + assert(IDC && "ImmediatelyDeclaredConstraint can't be null here."); ExprResult Constraint = SubstExpr(IDC, MLTAL); if (Constraint.isInvalid()) { - Status = concepts::ExprRequirement::SS_ExprSubstitutionFailure; - } else { - SubstitutedConstraintExpr = - cast<ConceptSpecializationExpr>(Constraint.get()); - if (!SubstitutedConstraintExpr->isSatisfied()) - Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied; - } + return new (Context) concepts::ExprRequirement( + concepts::createSubstDiagAt(*this, IDC->getExprLoc(), + [&](llvm::raw_ostream &OS) { + IDC->printPretty(OS, /*Helper=*/nullptr, + getPrintingPolicy()); + }), + IsSimple, NoexceptLoc, ReturnTypeRequirement); + } + SubstitutedConstraintExpr = + cast<ConceptSpecializationExpr>(Constraint.get()); + if (!SubstitutedConstraintExpr->isSatisfied()) + Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied; } return new (Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc, ReturnTypeRequirement, Status, diff --git a/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp index c4f4edb6666c..d1ff688c2a21 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp @@ -513,42 +513,21 @@ void LookupResult::resolveKind() { const NamedDecl *HasNonFunction = nullptr; llvm::SmallVector<const NamedDecl *, 4> EquivalentNonFunctions; - llvm::BitVector RemovedDecls(N); - for (unsigned I = 0; I < N; I++) { + unsigned UniqueTagIndex = 0; + + unsigned I = 0; + while (I < N) { const NamedDecl *D = Decls[I]->getUnderlyingDecl(); D = cast<NamedDecl>(D->getCanonicalDecl()); // Ignore an invalid declaration unless it's the only one left. // Also ignore HLSLBufferDecl which not have name conflict with other Decls. - if ((D->isInvalidDecl() || isa<HLSLBufferDecl>(D)) && - N - RemovedDecls.count() > 1) { - RemovedDecls.set(I); + if ((D->isInvalidDecl() || isa<HLSLBufferDecl>(D)) && !(I == 0 && N == 1)) { + Decls[I] = Decls[--N]; continue; } - // C++ [basic.scope.hiding]p2: - // A class name or enumeration name can be hidden by the name of - // an object, function, or enumerator declared in the same - // scope. If a class or enumeration name and an object, function, - // or enumerator are declared in the same scope (in any order) - // with the same name, the class or enumeration name is hidden - // wherever the object, function, or enumerator name is visible. - if (HideTags && isa<TagDecl>(D)) { - bool Hidden = false; - for (auto *OtherDecl : Decls) { - if (canHideTag(OtherDecl) && - getContextForScopeMatching(OtherDecl)->Equals( - getContextForScopeMatching(Decls[I]))) { - RemovedDecls.set(I); - Hidden = true; - break; - } - } - if (Hidden) - continue; - } - std::optional<unsigned> ExistingI; // Redeclarations of types via typedef can occur both within a scope @@ -581,7 +560,7 @@ void LookupResult::resolveKind() { if (isPreferredLookupResult(getSema(), getLookupKind(), Decls[I], Decls[*ExistingI])) Decls[*ExistingI] = Decls[I]; - RemovedDecls.set(I); + Decls[I] = Decls[--N]; continue; } @@ -592,6 +571,7 @@ void LookupResult::resolveKind() { } else if (isa<TagDecl>(D)) { if (HasTag) Ambiguous = true; + UniqueTagIndex = I; HasTag = true; } else if (isa<FunctionTemplateDecl>(D)) { HasFunction = true; @@ -607,7 +587,7 @@ void LookupResult::resolveKind() { if (getSema().isEquivalentInternalLinkageDeclaration(HasNonFunction, D)) { EquivalentNonFunctions.push_back(D); - RemovedDecls.set(I); + Decls[I] = Decls[--N]; continue; } @@ -615,6 +595,28 @@ void LookupResult::resolveKind() { } HasNonFunction = D; } + I++; + } + + // C++ [basic.scope.hiding]p2: + // A class name or enumeration name can be hidden by the name of + // an object, function, or enumerator declared in the same + // scope. If a class or enumeration name and an object, function, + // or enumerator are declared in the same scope (in any order) + // with the same name, the class or enumeration name is hidden + // wherever the object, function, or enumerator name is visible. + // But it's still an error if there are distinct tag types found, + // even if they're not visible. (ref?) + if (N > 1 && HideTags && HasTag && !Ambiguous && + (HasFunction || HasNonFunction || HasUnresolved)) { + const NamedDecl *OtherDecl = Decls[UniqueTagIndex ? 0 : N - 1]; + if (isa<TagDecl>(Decls[UniqueTagIndex]->getUnderlyingDecl()) && + getContextForScopeMatching(Decls[UniqueTagIndex])->Equals( + getContextForScopeMatching(OtherDecl)) && + canHideTag(OtherDecl)) + Decls[UniqueTagIndex] = Decls[--N]; + else + Ambiguous = true; } // FIXME: This diagnostic should really be delayed until we're done with @@ -623,15 +625,9 @@ void LookupResult::resolveKind() { getSema().diagnoseEquivalentInternalLinkageDeclarations( getNameLoc(), HasNonFunction, EquivalentNonFunctions); - // Remove decls by replacing them with decls from the end (which - // means that we need to iterate from the end) and then truncating - // to the new size. - for (int I = RemovedDecls.find_last(); I >= 0; I = RemovedDecls.find_prev(I)) - Decls[I] = Decls[--N]; Decls.truncate(N); - if ((HasNonFunction && (HasFunction || HasUnresolved)) || - (HideTags && HasTag && (HasFunction || HasNonFunction || HasUnresolved))) + if (HasNonFunction && (HasFunction || HasUnresolved)) Ambiguous = true; if (Ambiguous) diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp index 8702e2ca3a1b..394006a57747 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2276,9 +2276,9 @@ QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType( getPackIndex(Pack), Arg, TL.getNameLoc()); } -template<typename EntityPrinter> static concepts::Requirement::SubstitutionDiagnostic * -createSubstDiag(Sema &S, TemplateDeductionInfo &Info, EntityPrinter Printer) { +createSubstDiag(Sema &S, TemplateDeductionInfo &Info, + concepts::EntityPrinter Printer) { SmallString<128> Message; SourceLocation ErrorLoc; if (Info.hasSFINAEDiagnostic()) { @@ -2302,6 +2302,19 @@ createSubstDiag(Sema &S, TemplateDeductionInfo &Info, EntityPrinter Printer) { StringRef(MessageBuf, Message.size())}; } +concepts::Requirement::SubstitutionDiagnostic * +concepts::createSubstDiagAt(Sema &S, SourceLocation Location, + EntityPrinter Printer) { + SmallString<128> Entity; + llvm::raw_svector_ostream OS(Entity); + Printer(OS); + char *EntityBuf = new (S.Context) char[Entity.size()]; + llvm::copy(Entity, EntityBuf); + return new (S.Context) concepts::Requirement::SubstitutionDiagnostic{ + /*SubstitutedEntity=*/StringRef(EntityBuf, Entity.size()), + /*DiagLoc=*/Location, /*DiagMessage=*/StringRef()}; +} + ExprResult TemplateInstantiator::TransformRequiresTypeParams( SourceLocation KWLoc, SourceLocation RBraceLoc, const RequiresExpr *RE, RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> Params, diff --git a/contrib/llvm-project/clang/lib/Sema/TreeTransform.h b/contrib/llvm-project/clang/lib/Sema/TreeTransform.h index 10b3587885e3..097e81ea7d45 100644 --- a/contrib/llvm-project/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm-project/clang/lib/Sema/TreeTransform.h @@ -7478,6 +7478,10 @@ StmtResult TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr) { Sema::CompoundScopeRAII CompoundScope(getSema()); + Sema::FPFeaturesStateRAII FPSave(getSema()); + if (S->hasStoredFPFeatures()) + getSema().resetFPOptions( + S->getStoredFPFeatures().applyOverrides(getSema().getLangOpts())); const Stmt *ExprResult = S->getStmtExprResult(); bool SubStmtInvalid = false; diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp index 10c92f8d2149..c8cbee14be4f 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp @@ -181,6 +181,13 @@ namespace clang { static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index, NamedDecl *D); + /// Commit to a primary definition of the class RD, which is known to be + /// a definition of the class. We might not have read the definition data + /// for it yet. If we haven't then allocate placeholder definition data + /// now too. + static CXXRecordDecl *getOrFakePrimaryClassDefinition(ASTReader &Reader, + CXXRecordDecl *RD); + /// Results from loading a RedeclarableDecl. class RedeclarableResult { Decl *MergeWith; @@ -598,7 +605,13 @@ void ASTDeclReader::VisitDecl(Decl *D) { auto *LexicalDC = readDeclAs<DeclContext>(); if (!LexicalDC) LexicalDC = SemaDC; - DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC); + // If the context is a class, we might not have actually merged it yet, in + // the case where the definition comes from an update record. + DeclContext *MergedSemaDC; + if (auto *RD = dyn_cast<CXXRecordDecl>(SemaDC)) + MergedSemaDC = getOrFakePrimaryClassDefinition(Reader, RD); + else + MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC); // Avoid calling setLexicalDeclContext() directly because it uses // Decl::getASTContext() internally which is unsafe during derialization. D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC, @@ -3198,6 +3211,32 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint64_t LocalOffset) { return LocalOffset + M.GlobalBitOffset; } +CXXRecordDecl * +ASTDeclReader::getOrFakePrimaryClassDefinition(ASTReader &Reader, + CXXRecordDecl *RD) { + // Try to dig out the definition. + auto *DD = RD->DefinitionData; + if (!DD) + DD = RD->getCanonicalDecl()->DefinitionData; + + // If there's no definition yet, then DC's definition is added by an update + // record, but we've not yet loaded that update record. In this case, we + // commit to DC being the canonical definition now, and will fix this when + // we load the update record. + if (!DD) { + DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD); + RD->setCompleteDefinition(true); + RD->DefinitionData = DD; + RD->getCanonicalDecl()->DefinitionData = DD; + + // Track that we did this horrible thing so that we can fix it later. + Reader.PendingFakeDefinitionData.insert( + std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake)); + } + + return DD->Definition; +} + /// Find the context in which we should search for previous declarations when /// looking for declarations to merge. DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, @@ -3205,29 +3244,8 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, if (auto *ND = dyn_cast<NamespaceDecl>(DC)) return ND->getOriginalNamespace(); - if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) { - // Try to dig out the definition. - auto *DD = RD->DefinitionData; - if (!DD) - DD = RD->getCanonicalDecl()->DefinitionData; - - // If there's no definition yet, then DC's definition is added by an update - // record, but we've not yet loaded that update record. In this case, we - // commit to DC being the canonical definition now, and will fix this when - // we load the update record. - if (!DD) { - DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD); - RD->setCompleteDefinition(true); - RD->DefinitionData = DD; - RD->getCanonicalDecl()->DefinitionData = DD; - - // Track that we did this horrible thing so that we can fix it later. - Reader.PendingFakeDefinitionData.insert( - std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake)); - } - - return DD->Definition; - } + if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) + return getOrFakePrimaryClassDefinition(Reader, RD); if (auto *RD = dyn_cast<RecordDecl>(DC)) return RD->getDefinition(); diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp index 59dbc36d24e8..8dd78152bd68 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp @@ -580,7 +580,7 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { } void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { - static_assert(DeclContext::NumFunctionDeclBits == 30, + static_assert(DeclContext::NumFunctionDeclBits == 31, "You need to update the serializer after you change the " "FunctionDeclBits"); @@ -1495,7 +1495,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { } void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - static_assert(DeclContext::NumCXXConstructorDeclBits == 21, + static_assert(DeclContext::NumCXXConstructorDeclBits == 20, "You need to update the serializer after you change the " "CXXConstructorDeclBits"); diff --git a/contrib/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc b/contrib/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc index a08ec11e77a4..b46bd2e4d7a4 100644 --- a/contrib/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc +++ b/contrib/llvm-project/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc @@ -3773,6 +3773,33 @@ SYMBOL(viewable_range, std::ranges::, <ranges>) SYMBOL(wistream_view, std::ranges::, <ranges>) SYMBOL(zip_transform_view, std::ranges::, <ranges>) SYMBOL(zip_view, std::ranges::, <ranges>) +SYMBOL(all, std::ranges::views::, <ranges>) +SYMBOL(all_t, std::ranges::views::, <ranges>) +SYMBOL(as_const, std::ranges::views::, <ranges>) +SYMBOL(as_rvalue, std::ranges::views::, <ranges>) +SYMBOL(common, std::ranges::views::, <ranges>) +SYMBOL(counted, std::ranges::views::, <ranges>) +SYMBOL(drop, std::ranges::views::, <ranges>) +SYMBOL(drop_while, std::ranges::views::, <ranges>) +SYMBOL(elements, std::ranges::views::, <ranges>) +SYMBOL(empty, std::ranges::views::, <ranges>) +SYMBOL(filter, std::ranges::views::, <ranges>) +SYMBOL(iota, std::ranges::views::, <ranges>) +SYMBOL(istream, std::ranges::views::, <ranges>) +SYMBOL(istream, std::ranges::views::, <iosfwd>) +SYMBOL(join, std::ranges::views::, <ranges>) +SYMBOL(join_with, std::ranges::views::, <ranges>) +SYMBOL(keys, std::ranges::views::, <ranges>) +SYMBOL(lazy_split, std::ranges::views::, <ranges>) +SYMBOL(reverse, std::ranges::views::, <ranges>) +SYMBOL(single, std::ranges::views::, <ranges>) +SYMBOL(split, std::ranges::views::, <ranges>) +SYMBOL(take, std::ranges::views::, <ranges>) +SYMBOL(take_while, std::ranges::views::, <ranges>) +SYMBOL(transform, std::ranges::views::, <ranges>) +SYMBOL(values, std::ranges::views::, <ranges>) +SYMBOL(zip, std::ranges::views::, <ranges>) +SYMBOL(zip_transform, std::ranges::views::, <ranges>) SYMBOL(ECMAScript, std::regex_constants::, <regex>) SYMBOL(awk, std::regex_constants::, <regex>) SYMBOL(basic, std::regex_constants::, <regex>) @@ -3817,3 +3844,30 @@ SYMBOL(get_id, std::this_thread::, <thread>) SYMBOL(sleep_for, std::this_thread::, <thread>) SYMBOL(sleep_until, std::this_thread::, <thread>) SYMBOL(yield, std::this_thread::, <thread>) +SYMBOL(all, std::views::, <ranges>) +SYMBOL(all_t, std::views::, <ranges>) +SYMBOL(as_const, std::views::, <ranges>) +SYMBOL(as_rvalue, std::views::, <ranges>) +SYMBOL(common, std::views::, <ranges>) +SYMBOL(counted, std::views::, <ranges>) +SYMBOL(drop, std::views::, <ranges>) +SYMBOL(drop_while, std::views::, <ranges>) +SYMBOL(elements, std::views::, <ranges>) +SYMBOL(empty, std::views::, <ranges>) +SYMBOL(filter, std::views::, <ranges>) +SYMBOL(iota, std::views::, <ranges>) +SYMBOL(istream, std::views::, <ranges>) +SYMBOL(istream, std::views::, <iosfwd>) +SYMBOL(join, std::views::, <ranges>) +SYMBOL(join_with, std::views::, <ranges>) +SYMBOL(keys, std::views::, <ranges>) +SYMBOL(lazy_split, std::views::, <ranges>) +SYMBOL(reverse, std::views::, <ranges>) +SYMBOL(single, std::views::, <ranges>) +SYMBOL(split, std::views::, <ranges>) +SYMBOL(take, std::views::, <ranges>) +SYMBOL(take_while, std::views::, <ranges>) +SYMBOL(transform, std::views::, <ranges>) +SYMBOL(values, std::views::, <ranges>) +SYMBOL(zip, std::views::, <ranges>) +SYMBOL(zip_transform, std::views::, <ranges>) |