diff options
80 files changed, 1600 insertions, 989 deletions
diff --git a/benchmark.txt b/benchmark.txt new file mode 100644 index 0000000..428114a --- /dev/null +++ b/benchmark.txt @@ -0,0 +1,91 @@ +stage1-O3: + +Benchmark Old New +kimwitu++ 42984M 43445M (+1.07%) +sqlite3 38976M 39006M (+0.08%) +consumer-typeset 35207M 35272M (+0.18%) +Bullet 104230M 105079M (+0.82%) +tramp3d-v4 87692M 87953M (+0.30%) +mafft 36675M 36746M (+0.19%) +ClamAV 55998M 56096M (+0.17%) +lencod 67627M 67727M (+0.15%) +SPASS 47456M 47609M (+0.32%) +7zip 214160M 217285M (+1.46%) +geomean 61396M 61686M (+0.47%) +stage1-ReleaseThinLTO: + +Benchmark Old New +kimwitu++ 53856M 54341M (+0.90%) +sqlite3 51098M 51104M (+0.01%) +consumer-typeset 49397M 49473M (+0.15%) +Bullet 98328M 99182M (+0.87%) +tramp3d-v4 142518M 142862M (+0.24%) +mafft 31630M 31701M (+0.22%) +ClamAV 74595M 74691M (+0.13%) +lencod 116718M 116741M (+0.02%) +SPASS 66986M 67120M (+0.20%) +7zip 266444M 269535M (+1.16%) +geomean 78912M 79220M (+0.39%) +stage1-ReleaseLTO-g: + +Benchmark Old New +kimwitu++ 58953M 59413M (+0.78%) +sqlite3 62117M 62104M (-0.02%) +consumer-typeset 55231M 55311M (+0.15%) +Bullet 111542M 112397M (+0.77%) +tramp3d-v4 171205M 171520M (+0.18%) +mafft 39383M 39452M (+0.17%) +ClamAV 86874M 86962M (+0.10%) +lencod 134904M 135012M (+0.08%) +SPASS 78556M 78680M (+0.16%) +7zip 273629M 276683M (+1.12%) +geomean 90854M 91170M (+0.35%) +stage1-O0-g: + +Benchmark Old New +kimwitu++ 24880M 25346M (+1.87%) +sqlite3 4819M 4831M (+0.25%) +consumer-typeset 12581M 12648M (+0.54%) +Bullet 64850M 65658M (+1.25%) +tramp3d-v4 21204M 21503M (+1.41%) +mafft 6744M 6812M (+1.02%) +ClamAV 13666M 13766M (+0.73%) +lencod 12768M 12861M (+0.72%) +SPASS 14417M 14560M (+0.99%) +7zip 142702M 145480M (+1.95%) +geomean 18624M 18824M (+1.07%) +stage2-O3: + +Benchmark Old New +kimwitu++ 38237M 38648M (+1.07%) +sqlite3 34510M 34521M (+0.03%) +consumer-typeset 31500M 31555M (+0.17%) +Bullet 91970M 92608M (+0.69%) +tramp3d-v4 77162M 77411M (+0.32%) +mafft 32367M 32426M (+0.18%) +ClamAV 49676M 49761M (+0.17%) +lencod 60029M 60110M (+0.14%) +SPASS 42203M 42319M (+0.27%) +7zip 189874M 192365M (+1.31%) +geomean 54428M 54665M (+0.44%) +stage2-O0-g: + +Benchmark Old New +kimwitu++ 21908M 22281M (+1.71%) +sqlite3 4153M 4161M (+0.19%) +consumer-typeset 11226M 11286M (+0.53%) +Bullet 56719M 57407M (+1.21%) +tramp3d-v4 18519M 18754M (+1.27%) +mafft 5971M 6031M (+1.00%) +ClamAV 12197M 12284M (+0.71%) +lencod 11286M 11366M (+0.71%) +SPASS 12839M 12969M (+1.01%) +7zip 126866M 129246M (+1.88%) +geomean 16433M 16601M (+1.02%) +clang build: + +Metric Old New +instructions:u 32641635M 33228307M (+1.80%) +wall-time 558.38s 568.45s (+1.80%) +size-file 130961KiB 130988KiB (+0.02%) +size-file (stage1) 131043KiB 131064KiB (+0.02%) diff --git a/clang-tools-extra/test/clang-change-namespace/lambda-function.cpp b/clang-tools-extra/test/clang-change-namespace/lambda-function.cpp index 452983e..9fd6c5e 100644 --- a/clang-tools-extra/test/clang-change-namespace/lambda-function.cpp +++ b/clang-tools-extra/test/clang-change-namespace/lambda-function.cpp @@ -22,10 +22,8 @@ namespace nb { void f(function<void(int)> func, int param) { func(param); } void g() { f([](int x) {}, 1); } -// x::X in function type parameter list will have translation unit context, so -// we simply replace it with fully-qualified name. using TX = function<x::X(x::X)>; -// CHECK: using TX = function<X(x::X)>; +// CHECK: using TX = function<X(X)>; class A {}; using TA = function<A(A)>; diff --git a/clang/include/clang/AST/ASTLambda.h b/clang/include/clang/AST/ASTLambda.h index 646cb57..ae38e57 100644 --- a/clang/include/clang/AST/ASTLambda.h +++ b/clang/include/clang/AST/ASTLambda.h @@ -79,17 +79,6 @@ inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) { dyn_cast<CXXMethodDecl>(DC)); } -inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization( - const DeclContext *DC) { - const auto *MD = dyn_cast<CXXMethodDecl>(DC); - if (!MD) return false; - const CXXRecordDecl *LambdaClass = MD->getParent(); - if (LambdaClass && LambdaClass->isGenericLambda()) - return (isLambdaCallOperator(MD) || MD->isLambdaStaticInvoker()) && - MD->isFunctionTemplateSpecialization(); - return false; -} - // This returns the parent DeclContext ensuring that the correct // parent DeclContext is returned for Lambdas inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) { diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 0600ecc..8f7b620 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -986,6 +986,11 @@ protected: LLVM_PREFERRED_TYPE(bool) unsigned IsObjCMethodParam : 1; + /// Whether this parameter was initially created in a context with a + /// different template depth. + LLVM_PREFERRED_TYPE(bool) + unsigned HasLazyTemplateDepth : 1; + /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. /// Otherwise, the number of function parameter scopes enclosing /// the function parameter scope in which this parameter was @@ -1719,7 +1724,8 @@ public: }; /// Represents a parameter to a function. -class ParmVarDecl : public VarDecl { +class ParmVarDecl final : public VarDecl, + private llvm::TrailingObjects<ParmVarDecl, uint16_t> { public: enum { MaxFunctionScopeDepth = 255 }; enum { MaxFunctionScopeIndex = 255 }; @@ -1727,13 +1733,20 @@ public: protected: ParmVarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) + TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg, + std::optional<unsigned> TemplateDepth) : VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) { assert(ParmVarDeclBits.HasInheritedDefaultArg == false); assert(ParmVarDeclBits.DefaultArgKind == DAK_None); assert(ParmVarDeclBits.IsKNRPromoted == false); assert(ParmVarDeclBits.IsObjCMethodParam == false); setDefaultArg(DefArg); + ParmVarDeclBits.HasLazyTemplateDepth = bool(TemplateDepth); + if (TemplateDepth) { + assert(*TemplateDepth != + Decl::castFromDeclContext(DC)->getTemplateDepth()); + *getTrailingObjects<uint16_t>() = *TemplateDepth; + } } public: @@ -1741,7 +1754,8 @@ public: SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, - Expr *DefArg); + Expr *DefArg, + std::optional<unsigned> TemplateDepth); static ParmVarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); @@ -1872,6 +1886,12 @@ public: ParmVarDeclBits.HasInheritedDefaultArg = I; } + unsigned getTemplateDepth() const { + if (numTrailingObjects(OverloadToken<uint16_t>())) + return *getTrailingObjects<uint16_t>(); + return Decl::castFromDeclContext(getDeclContext())->getTemplateDepth(); + } + QualType getOriginalType() const; /// Sets the function declaration that owns this @@ -1885,11 +1905,16 @@ public: static bool classofKind(Kind K) { return K == ParmVar; } private: + friend TrailingObjects; friend class ASTDeclReader; enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 }; SourceLocation ExplicitObjectParameterIntroducerLoc; + size_t numTrailingObjects(OverloadToken<uint16_t>) const { + return ParmVarDeclBits.HasLazyTemplateDepth; + } + void setParameterIndex(unsigned parameterIndex) { if (parameterIndex >= ParameterIndexSentinel) { setParameterIndexLarge(parameterIndex); diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index ee662ed..4b4fd5a 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -930,7 +930,8 @@ public: /// Determine the number of levels of template parameter surrounding this /// declaration. - unsigned getTemplateDepth() const; + unsigned + getTemplateDepth(ArrayRef<TemplateArgument> SpecArgs = std::nullopt) const; /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this /// scoped decl is defined outside the current function or method. This is @@ -1995,6 +1996,16 @@ class DeclContext { uint64_t CanAvoidCopyToHeap : 1; }; + class RequiresExprBodyDeclBitfields { + friend class RequiresExprBodyDecl; + /// For the bits in DeclContextBitfields. + LLVM_PREFERRED_TYPE(DeclContextBitfields) + uint64_t : NumDeclContextBits; + + LLVM_PREFERRED_TYPE(unsigned) + uint64_t NumContextArgsOrNoContext : 20; + }; + /// Number of inherited and non-inherited bits in BlockDeclBitfields. enum { NumBlockDeclBits = NumDeclContextBits + 5 }; @@ -2028,6 +2039,7 @@ protected: ObjCContainerDeclBitfields ObjCContainerDeclBits; LinkageSpecDeclBitfields LinkageSpecDeclBits; BlockDeclBitfields BlockDeclBits; + RequiresExprBodyDeclBitfields RequiresExprBodyDeclBits; static_assert(sizeof(DeclContextBitfields) <= 8, "DeclContextBitfields is larger than 8 bytes!"); @@ -2053,6 +2065,8 @@ protected: "LinkageSpecDeclBitfields is larger than 8 bytes!"); static_assert(sizeof(BlockDeclBitfields) <= 8, "BlockDeclBitfields is larger than 8 bytes!"); + static_assert(sizeof(RequiresExprBodyDeclBitfields) <= 8, + "RequiresExprBodyDeclBitfields is larger than 8 bytes!"); }; /// FirstDecl - The first declaration stored within this declaration diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 252e6e92..1a780e7 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -254,6 +254,33 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; +class ContextDeclOrSentinel { + uintptr_t Pointer; + +public: + ContextDeclOrSentinel(Decl *Pointer) : Pointer(uintptr_t(Pointer)) {} + explicit ContextDeclOrSentinel(unsigned TemplateDepth) + : Pointer(TemplateDepth << 1 | 1) {} + + operator bool() const { return !(hasValue() && getValue() == nullptr); } + + bool hasValue() const { return (Pointer & 1) == 0; } + Decl *getValue() const { + assert(hasValue()); + return reinterpret_cast<Decl *>(Pointer); + } + unsigned getTemplateDepth() const { + assert(!hasValue()); + return Pointer >> 1; + } + bool isDependent() const { return getTemplateDepth() != 0; } +}; + +struct ContextDeclAndArgs { + ContextDeclOrSentinel CDS; + ArrayRef<TemplateArgument> Args; +}; + /// Represents a C++ struct/union/class. class CXXRecordDecl : public RecordDecl { friend class ASTDeclMerger; @@ -281,14 +308,6 @@ class CXXRecordDecl : public RecordDecl { SMF_All = 0x3f }; -public: - enum LambdaDependencyKind { - LDK_Unknown = 0, - LDK_AlwaysDependent, - LDK_NeverDependent, - }; - -private: struct DefinitionData { #define FIELD(Name, Width, Merge) \ unsigned Name : Width; @@ -380,21 +399,32 @@ private: struct DefinitionData *DefinitionData; + struct LambdaContext { + /// The declaration that provides context for this lambda, if the + /// actual DeclContext does not suffice. This is used for lambdas that + /// occur within default arguments of function parameters within the class + /// or within a data member initializer. + ContextDeclOrSentinel Decl; + + /// The number of template arguments this context has, for context + /// declarations which lack template specializations. + unsigned NumArgs : 20; + + // Is the ContextDecl needed for mangling. + unsigned IsMangled : 1; + + /// The index of this lambda within its context declaration. This is not in + /// general the same as the mangling number. + unsigned Index : 32; + }; + /// Describes a C++ closure type (generated by a lambda expression). - struct LambdaDefinitionData : public DefinitionData { + struct LambdaDefinitionData final + : public DefinitionData, + private llvm::TrailingObjects<LambdaDefinitionData, LambdaContext, + TemplateArgument> { using Capture = LambdaCapture; - /// Whether this lambda is known to be dependent, even if its - /// context isn't dependent. - /// - /// A lambda with a non-dependent context can be dependent if it occurs - /// within the default argument of a function template, because the - /// lambda will have been created with the enclosing context as its - /// declaration context, rather than function. This is an unfortunate - /// artifact of having to parse the default arguments before. - LLVM_PREFERRED_TYPE(LambdaDependencyKind) - unsigned DependencyKind : 2; - /// Whether this lambda is a generic lambda. LLVM_PREFERRED_TYPE(bool) unsigned IsGenericLambda : 1; @@ -411,21 +441,15 @@ private: /// Has known `internal` linkage. LLVM_PREFERRED_TYPE(bool) + unsigned HasContext : 1; + + /// Has known `internal` linkage. + LLVM_PREFERRED_TYPE(bool) unsigned HasKnownInternalLinkage : 1; /// The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. - unsigned ManglingNumber : 31; - - /// The index of this lambda within its context declaration. This is not in - /// general the same as the mangling number. - unsigned IndexInContext; - - /// The declaration that provides context for this lambda, if the - /// actual DeclContext does not suffice. This is used for lambdas that - /// occur within default arguments of function parameters within the class - /// or within a data member initializer. - LazyDeclPtr ContextDecl; + unsigned ManglingNumber : 32; /// The lists of captures, both explicit and implicit, for this /// lambda. One list is provided for each merged copy of the lambda. @@ -436,22 +460,67 @@ private: /// The type of the call method. TypeSourceInfo *MethodTyInfo; - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, unsigned DK, - bool IsGeneric, LambdaCaptureDefault CaptureDefault) - : DefinitionData(D), DependencyKind(DK), IsGenericLambda(IsGeneric), - CaptureDefault(CaptureDefault), NumCaptures(0), - NumExplicitCaptures(0), HasKnownInternalLinkage(0), ManglingNumber(0), - IndexInContext(0), MethodTyInfo(Info) { - IsLambda = true; - - // C++1z [expr.prim.lambda]p4: - // This class type is not an aggregate type. - Aggregate = false; - PlainOldData = false; - } + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool IsGeneric, + LambdaCaptureDefault CaptureDefault, + ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs); + + static LambdaDefinitionData *Create(const ASTContext &C, CXXRecordDecl *D, + TypeSourceInfo *Info, bool IsGeneric, + LambdaCaptureDefault CaptureDefault, + ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs); // Add a list of captures. void AddCaptureList(ASTContext &Ctx, Capture *CaptureList); + + ContextDeclAndArgs getContext() const { + auto *Ctx = getLambdaContext(); + if (!Ctx) + return {nullptr, std::nullopt}; + return {Ctx->Decl, getContextArgs()}; + } + + void setContextDecl(Decl *D) { + assert(!getLambdaContext()->Decl.hasValue()); + getLambdaContext()->Decl = D; + } + + void setContextMangling(bool IsMangled, unsigned IndexInContext) { + auto *Ctx = getLambdaContext(); + Ctx->IsMangled = IsMangled; + Ctx->Index = IndexInContext; + } + + ArrayRef<TemplateArgument> getContextArgs() const { + return {/*data=*/getTrailingObjects<TemplateArgument>(), + /*length=*/numTrailingObjects(OverloadToken<TemplateArgument>())}; + } + + bool getContextIsMangled() const { return getLambdaContext()->IsMangled; } + + unsigned getContextIndex() const { return getLambdaContext()->Index; } + + private: + friend TrailingObjects; + friend CXXRecordDecl; + + LambdaContext *getLambdaContext() { + if (!HasContext) + return nullptr; + return getTrailingObjects<LambdaContext>(); + } + const LambdaContext *getLambdaContext() const { + return const_cast<LambdaDefinitionData *>(this)->getLambdaContext(); + } + + size_t numTrailingObjects(OverloadToken<LambdaContext>) const { + return HasContext; + } + + size_t numTrailingObjects(OverloadToken<TemplateArgument>) const { + return getLambdaContext()->NumArgs; + } }; struct DefinitionData *dataPtr() const { @@ -578,8 +647,10 @@ public: bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - unsigned DependencyKind, bool IsGeneric, - LambdaCaptureDefault CaptureDefault); + bool IsGeneric, + LambdaCaptureDefault CaptureDefault, + ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, GlobalDeclID ID); @@ -1793,22 +1864,37 @@ public: /// the declaration in which the lambda occurs, e.g., the function parameter /// or the non-static data member. Otherwise, it returns NULL to imply that /// the declaration context suffices. - Decl *getLambdaContextDecl() const; + ContextDeclAndArgs getLambdaContext() const { + return getLambdaData().getContext(); + } + void setLambdaContextDecl(Decl *ContextDecl); + + Decl *getLambdaManglingContextDecl() const { + assert(isLambda() && "Not a lambda closure type!"); + auto ContextDecl = getLambdaContext().CDS; + return ContextDecl && getLambdaManglingInContext() ? ContextDecl.getValue() + : nullptr; + } /// Retrieve the index of this lambda within the context declaration returned /// by getLambdaContextDecl(). unsigned getLambdaIndexInContext() const { assert(isLambda() && "Not a lambda closure type!"); - return getLambdaData().IndexInContext; + return getLambdaData().getContextIndex(); + } + + bool getLambdaManglingInContext() const { + assert(isLambda() && "Not a lambda closure type!"); + return getLambdaData().getContextIsMangled(); } /// Information about how a lambda is numbered within its context. struct LambdaNumbering { - Decl *ContextDecl = nullptr; unsigned IndexInContext = 0; unsigned ManglingNumber = 0; unsigned DeviceManglingNumber = 0; bool HasKnownInternalLinkage = false; + bool ManglingInContext = false; }; /// Set the mangling numbers and context declaration for a lambda class. @@ -1816,9 +1902,15 @@ public: // Get the mangling numbers and context declaration for a lambda class. LambdaNumbering getLambdaNumbering() const { - return {getLambdaContextDecl(), getLambdaIndexInContext(), - getLambdaManglingNumber(), getDeviceLambdaManglingNumber(), - hasKnownLambdaInternalLinkage()}; + unsigned IndexInContext = 0; + bool ManglingInContext = false; + if (getLambdaContext().CDS) { + IndexInContext = getLambdaIndexInContext(); + ManglingInContext = getLambdaManglingInContext(); + } + return {IndexInContext, getLambdaManglingNumber(), + getDeviceLambdaManglingNumber(), hasKnownLambdaInternalLinkage(), + ManglingInContext}; } /// Retrieve the device side mangling number. @@ -1842,31 +1934,6 @@ public: /// virtual base. MSVtorDispMode getMSVtorDispMode() const; - /// Determine whether this lambda expression was known to be dependent - /// at the time it was created, even if its context does not appear to be - /// dependent. - /// - /// This flag is a workaround for an issue with parsing, where default - /// arguments are parsed before their enclosing function declarations have - /// been created. This means that any lambda expressions within those - /// default arguments will have as their DeclContext the context enclosing - /// the function declaration, which may be non-dependent even when the - /// function declaration itself is dependent. This flag indicates when we - /// know that the lambda is dependent despite that. - bool isDependentLambda() const { - return isLambda() && getLambdaData().DependencyKind == LDK_AlwaysDependent; - } - - bool isNeverDependentLambda() const { - return isLambda() && getLambdaData().DependencyKind == LDK_NeverDependent; - } - - unsigned getLambdaDependencyKind() const { - if (!isLambda()) - return LDK_Unknown; - return getLambdaData().DependencyKind; - } - TypeSourceInfo *getLambdaTypeInfo() const { return getLambdaData().MethodTyInfo; } @@ -1878,10 +1945,6 @@ public: DL.MethodTyInfo = TS; } - void setLambdaDependencyKind(unsigned Kind) { - getLambdaData().DependencyKind = Kind; - } - void setLambdaIsGeneric(bool IsGeneric) { assert(DefinitionData && DefinitionData->IsLambda && "setting lambda property of non-lambda class"); @@ -2034,19 +2097,53 @@ public: /// In this example, a RequiresExpr object will be generated for the expression, /// and a RequiresExprBodyDecl will be created to hold the parameter t and the /// template argument list imposed by the compound requirement. -class RequiresExprBodyDecl : public Decl, public DeclContext { - RequiresExprBodyDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc) - : Decl(RequiresExprBody, DC, StartLoc), DeclContext(RequiresExprBody) {} +class RequiresExprBodyDecl final + : public Decl, + public DeclContext, + private llvm::TrailingObjects<RequiresExprBodyDecl, ContextDeclOrSentinel, + TemplateArgument> { + RequiresExprBodyDecl(ASTContext &C, DeclContext *DC, + ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs, + SourceLocation StartLoc); + + size_t numTrailingObjects(OverloadToken<ContextDeclOrSentinel>) const { + return RequiresExprBodyDeclBits.NumContextArgsOrNoContext != 0; + } + size_t numTrailingObjects(OverloadToken<TemplateArgument>) const { + assert(RequiresExprBodyDeclBits.NumContextArgsOrNoContext != 0); + return RequiresExprBodyDeclBits.NumContextArgsOrNoContext - 1; + } + + void setContextArgs(ArrayRef<TemplateArgument> ContextArgs); public: + friend TrailingObjects; friend class ASTDeclReader; friend class ASTDeclWriter; static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC, + ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs, SourceLocation StartLoc); - static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, - GlobalDeclID ID); + static RequiresExprBodyDecl * + CreateDeserialized(ASTContext &C, GlobalDeclID ID, + ContextDeclOrSentinel ContextDecl, + unsigned NumContextArgs); + + ContextDeclAndArgs getContext() const { + if (numTrailingObjects(OverloadToken<ContextDeclOrSentinel>()) == 0) + return {/*CDS=*/nullptr, /*Args=*/std::nullopt}; + return {/*CDS=*/*getTrailingObjects<ContextDeclOrSentinel>(), + getContextArgs()}; + } + void setContextDecl(Decl *D); + + ArrayRef<TemplateArgument> getContextArgs() const { + return {/*data=*/getTrailingObjects<TemplateArgument>(), + /*length=*/numTrailingObjects(OverloadToken<TemplateArgument>())}; + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/clang/include/clang/Basic/Linkage.h b/clang/include/clang/Basic/Linkage.h index fcf56b9..dc1522b 100644 --- a/clang/include/clang/Basic/Linkage.h +++ b/clang/include/clang/Basic/Linkage.h @@ -25,6 +25,9 @@ enum class Linkage : unsigned char { // Linkage hasn't been computed. Invalid = 0, + /// The linkage for this entity is currently being computed. + Computing, + /// No linkage, which means that the entity is unique and /// can only be referred to from within its scope. None, @@ -99,6 +102,8 @@ inline bool isExternallyVisible(Linkage L) { case Linkage::Module: case Linkage::External: return true; + case Linkage::Computing: + llvm_unreachable("Recursive linkage"); } llvm_unreachable("Unhandled Linkage enum"); } diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 47f7213..442db14 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2080,7 +2080,9 @@ private: // C++ 5.3.4 and 5.3.5: C++ new and delete bool ParseExpressionListOrTypeId(SmallVectorImpl<Expr*> &Exprs, Declarator &D); - void ParseDirectNewDeclarator(Declarator &D); + void + ParseDirectNewDeclarator(Declarator &D, + TemplateParameterDepthRAII *CurTemplateDepthTracker); ExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start); ExprResult ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start); @@ -3200,11 +3202,15 @@ private: }; /// ParseDeclarator - Parse and verify a newly-initialized declarator. - void ParseDeclarator(Declarator &D); + void ParseDeclarator( + Declarator &D, + TemplateParameterDepthRAII *CurTemplateDepthTracker = nullptr); /// A function that parses a variant of direct-declarator. - typedef void (Parser::*DirectDeclParseFunction)(Declarator&); - void ParseDeclaratorInternal(Declarator &D, - DirectDeclParseFunction DirectDeclParser); + typedef void (Parser::*DirectDeclParseFunction)( + Declarator &, TemplateParameterDepthRAII *CurTemplateDepthTracker); + void ParseDeclaratorInternal( + Declarator &D, DirectDeclParseFunction DirectDeclParser, + TemplateParameterDepthRAII *CurTemplateDepthTracker = nullptr); enum AttrRequirements { AR_NoAttributesParsed = 0, ///< No attributes are diagnosed. @@ -3224,12 +3230,16 @@ private: bool AtomicAllowed = true, bool IdentifierRequired = false, std::optional<llvm::function_ref<void()>> CodeCompletionHandler = std::nullopt); - void ParseDirectDeclarator(Declarator &D); + void ParseDirectDeclarator( + Declarator &D, + TemplateParameterDepthRAII *CurTemplateDepthTracker = nullptr); void ParseDecompositionDeclarator(Declarator &D); void ParseParenDeclarator(Declarator &D); - void ParseFunctionDeclarator(Declarator &D, ParsedAttributes &FirstArgAttrs, - BalancedDelimiterTracker &Tracker, - bool IsAmbiguous, bool RequiresArg = false); + void + ParseFunctionDeclarator(Declarator &D, ParsedAttributes &FirstArgAttrs, + BalancedDelimiterTracker &Tracker, + TemplateParameterDepthRAII *CurTemplateDepthTracker, + bool IsAmbiguous, bool RequiresArg = false); void InitCXXThisScopeForDeclaratorIfRelevant( const Declarator &D, const DeclSpec &DS, std::optional<Sema::CXXThisScopeRAII> &ThisScope); @@ -3242,16 +3252,19 @@ private: void ParseParameterDeclarationClause( Declarator &D, ParsedAttributes &attrs, SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, - SourceLocation &EllipsisLoc) { + SourceLocation &EllipsisLoc, + TemplateParameterDepthRAII *CurTemplateDepthTracker) { return ParseParameterDeclarationClause( - D.getContext(), attrs, ParamInfo, EllipsisLoc, + D.getContext(), attrs, ParamInfo, EllipsisLoc, CurTemplateDepthTracker, D.getCXXScopeSpec().isSet() && D.isFunctionDeclaratorAFunctionDeclaration()); } void ParseParameterDeclarationClause( DeclaratorContext DeclaratorContext, ParsedAttributes &attrs, SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, - SourceLocation &EllipsisLoc, bool IsACXXFunctionDeclaration = false); + SourceLocation &EllipsisLoc, + TemplateParameterDepthRAII *CurTemplateDepthTracker, + bool IsACXXFunctionDeclaration = false); void ParseBracketDeclarator(Declarator &D); void ParseMisplacedBracketDeclarator(Declarator &D); diff --git a/clang/include/clang/Sema/EnterExpressionEvaluationContext.h b/clang/include/clang/Sema/EnterExpressionEvaluationContext.h index 5eca797..bc15739 100644 --- a/clang/include/clang/Sema/EnterExpressionEvaluationContext.h +++ b/clang/include/clang/Sema/EnterExpressionEvaluationContext.h @@ -23,14 +23,15 @@ class EnterExpressionEvaluationContext { public: EnterExpressionEvaluationContext( Sema &Actions, Sema::ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = nullptr, + Sema::ContextDeclOrLazy ContextDecl = nullptr, + ArrayRef<TemplateArgument> TemplateArgs = std::nullopt, Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = Sema::ExpressionEvaluationContextRecord::EK_Other, bool ShouldEnter = true) : Actions(Actions), Entered(ShouldEnter) { if (Entered) - Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, - ExprContext); + Actions.PushExpressionEvaluationContext(NewContext, ContextDecl, + TemplateArgs, ExprContext); } EnterExpressionEvaluationContext( Sema &Actions, Sema::ExpressionEvaluationContext NewContext, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ac4c119..d022625 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3639,8 +3639,10 @@ public: /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. - Decl *ActOnParamDeclarator(Scope *S, Declarator &D, - SourceLocation ExplicitThisLoc = {}); + ParmVarDecl *ActOnParamDeclarator(Scope *S, Declarator &D, + unsigned TemplateDepth, + bool &StartImplicitTemplate, + SourceLocation ExplicitThisLoc = {}); /// Synthesizes a variable for a parameter arising from a /// typedef. @@ -3649,7 +3651,8 @@ public: ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, const IdentifierInfo *Name, QualType T, - TypeSourceInfo *TSInfo, StorageClass SC); + TypeSourceInfo *TSInfo, StorageClass SC, + unsigned TemplateDepth); // Contexts where using non-trivial C union types can be disallowed. This is // passed to err_non_trivial_c_union_in_invalid_context. @@ -3747,7 +3750,8 @@ public: }; void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, - SourceLocation LocAfterDecls); + SourceLocation LocAfterDecls, + unsigned TemplateDepth); void CheckForFunctionRedefinition( FunctionDecl *FD, const FunctionDecl *EffectiveDefinition = nullptr, SkipBodyInfo *SkipBody = nullptr); @@ -6319,6 +6323,25 @@ public: using ImmediateInvocationCandidate = llvm::PointerIntPair<ConstantExpr *, 1>; + static inline struct { + } LazyContextDecl; + class ContextDeclOrLazy { + uintptr_t Pointer; + + public: + ContextDeclOrLazy(Decl *Pointer) : Pointer(uintptr_t(Pointer)) {} + constexpr ContextDeclOrLazy(decltype(LazyContextDecl)) + : Pointer(-uintptr_t(1)) {} + + operator bool() const { return hasValue() && operator*() != nullptr; } + + bool hasValue() const { return Pointer != -uintptr_t(1); } + Decl *operator*() const { + assert(hasValue()); + return reinterpret_cast<Decl *>(Pointer); + } + }; + /// Data structure used to record current or nested /// expression evaluation contexts. struct ExpressionEvaluationContextRecord { @@ -6336,6 +6359,8 @@ public: /// context (i.e. the number of TypoExprs created). unsigned NumTypos; + unsigned LazyContextDeclPos; + MaybeODRUseExprSet SavedMaybeODRUseExprs; /// The lambdas that are present within this context, if it @@ -6345,7 +6370,8 @@ public: /// The declaration that provides context for lambda expressions /// and block literals if the normal declaration context does not /// suffice, e.g., in a default function argument. - Decl *ManglingContextDecl; + ContextDeclOrLazy ContextDecl; + ArrayRef<TemplateArgument> ContextArgs; /// If we are processing a decltype type, a set of call expressions /// for which we have deferred checking the completeness of the return type. @@ -6385,6 +6411,8 @@ public: EK_Other } ExprContext; + bool HasReusedDeclContext = false; + // A context can be nested in both a discarded statement context and // an immediate function context, so they need to be tracked independently. bool InDiscardedStatement; @@ -6426,11 +6454,14 @@ public: ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, CleanupInfo ParentCleanup, - Decl *ManglingContextDecl, - ExpressionKind ExprContext) + ContextDeclOrLazy ContextDecl, + ArrayRef<TemplateArgument> ContextArgs, + ExpressionKind ExprContext, + unsigned LazyContextDeclPos) : Context(Context), ParentCleanup(ParentCleanup), NumCleanupObjects(NumCleanupObjects), NumTypos(0), - ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext), + LazyContextDeclPos(LazyContextDeclPos), ContextDecl(ContextDecl), + ContextArgs(ContextArgs), ExprContext(ExprContext), InDiscardedStatement(false), InImmediateFunctionContext(false), InImmediateEscalatingFunctionContext(false) {} @@ -6556,7 +6587,9 @@ public: ArrayRef<Expr *> Args); void PushExpressionEvaluationContext( - ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, + ExpressionEvaluationContext NewContext, + ContextDeclOrLazy ContextDecl = nullptr, + ArrayRef<TemplateArgument> ContextArgs = std::nullopt, ExpressionEvaluationContextRecord::ExpressionKind Type = ExpressionEvaluationContextRecord::EK_Other); enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; @@ -6564,6 +6597,7 @@ public: ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, ExpressionEvaluationContextRecord::ExpressionKind Type = ExpressionEvaluationContextRecord::EK_Other); + void UpdateCurrentContextDecl(Decl *ContextDecl); void PopExpressionEvaluationContext(); void DiscardCleanupsInEvaluationContext(); @@ -7946,6 +7980,8 @@ public: /// A stack of expression evaluation contexts. SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts; + SmallVector<Decl *, 8> PendingLazyContextDecls; + // Set of failed immediate invocations to avoid double diagnosing. llvm::SmallPtrSet<ConstantExpr *, 4> FailedImmediateInvocations; @@ -8510,7 +8546,7 @@ public: RequiresExprBodyDecl * ActOnStartRequiresExpr(SourceLocation RequiresKWLoc, ArrayRef<ParmVarDecl *> LocalParameters, - Scope *BodyScope); + Scope *BodyScope, unsigned TemplateDepth); void ActOnFinishRequiresExpr(); concepts::Requirement *ActOnSimpleRequirement(Expr *E); concepts::Requirement *ActOnTypeRequirement(SourceLocation TypenameKWLoc, @@ -8753,13 +8789,14 @@ public: /// Create a new lambda closure type. CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, - unsigned LambdaDependencyKind, - LambdaCaptureDefault CaptureDefault); + LambdaCaptureDefault CaptureDefault, + unsigned TemplateDepth); /// Number lambda for linkage purposes if necessary. void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method, std::optional<CXXRecordDecl::LambdaNumbering> - NumberingOverride = std::nullopt); + NumberingOverride = std::nullopt, + bool InSignature = false); /// Endow the lambda scope info with the relevant properties. void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator, @@ -8826,7 +8863,8 @@ public: /// We do the capture lookup here, but they are not actually captured until /// after we know what the qualifiers of the call operator are. void ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, - Scope *CurContext); + Scope *CurContext, + unsigned TemplateDepth); /// This is called after parsing the explicit template parameter list /// on a lambda (if it exists) in C++2a. @@ -8904,8 +8942,10 @@ public: /// /// \param DC - The DeclContext containing the lambda expression or /// block literal. - std::tuple<MangleNumberingContext *, Decl *> - getCurrentMangleNumberContext(const DeclContext *DC); + std::tuple<MangleNumberingContext *, bool> + getCurrentMangleNumberContext(const DeclContext *DC, + Decl *ManglingContextDecl, + bool InSignature = false); ///@} @@ -11217,8 +11257,6 @@ public: /// "class" or "typename" keyword. ParamName is the name of the /// parameter (NULL indicates an unnamed template parameter) and /// ParamNameLoc is the location of the parameter name (if any). - /// If the type parameter has a default argument, it will be added - /// later via ActOnTypeParameterDefault. NamedDecl *ActOnTypeParameter(Scope *S, bool Typename, SourceLocation EllipsisLoc, SourceLocation KeyLoc, @@ -14784,7 +14822,8 @@ public: /// /// The result of this call will never be null, but the associated /// type may be a null type if there's an unrecoverable error. - TypeSourceInfo *GetTypeForDeclarator(Declarator &D); + TypeSourceInfo *GetTypeForDeclarator(Declarator &D, + bool *StartImplicitTemplate = nullptr); TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); /// Package the given type and TSI into a ParsedType. diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 0340c23..5202854 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -143,6 +143,8 @@ enum class TemplateSubstitutionKind : char { /// Determine how many of the \p OldDepth outermost template parameter /// lists would be removed by substituting these arguments. unsigned getNewDepth(unsigned OldDepth) const { + if (Kind == TemplateSubstitutionKind::Rewrite) + return OldDepth; if (OldDepth < NumRetainedOuterLevels) return OldDepth; if (OldDepth < getNumLevels()) diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 898f439..9a04127 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1148,6 +1148,9 @@ private: /// need to be marked as incomplete once we're done deserializing things. SmallVector<Decl *, 16> PendingIncompleteDeclChains; + /// The list of pending declarations that still need their ContextDecl. + SmallVector<std::pair<Decl *, GlobalDeclID>, 16> PendingContextDecls; + /// The Decl IDs for the Sema/Lexical DeclContext of a Decl that has /// been loaded but its DeclContext was not set yet. struct PendingDeclContextInfo { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index fa9cc38..c49b172 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7210,7 +7210,7 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const NamedDecl *Y) const { return false; } - return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() && + return FuncX->getStorageClass() == FuncY->getStorageClass() && hasSameOverloadableAttrs(FuncX, FuncY); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c2fb7dd..b2cd022 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -3197,16 +3197,23 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { auto TInfoOrErr = import(DCXX->getLambdaTypeInfo()); if (!TInfoOrErr) return TInfoOrErr.takeError(); + + llvm::SmallVector<TemplateArgument, 4> ToArgs; + auto Context = DCXX->getLambdaContext(); + if (Context.CDS) + if (Error Err = ImportTemplateArguments(Context.Args, ToArgs)) + return std::move(Err); + + // The ContextDecl will be set later after we create the LambdaExpr, in + // order to avoid a cycle. if (GetImportedOrCreateSpecialDecl( D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), - DC, *TInfoOrErr, Loc, DCXX->getLambdaDependencyKind(), - DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) + DC, *TInfoOrErr, Loc, DCXX->isGenericLambda(), + DCXX->getLambdaCaptureDefault(), + /*ContextDecl=*/Context.CDS ? ContextDeclOrSentinel(0u) : nullptr, + ToArgs)) return D2CXX; CXXRecordDecl::LambdaNumbering Numbering = DCXX->getLambdaNumbering(); - ExpectedDecl CDeclOrErr = import(Numbering.ContextDecl); - if (!CDeclOrErr) - return CDeclOrErr.takeError(); - Numbering.ContextDecl = *CDeclOrErr; D2CXX->setLambdaNumbering(Numbering); } else if (DCXX->isInjectedClassName()) { // We have to be careful to do a similar dance to the one in @@ -4753,7 +4760,7 @@ ExpectedDecl ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { ToInnerLocStart, ToLocation, ToDeclName.getAsIdentifierInfo(), ToType, ToTypeSourceInfo, D->getStorageClass(), - /*DefaultArg*/ nullptr)) + /*DefaultArg=*/nullptr, D->getTemplateDepth())) return ToParm; // Set the default argument. It should be no problem if it was already done. @@ -8724,11 +8731,20 @@ ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { if (Err) return std::move(Err); - return LambdaExpr::Create(Importer.getToContext(), ToClass, ToIntroducerRange, - E->getCaptureDefault(), ToCaptureDefaultLoc, - E->hasExplicitParameters(), - E->hasExplicitResultType(), ToCaptureInits, - ToEndLoc, E->containsUnexpandedParameterPack()); + LambdaExpr *ToExpr = LambdaExpr::Create( + Importer.getToContext(), ToClass, ToIntroducerRange, + E->getCaptureDefault(), ToCaptureDefaultLoc, E->hasExplicitParameters(), + E->hasExplicitResultType(), ToCaptureInits, ToEndLoc, + E->containsUnexpandedParameterPack()); + + if (auto ContextDecl = FromClass->getLambdaContext().CDS) { + ExpectedDecl CDeclOrErr = import(ContextDecl.getValue()); + if (!CDeclOrErr) + return CDeclOrErr.takeError(); + ToClass->getLambdaData().setContextDecl(*CDeclOrErr); + } + + return ToExpr; } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index a14b1b3..6e9fad4 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -602,8 +602,7 @@ static StorageClass getStorageClass(const Decl *D) { LinkageInfo LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, - LVComputationKind computation, - bool IgnoreVarTypeLinkage) { + LVComputationKind computation) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && "Not a name having namespace scope"); ASTContext &Context = D->getASTContext(); @@ -669,7 +668,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // - a data member of an anonymous union. const VarDecl *VD = IFD->getVarDecl(); assert(VD && "Expected a VarDecl in this IndirectFieldDecl!"); - return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage); + return getLVForNamespaceScopeDecl(VD, computation); } assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!"); @@ -772,13 +771,14 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. - if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) && - !IgnoreVarTypeLinkage) { + if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) { LinkageInfo TypeLV = getLVForType(*Var->getType(), computation); - if (!isExternallyVisible(TypeLV.getLinkage())) - return LinkageInfo::uniqueExternal(); - if (!LV.isVisibilityExplicit()) - LV.mergeVisibility(TypeLV); + if (TypeLV.getLinkage() != Linkage::Computing) { + if (!isExternallyVisible(TypeLV.getLinkage())) + return LinkageInfo::uniqueExternal(); + if (!LV.isVisibilityExplicit()) + LV.mergeVisibility(TypeLV); + } } if (Var->getStorageClass() == SC_PrivateExtern) @@ -913,8 +913,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, LinkageInfo LinkageComputer::getLVForClassMember(const NamedDecl *D, - LVComputationKind computation, - bool IgnoreVarTypeLinkage) { + LVComputationKind computation) { // Only certain class members have linkage. Note that fields don't // really have linkage, but it's convenient to say they do for the // purposes of calculating linkage of pointer-to-data-member @@ -1026,8 +1025,8 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D, // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. - if (!IgnoreVarTypeLinkage) { - LinkageInfo typeLV = getLVForType(*VD->getType(), computation); + LinkageInfo typeLV = getLVForType(*VD->getType(), computation); + if (typeLV.getLinkage() != Linkage::Computing) { // FIXME: If the type's linkage is not externally visible, we can // give this static data member UniqueExternalLinkage. if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()) @@ -1327,15 +1326,9 @@ LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC, if (!Owner) return LinkageInfo::none(); - // If the owner has a deduced type, we need to skip querying the linkage and - // visibility of that type, because it might involve this closure type. The - // only effect of this is that we might give a lambda VisibleNoLinkage rather - // than NoLinkage when we don't strictly need to, which is benign. - auto *VD = dyn_cast<VarDecl>(Owner); - LinkageInfo OwnerLV = - VD && VD->getType()->getContainedDeducedType() - ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true) - : getLVForDecl(Owner, computation); + LinkageInfo OwnerLV = getLVForDecl(Owner, computation); + if (OwnerLV.getLinkage() == Linkage::Computing) + return LinkageInfo::visible_none(); // A lambda never formally has linkage. But if the owner is externally // visible, then the lambda is too. We apply the same rules to blocks. @@ -1449,8 +1442,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, } LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, - LVComputationKind computation, - bool IgnoreVarTypeLinkage) { + LVComputationKind computation) { // Internal_linkage attribute overrides other considerations. if (D->hasAttr<InternalLinkageAttr>()) return LinkageInfo::internal(); @@ -1514,9 +1506,9 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, return LinkageInfo::internal(); } - return getLVForClosure( - Record->getDeclContext()->getRedeclContext(), - Record->getLambdaContextDecl(), computation); + return getLVForClosure(Record->getDeclContext()->getRedeclContext(), + Record->getLambdaManglingContextDecl(), + computation); } break; @@ -1534,7 +1526,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, // Handle linkage for namespace-scope names. if (D->getDeclContext()->getRedeclContext()->isFileContext()) - return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage); + return getLVForNamespaceScopeDecl(D, computation); // C++ [basic.link]p5: // In addition, a member function, static data member, a named @@ -1544,7 +1536,7 @@ LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, // purposes (7.1.3), has external linkage if the name of the class // has external linkage. if (D->getDeclContext()->isRecord()) - return getLVForClassMember(D, computation, IgnoreVarTypeLinkage); + return getLVForClassMember(D, computation); // C++ [basic.link]p6: // The name of a function declared in block scope and the name of @@ -1572,15 +1564,19 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D, if (D->hasAttr<InternalLinkageAttr>()) return LinkageInfo::internal(); - if (computation.IgnoreAllVisibility && D->hasCachedLinkage()) + if (Linkage L = D->getCachedLinkage(); + L == Linkage::Computing || + (L != Linkage::Invalid && computation.IgnoreAllVisibility)) return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); if (std::optional<LinkageInfo> LI = lookup(D, computation)) return *LI; + // If we recursively depend on this linkage, make sure it does not + // fall back here. + D->setCachedLinkage(Linkage::Computing); LinkageInfo LV = computeLVForDecl(D, computation); - if (D->hasCachedLinkage()) - assert(D->getCachedLinkage() == LV.getLinkage()); + assert(D->getCachedLinkage() == Linkage::Computing); D->setCachedLinkage(LV.getLinkage()); cache(D, computation, LV); @@ -1601,7 +1597,8 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D, auto *T = cast<NamedDecl>(I); if (T == D) continue; - if (!T->isInvalidDecl() && T->hasCachedLinkage()) { + if (!T->isInvalidDecl() && T->hasCachedLinkage() && + T->getCachedLinkage() != Linkage::Computing) { Old = T; break; } @@ -1924,6 +1921,8 @@ bool NamedDecl::hasLinkage() const { case Linkage::Module: case Linkage::External: return true; + case Linkage::Computing: + llvm_unreachable("Linkage is being computed!"); } llvm_unreachable("Unhandled Linkage enum"); } @@ -2913,9 +2912,14 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, - Expr *DefArg) { - return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo, - S, DefArg); + Expr *DefArg, + std::optional<unsigned> TemplateDepth) { + if (TemplateDepth && + *TemplateDepth == castFromDeclContext(DC)->getTemplateDepth()) + TemplateDepth = std::nullopt; + unsigned Extra = additionalSizeToAlloc<uint16_t>(bool(TemplateDepth)); + return new (C, DC, Extra) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, + TInfo, S, DefArg, TemplateDepth); } QualType ParmVarDecl::getOriginalType() const { @@ -2929,7 +2933,7 @@ QualType ParmVarDecl::getOriginalType() const { ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { return new (C, ID) ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(), - nullptr, QualType(), nullptr, SC_None, nullptr); + nullptr, QualType(), nullptr, SC_None, nullptr, std::nullopt); } SourceRange ParmVarDecl::getSourceRange() const { diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index f42857f..20e5364 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -293,7 +293,21 @@ bool Decl::isTemplated() const { getDescribedTemplateParams(); } -unsigned Decl::getTemplateDepth() const { +unsigned Decl::getTemplateDepth(ArrayRef<TemplateArgument> SpecArgs) const { + if (auto *AD = dyn_cast<TypeAliasDecl>(this)) { + if (TypeAliasTemplateDecl *TD = AD->getDescribedAliasTemplate()) { + bool Instantiated = + !SpecArgs.empty() && + llvm::none_of(SpecArgs, [](const TemplateArgument &A) { + return A.isInstantiationDependent(); + }); + return TD->getTemplateParameters()->getDepth() + !Instantiated; + } + } + // The other declarations either cannot be specialized, or have a dedicated + // specialization declaration. + assert(SpecArgs.empty()); + if (auto *DC = dyn_cast<DeclContext>(this)) if (DC->isFileContext()) return 0; @@ -301,13 +315,42 @@ unsigned Decl::getTemplateDepth() const { if (auto *TPL = getDescribedTemplateParams()) return TPL->getDepth() + 1; - // If this is a dependent lambda, there might be an enclosing variable - // template. In this case, the next step is not the parent DeclContext (or - // even a DeclContext at all). - auto *RD = dyn_cast<CXXRecordDecl>(this); - if (RD && RD->isDependentLambda()) - if (Decl *Context = RD->getLambdaContextDecl()) - return Context->getTemplateDepth(); + // A ConceptDecl can't be declared in a templated context, so it's always + // depth 1. + if (isa<ConceptDecl>(this)) + return 1; + // Therefore, their specializations always live at depth 0. + if (isa<ImplicitConceptSpecializationDecl>(this)) + return 0; + + if (auto *D = dyn_cast<TemplateTypeParmDecl>(this)) + return D->getDepth() + 1; + if (auto *D = dyn_cast<NonTypeTemplateParmDecl>(this)) + return D->getDepth() + 1; + if (auto *D = dyn_cast<TemplateTemplateParmDecl>(this)) + return D->getDepth() + 1; + + if (auto *PD = dyn_cast<ParmVarDecl>(this)) + return PD->getTemplateDepth(); + + auto handleContext = + [](ContextDeclAndArgs Context) -> std::optional<unsigned> { + if (!Context.CDS.hasValue()) + return Context.CDS.getTemplateDepth(); + if (Decl *LCD = Context.CDS.getValue()) + return LCD->getTemplateDepth(Context.Args); + return std::nullopt; + }; + + // For certain declarations, there might be an enclosing templated entity + // which is not a DeclContext. + if (auto *RD = dyn_cast<CXXRecordDecl>(this); RD && RD->isLambda()) + if (auto DepthOrNone = handleContext(RD->getLambdaContext())) + return *DepthOrNone; + + if (auto *RD = dyn_cast<RequiresExprBodyDecl>(this)) + if (auto DepthOrNone = handleContext(RD->getContext())) + return *DepthOrNone; const DeclContext *DC = getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext(); @@ -1097,7 +1140,7 @@ bool Decl::AccessDeclContextCheck() const { isa<StaticAssertDecl>(this) || isa<BlockDecl>(this) || // FIXME: a ParmVarDecl can have ClassTemplateSpecialization // as DeclContext (?). - isa<ParmVarDecl>(this) || + isa<ParmVarDecl>(this) || isa<RequiresExprBodyDecl>(this) || // FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have // AS_none as access specifier. isa<CXXRecordDecl>(this) || isa<LifetimeExtendedTemporaryDecl>(this)) @@ -1331,37 +1374,7 @@ bool DeclContext::isStdNamespace() const { } bool DeclContext::isDependentContext() const { - if (isFileContext()) - return false; - - if (isa<ClassTemplatePartialSpecializationDecl>(this)) - return true; - - if (const auto *Record = dyn_cast<CXXRecordDecl>(this)) { - if (Record->getDescribedClassTemplate()) - return true; - - if (Record->isDependentLambda()) - return true; - if (Record->isNeverDependentLambda()) - return false; - } - - if (const auto *Function = dyn_cast<FunctionDecl>(this)) { - if (Function->getDescribedFunctionTemplate()) - return true; - - // Friend function declarations are dependent if their *lexical* - // context is dependent. - if (cast<Decl>(this)->getFriendObjectKind()) - return getLexicalParent()->isDependentContext(); - } - - // FIXME: A variable template is a dependent context, but is not a - // DeclContext. A context within it (such as a lambda-expression) - // should be considered dependent. - - return getParent() && getParent()->isDependentContext(); + return Decl::castFromDeclContext(this)->getTemplateDepth() > 0; } bool DeclContext::isTransparentContext() const { diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 0114339..88944ba 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -121,6 +121,43 @@ CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase() const { return VBases.get(Definition->getASTContext().getExternalSource()); } +CXXRecordDecl::LambdaDefinitionData::LambdaDefinitionData( + CXXRecordDecl *D, TypeSourceInfo *Info, bool IsGeneric, + LambdaCaptureDefault CaptureDefault, ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs) + : DefinitionData(D), IsGenericLambda(IsGeneric), + CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), + HasKnownInternalLinkage(0), ManglingNumber(0), MethodTyInfo(Info) { + IsLambda = true; + + // C++1z [expr.prim.lambda]p4: + // This class type is not an aggregate type. + Aggregate = false; + PlainOldData = false; + + HasContext = ContextDecl; + if (auto *Ctx = getLambdaContext()) { + Ctx->Decl = ContextDecl; + Ctx->Index = 0; + Ctx->IsMangled = false; + Ctx->NumArgs = ContextArgs.size(); + std::uninitialized_copy(ContextArgs.begin(), ContextArgs.end(), + getContextArgs().begin()); + } +} + +auto CXXRecordDecl::LambdaDefinitionData::Create( + const ASTContext &C, CXXRecordDecl *D, TypeSourceInfo *Info, bool IsGeneric, + LambdaCaptureDefault CaptureDefault, ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs) -> LambdaDefinitionData * { + unsigned Extra = LambdaDefinitionData::additionalSizeToAlloc< + LambdaContext, TemplateArgument>(bool(ContextDecl), ContextArgs.size()); + auto *Mem = C.Allocate(sizeof(LambdaDefinitionData) + Extra, + alignof(LambdaDefinitionData)); + return new (Mem) struct LambdaDefinitionData( + D, Info, IsGeneric, CaptureDefault, ContextDecl, ContextArgs); +} + CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, @@ -144,21 +181,20 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, return R; } -CXXRecordDecl * -CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, - TypeSourceInfo *Info, SourceLocation Loc, - unsigned DependencyKind, bool IsGeneric, - LambdaCaptureDefault CaptureDefault) { - auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TagTypeKind::Class, C, DC, Loc, +CXXRecordDecl *CXXRecordDecl::CreateLambda( + const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, + SourceLocation Loc, bool IsGeneric, LambdaCaptureDefault CaptureDefault, + ContextDeclOrSentinel ContextDecl, ArrayRef<TemplateArgument> ContextArgs) { + auto *D = new (C, DC) CXXRecordDecl(CXXRecord, TagTypeKind::Class, C, DC, Loc, Loc, nullptr, nullptr); - R->setBeingDefined(true); - R->DefinitionData = new (C) struct LambdaDefinitionData( - R, Info, DependencyKind, IsGeneric, CaptureDefault); - R->setMayHaveOutOfDateDef(false); - R->setImplicit(true); + D->setBeingDefined(true); + D->DefinitionData = LambdaDefinitionData::Create( + C, D, Info, IsGeneric, CaptureDefault, ContextDecl, ContextArgs); + D->setMayHaveOutOfDateDef(false); + D->setImplicit(true); - C.getTypeDeclType(R, /*PrevDecl=*/nullptr); - return R; + C.getTypeDeclType(D, /*PrevDecl=*/nullptr); + return D; } CXXRecordDecl *CXXRecordDecl::CreateDeserialized(const ASTContext &C, @@ -170,6 +206,26 @@ CXXRecordDecl *CXXRecordDecl::CreateDeserialized(const ASTContext &C, return R; } +void CXXRecordDecl::setLambdaContextDecl(Decl *D) { + auto [CDS, Args] = getLambdaContext(); + assert(!CDS.hasValue()); + if (!D) + return; + assert(CDS.getTemplateDepth() == D->getTemplateDepth(Args)); + DeclContext *DC; + if (DeclContext::classof(D)) { + assert(Args.empty()); + getLambdaData().setContextDecl(nullptr); + DC = Decl::castToDeclContext(D); + } else { + getLambdaData().setContextDecl(D); + DC = D->getDeclContext(); + } + getDeclContext()->removeDecl(this); + setDeclContext(DC); + DC->addDecl(this); +} + /// Determine whether a class has a repeated base class. This is intended for /// use when determining if a class is standard-layout, so makes no attempt to /// handle virtual bases. @@ -1736,20 +1792,16 @@ CXXRecordDecl::getLambdaExplicitTemplateParameters() const { return llvm::ArrayRef(List->begin(), ExplicitEnd); } -Decl *CXXRecordDecl::getLambdaContextDecl() const { - assert(isLambda() && "Not a lambda closure type!"); - ExternalASTSource *Source = getParentASTContext().getExternalSource(); - return getLambdaData().ContextDecl.get(Source); -} - void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) { assert(isLambda() && "Not a lambda closure type!"); getLambdaData().ManglingNumber = Numbering.ManglingNumber; if (Numbering.DeviceManglingNumber) getASTContext().DeviceLambdaManglingNumbers[this] = Numbering.DeviceManglingNumber; - getLambdaData().IndexInContext = Numbering.IndexInContext; - getLambdaData().ContextDecl = Numbering.ContextDecl; + if (auto *LambdaContext = getLambdaData().getLambdaContext()) { + LambdaContext->IsMangled = Numbering.ManglingInContext; + LambdaContext->Index = Numbering.IndexInContext; + } getLambdaData().HasKnownInternalLinkage = Numbering.HasKnownInternalLinkage; } @@ -2224,14 +2276,69 @@ CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { DeductionCandidate::Normal); } +RequiresExprBodyDecl::RequiresExprBodyDecl( + ASTContext &C, DeclContext *DC, ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs, SourceLocation StartLoc) + : Decl(RequiresExprBody, DC, StartLoc), DeclContext(RequiresExprBody) { + if (ContextDecl) { + RequiresExprBodyDeclBits.NumContextArgsOrNoContext = ContextArgs.size() + 1; + *getTrailingObjects<ContextDeclOrSentinel>() = ContextDecl; + setContextArgs(ContextArgs); + } else { + RequiresExprBodyDeclBits.NumContextArgsOrNoContext = 0; + assert(ContextArgs.empty()); + } +} + +void RequiresExprBodyDecl::setContextArgs( + ArrayRef<TemplateArgument> ContextArgs) { + assert(RequiresExprBodyDeclBits.NumContextArgsOrNoContext == + ContextArgs.size() + 1); + std::uninitialized_copy(ContextArgs.begin(), ContextArgs.end(), + getContextArgs().begin()); +} + RequiresExprBodyDecl *RequiresExprBodyDecl::Create( - ASTContext &C, DeclContext *DC, SourceLocation StartLoc) { - return new (C, DC) RequiresExprBodyDecl(C, DC, StartLoc); + ASTContext &C, DeclContext *DC, ContextDeclOrSentinel ContextDecl, + ArrayRef<TemplateArgument> ContextArgs, SourceLocation StartLoc) { + unsigned Extra = + additionalSizeToAlloc<ContextDeclOrSentinel, TemplateArgument>( + bool(ContextDecl), ContextArgs.size()); + return new (C, DC, Extra) + RequiresExprBodyDecl(C, DC, ContextDecl, ContextArgs, StartLoc); } RequiresExprBodyDecl * -RequiresExprBodyDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { - return new (C, ID) RequiresExprBodyDecl(C, nullptr, SourceLocation()); +RequiresExprBodyDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID, + ContextDeclOrSentinel ContextDecl, + unsigned NumContextArgs) { + assert(!ContextDecl || !ContextDecl.hasValue()); + unsigned Extra = + additionalSizeToAlloc<ContextDeclOrSentinel, TemplateArgument>( + bool(ContextDecl), NumContextArgs); + auto *D = new (C, ID, Extra) RequiresExprBodyDecl( + C, /*DC=*/nullptr, /*ContextDecl=*/ContextDecl, + /*ContextArgs=*/std::nullopt, /*StartLoc=*/SourceLocation()); + D->RequiresExprBodyDeclBits.NumContextArgsOrNoContext = + bool(ContextDecl) ? NumContextArgs + 1 : 0; + return D; +} + +void RequiresExprBodyDecl::setContextDecl(Decl *D) { + assert(numTrailingObjects(OverloadToken<ContextDeclOrSentinel>()) != 0); + auto &CDS = *getTrailingObjects<ContextDeclOrSentinel>(); + assert(!CDS.hasValue()); + if (!D) + return; + assert(CDS.getTemplateDepth() == D->getTemplateDepth(getContextArgs())); + if (DeclContext::classof(D)) { + assert(getContextArgs().empty()); + CDS = nullptr; + setDeclContext(Decl::castToDeclContext(D)); + } else { + CDS = D; + setDeclContext(D->getDeclContext()); + } } void CXXMethodDecl::anchor() {} diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 7d638be..101a364 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -173,7 +173,7 @@ public: // the string that is used in lambda mangled names. assert(Lambda->isLambda() && "RD must be a lambda!"); std::string Name("<lambda"); - Decl *LambdaContextDecl = Lambda->getLambdaContextDecl(); + Decl *LambdaContextDecl = Lambda->getLambdaManglingContextDecl(); unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber(); unsigned LambdaId; const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl); @@ -657,13 +657,11 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) { // the way in which Clang parses and creates function declarations, this is // not the case: the lambda closure type ends up living in the context // where the function itself resides, because the function declaration itself - // had not yet been created. Fix the context here. - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - if (RD->isLambda()) - if (ParmVarDecl *ContextParam = - dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) - return ContextParam->getDeclContext(); - } + // had not yet been created. Fix the context here. FIXME: Remove. + if (auto *RD = dyn_cast<CXXRecordDecl>(D); RD && RD->isLambda()) + if (auto *ContextParam = + dyn_cast_or_null<ParmVarDecl>(RD->getLambdaManglingContextDecl())) + return ContextParam->getDeclContext(); // Perform the same check for block literals. if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { @@ -1061,6 +1059,9 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, // ::= <local-name> // const DeclContext *DC = Context.getEffectiveDeclContext(ND); + while (auto *D = dyn_cast<RequiresExprBodyDecl>(DC)) + DC = D->getDeclContext(); + bool IsLambda = isLambda(ND); // If this is an extern variable declared locally, the relevant DeclContext @@ -1085,6 +1086,11 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD, return; } + if (Decl::castFromDeclContext(DC) == Structor) { + mangleUnqualifiedName(GD, DC, AdditionalAbiTags); + return; + } + if (isLocalContainerContext(DC)) { mangleLocalName(GD, AdditionalAbiTags); return; @@ -1462,13 +1468,12 @@ void CXXNameMangler::mangleUnresolvedName( void CXXNameMangler::mangleUnqualifiedName( GlobalDecl GD, DeclarationName Name, const DeclContext *DC, unsigned KnownArity, const AbiTagList *AdditionalAbiTags) { - const NamedDecl *ND = cast_or_null<NamedDecl>(GD.getDecl()); + const NamedDecl *ND = cast<NamedDecl>(GD.getDecl()); // <unqualified-name> ::= [<module-name>] [F] <operator-name> // ::= <ctor-dtor-name> // ::= [<module-name>] [F] <source-name> // ::= [<module-name>] DC <source-name>* E - - if (ND && DC && DC->isFileContext()) + if (DC && DC->isFileContext()) mangleModuleName(ND); // A member-like constrained friend is mangled with a leading 'F'. @@ -1888,8 +1893,8 @@ void CXXNameMangler::mangleLocalName(GlobalDecl GD, // -- other default arguments do not affect its encoding. const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD); if (CXXRD && CXXRD->isLambda()) { - if (const ParmVarDecl *Parm - = dyn_cast_or_null<ParmVarDecl>(CXXRD->getLambdaContextDecl())) { + if (const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>( + CXXRD->getLambdaManglingContextDecl())) { if (const FunctionDecl *Func = dyn_cast<FunctionDecl>(Parm->getDeclContext())) { Out << 'd'; @@ -2087,7 +2092,7 @@ void CXXNameMangler::mangleRequiresClause(const Expr *RequiresClause) { void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // When trying to be ABI-compatibility with clang 12 and before, mangle a // <data-member-prefix> now, with no substitutions. - if (Decl *Context = Lambda->getLambdaContextDecl()) { + if (Decl *Context = Lambda->getLambdaManglingContextDecl()) { if (isCompatibleWith(LangOptions::ClangABI::Ver12) && (isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && !isa<ParmVarDecl>(Context)) { @@ -2199,6 +2204,9 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (DC->isTranslationUnit()) return; + while (DC->isRequiresExprBody()) + DC = DC->getParent(); + if (NoFunction && isLocalContainerContext(DC)) return; @@ -2290,7 +2298,7 @@ const NamedDecl *CXXNameMangler::getClosurePrefix(const Decl *ND) { Context = dyn_cast_or_null<NamedDecl>(Block->getBlockManglingContextDecl()); } else if (auto *RD = dyn_cast<CXXRecordDecl>(ND)) { if (RD->isLambda()) - Context = dyn_cast_or_null<NamedDecl>(RD->getLambdaContextDecl()); + Context = dyn_cast_or_null<NamedDecl>(RD->getLambdaManglingContextDecl()); } if (!Context) return nullptr; diff --git a/clang/lib/AST/Linkage.h b/clang/lib/AST/Linkage.h index e4dcb5e..25a310b 100644 --- a/clang/lib/AST/Linkage.h +++ b/clang/lib/AST/Linkage.h @@ -125,12 +125,10 @@ class LinkageComputer { LVComputationKind computation); LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, - LVComputationKind computation, - bool IgnoreVarTypeLinkage); + LVComputationKind computation); LinkageInfo getLVForClassMember(const NamedDecl *D, - LVComputationKind computation, - bool IgnoreVarTypeLinkage); + LVComputationKind computation); LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl, LVComputationKind computation); @@ -147,8 +145,7 @@ class LinkageComputer { public: LinkageInfo computeLVForDecl(const NamedDecl *D, - LVComputationKind computation, - bool IgnoreVarTypeLinkage = false); + LVComputationKind computation); LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 018ab61..736c675 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -90,7 +90,7 @@ getLambdaDefaultArgumentDeclContext(const Decl *D) { if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) if (RD->isLambda()) if (const auto *Parm = - dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) + dyn_cast_or_null<ParmVarDecl>(RD->getLambdaManglingContextDecl())) return Parm->getDeclContext(); return nullptr; } @@ -253,7 +253,7 @@ public: assert(Lambda->isLambda() && "RD must be a lambda!"); std::string Name("<lambda_"); - Decl *LambdaContextDecl = Lambda->getLambdaContextDecl(); + Decl *LambdaContextDecl = Lambda->getLambdaManglingContextDecl(); unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber(); unsigned LambdaId; const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl); @@ -1236,7 +1236,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(GlobalDecl GD, if (Record->isLambda()) { llvm::SmallString<10> Name("<lambda_"); - Decl *LambdaContextDecl = Record->getLambdaContextDecl(); + Decl *LambdaContextDecl = Record->getLambdaManglingContextDecl(); unsigned LambdaManglingNumber = Record->getLambdaManglingNumber(); unsigned LambdaId; const ParmVarDecl *Parm = diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index e1f68e4..1ac9f3b 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -530,8 +530,8 @@ void Environment::initialize() { SurroundingMethodDecl->getFunctionObjectParameterType(); setThisPointeeStorageLocation( cast<RecordStorageLocation>(createObject(ThisPointeeType))); - } else if (auto *FieldBeingInitialized = - dyn_cast<FieldDecl>(Parent->getLambdaContextDecl())) { + } else if (auto *FieldBeingInitialized = dyn_cast<FieldDecl>( + Parent->getLambdaContext().CDS.getValue())) { // This is in a field initializer, rather than a method. setThisPointeeStorageLocation( cast<RecordStorageLocation>(createObject(QualType( diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index a73a71f..22900b3 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -3738,12 +3738,12 @@ CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction( ParmVarDecl *DstDecl = ParmVarDecl::Create( C, FD, SourceLocation(), SourceLocation(), nullptr, DestTy, C.getTrivialTypeSourceInfo(DestTy, SourceLocation()), SC_None, - /*DefArg=*/nullptr); + /*DefArg=*/nullptr, FD->getTemplateDepth()); args.push_back(Params[0] = DstDecl); ParmVarDecl *SrcDecl = ParmVarDecl::Create( C, FD, SourceLocation(), SourceLocation(), nullptr, SrcTy, C.getTrivialTypeSourceInfo(SrcTy, SourceLocation()), SC_None, - /*DefArg=*/nullptr); + /*DefArg=*/nullptr, FD->getTemplateDepth()); args.push_back(Params[1] = SrcDecl); FD->setParams(Params); @@ -3836,12 +3836,12 @@ llvm::Constant *CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( ParmVarDecl *DstDecl = ParmVarDecl::Create( C, FD, SourceLocation(), SourceLocation(), nullptr, DestTy, C.getTrivialTypeSourceInfo(DestTy, SourceLocation()), SC_None, - /*DefArg=*/nullptr); + /*DefArg=*/nullptr, FD->getTemplateDepth()); args.push_back(Params[0] = DstDecl); ParmVarDecl *SrcDecl = ParmVarDecl::Create( C, FD, SourceLocation(), SourceLocation(), nullptr, SrcTy, C.getTrivialTypeSourceInfo(SrcTy, SourceLocation()), SC_None, - /*DefArg=*/nullptr); + /*DefArg=*/nullptr, FD->getTemplateDepth()); args.push_back(Params[1] = SrcDecl); FD->setParams(Params); diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 9e095a3..d53e88f 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -1791,7 +1791,8 @@ CGOpenMPRuntimeGPU::translateParameter(const FieldDecl *FD, const_cast<DeclContext *>(NativeParam->getDeclContext()), NativeParam->getBeginLoc(), NativeParam->getLocation(), NativeParam->getIdentifier(), ArgType, - /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr); + /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr, + NativeParam->getTemplateDepth()); } Address diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 8afe2ab..d70f641 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -545,7 +545,8 @@ static llvm::Function *emitOutlinedFunctionPrologue( Ctx, DebugFunctionDecl, CapVar ? CapVar->getBeginLoc() : FD->getBeginLoc(), CapVar ? CapVar->getLocation() : FD->getLocation(), II, ArgType, - /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr); + /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr, + DebugFunctionDecl->getTemplateDepth()); } else { Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(), II, ArgType, ImplicitParamKind::Other); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index fb1eb72..ea36035 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3997,6 +3997,8 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, switch (Ty->getLinkage()) { case Linkage::Invalid: llvm_unreachable("Linkage hasn't been computed!"); + case Linkage::Computing: + llvm_unreachable("Linkage is being computed!"); case Linkage::None: case Linkage::Internal: diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 76d0191..cd13831 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -3664,6 +3664,8 @@ static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) { switch (Ty->getLinkage()) { case Linkage::Invalid: llvm_unreachable("Linkage hasn't been computed!"); + case Linkage::Computing: + llvm_unreachable("Linkage is being computed!"); case Linkage::None: case Linkage::Internal: diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp index 419ff79..5cbc7a6 100644 --- a/clang/lib/Index/IndexSymbol.cpp +++ b/clang/lib/Index/IndexSymbol.cpp @@ -77,6 +77,8 @@ bool index::isFunctionLocalSymbol(const Decl *D) { case Linkage::Module: case Linkage::External: return false; + case Linkage::Computing: + llvm_unreachable("Linkage is being computed!"); } } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 1f56884..dcb1d8a 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -624,7 +624,7 @@ unsigned Parser::ParseAttributeArgsCommon( Actions, Uneval ? Sema::ExpressionEvaluationContext::Unevaluated : Sema::ExpressionEvaluationContext::ConstantEvaluated, - nullptr, + /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt, Sema::ExpressionEvaluationContextRecord::EK_AttrArgument); ExprResult ArgExpr( @@ -646,7 +646,7 @@ unsigned Parser::ParseAttributeArgsCommon( Actions, Uneval ? Sema::ExpressionEvaluationContext::Unevaluated : Sema::ExpressionEvaluationContext::ConstantEvaluated, - nullptr, + /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt, Sema::ExpressionEvaluationContextRecord::ExpressionKind:: EK_AttrArgument); @@ -2075,6 +2075,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, ProhibitAttributes(DeclSpecAttrs); return ParseNamespace(Context, DeclEnd); case tok::kw_using: { + EnterExpressionEvaluationContext Eval( + Actions, Actions.currentEvaluationContext().Context, + Sema::LazyContextDecl); ParsedAttributes Attrs(AttrFactory); takeAndConcatenateAttrs(DeclAttrs, DeclSpecAttrs, Attrs); return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), @@ -2134,6 +2137,10 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context); ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, DSContext); + EnterExpressionEvaluationContext Eval( + getActions(), getActions().currentEvaluationContext().Context, + Sema::LazyContextDecl); + // If we had a free-standing type definition with a missing semicolon, we // may get this far before the problem becomes obvious. if (DS.hasTagDefinition() && @@ -2339,7 +2346,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization); SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst); - ParseDeclarator(D); + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + ParseDeclarator(D, &CurTemplateDepthTracker); if (IsTemplateSpecOrInst) SAC.done(); @@ -2362,8 +2370,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList. LateParsedAttrList LateParsedAttrs(true); if (D.isFunctionDeclarator()) { - MaybeParseGNUAttributes(D, &LateParsedAttrs); - + { + std::optional<Sema::ContextRAII> Ctx; + if (DeclContext *DC = Actions.computeDeclContext(D.getCXXScopeSpec())) + Ctx.emplace(Actions, DC); + MaybeParseGNUAttributes(D, &LateParsedAttrs); + } // The _Noreturn keyword can't appear here, unlike the GNU noreturn // attribute. If we find the keyword here, tell the user to put it // at the start instead. @@ -2392,7 +2404,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } // We're at the point where the parsing of function declarator is finished. // - // A common error is that users accidently add a virtual specifier + // A common error is that users accidentally add a virtual specifier // (e.g. override) in an out-line method definition. // We attempt to recover by stripping all these specifiers coming after // the declarator. @@ -2459,7 +2471,6 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, TheDecl = ParseFunctionDefinition(D, TemplateInfo, &LateParsedAttrs); } - return Actions.ConvertDeclToDeclGroup(TheDecl); } @@ -2503,7 +2514,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, IsForRangeLoop = true; EnterExpressionEvaluationContext ForRangeInitContext( Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, - /*LambdaContextDecl=*/nullptr, + /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt, Sema::ExpressionEvaluationContextRecord::EK_Other, getLangOpts().CPlusPlus23); @@ -2584,6 +2595,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, D.clear(); D.setCommaLoc(CommaLoc); + EnterExpressionEvaluationContext Eval( + getActions(), getActions().currentEvaluationContext().Context, + Sema::LazyContextDecl); + // Accept attributes in an init-declarator. In the first declarator in a // declaration, these would be part of the declspec. In subsequent // declarators, they become part of the declarator itself, so that they @@ -2796,7 +2811,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( } break; } - } + } SemaCUDA::CUDATargetContextRAII X(Actions.CUDA(), SemaCUDA::CTCK_InitGlobalVar, ThisDecl); @@ -3424,7 +3439,8 @@ void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName, using ExpressionKind = Sema::ExpressionEvaluationContextRecord::ExpressionKind; EnterExpressionEvaluationContext EC( - Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr, + Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, + /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt, ExpressionKind::EK_AttrArgument); ExprResult ArgExpr( @@ -6291,7 +6307,8 @@ bool Parser::isDeclarationSpecifier( bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide, DeclSpec::FriendSpecified IsFriend, const ParsedTemplateInfo *TemplateInfo) { - RevertingTentativeParsingAction TPA(*this); + RevertingTentativeParsingAction TPA(*this, /*Unannotated=*/true); + Sema::SFINAETrap Trap(Actions); // Parse the C++ scope specifier. CXXScopeSpec SS; if (TemplateInfo && TemplateInfo->TemplateParams) @@ -6612,11 +6629,13 @@ void Parser::ParseTypeQualifierListOpt( } /// ParseDeclarator - Parse and verify a newly-initialized declarator. -void Parser::ParseDeclarator(Declarator &D) { +void Parser::ParseDeclarator( + Declarator &D, TemplateParameterDepthRAII *CurTemplateDepthTracker) { /// This implements the 'declarator' production in the C grammar, then checks /// for well-formedness and issues diagnostics. Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { - ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); + ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator, + CurTemplateDepthTracker); }); } @@ -6684,8 +6703,9 @@ static bool isPipeDeclarator(const Declarator &D) { /// [GNU] '&' restrict[opt] attributes[opt] /// [GNU?] '&&' restrict[opt] attributes[opt] /// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] -void Parser::ParseDeclaratorInternal(Declarator &D, - DirectDeclParseFunction DirectDeclParser) { +void Parser::ParseDeclaratorInternal( + Declarator &D, DirectDeclParseFunction DirectDeclParser, + TemplateParameterDepthRAII *CurTemplateDepthTracker) { if (Diags.hasAllExtensionsSilenced()) D.setExtension(); @@ -6756,7 +6776,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, AnnotateScopeToken(SS, true); if (DirectDeclParser) - (this->*DirectDeclParser)(D); + (this->*DirectDeclParser)(D, CurTemplateDepthTracker); return; } } @@ -6775,7 +6795,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Not a pointer, C++ reference, or block. if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) { if (DirectDeclParser) - (this->*DirectDeclParser)(D); + (this->*DirectDeclParser)(D, CurTemplateDepthTracker); return; } @@ -6798,8 +6818,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.ExtendWithDeclSpec(DS); // Recursively parse the declarator. - Actions.runWithSufficientStackSpace( - D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); }); + Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { + ParseDeclaratorInternal(D, DirectDeclParser, CurTemplateDepthTracker); + }); if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getPointer( @@ -6844,8 +6865,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, } // Recursively parse the declarator. - Actions.runWithSufficientStackSpace( - D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); }); + Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { + ParseDeclaratorInternal(D, DirectDeclParser, CurTemplateDepthTracker); + }); if (D.getNumTypeObjects() > 0) { // C++ [dcl.ref]p4: There shall be no references to references. @@ -6930,7 +6952,8 @@ static SourceLocation getMissingDeclaratorIdLoc(Declarator &D, /// /// Note, any additional constructs added here may need corresponding changes /// in isConstructorDeclarator. -void Parser::ParseDirectDeclarator(Declarator &D) { +void Parser::ParseDirectDeclarator( + Declarator &D, TemplateParameterDepthRAII *CurTemplateDepthTracker) { DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec()); if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) { @@ -7256,7 +7279,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (IsFunctionDeclaration) Actions.ActOnStartFunctionDeclarationDeclarator(D, TemplateParameterDepth); - ParseFunctionDeclarator(D, attrs, T, IsAmbiguous); + ParseFunctionDeclarator(D, attrs, T, CurTemplateDepthTracker, + IsAmbiguous); if (IsFunctionDeclaration) Actions.ActOnFinishFunctionDeclarationDeclarator(D); PrototypeScope.Exit(); @@ -7292,7 +7316,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { break; } } -} + } void Parser::ParseDecompositionDeclarator(Declarator &D) { assert(Tok.is(tok::l_square)); @@ -7486,7 +7510,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { Scope::FunctionPrototypeScope | Scope::DeclScope | (D.isFunctionDeclaratorAFunctionDeclaration() ? Scope::FunctionDeclarationScope : 0)); - ParseFunctionDeclarator(D, attrs, T, false, RequiresArg); + + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + ParseFunctionDeclarator(D, attrs, T, &CurTemplateDepthTracker, + /*IsAmbiguous=*/false, RequiresArg); PrototypeScope.Exit(); } @@ -7552,11 +7579,11 @@ void Parser::InitCXXThisScopeForDeclaratorIfRelevant( /// dynamic-exception-specification /// noexcept-specification /// -void Parser::ParseFunctionDeclarator(Declarator &D, - ParsedAttributes &FirstArgAttrs, - BalancedDelimiterTracker &Tracker, - bool IsAmbiguous, - bool RequiresArg) { +void Parser::ParseFunctionDeclarator( + Declarator &D, ParsedAttributes &FirstArgAttrs, + BalancedDelimiterTracker &Tracker, + TemplateParameterDepthRAII *CurTemplateDepthTracker, bool IsAmbiguous, + bool RequiresArg) { assert(getCurScope()->isFunctionPrototypeScope() && "Should call from a Function scope"); // lparen is already consumed! @@ -7608,7 +7635,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, ProhibitAttributes(FnAttrs); } else { if (Tok.isNot(tok::r_paren)) - ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc); + ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc, + CurTemplateDepthTracker); else if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); @@ -7885,7 +7913,9 @@ void Parser::ParseFunctionDeclaratorIdentifierList( void Parser::ParseParameterDeclarationClause( DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs, SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, - SourceLocation &EllipsisLoc, bool IsACXXFunctionDeclaration) { + SourceLocation &EllipsisLoc, + TemplateParameterDepthRAII *CurTemplateDepthTracker, + bool IsACXXFunctionDeclaration) { // Avoid exceeding the maximum function scope depth. // See https://bugs.llvm.org/show_bug.cgi?id=19607 @@ -7964,6 +7994,11 @@ void Parser::ParseParameterDeclarationClause( Diag(ThisLoc, diag::err_requires_expr_explicit_object_parameter); } + EnterExpressionEvaluationContext Eval( + getActions(), + Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, + Sema::LazyContextDecl); + ParsedTemplateInfo TemplateInfo; ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, DeclSpecContext::DSC_normal, @@ -7980,6 +8015,7 @@ void Parser::ParseParameterDeclarationClause( : DeclaratorCtx == DeclaratorContext::LambdaExpr ? DeclaratorContext::LambdaExprParameter : DeclaratorContext::Prototype); + ParseDeclarator(ParmDeclarator); if (ThisLoc.isValid()) @@ -8065,8 +8101,18 @@ void Parser::ParseParameterDeclarationClause( // Inform the actions module about the parameter declarator, so it gets // added to the current scope. - Decl *Param = - Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, ThisLoc); + bool StartImplicitTemplate = false; + ParmVarDecl *Param = Actions.ActOnParamDeclarator( + getCurScope(), ParmDeclarator, TemplateParameterDepth, + StartImplicitTemplate, ThisLoc); + getActions().UpdateCurrentContextDecl(Param); + if (StartImplicitTemplate) { + assert(CurTemplateDepthTracker && + "A parsing context which can introduce an implicit template is " + "not handled"); + CurTemplateDepthTracker->setAddedDepth(1); + } + // Parse the default argument, if any. We parse the default // arguments in all dialects; the semantic analysis in // ActOnParamDefaultArgument will reject the default argument in @@ -8089,13 +8135,6 @@ void Parser::ParseParameterDeclarationClause( // Consume the '='. ConsumeToken(); - // The argument isn't actually potentially evaluated unless it is - // used. - EnterExpressionEvaluationContext Eval( - Actions, - Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, - Param); - ExprResult DefArgResult; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 6370da1..f761fc4 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1172,7 +1172,8 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // C++11 [dcl.type.simple]p4: // The operand of the decltype specifier is an unevaluated operand. EnterExpressionEvaluationContext Unevaluated( - Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, + Actions, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl, Sema::ExpressionEvaluationContextRecord::EK_Decltype); Result = Actions.CorrectDelayedTyposInExpr( ParseExpression(), /*InitDecl=*/nullptr, @@ -2716,8 +2717,9 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( // // NOTE: the latter two productions are a proposed bugfix rather than the // current grammar rules as of C++20. + TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); if (Tok.isNot(tok::colon)) - ParseDeclarator(DeclaratorInfo); + ParseDeclarator(DeclaratorInfo, &CurTemplateDepthTracker); else DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation()); @@ -3299,6 +3301,22 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration( // member-declarator-list ',' member-declarator while (true) { + std::optional<EnterExpressionEvaluationContext> Eval; + if (!DeclaratorInfo.isFirstDeclarator()) { + Eval.emplace(Actions, Actions.currentEvaluationContext().Context, + Sema::LazyContextDecl); + // GNU attributes are allowed before the second and subsequent declarator. + // However, this does not apply for [[]] attributes (which could show up + // before or after the __attribute__ attributes). + DiagnoseAndSkipCXX11Attributes(); + MaybeParseGNUAttributes(DeclaratorInfo); + DiagnoseAndSkipCXX11Attributes(); + + if (ParseCXXMemberDeclaratorBeforeInitializer( + DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) + break; + } + InClassInitStyle HasInClassInit = ICIS_NoInit; bool HasStaticInitializer = false; if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) { @@ -3468,23 +3486,12 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration( << TemplateInfo.Kind; } - // Parse the next declarator. + // Prepare to parse the next declarator. DeclaratorInfo.clear(); VS.clear(); BitfieldSize = ExprResult(/*Invalid=*/false); EqualLoc = PureSpecLoc = SourceLocation(); DeclaratorInfo.setCommaLoc(CommaLoc); - - // GNU attributes are allowed before the second and subsequent declarator. - // However, this does not apply for [[]] attributes (which could show up - // before or after the __attribute__ attributes). - DiagnoseAndSkipCXX11Attributes(); - MaybeParseGNUAttributes(DeclaratorInfo); - DiagnoseAndSkipCXX11Attributes(); - - if (ParseCXXMemberDeclaratorBeforeInitializer( - DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) - break; } if (ExpectSemi && @@ -3736,6 +3743,9 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( return nullptr; } ParsedTemplateInfo TemplateInfo; + EnterExpressionEvaluationContext Eval( + Actions, Actions.currentEvaluationContext().Context, + Sema::LazyContextDecl); return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo); } } @@ -5327,6 +5337,9 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration( ParsedTemplateInfo TemplateInfo; // Parse all the comma separated declarators. + EnterExpressionEvaluationContext Eval( + Actions, Actions.currentEvaluationContext().Context, + Sema::LazyContextDecl); ParseCXXClassMemberDeclaration(CurAS, AccessAttrs, TemplateInfo); } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 64f284d..4d2f311 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -244,7 +244,8 @@ ExprResult Parser::ParseConstantExpression() { ExprResult Parser::ParseArrayBoundExpression() { EnterExpressionEvaluationContext ConstantEvaluated( - Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated, + Sema::ReuseLambdaContextDecl); // If we parse the bound of a VLA... we parse a non-constant // constant-expression! Actions.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true; @@ -267,7 +268,8 @@ ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) { /// \endverbatim ExprResult Parser::ParseConstraintExpression() { EnterExpressionEvaluationContext ConstantEvaluated( - Actions, Sema::ExpressionEvaluationContext::Unevaluated); + Actions, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); ExprResult LHS(ParseCastExpression(AnyCastExpr)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr)); if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) { @@ -289,7 +291,8 @@ ExprResult Parser::ParseConstraintExpression() { ExprResult Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) { EnterExpressionEvaluationContext ConstantEvaluated( - Actions, Sema::ExpressionEvaluationContext::Unevaluated); + Actions, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); bool NotPrimaryExpression = false; auto ParsePrimary = [&] () { ExprResult E = ParseCastExpression(PrimaryExprOnly, diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 9bb0fff..db08d44 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -25,6 +25,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCodeCompletion.h" +#include "clang/Sema/Template.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include <numeric> @@ -1361,7 +1362,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( Scope::FunctionPrototypeScope); Actions.PushLambdaScope(); - Actions.ActOnLambdaExpressionAfterIntroducer(Intro, getCurScope()); + Actions.ActOnLambdaExpressionAfterIntroducer(Intro, getCurScope(), + TemplateParameterDepth); ParsedAttributes Attributes(AttrFactory); if (getLangOpts().CUDA) { @@ -1465,15 +1467,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( if (Tok.isNot(tok::r_paren)) { Actions.RecordParsingTemplateParameterDepth( CurTemplateDepthTracker.getOriginalDepth()); - - ParseParameterDeclarationClause(D, Attributes, ParamInfo, EllipsisLoc); - // For a generic lambda, each 'auto' within the parameter declaration - // clause creates a template type parameter, so increment the depth. - // If we've parsed any explicit template parameters, then the depth will - // have already been incremented. So we make sure that at most a single - // depth level is added. - if (Actions.getCurGenericLambda()) - CurTemplateDepthTracker.setAddedDepth(1); + ParseParameterDeclarationClause(D, Attributes, ParamInfo, EllipsisLoc, + &CurTemplateDepthTracker); } T.consumeClose(); @@ -1608,6 +1603,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( Scope::CompoundStmtScope; ParseScope BodyScope(this, ScopeFlags); + // ActOnStartOfLambdaDefinition reintroduces the context + Actions.PopExpressionEvaluationContext(); Actions.ActOnStartOfLambdaDefinition(Intro, D, DS); // Parse compound-statement. @@ -2081,6 +2078,10 @@ Parser::ParseAliasDeclarationInInitStatement(DeclaratorContext Context, DeclGroupPtrTy DG; SourceLocation DeclStart = ConsumeToken(), DeclEnd; + EnterExpressionEvaluationContext Eval( + Actions, Actions.currentEvaluationContext().Context, + Sema::LazyContextDecl); + DG = ParseUsingDeclaration(Context, {}, DeclStart, DeclEnd, Attrs, AS_none); if (!DG) return DG; @@ -2239,6 +2240,10 @@ Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, // If this is a for loop, we're entering its condition. ForConditionScope.enter(/*IsConditionVariable=*/true); + EnterExpressionEvaluationContext Eval( + Actions, Actions.currentEvaluationContext().Context, + Sema::LazyContextDecl); + // type-specifier-seq DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_condition); @@ -3422,7 +3427,8 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { /// '[' expression[opt] ']' /// direct-new-declarator '[' constant-expression ']' /// -void Parser::ParseDirectNewDeclarator(Declarator &D) { +void Parser::ParseDirectNewDeclarator(Declarator &D, + TemplateParameterDepthRAII *) { // Parse the array dimensions. bool First = true; while (Tok.is(tok::l_square)) { @@ -3618,9 +3624,11 @@ ExprResult Parser::ParseRequiresExpression() { ParsedAttributes FirstArgAttrs(getAttrFactory()); SourceLocation EllipsisLoc; llvm::SmallVector<DeclaratorChunk::ParamInfo, 2> LocalParameters; + TemplateParameterDepthRAII CurTemplateDepthTracker( + TemplateParameterDepth); ParseParameterDeclarationClause(DeclaratorContext::RequiresExpr, FirstArgAttrs, LocalParameters, - EllipsisLoc); + EllipsisLoc, &CurTemplateDepthTracker); if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_requires_expr_parameter_list_ellipsis); for (auto &ParamInfo : LocalParameters) @@ -3636,18 +3644,23 @@ ExprResult Parser::ParseRequiresExpression() { // Start of requirement list llvm::SmallVector<concepts::Requirement *, 2> Requirements; - // C++2a [expr.prim.req]p2 - // Expressions appearing within a requirement-body are unevaluated operands. - EnterExpressionEvaluationContext Ctx( - Actions, Sema::ExpressionEvaluationContext::Unevaluated); - ParseScope BodyScope(this, Scope::DeclScope); // Create a separate diagnostic pool for RequiresExprBodyDecl. // Dependent diagnostics are attached to this Decl and non-depenedent // diagnostics are surfaced after this parse. ParsingDeclRAIIObject ParsingBodyDecl(*this, ParsingDeclRAIIObject::NoParent); - RequiresExprBodyDecl *Body = Actions.ActOnStartRequiresExpr( - RequiresKWLoc, LocalParameterDecls, getCurScope()); + RequiresExprBodyDecl *Body = + Actions.ActOnStartRequiresExpr(RequiresKWLoc, LocalParameterDecls, + getCurScope(), TemplateParameterDepth); + + LocalInstantiationScope InstScope(getActions()); + for (ParmVarDecl *D : LocalParameterDecls) + InstScope.InstantiatedLocal(D, D); + + // C++2a [expr.prim.req]p2 + // Expressions appearing within a requirement-body are unevaluated operands. + EnterExpressionEvaluationContext Ctx( + Actions, Sema::ExpressionEvaluationContext::Unevaluated); if (Tok.is(tok::r_brace)) { // Grammar does not allow an empty body. diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index dad39d8..3b4add8 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -20,6 +20,7 @@ #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCodeCompletion.h" #include "clang/Sema/SemaObjC.h" @@ -649,6 +650,10 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, SourceRange AtEnd; while (true) { + EnterExpressionEvaluationContext Eval( + getActions(), getActions().currentEvaluationContext().Context, + Sema::LazyContextDecl); + // If this is a method prototype, parse it. if (Tok.isOneOf(tok::minus, tok::plus)) { if (Decl *methodPrototype = @@ -1547,8 +1552,13 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Declarator ParmDecl(DS, ParsedAttributesView::none(), DeclaratorContext::Prototype); ParseDeclarator(ParmDecl); + + bool StartImplicitTemplate = false; + Decl *Param = Actions.ActOnParamDeclarator( + getCurScope(), ParmDecl, TemplateParameterDepth, StartImplicitTemplate); + assert(!StartImplicitTemplate); + const IdentifierInfo *ParmII = ParmDecl.getIdentifier(); - Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl); CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, ParmDecl.getIdentifierLoc(), Param, diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index bdb3fc0..7d232e0 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1612,7 +1612,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { } EnterExpressionEvaluationContext PotentiallyDiscarded( - Actions, Context, nullptr, + Actions, Context, /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt, Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter); ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc); } @@ -1657,7 +1657,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { } EnterExpressionEvaluationContext PotentiallyDiscarded( - Actions, Context, nullptr, + Actions, Context, /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt, Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter); ElseStmt = ParseStatement(); diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index de29652..9399e9d 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -113,6 +113,9 @@ Parser::DeclGroupPtrTy Parser::ParseTemplateDeclarationOrSpecialization( bool LastParamListWasEmpty = false; TemplateParameterLists ParamLists; TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + EnterExpressionEvaluationContext Eval( + getActions(), getActions().currentEvaluationContext().Context, + Sema::LazyContextDecl); do { // Consume the 'export', if any. @@ -325,6 +328,11 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo, ConceptDecl *D = Actions.ActOnStartConceptDefinition( getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc); + EnterExpressionEvaluationContext Uneval( + Actions, Actions.currentEvaluationContext().Context, + D ? Sema::ContextDeclOrLazy(D) + : Sema::ContextDeclOrLazy(Sema::LazyContextDecl)); + ParsedAttributes Attrs(AttrFactory); MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs); @@ -747,6 +755,9 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { SourceLocation EqualLoc; ParsedType DefaultArg; std::optional<DelayTemplateIdDestructionRAII> DontDestructTemplateIds; + EnterExpressionEvaluationContext Eval( + Actions, Actions.currentEvaluationContext().Context, + Sema::LazyContextDecl); if (TryConsumeToken(tok::equal, EqualLoc)) { // The default argument might contain a lambda declaration; avoid destroying // parsed template ids at the end of that declaration because they can be @@ -763,13 +774,11 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { .get(); } - NamedDecl *NewDecl = Actions.ActOnTypeParameter(getCurScope(), - TypenameKeyword, EllipsisLoc, - KeyLoc, ParamName, NameLoc, - Depth, Position, EqualLoc, - DefaultArg, - TypeConstraint != nullptr); - + NamedDecl *NewDecl = Actions.ActOnTypeParameter( + getCurScope(), TypenameKeyword, EllipsisLoc, KeyLoc, ParamName, NameLoc, + Depth, Position, EqualLoc, DefaultArg, TypeConstraint != nullptr); + if (EqualLoc.isValid()) + Actions.UpdateCurrentContextDecl(NewDecl); if (TypeConstraint) { Actions.ActOnTypeConstraint(TypeConstraintSS, TypeConstraint, cast<TemplateTypeParmDecl>(NewDecl), @@ -938,6 +947,10 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // we introduce the template parameter into the local scope. SourceLocation EqualLoc; ExprResult DefaultArg; + EnterExpressionEvaluationContext Eval( + Actions, Actions.currentEvaluationContext().Context, + /*ContextDecl=*/nullptr); + auto &ContextDecl = Actions.currentEvaluationContext().ContextDecl; if (TryConsumeToken(tok::equal, EqualLoc)) { if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) { Diag(Tok.getLocation(), diag::err_stmt_expr_in_default_arg) << 1; @@ -966,9 +979,11 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { } // Create the parameter. - return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl, - Depth, Position, EqualLoc, - DefaultArg.get()); + NamedDecl *NewDecl = Actions.ActOnNonTypeTemplateParameter( + getCurScope(), ParamDecl, Depth, Position, EqualLoc, DefaultArg.get()); + if (ContextDecl) + Actions.UpdateCurrentContextDecl(NewDecl); + return NewDecl; } void Parser::DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc, @@ -1492,9 +1507,10 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // argument before trying to disambiguate. EnterExpressionEvaluationContext EnterConstantEvaluated( - Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated, - /*LambdaContextDecl=*/nullptr, - /*ExprContext=*/Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated, + Sema::ReuseLambdaContextDecl, + /*ExprContext=*/ + Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); if (isCXXTypeId(TypeIdAsTemplateArgument)) { TypeResult TypeArg = ParseTypeName( /*Range=*/nullptr, DeclaratorContext::TemplateArg); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 04c2f1d..67d5388 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -19,6 +19,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCodeCompletion.h" @@ -808,6 +809,10 @@ Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, ParsingDeclSpec *DS) { DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this); ParenBraceBracketBalancer BalancerRAIIObj(*this); + assert(TemplateParameterDepth == 0); + EnterExpressionEvaluationContext Eval( + getActions(), getActions().currentEvaluationContext().Context, + Sema::LazyContextDecl); if (PP.isCodeCompletionReached()) { cutOffParsing(); @@ -1291,7 +1296,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Poison SEH identifiers so they are flagged as illegal in function bodies. PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true); const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); // If this is C89 and the declspecs were completely missing, fudge in an // implicit int. We do this here because this is the only place where @@ -1480,15 +1484,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return Res; } - // With abbreviated function templates - we need to explicitly add depth to - // account for the implicit template parameter list induced by the template. - if (const auto *Template = dyn_cast_if_present<FunctionTemplateDecl>(Res); - Template && Template->isAbbreviated() && - Template->getTemplateParameters()->getParam(0)->isImplicit()) - // First template parameter is implicit - meaning no explicit template - // parameter list was specified. - CurTemplateDepthTracker.addDepth(1); - if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) && trySkippingFunctionBody()) { BodyScope.Exit(); @@ -1596,9 +1591,12 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // If attributes are present, parse them. MaybeParseGNUAttributes(ParmDeclarator); + bool StartImplicitTemplate = false; // Ask the actions module to compute the type for this declarator. - Decl *Param = - Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator); + Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, + TemplateParameterDepth, + StartImplicitTemplate); + assert(!StartImplicitTemplate); if (Param && // A missing identifier has already been diagnosed. @@ -1654,7 +1652,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { } // The actions module must verify that all arguments were declared. - Actions.ActOnFinishKNRParamDeclarations(getCurScope(), D, Tok.getLocation()); + Actions.ActOnFinishKNRParamDeclarations(getCurScope(), D, Tok.getLocation(), + TemplateParameterDepth); } diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 071e64f..4102258 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -264,7 +264,7 @@ struct BuiltinTypeDeclBuilder { AST, MethodDecl->getDeclContext(), SourceLocation(), SourceLocation(), &II, AST.UnsignedIntTy, AST.getTrivialTypeSourceInfo(AST.UnsignedIntTy, SourceLocation()), - SC_None, nullptr); + SC_None, nullptr, MethodDecl->getTemplateDepth()); MethodDecl->setParams({IdxParam}); // Also add the parameter to the function prototype. diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 46ddd36..545244e 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -287,7 +287,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, // evaluation stack. ExprEvalContexts.emplace_back( ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{}, - nullptr, ExpressionEvaluationContextRecord::EK_Other); + nullptr, std::nullopt, ExpressionEvaluationContextRecord::EK_Other, 0); // Initialization of data sharing attributes stack for OpenMP OpenMP().InitDataSharingAttributesStack(); @@ -529,6 +529,8 @@ void Sema::Initialize() { Sema::~Sema() { assert(InstantiatingSpecializations.empty() && "failed to clean up an InstantiatingTemplate?"); + assert(PendingLazyContextDecls.empty() && + "failed to clean up a lazy ContextDecl?"); if (VisContext) FreeVisContext(); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 5b2d652..4414b36 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -106,16 +106,11 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, } if (PartialSpec) { - // A declaration of the partial specialization must be visible. - // We can always recover here, because this only happens when we're - // entering the context, and that can't happen in a SFINAE context. - assert(!isSFINAEContext() && "partial specialization scope " - "specifier in SFINAE context?"); if (PartialSpec->hasDefinition() && !hasReachableDefinition(PartialSpec)) diagnoseMissingImport(SS.getLastQualifierNameLoc(), PartialSpec, MissingImportKind::PartialSpecialization, - true); + /*Recover=*/!isSFINAEContext()); return PartialSpec; } diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 6a1b325..f8902f3 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -961,6 +961,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( if (MLTAL.getNumSubstitutedLevels() == 0) return ConstrExpr; + MLTAL.setKind(TemplateSubstitutionKind::Rewrite); Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 3c6a0df..64194a5 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -24,8 +24,8 @@ #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/MangleNumberingContext.h" +#include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/Randstruct.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" @@ -41,6 +41,7 @@ #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" @@ -2314,9 +2315,10 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type, if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(Type)) { SmallVector<ParmVarDecl *, 16> Params; for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { - ParmVarDecl *parm = ParmVarDecl::Create( - Context, New, SourceLocation(), SourceLocation(), nullptr, - FT->getParamType(i), /*TInfo=*/nullptr, SC_None, nullptr); + ParmVarDecl *parm = + ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(), + nullptr, FT->getParamType(i), /*TInfo=*/nullptr, + SC_None, nullptr, /*TemplateDepth=*/0); parm->setScopeInfo(0, i); Params.push_back(parm); } @@ -4164,7 +4166,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, for (const auto &ParamType : OldProto->param_types()) { ParmVarDecl *Param = ParmVarDecl::Create( Context, New, SourceLocation(), SourceLocation(), nullptr, - ParamType, /*TInfo=*/nullptr, SC_None, nullptr); + ParamType, /*TInfo=*/nullptr, SC_None, nullptr, + New->getTemplateDepth()); Param->setScopeInfo(0, Params.size()); Param->setImplicit(); Params.push_back(Param); @@ -4815,11 +4818,10 @@ void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) { return; } + ContextDeclOrLazy ContextDecl = ExprEvalContexts.back().ContextDecl; // If this tag isn't a direct child of a class, number it if it is local. - MangleNumberingContext *MCtx; - Decl *ManglingContextDecl; - std::tie(MCtx, ManglingContextDecl) = - getCurrentMangleNumberContext(Tag->getDeclContext()); + MangleNumberingContext *MCtx = std::get<0>(getCurrentMangleNumberContext( + Tag->getDeclContext(), ContextDecl ? *ContextDecl : nullptr)); if (MCtx) { Context.setManglingNumber( Tag, MCtx->getManglingNumber( @@ -5711,10 +5713,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (VarDecl *NewVD = dyn_cast<VarDecl>(Anon)) { if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { - MangleNumberingContext *MCtx; - Decl *ManglingContextDecl; - std::tie(MCtx, ManglingContextDecl) = - getCurrentMangleNumberContext(NewVD->getDeclContext()); + ContextDeclOrLazy ContextDecl = ExprEvalContexts.back().ContextDecl; + MangleNumberingContext *MCtx = std::get<0>(getCurrentMangleNumberContext( + NewVD->getDeclContext(), ContextDecl ? *ContextDecl : nullptr)); if (MCtx) { Context.setManglingNumber( NewVD, MCtx->getManglingNumber( @@ -8071,10 +8072,9 @@ NamedDecl *Sema::ActOnVariableDeclarator( RegisterLocallyScopedExternCDecl(NewVD, S); if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { - MangleNumberingContext *MCtx; - Decl *ManglingContextDecl; - std::tie(MCtx, ManglingContextDecl) = - getCurrentMangleNumberContext(NewVD->getDeclContext()); + ContextDeclOrLazy ContextDecl = currentEvaluationContext().ContextDecl; + MangleNumberingContext *MCtx = std::get<0>(getCurrentMangleNumberContext( + NewVD->getDeclContext(), ContextDecl ? *ContextDecl : nullptr)); if (MCtx) { Context.setManglingNumber( NewVD, MCtx->getManglingNumber( @@ -14940,8 +14940,10 @@ static void CheckExplicitObjectParameter(Sema &S, ParmVarDecl *P, LSI->ExplicitObjectParameter = P; } -Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, - SourceLocation ExplicitThisLoc) { +ParmVarDecl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, + unsigned TemplateDepth, + bool &StartImplicitTemplate, + SourceLocation ExplicitThisLoc) { const DeclSpec &DS = D.getDeclSpec(); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. @@ -14981,7 +14983,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, CheckFunctionOrTemplateParamDeclarator(S, D); - TypeSourceInfo *TInfo = GetTypeForDeclarator(D); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, &StartImplicitTemplate); + if (StartImplicitTemplate) + TemplateDepth += 1; + QualType parmDeclType = TInfo->getType(); // Check for redeclaration of parameters, e.g. int foo(int x, int x); @@ -15009,12 +15014,9 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, } } - // Temporarily put parameter variables in the translation unit, not - // the enclosing context. This prevents them from accidentally - // looking like class members in C++. ParmVarDecl *New = - CheckParameter(Context.getTranslationUnitDecl(), D.getBeginLoc(), - D.getIdentifierLoc(), II, parmDeclType, TInfo, SC); + CheckParameter(CurContext, D.getBeginLoc(), D.getIdentifierLoc(), II, + parmDeclType, TInfo, SC, TemplateDepth); if (D.isInvalidType()) New->setInvalidDecl(); @@ -15054,9 +15056,10 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, /* FIXME: setting StartLoc == Loc. Would it be worth to modify callers so as to provide proper source location for the unnamed parameters, embedding the parameter's type? */ - ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, nullptr, - T, Context.getTrivialTypeSourceInfo(T, Loc), - SC_None, nullptr); + ParmVarDecl *Param = ParmVarDecl::Create( + Context, DC, Loc, Loc, nullptr, T, + Context.getTrivialTypeSourceInfo(T, Loc), SC_None, nullptr, + Decl::castFromDeclContext(DC)->getTemplateDepth()); Param->setImplicit(); return Param; } @@ -15106,7 +15109,8 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue( ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, const IdentifierInfo *Name, QualType T, - TypeSourceInfo *TSInfo, StorageClass SC) { + TypeSourceInfo *TSInfo, StorageClass SC, + unsigned TemplateDepth) { // In ARC, infer a lifetime qualifier for appropriate parameter types. if (getLangOpts().ObjCAutoRefCount && T.getObjCLifetime() == Qualifiers::OCL_None && @@ -15136,7 +15140,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, Context.getAdjustedParameterType(T), - TSInfo, SC, nullptr); + TSInfo, SC, nullptr, TemplateDepth); // Make a note if we created a new pack in the scope of a lambda, so that // we know that references to that pack must also be expanded within the @@ -15189,7 +15193,8 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, } void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, - SourceLocation LocAfterDecls) { + SourceLocation LocAfterDecls, + unsigned TemplateDepth) { DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // C99 6.9.1p6 "If a declarator includes an identifier list, each declaration @@ -15229,7 +15234,9 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, Declarator ParamD(DS, ParsedAttributesView::none(), DeclaratorContext::KNRTypeList); ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc); - FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD); + bool StartImplicitTemplate = false; + FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD, TemplateDepth, + StartImplicitTemplate); } } } @@ -15257,6 +15264,13 @@ Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D, D.setFunctionDefinitionKind(FunctionDefinitionKind::Definition); Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists); + if (auto *D = DP) { + if (auto *TD = dyn_cast<FunctionTemplateDecl>(D)) + D = TD->getTemplatedDecl(); + else + assert(isa<FunctionDecl>(D)); + UpdateCurrentContextDecl(D); + } Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody, BodyKind); if (!Bases.empty()) @@ -15475,8 +15489,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, // potentially evaluated and either: its innermost enclosing non-block scope // is a function parameter scope of an immediate function. PushExpressionEvaluationContext( - FD->isConsteval() ? ExpressionEvaluationContext::ImmediateFunctionContext - : ExprEvalContexts.back().Context); + FD->isConsteval() + ? ExpressionEvaluationContext::ImmediateFunctionContext + : ExprEvalContexts.back().Context, + FD); // Each ExpressionEvaluationContextRecord also keeps track of whether the // context is nested in an immediate function context, so smaller contexts @@ -16404,6 +16420,9 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, std::move(DS.getAttributes()), SourceLocation()); D.SetIdentifier(&II, Loc); + EnterExpressionEvaluationContext EvalContext( + *this, currentEvaluationContext().Context, LazyContextDecl); + // Insert this function into the enclosing block scope. FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(BlockScope, D)); FD->setImplicit(); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 6b6fa98..e79c204 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3540,6 +3540,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, NonTemplateMember = FunTmpl->getTemplatedDecl(); else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member)) NonTemplateMember = VarTmpl->getTemplatedDecl(); + UpdateCurrentContextDecl(NonTemplateMember); Member->setAccess(AS); @@ -13520,6 +13521,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, NewND = NewTD; } + UpdateCurrentContextDecl(NewTD); PushOnScopeChains(NewND, S); ActOnDocumentableDecl(NewND); return NewND; @@ -14009,7 +14011,8 @@ Sema::findInheritingConstructor(SourceLocation Loc, Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc); ParmVarDecl *PD = ParmVarDecl::Create( Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr, - FPT->getParamType(I), TInfo, SC_None, /*DefArg=*/nullptr); + FPT->getParamType(I), TInfo, SC_None, /*DefArg=*/nullptr, + DerivedCtor->getTemplateDepth()); PD->setScopeInfo(0, I); PD->setImplicit(); // Ensure attributes are propagated onto parameters (this matters for @@ -14802,11 +14805,10 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { /* Diagnose */ false); // Add the parameter to the operator. - ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, - ClassLoc, ClassLoc, - /*Id=*/nullptr, ArgType, - /*TInfo=*/nullptr, SC_None, - nullptr); + ParmVarDecl *FromParam = ParmVarDecl::Create( + Context, CopyAssignment, ClassLoc, ClassLoc, + /*Id=*/nullptr, ArgType, + /*TInfo=*/nullptr, SC_None, nullptr, CopyAssignment->getTemplateDepth()); CopyAssignment->setParams(FromParam); CopyAssignment->setTrivial( @@ -15154,11 +15156,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { /* Diagnose */ false); // Add the parameter to the operator. - ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment, - ClassLoc, ClassLoc, - /*Id=*/nullptr, ArgType, - /*TInfo=*/nullptr, SC_None, - nullptr); + ParmVarDecl *FromParam = ParmVarDecl::Create( + Context, MoveAssignment, ClassLoc, ClassLoc, + /*Id=*/nullptr, ArgType, + /*TInfo=*/nullptr, SC_None, nullptr, MoveAssignment->getTemplateDepth()); MoveAssignment->setParams(FromParam); MoveAssignment->setTrivial( @@ -15559,10 +15560,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( TSI = Context.getTrivialTypeSourceInfo(ArgType); // Add the parameter to the constructor. - ParmVarDecl *FromParam = - ParmVarDecl::Create(Context, CopyConstructor, ClassLoc, ClassLoc, - /*IdentifierInfo=*/nullptr, ArgType, - /*TInfo=*/TSI, SC_None, nullptr); + ParmVarDecl *FromParam = ParmVarDecl::Create( + Context, CopyConstructor, ClassLoc, ClassLoc, + /*IdentifierInfo=*/nullptr, ArgType, + /*TInfo=*/TSI, SC_None, nullptr, CopyConstructor->getTemplateDepth()); CopyConstructor->setParams(FromParam); CopyConstructor->setTrivial( @@ -15697,11 +15698,10 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( /* Diagnose */ false); // Add the parameter to the constructor. - ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, - ClassLoc, ClassLoc, - /*IdentifierInfo=*/nullptr, - ArgType, /*TInfo=*/nullptr, - SC_None, nullptr); + ParmVarDecl *FromParam = ParmVarDecl::Create( + Context, MoveConstructor, ClassLoc, ClassLoc, + /*IdentifierInfo=*/nullptr, ArgType, /*TInfo=*/nullptr, SC_None, nullptr, + MoveConstructor->getTemplateDepth()); MoveConstructor->setParams(FromParam); MoveConstructor->setTrivial( @@ -17862,6 +17862,14 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, assert(ND->getLexicalDeclContext() == CurContext); + if (auto *D = ND) { + if (auto *TD = dyn_cast<FunctionTemplateDecl>(D)) + D = TD->getTemplatedDecl(); + else + assert(isa<FunctionDecl>(D)); + UpdateCurrentContextDecl(D); + } + // If we performed typo correction, we might have added a scope specifier // and changed the decl context. DC = ND->getDeclContext(); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 8074534..bc08327 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -4805,9 +4805,9 @@ Decl *SemaObjC::ActOnMethodDeclaration( ? DI->getTypeLoc().getBeginLoc() : ArgInfo[i].NameLoc; - ParmVarDecl *Param = - SemaRef.CheckParameter(ObjCMethod, StartLoc, ArgInfo[i].NameLoc, - ArgInfo[i].Name, ArgType, DI, SC_None); + ParmVarDecl *Param = SemaRef.CheckParameter( + ObjCMethod, StartLoc, ArgInfo[i].NameLoc, ArgInfo[i].Name, ArgType, DI, + SC_None, ObjCMethod->getTemplateDepth()); Param->setObjCMethodScopeInfo(i); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 30e5fe4..818bb7a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6255,10 +6255,10 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context, FT = cast<FunctionProtoType>(OverloadTy); for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { QualType ParamType = FT->getParamType(i); - ParmVarDecl *Parm = - ParmVarDecl::Create(Context, OverloadDecl, SourceLocation(), - SourceLocation(), nullptr, ParamType, - /*TInfo=*/nullptr, SC_None, nullptr); + ParmVarDecl *Parm = ParmVarDecl::Create( + Context, OverloadDecl, SourceLocation(), SourceLocation(), nullptr, + ParamType, + /*TInfo=*/nullptr, SC_None, nullptr, OverloadDecl->getTemplateDepth()); Parm->setScopeInfo(0, i); Params.push_back(Parm); } @@ -15990,13 +15990,13 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); if (LangOpts.CPlusPlus) { - MangleNumberingContext *MCtx; - Decl *ManglingContextDecl; - std::tie(MCtx, ManglingContextDecl) = - getCurrentMangleNumberContext(Block->getDeclContext()); + Decl *ManglingContextDecl = *ExprEvalContexts.back().ContextDecl; + auto [MCtx, ManglingContext] = getCurrentMangleNumberContext( + Block->getDeclContext(), ManglingContextDecl); if (MCtx) { unsigned ManglingNumber = MCtx->getManglingNumber(Block); - Block->setBlockMangling(ManglingNumber, ManglingContextDecl); + Block->setBlockMangling(ManglingNumber, + ManglingContext ? ManglingContextDecl : nullptr); } } @@ -17224,12 +17224,13 @@ TypeSourceInfo *Sema::TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo) { return TransformToPE(*this).TransformType(TInfo); } -void -Sema::PushExpressionEvaluationContext( - ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl, +void Sema::PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, ContextDeclOrLazy ContextDecl, + ArrayRef<TemplateArgument> ContextArgs, ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, - LambdaContextDecl, ExprContext); + ContextDecl, ContextArgs, ExprContext, + PendingLazyContextDecls.size()); // Discarded statements and immediate contexts nested in other // discarded statements or immediate context are themselves @@ -17257,8 +17258,11 @@ void Sema::PushExpressionEvaluationContext( ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { - Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl; - PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext); + const auto &PrevRec = ExprEvalContexts.back(); + PushExpressionEvaluationContext(NewContext, PrevRec.ContextDecl, + PrevRec.ContextArgs, ExprContext); + ExprEvalContexts.back().HasReusedDeclContext = true; + ExprEvalContexts.back().LazyContextDeclPos = PrevRec.LazyContextDeclPos; } namespace { @@ -17658,8 +17662,49 @@ HandleImmediateInvocations(Sema &SemaRef, } } +static void setContextDecl(Sema &S, Decl *Base, Decl *ContextDecl) { + switch (Base->getKind()) { + case Decl::CXXRecord: { + auto *RD = cast<CXXRecordDecl>(Base); + RD->setLambdaContextDecl(ContextDecl); + S.handleLambdaNumbering(RD, RD->getLambdaCallOperator(), + /*NumberingOverride=*/std::nullopt, + /*InSignature=*/true); + } break; + case Decl::RequiresExprBody: + cast<RequiresExprBodyDecl>(Base)->setContextDecl(ContextDecl); + break; + default: + llvm_unreachable("Undexpected Decl Kind"); + } +} + +void Sema::UpdateCurrentContextDecl(Decl *ContextDecl) { + assert(ContextDecl); + ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back(); + assert(!Rec.ContextDecl.hasValue()); + assert(Rec.LazyContextDeclPos <= PendingLazyContextDecls.size()); + Rec.ContextDecl = ContextDecl; + while (PendingLazyContextDecls.size() > Rec.LazyContextDeclPos) + setContextDecl(*this, PendingLazyContextDecls.pop_back_val(), ContextDecl); +} + void Sema::PopExpressionEvaluationContext() { ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back(); + assert(Rec.LazyContextDeclPos <= PendingLazyContextDecls.size()); + if (!Rec.HasReusedDeclContext) { + if (Rec.ContextDecl.hasValue()) { + assert(Rec.LazyContextDeclPos == PendingLazyContextDecls.size()); + } else { + while (PendingLazyContextDecls.size() > Rec.LazyContextDeclPos) { + Decl *D = PendingLazyContextDecls.pop_back_val(); + setContextDecl(*this, D, nullptr); + if (auto *TD = dyn_cast<TagDecl>(D); TD && !TD->isCompleteDefinition()) + TD->setInvalidDecl(); + } + } + } + unsigned NumTypos = Rec.NumTypos; if (!Rec.Lambdas.empty()) { @@ -17728,9 +17773,23 @@ void Sema::PopExpressionEvaluationContext() { Rec.SavedMaybeODRUseExprs.end()); } + bool HasReusedDeclContext = Rec.HasReusedDeclContext; + unsigned LazyContextDeclPos = Rec.LazyContextDeclPos; + ContextDeclOrLazy ContextDecl = Rec.ContextDecl; + ArrayRef<TemplateArgument> ContextArgs = Rec.ContextArgs; + // Pop the current expression evaluation context off the stack. ExprEvalContexts.pop_back(); + if (HasReusedDeclContext) { + assert(ContextDecl.hasValue() || + !ExprEvalContexts.back().ContextDecl.hasValue()); + assert(ExprEvalContexts.back().LazyContextDeclPos <= LazyContextDeclPos); + ExprEvalContexts.back().ContextDecl = ContextDecl; + ExprEvalContexts.back().ContextArgs = ContextArgs; + ExprEvalContexts.back().LazyContextDeclPos = LazyContextDeclPos; + } + // The global expression evaluation context record is never popped. ExprEvalContexts.back().NumTypos += NumTypos; } @@ -18750,6 +18809,12 @@ static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI, } } +static auto skipRequiresBody(DeclContext *DC) { + while (DC->isRequiresExprBody()) + DC = DC->getParent(); + return DC; +} + bool Sema::tryCaptureVariable( ValueDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, @@ -18757,11 +18822,8 @@ bool Sema::tryCaptureVariable( // An init-capture is notionally from the context surrounding its // declaration, but its parent DC is the lambda class. DeclContext *VarDC = Var->getDeclContext(); - DeclContext *DC = CurContext; - // Skip past RequiresExprBodys because they don't constitute function scopes. - while (DC->isRequiresExprBody()) - DC = DC->getParent(); + DeclContext *DC = skipRequiresBody(CurContext); // tryCaptureVariable is called every time a DeclRef is formed, // it can therefore have non-negigible impact on performances. @@ -18770,12 +18832,6 @@ bool Sema::tryCaptureVariable( if (CapturingFunctionScopes == 0 && (!BuildAndDiagnose || VarDC == DC)) return true; - // Exception: Function parameters are not tied to the function's DeclContext - // until we enter the function definition. Capturing them anyway would result - // in an out-of-bounds error while traversing DC and its parents. - if (isa<ParmVarDecl>(Var) && !VarDC->isFunctionOrMethod()) - return true; - const auto *VD = dyn_cast<VarDecl>(Var); if (VD) { if (VD->isInitCapture()) @@ -19000,7 +19056,7 @@ bool Sema::tryCaptureVariable( Explicit = false; FunctionScopesIndex--; if (IsInScopeDeclarationContext) - DC = ParentDC; + DC = skipRequiresBody(ParentDC); } while (!VarDC->Equals(DC)); // Walk back down the scope stack, (e.g. from outer lambda to inner lambda) @@ -19998,9 +20054,9 @@ bool Sema::DiagIfReachable(SourceLocation Loc, ArrayRef<const Stmt *> Stmts, // static data member is not syntactically a constant evaluated constant, // but nonetheless is always required to be a constant expression, so we // can skip diagnosing. - // FIXME: Using the mangling context here is a hack. - if (auto *VD = dyn_cast_or_null<VarDecl>( - ExprEvalContexts.back().ManglingContextDecl)) { + if (auto ContextDecl = currentEvaluationContext().ContextDecl; + auto *VD = + dyn_cast_or_null<VarDecl>(ContextDecl ? *ContextDecl : nullptr)) { if (VD->isConstexpr() || (VD->isStaticDataMember() && VD->isFirstDecl() && !VD->isInline())) return false; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e086c60..7ee9f3e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3239,7 +3239,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, for (QualType T : Params) { ParamDecls.push_back(ParmVarDecl::Create( Context, Alloc, SourceLocation(), SourceLocation(), nullptr, T, - /*TInfo=*/nullptr, SC_None, nullptr)); + /*TInfo=*/nullptr, SC_None, nullptr, Alloc->getTemplateDepth())); ParamDecls.back()->setImplicit(); } Alloc->setParams(ParamDecls); @@ -9497,11 +9497,16 @@ Sema::BuildNestedRequirement(StringRef InvalidConstraintEntity, RequiresExprBodyDecl * Sema::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc, ArrayRef<ParmVarDecl *> LocalParameters, - Scope *BodyScope) { + Scope *BodyScope, unsigned TemplateDepth) { assert(BodyScope); - - RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(Context, CurContext, - RequiresKWLoc); + ContextDeclOrLazy CurContextDecl = currentEvaluationContext().ContextDecl; + RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create( + Context, CurContext, + CurContextDecl.hasValue() ? *CurContextDecl + : ContextDeclOrSentinel(TemplateDepth), + currentEvaluationContext().ContextArgs, RequiresKWLoc); + if (!CurContextDecl.hasValue()) + PendingLazyContextDecls.push_back(Body); PushDeclContext(BodyScope, Body); diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 2f914ddc..89ca8df 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -301,10 +301,10 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(SemaObjC &S, SourceLocation Loc, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCImplementationControl::Required, /*HasRelatedResultType=*/false); - ParmVarDecl *value = - ParmVarDecl::Create(S.SemaRef.Context, Method, SourceLocation(), - SourceLocation(), &CX.Idents.get("value"), - NumberType, /*TInfo=*/nullptr, SC_None, nullptr); + ParmVarDecl *value = ParmVarDecl::Create( + S.SemaRef.Context, Method, SourceLocation(), SourceLocation(), + &CX.Idents.get("value"), NumberType, /*TInfo=*/nullptr, SC_None, + nullptr, /*TemplateDepth=*/0); Method->setMethodParams(S.SemaRef.Context, value, std::nullopt); } @@ -581,13 +581,12 @@ ExprResult SemaObjC::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { /*isDefined=*/false, ObjCImplementationControl::Required, /*HasRelatedResultType=*/false); QualType ConstCharType = Context.CharTy.withConst(); - ParmVarDecl *value = - ParmVarDecl::Create(Context, M, - SourceLocation(), SourceLocation(), - &Context.Idents.get("value"), - Context.getPointerType(ConstCharType), - /*TInfo=*/nullptr, - SC_None, nullptr); + ParmVarDecl *value = ParmVarDecl::Create( + Context, M, SourceLocation(), SourceLocation(), + &Context.Idents.get("value"), + Context.getPointerType(ConstCharType), + /*TInfo=*/nullptr, SC_None, nullptr, + NSStringDecl->getTemplateDepth()); M->setMethodParams(Context, value, std::nullopt); BoxingMethod = M; } @@ -694,23 +693,18 @@ ExprResult SemaObjC::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { SmallVector<ParmVarDecl *, 2> Params; - ParmVarDecl *bytes = - ParmVarDecl::Create(Context, M, - SourceLocation(), SourceLocation(), - &Context.Idents.get("bytes"), - Context.VoidPtrTy.withConst(), - /*TInfo=*/nullptr, - SC_None, nullptr); + unsigned TemplateDepth = NSValueDecl->getTemplateDepth(); + ParmVarDecl *bytes = ParmVarDecl::Create( + Context, M, SourceLocation(), SourceLocation(), + &Context.Idents.get("bytes"), Context.VoidPtrTy.withConst(), + /*TInfo=*/nullptr, SC_None, nullptr, TemplateDepth); Params.push_back(bytes); QualType ConstCharType = Context.CharTy.withConst(); - ParmVarDecl *type = - ParmVarDecl::Create(Context, M, - SourceLocation(), SourceLocation(), - &Context.Idents.get("type"), - Context.getPointerType(ConstCharType), - /*TInfo=*/nullptr, - SC_None, nullptr); + ParmVarDecl *type = ParmVarDecl::Create( + Context, M, SourceLocation(), SourceLocation(), + &Context.Idents.get("type"), Context.getPointerType(ConstCharType), + /*TInfo=*/nullptr, SC_None, nullptr, TemplateDepth); Params.push_back(type); M->setMethodParams(Context, Params, std::nullopt); @@ -827,21 +821,15 @@ ExprResult SemaObjC::BuildObjCArrayLiteral(SourceRange SR, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCImplementationControl::Required, false); SmallVector<ParmVarDecl *, 2> Params; - ParmVarDecl *objects = ParmVarDecl::Create(Context, Method, - SourceLocation(), - SourceLocation(), - &Context.Idents.get("objects"), - Context.getPointerType(IdT), - /*TInfo=*/nullptr, - SC_None, nullptr); + ParmVarDecl *objects = ParmVarDecl::Create( + Context, Method, SourceLocation(), SourceLocation(), + &Context.Idents.get("objects"), Context.getPointerType(IdT), + /*TInfo=*/nullptr, SC_None, nullptr, /*TemplateDepth=*/0); Params.push_back(objects); - ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, - SourceLocation(), - SourceLocation(), - &Context.Idents.get("cnt"), - Context.UnsignedLongTy, - /*TInfo=*/nullptr, SC_None, - nullptr); + ParmVarDecl *cnt = ParmVarDecl::Create( + Context, Method, SourceLocation(), SourceLocation(), + &Context.Idents.get("cnt"), Context.UnsignedLongTy, + /*TInfo=*/nullptr, SC_None, nullptr, /*TemplateDepth=*/0); Params.push_back(cnt); Method->setMethodParams(Context, Params, std::nullopt); } @@ -988,29 +976,20 @@ ExprResult SemaObjC::BuildObjCDictionaryLiteral( /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCImplementationControl::Required, false); SmallVector<ParmVarDecl *, 3> Params; - ParmVarDecl *objects = ParmVarDecl::Create(Context, Method, - SourceLocation(), - SourceLocation(), - &Context.Idents.get("objects"), - Context.getPointerType(IdT), - /*TInfo=*/nullptr, SC_None, - nullptr); + ParmVarDecl *objects = ParmVarDecl::Create( + Context, Method, SourceLocation(), SourceLocation(), + &Context.Idents.get("objects"), Context.getPointerType(IdT), + /*TInfo=*/nullptr, SC_None, nullptr, /*TemplateDepth=*/0); Params.push_back(objects); - ParmVarDecl *keys = ParmVarDecl::Create(Context, Method, - SourceLocation(), - SourceLocation(), - &Context.Idents.get("keys"), - Context.getPointerType(IdT), - /*TInfo=*/nullptr, SC_None, - nullptr); + ParmVarDecl *keys = ParmVarDecl::Create( + Context, Method, SourceLocation(), SourceLocation(), + &Context.Idents.get("keys"), Context.getPointerType(IdT), + /*TInfo=*/nullptr, SC_None, nullptr, /*TemplateDepth=*/0); Params.push_back(keys); - ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, - SourceLocation(), - SourceLocation(), - &Context.Idents.get("cnt"), - Context.UnsignedLongTy, - /*TInfo=*/nullptr, SC_None, - nullptr); + ParmVarDecl *cnt = ParmVarDecl::Create( + Context, Method, SourceLocation(), SourceLocation(), + &Context.Idents.get("cnt"), Context.UnsignedLongTy, + /*TInfo=*/nullptr, SC_None, nullptr, /*TemplateDepth=*/0); Params.push_back(cnt); Method->setMethodParams(Context, Params, std::nullopt); } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 15ed857..7dbdc1d 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -190,11 +190,6 @@ clang::getStackIndexOfNearestEnclosingCaptureCapableLambda( return NoLambdaIsCaptureCapable; const unsigned IndexOfCaptureReadyLambda = *OptionalStackIndex; - assert(((IndexOfCaptureReadyLambda != (FunctionScopes.size() - 1)) || - S.getCurGenericLambda()) && - "The capture ready lambda for a potential capture can only be the " - "current lambda if it is a generic lambda"); - const sema::LambdaScopeInfo *const CaptureReadyLambdaLSI = cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambda]); @@ -247,18 +242,23 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { CXXRecordDecl * Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, - unsigned LambdaDependencyKind, - LambdaCaptureDefault CaptureDefault) { + LambdaCaptureDefault CaptureDefault, + unsigned TemplateDepth) { DeclContext *DC = CurContext; - while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) - DC = DC->getParent(); bool IsGenericLambda = Info && getGenericLambdaTemplateParameterList(getCurLambda(), *this); // Start constructing the lambda class. + ContextDeclOrLazy ContextDecl = currentEvaluationContext().ContextDecl; CXXRecordDecl *Class = CXXRecordDecl::CreateLambda( - Context, DC, Info, IntroducerRange.getBegin(), LambdaDependencyKind, - IsGenericLambda, CaptureDefault); + Context, DC, Info, IntroducerRange.getBegin(), IsGenericLambda, + CaptureDefault, + ContextDecl.hasValue() ? *ContextDecl + : ContextDeclOrSentinel(TemplateDepth), + currentEvaluationContext().ContextArgs); + if (!ContextDecl.hasValue()) + PendingLazyContextDecls.push_back(Class); + DC->addDecl(Class); return Class; @@ -278,11 +278,10 @@ static bool isInInlineFunction(const DeclContext *DC) { return false; } -std::tuple<MangleNumberingContext *, Decl *> -Sema::getCurrentMangleNumberContext(const DeclContext *DC) { +std::tuple<MangleNumberingContext *, bool> Sema::getCurrentMangleNumberContext( + const DeclContext *DC, Decl *ManglingContextDecl, bool InSignature) { // Compute the context for allocating mangling numbers in the current // expression, if the ABI requires them. - Decl *ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl; enum ContextKind { Normal, @@ -329,15 +328,15 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { switch (Kind) { case Normal: { // -- the bodies of inline or templated functions - if ((IsInNonspecializedTemplate && + if (((IsInNonspecializedTemplate || InSignature) && !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) || isInInlineFunction(CurContext)) { while (auto *CD = dyn_cast<CapturedDecl>(DC)) DC = CD->getParent(); - return std::make_tuple(&Context.getManglingNumberContext(DC), nullptr); + return std::make_tuple(&Context.getManglingNumberContext(DC), false); } - return std::make_tuple(nullptr, nullptr); + return std::make_tuple(nullptr, false); } case Concept: @@ -355,7 +354,7 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC) { return std::make_tuple( &Context.getManglingNumberContext(ASTContext::NeedExtraManglingDecl, ManglingContextDecl), - ManglingContextDecl); + true); } llvm_unreachable("unexpected context"); @@ -455,7 +454,8 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda( void Sema::handleLambdaNumbering( CXXRecordDecl *Class, CXXMethodDecl *Method, - std::optional<CXXRecordDecl::LambdaNumbering> NumberingOverride) { + std::optional<CXXRecordDecl::LambdaNumbering> NumberingOverride, + bool InSignature) { if (NumberingOverride) { Class->setLambdaNumbering(*NumberingOverride); return; @@ -477,10 +477,15 @@ void Sema::handleLambdaNumbering( return &Context.getManglingNumberContext(DC); }; + ContextDeclOrSentinel CDS = Class->getLambdaContext().CDS; + if (!CDS.hasValue()) + return; + + Decl *ContextDecl = CDS.getValue(); CXXRecordDecl::LambdaNumbering Numbering; MangleNumberingContext *MCtx; - std::tie(MCtx, Numbering.ContextDecl) = - getCurrentMangleNumberContext(Class->getDeclContext()); + std::tie(MCtx, Numbering.ManglingInContext) = getCurrentMangleNumberContext( + Class->getDeclContext(), ContextDecl, InSignature); if (!MCtx && (getLangOpts().CUDA || getLangOpts().SYCLIsDevice || getLangOpts().SYCLIsHost)) { // Force lambda numbering in CUDA/HIP as we need to name lambdas following @@ -490,7 +495,8 @@ void Sema::handleLambdaNumbering( // Also force for SYCL, since we need this for the // __builtin_sycl_unique_stable_name implementation, which depends on lambda // mangling. - MCtx = getMangleNumberingContext(Class, Numbering.ContextDecl); + MCtx = getMangleNumberingContext( + Class, Numbering.ManglingInContext ? ContextDecl : nullptr); assert(MCtx && "Retrieving mangle numbering context failed!"); Numbering.HasKnownInternalLinkage = true; } @@ -1060,7 +1066,8 @@ void Sema::CompleteLambdaCallOperator( } void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, - Scope *CurrentScope) { + Scope *CurrentScope, + unsigned TemplateDepth) { LambdaScopeInfo *LSI = getCurLambda(); assert(LSI && "LambdaScopeInfo should be on stack!"); @@ -1075,35 +1082,8 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, assert(LSI->NumExplicitTemplateParams == 0); - // Determine if we're within a context where we know that the lambda will - // be dependent, because there are template parameters in scope. - CXXRecordDecl::LambdaDependencyKind LambdaDependencyKind = - CXXRecordDecl::LDK_Unknown; - if (CurScope->getTemplateParamParent() != nullptr) { - LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent; - } else if (Scope *P = CurScope->getParent()) { - // Given a lambda defined inside a requires expression, - // - // struct S { - // S(auto var) requires requires { [&] -> decltype(var) { }; } - // {} - // }; - // - // The parameter var is not injected into the function Decl at the point of - // parsing lambda. In such scenarios, perceiving it as dependent could - // result in the constraint being evaluated, which matches what GCC does. - while (P->getEntity() && P->getEntity()->isRequiresExprBody()) - P = P->getParent(); - if (P->isFunctionDeclarationScope() && - llvm::any_of(P->decls(), [](Decl *D) { - return isa<ParmVarDecl>(D) && - cast<ParmVarDecl>(D)->getType()->isTemplateTypeParmType(); - })) - LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent; - } - - CXXRecordDecl *Class = createLambdaClosureType( - Intro.Range, /*Info=*/nullptr, LambdaDependencyKind, Intro.Default); + CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, /*Info=*/nullptr, + Intro.Default, TemplateDepth); LSI->Lambda = Class; CXXMethodDecl *Method = CreateLambdaCallOperator(Intro.Range, Class); @@ -1113,6 +1093,7 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, Method->setLexicalDeclContext(CurContext); PushDeclContext(CurScope, Method); + PushExpressionEvaluationContext(currentEvaluationContext().Context, Method); bool ContainsUnexpandedParameterPack = false; @@ -1549,7 +1530,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, PushExpressionEvaluationContext( LSI->CallOperator->isConsteval() ? ExpressionEvaluationContext::ImmediateFunctionContext - : ExpressionEvaluationContext::PotentiallyEvaluated); + : ExpressionEvaluationContext::PotentiallyEvaluated, + LSI->CallOperator); ExprEvalContexts.back().InImmediateFunctionContext = LSI->CallOperator->isConsteval(); ExprEvalContexts.back().InImmediateEscalatingFunctionContext = @@ -1746,7 +1728,7 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, S.Context.getTranslationUnitDecl(), From->getBeginLoc(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), - /*DefArg=*/nullptr)); + /*DefArg=*/nullptr, CallOperator->getTemplateDepth())); CallOpConvTL.setParam(I, From); CallOpConvNameTL.setParam(I, From); } @@ -2326,7 +2308,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, Context, Block, From->getBeginLoc(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), - /*DefArg=*/nullptr)); + /*DefArg=*/nullptr, Block->getTemplateDepth())); } Block->setParams(BlockParams); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index d3d4bf27..1a41a42 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -888,7 +888,8 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, for (unsigned IParm = 0, e = FP->getNumParams(); IParm != e; ++IParm) { ParmVarDecl *Parm = ParmVarDecl::Create( Context, NewOpenCLBuiltin, SourceLocation(), SourceLocation(), - nullptr, FP->getParamType(IParm), nullptr, SC_None, nullptr); + nullptr, FP->getParamType(IParm), nullptr, SC_None, nullptr, + /*TemplateDepth=*/0); Parm->setScopeInfo(0, IParm); ParmList.push_back(Parm); } diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 031f2a6..1c61fa2 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -2545,13 +2545,10 @@ void SemaObjC::ProcessPropertyDecl(ObjCPropertyDecl *property) { // Invent the arguments for the setter. We don't bother making a // nice name for the argument. - ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, - Loc, Loc, - property->getIdentifier(), - paramTy, - /*TInfo=*/nullptr, - SC_None, - nullptr); + ParmVarDecl *Argument = ParmVarDecl::Create( + Context, SetterMethod, Loc, Loc, property->getIdentifier(), paramTy, + /*TInfo=*/nullptr, SC_None, nullptr, + SetterMethod->getTemplateDepth()); SetterMethod->setMethodParams(Context, Argument, std::nullopt); AddPropertyAttrs(SemaRef, SetterMethod, property); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index b952ffb..3403da1 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6951,7 +6951,8 @@ static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, for (const ParmVarDecl *P : FDWithProto->parameters()) { auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(), SourceLocation(), nullptr, P->getType(), - /*TInfo=*/nullptr, SC_None, nullptr); + /*TInfo=*/nullptr, SC_None, nullptr, + FD->getTemplateDepth()); Param->setScopeInfo(0, Params.size()); Param->setImplicit(); Params.push_back(Param); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 861b0a9..bfa4177 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -13534,6 +13534,9 @@ static void AddOverloadedCallCandidate(Sema &S, if (!isa<FunctionProtoType>(Func->getType()->getAs<FunctionType>())) return; + EnterExpressionEvaluationContext Eval(S, + S.currentEvaluationContext().Context, + /*ContextDecl=*/Func); S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, /*SuppressUserConversions=*/false, PartialOverloading); @@ -13542,6 +13545,9 @@ static void AddOverloadedCallCandidate(Sema &S, if (FunctionTemplateDecl *FuncTemplate = dyn_cast<FunctionTemplateDecl>(Callee)) { + EnterExpressionEvaluationContext Eval( + S, S.currentEvaluationContext().Context, + /*ContextDecl=*/FuncTemplate->getTemplatedDecl()); S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl, ExplicitTemplateArgs, Args, CandidateSet, /*SuppressUserConversions=*/false, diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index 30ed47e..69b81a5 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -1122,15 +1122,12 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { /*isSynthesizedAccessorStub=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCImplementationControl::Required, false); - ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter, - SourceLocation(), SourceLocation(), - arrayRef ? &S.Context.Idents.get("index") - : &S.Context.Idents.get("key"), - arrayRef ? S.Context.UnsignedLongTy - : S.Context.getObjCIdType(), - /*TInfo=*/nullptr, - SC_None, - nullptr); + ParmVarDecl *Argument = ParmVarDecl::Create( + S.Context, AtIndexGetter, SourceLocation(), SourceLocation(), + arrayRef ? &S.Context.Idents.get("index") + : &S.Context.Idents.get("key"), + arrayRef ? S.Context.UnsignedLongTy : S.Context.getObjCIdType(), + /*TInfo=*/nullptr, SC_None, nullptr, /*TemplateDepth=*/0); AtIndexGetter->setMethodParams(S.Context, Argument, std::nullopt); } @@ -1225,23 +1222,17 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCImplementationControl::Required, false); SmallVector<ParmVarDecl *, 2> Params; - ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter, - SourceLocation(), SourceLocation(), - &S.Context.Idents.get("object"), - S.Context.getObjCIdType(), - /*TInfo=*/nullptr, - SC_None, - nullptr); + ParmVarDecl *object = ParmVarDecl::Create( + S.Context, AtIndexSetter, SourceLocation(), SourceLocation(), + &S.Context.Idents.get("object"), S.Context.getObjCIdType(), + /*TInfo=*/nullptr, SC_None, nullptr, /*TemplateDepth=*/0); Params.push_back(object); - ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter, - SourceLocation(), SourceLocation(), - arrayRef ? &S.Context.Idents.get("index") - : &S.Context.Idents.get("key"), - arrayRef ? S.Context.UnsignedLongTy - : S.Context.getObjCIdType(), - /*TInfo=*/nullptr, - SC_None, - nullptr); + ParmVarDecl *key = ParmVarDecl::Create( + S.Context, AtIndexSetter, SourceLocation(), SourceLocation(), + arrayRef ? &S.Context.Idents.get("index") + : &S.Context.Idents.get("key"), + arrayRef ? S.Context.UnsignedLongTy : S.Context.getObjCIdType(), + /*TInfo=*/nullptr, SC_None, nullptr, /*TemplateDepth=*/0); Params.push_back(key); AtIndexSetter->setMethodParams(S.Context, Params, std::nullopt); } diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp index 56d6f12..bebef1c 100644 --- a/clang/lib/Sema/SemaRISCV.cpp +++ b/clang/lib/Sema/SemaRISCV.cpp @@ -452,9 +452,9 @@ void RISCVIntrinsicManagerImpl::CreateRVVIntrinsicDecl(LookupResult &LR, const auto *FP = cast<FunctionProtoType>(BuiltinFuncType); SmallVector<ParmVarDecl *, 8> ParmList; for (unsigned IParm = 0, E = FP->getNumParams(); IParm != E; ++IParm) { - ParmVarDecl *Parm = - ParmVarDecl::Create(Context, RVVIntrinsicDecl, Loc, Loc, nullptr, - FP->getParamType(IParm), nullptr, SC_None, nullptr); + ParmVarDecl *Parm = ParmVarDecl::Create( + Context, RVVIntrinsicDecl, Loc, Loc, nullptr, FP->getParamType(IParm), + nullptr, SC_None, nullptr, /*TemplateDepth=*/0); Parm->setScopeInfo(0, IParm); ParmList.push_back(Parm); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 513f831..084a5f0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -989,15 +989,12 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) { TInfo->getTypeLoc().getBeginLoc()); } -NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename, - SourceLocation EllipsisLoc, - SourceLocation KeyLoc, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, - unsigned Depth, unsigned Position, - SourceLocation EqualLoc, - ParsedType DefaultArg, - bool HasTypeConstraint) { +NamedDecl * +Sema::ActOnTypeParameter(Scope *S, bool Typename, SourceLocation EllipsisLoc, + SourceLocation KeyLoc, IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, unsigned Depth, + unsigned Position, SourceLocation EqualLoc, + ParsedType DefaultArg, bool HasTypeConstraint) { assert(S->isTemplateParamScope() && "Template type parameter not in template parameter scope!"); @@ -3381,6 +3378,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (!AliasTemplate->getDeclContext()->isFileContext()) SavedContext.emplace(*this, AliasTemplate->getDeclContext()); + EnterExpressionEvaluationContext Eval( + *this, currentEvaluationContext().Context, Pattern, SugaredConverted); + CanonType = SubstType(Pattern->getUnderlyingType(), TemplateArgLists, AliasTemplate->getLocation(), AliasTemplate->getDeclName()); @@ -8384,6 +8384,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( CanonType = Context.getTypeDeclType(Specialization); } } + UpdateCurrentContextDecl(Specialization); // C++ [temp.expl.spec]p6: // If a template, a member template or the member of a class template is @@ -8494,10 +8495,21 @@ DeclResult Sema::ActOnClassTemplateSpecialization( return Specialization; } -Decl *Sema::ActOnTemplateDeclarator(Scope *S, - MultiTemplateParamsArg TemplateParameterLists, - Declarator &D) { +Decl *Sema::ActOnTemplateDeclarator( + Scope *S, MultiTemplateParamsArg TemplateParameterLists, Declarator &D) { Decl *NewDecl = HandleDeclarator(S, D, TemplateParameterLists); + if (auto *D = NewDecl) { + if (auto *TD = dyn_cast<FunctionTemplateDecl>(D)) + D = TD->getTemplatedDecl(); + else if (auto *TD = dyn_cast<VarTemplateDecl>(D)) + D = TD->getTemplatedDecl(); + else if (!(isa<FunctionDecl>(D) || isa<VarDecl>(D) || + isa<VarTemplateSpecializationDecl>(D))) { + D->dumpColor(); + llvm_unreachable("FU"); + } + UpdateCurrentContextDecl(D); + } ActOnDocumentableDecl(NewDecl); return NewDecl; } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 4c88159..129ff66 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3541,7 +3541,8 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( // Unevaluated SFINAE context. EnterExpressionEvaluationContext Unevaluated( - *this, Sema::ExpressionEvaluationContext::Unevaluated); + *this, Sema::ExpressionEvaluationContext::Unevaluated, + ReuseLambdaContextDecl); SFINAETrap Trap(*this); // C++ [temp.arg.explicit]p3: diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 545da21..47cde6e 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -391,9 +391,6 @@ struct ConvertConstructorToDeductionGuideTransform { /*EvaluateConstraint=*/false); } - assert(NewParam->getTemplateDepth() == 0 && - "Unexpected template parameter depth"); - AllParams.push_back(NewParam); SubstArgs.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam)); } @@ -401,13 +398,11 @@ struct ConvertConstructorToDeductionGuideTransform { // Substitute new template parameters into requires-clause if present. Expr *RequiresClause = nullptr; if (Expr *InnerRC = InnerParams->getRequiresClause()) { - MultiLevelTemplateArgumentList Args; - Args.setKind(TemplateSubstitutionKind::Rewrite); - Args.addOuterTemplateArguments(Depth1Args); - Args.addOuterRetainedLevel(); - if (NestedPattern) - Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth()); - ExprResult E = SemaRef.SubstExpr(InnerRC, Args); + MultiLevelTemplateArgumentList TemplateArgs(FTD, Depth1Args, + /*Final=*/true); + TemplateArgs.addOuterRetainedLevels( + 1 + (NestedPattern ? NestedPattern->getTemplateDepth() : 0)); + ExprResult E = SemaRef.SubstExpr(InnerRC, TemplateArgs); if (E.isInvalid()) return nullptr; RequiresClause = E.getAs<Expr>(); @@ -482,9 +477,9 @@ struct ConvertConstructorToDeductionGuideTransform { if (!TSI) return nullptr; - ParmVarDecl *NewParam = - ParmVarDecl::Create(SemaRef.Context, DC, Loc, Loc, nullptr, - TSI->getType(), TSI, SC_None, nullptr); + ParmVarDecl *NewParam = ParmVarDecl::Create( + SemaRef.Context, DC, Loc, Loc, nullptr, TSI->getType(), TSI, SC_None, + nullptr, Template->getTemplateDepth()); NewParam->setScopeInfo(0, Params.size()); FPTL.setParam(Params.size(), NewParam); Params.push_back(NewParam); @@ -621,10 +616,11 @@ private: if (NewType->isArrayType() || NewType->isFunctionType()) NewType = SemaRef.Context.getDecayedType(NewType); - ParmVarDecl *NewParam = ParmVarDecl::Create( - SemaRef.Context, DC, OldParam->getInnerLocStart(), - OldParam->getLocation(), OldParam->getIdentifier(), NewType, NewDI, - OldParam->getStorageClass(), NewDefArg.get()); + ParmVarDecl *NewParam = + ParmVarDecl::Create(SemaRef.Context, DC, OldParam->getInnerLocStart(), + OldParam->getLocation(), OldParam->getIdentifier(), + NewType, NewDI, OldParam->getStorageClass(), + NewDefArg.get(), Template->getTemplateDepth()); NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(), OldParam->getFunctionScopeIndex()); SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam); @@ -640,11 +636,13 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( struct TemplateParamsReferencedFinder : public RecursiveASTVisitor<TemplateParamsReferencedFinder> { const TemplateParameterList *TemplateParamList; + unsigned TargetDepth; llvm::BitVector ReferencedTemplateParams; TemplateParamsReferencedFinder( const TemplateParameterList *TemplateParamList) : TemplateParamList(TemplateParamList), + TargetDepth(TemplateParamList->getDepth()), ReferencedTemplateParams(TemplateParamList->size()) {} bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) { @@ -673,8 +671,7 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( } } void Mark(unsigned Depth, unsigned Index) { - if (Index < TemplateParamList->size() && - TemplateParamList->getParam(Index)->getTemplateDepth() == Depth) + if (Index < TemplateParamList->size() && Depth == TargetDepth) ReferencedTemplateParams.set(Index); } }; @@ -1182,7 +1179,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias( ParmVarDecl *NewParam = ParmVarDecl::Create( SemaRef.Context, G->getDeclContext(), DG->getParamDecl(I)->getBeginLoc(), P->getLocation(), nullptr, - TSI->getType(), TSI, SC_None, nullptr); + TSI->getType(), TSI, SC_None, nullptr, + AliasTemplate->getTemplateDepth()); NewParam->setScopeInfo(0, I); FPTL.setParam(I, NewParam); } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index c42cc25..6bb36ea 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -84,93 +84,6 @@ struct Response { } }; -// Retrieve the primary template for a lambda call operator. It's -// unfortunate that we only have the mappings of call operators rather -// than lambda classes. -const FunctionDecl * -getPrimaryTemplateOfGenericLambda(const FunctionDecl *LambdaCallOperator) { - if (!isLambdaCallOperator(LambdaCallOperator)) - return LambdaCallOperator; - while (true) { - if (auto *FTD = dyn_cast_if_present<FunctionTemplateDecl>( - LambdaCallOperator->getDescribedTemplate()); - FTD && FTD->getInstantiatedFromMemberTemplate()) { - LambdaCallOperator = - FTD->getInstantiatedFromMemberTemplate()->getTemplatedDecl(); - } else if (LambdaCallOperator->getPrimaryTemplate()) { - // Cases where the lambda operator is instantiated in - // TemplateDeclInstantiator::VisitCXXMethodDecl. - LambdaCallOperator = - LambdaCallOperator->getPrimaryTemplate()->getTemplatedDecl(); - } else if (auto *Prev = cast<CXXMethodDecl>(LambdaCallOperator) - ->getInstantiatedFromMemberFunction()) - LambdaCallOperator = Prev; - else - break; - } - return LambdaCallOperator; -} - -struct EnclosingTypeAliasTemplateDetails { - TypeAliasTemplateDecl *Template = nullptr; - TypeAliasTemplateDecl *PrimaryTypeAliasDecl = nullptr; - ArrayRef<TemplateArgument> AssociatedTemplateArguments; - - explicit operator bool() noexcept { return Template; } -}; - -// Find the enclosing type alias template Decl from CodeSynthesisContexts, as -// well as its primary template and instantiating template arguments. -EnclosingTypeAliasTemplateDetails -getEnclosingTypeAliasTemplateDecl(Sema &SemaRef) { - for (auto &CSC : llvm::reverse(SemaRef.CodeSynthesisContexts)) { - if (CSC.Kind != Sema::CodeSynthesisContext::SynthesisKind:: - TypeAliasTemplateInstantiation) - continue; - EnclosingTypeAliasTemplateDetails Result; - auto *TATD = cast<TypeAliasTemplateDecl>(CSC.Entity), - *Next = TATD->getInstantiatedFromMemberTemplate(); - Result = { - /*Template=*/TATD, - /*PrimaryTypeAliasDecl=*/TATD, - /*AssociatedTemplateArguments=*/CSC.template_arguments(), - }; - while (Next) { - Result.PrimaryTypeAliasDecl = Next; - Next = Next->getInstantiatedFromMemberTemplate(); - } - return Result; - } - return {}; -} - -// Check if we are currently inside of a lambda expression that is -// surrounded by a using alias declaration. e.g. -// template <class> using type = decltype([](auto) { ^ }()); -// We have to do so since a TypeAliasTemplateDecl (or a TypeAliasDecl) is never -// a DeclContext, nor does it have an associated specialization Decl from which -// we could collect these template arguments. -bool isLambdaEnclosedByTypeAliasDecl( - const FunctionDecl *LambdaCallOperator, - const TypeAliasTemplateDecl *PrimaryTypeAliasDecl) { - struct Visitor : RecursiveASTVisitor<Visitor> { - Visitor(const FunctionDecl *CallOperator) : CallOperator(CallOperator) {} - bool VisitLambdaExpr(const LambdaExpr *LE) { - // Return true to bail out of the traversal, implying the Decl contains - // the lambda. - return getPrimaryTemplateOfGenericLambda(LE->getCallOperator()) != - CallOperator; - } - const FunctionDecl *CallOperator; - }; - - QualType Underlying = - PrimaryTypeAliasDecl->getTemplatedDecl()->getUnderlyingType(); - - return !Visitor(getPrimaryTemplateOfGenericLambda(LambdaCallOperator)) - .TraverseType(Underlying); -} - // Add template arguments from a variable template instantiation. Response HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec, @@ -304,12 +217,6 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, if (!ForDefaultArgumentSubstitution && Function->getPrimaryTemplate()->isMemberSpecialization()) return Response::Done(); - - // If this function is a generic lambda specialization, we are done. - if (!ForConstraintInstantiation && - isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) - return Response::Done(); - } else if (Function->getDescribedFunctionTemplate()) { assert( (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && @@ -415,34 +322,22 @@ Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec, // This is to make sure we pick up the VarTemplateSpecializationDecl or the // TypeAliasTemplateDecl that this lambda is defined inside of. if (Rec->isLambda()) { - if (const Decl *LCD = Rec->getLambdaContextDecl()) - return Response::ChangeDecl(LCD); - // Retrieve the template arguments for a using alias declaration. - // This is necessary for constraint checking, since we always keep - // constraints relative to the primary template. - if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef); - ForConstraintInstantiation && TypeAlias) { - if (isLambdaEnclosedByTypeAliasDecl(Rec->getLambdaCallOperator(), - TypeAlias.PrimaryTypeAliasDecl)) { - Result.addOuterTemplateArguments(TypeAlias.Template, - TypeAlias.AssociatedTemplateArguments, - /*Final=*/false); - // Visit the parent of the current type alias declaration rather than - // the lambda thereof. - // E.g., in the following example: - // struct S { - // template <class> using T = decltype([]<Concept> {} ()); - // }; - // void foo() { - // S::T var; - // } - // The instantiated lambda expression (which we're visiting at 'var') - // has a function DeclContext 'foo' rather than the Record DeclContext - // S. This seems to be an oversight to me that we may want to set a - // Sema Context from the CXXScopeSpec before substituting into T. - return Response::ChangeDecl(TypeAlias.Template->getDeclContext()); + bool Continue = ForConstraintInstantiation || !Rec->isGenericLambda(); + if (auto Context = Rec->getLambdaContext(); Context.CDS.hasValue()) { + if (Decl *ND = Context.CDS.getValue()) { + if (TemplateDecl *TD = ND->getDescribedTemplate(); + ForConstraintInstantiation && TD && + TD->getKind() == Decl::TypeAliasTemplate) { + if (auto Args = Context.Args; !Args.empty()) + Result.addOuterTemplateArguments(TD, Args, + /*Final=*/true); + } + if (Continue) + return Response::ChangeDecl(ND); } } + if (!Continue) + return Response::Done(); } return Response::UseNextDecl(Rec); @@ -458,6 +353,21 @@ Response HandleImplicitConceptSpecializationDecl( return Response::UseNextDecl(CSD); } +Response HandleRequiresExprDecl(const RequiresExprBodyDecl *RBD, + MultiLevelTemplateArgumentList &Result) { + + if (auto Context = RBD->getContext(); Context.CDS.hasValue()) { + if (Decl *ND = Context.CDS.getValue(); !ND) + return Response::UseNextDecl(RBD); + else if (TemplateDecl *TD = ND->getDescribedTemplate(); + !TD || TD->getKind() != Decl::TypeAliasTemplate) + return Response::ChangeDecl(ND); + // FIXME: Add template arguments to the TypeAliasDecl, using them here. + llvm_unreachable("Unimplemented Template Type Alias Handling"); + } + return Response::UseNextDecl(RBD); +} + Response HandleGenericDeclContext(const Decl *CurDecl) { return Response::UseNextDecl(CurDecl); } @@ -522,6 +432,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( R = HandleFunctionTemplateDecl(FTD, Result); } else if (const auto *CTD = dyn_cast<ClassTemplateDecl>(CurDecl)) { R = Response::ChangeDecl(CTD->getLexicalDeclContext()); + } else if (const auto *RBD = dyn_cast<RequiresExprBodyDecl>(CurDecl)) { + R = HandleRequiresExprDecl(RBD, Result); } else if (!isa<DeclContext>(CurDecl)) { R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl); if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) { @@ -1655,23 +1567,6 @@ namespace { SubstTemplateTypeParmPackTypeLoc TL, bool SuppressObjCLifetime); - CXXRecordDecl::LambdaDependencyKind - ComputeLambdaDependency(LambdaScopeInfo *LSI) { - if (auto TypeAlias = - TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl( - getSema()); - TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl( - LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) { - unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth(); - if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels()) - return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent; - for (const TemplateArgument &TA : TypeAlias.AssociatedTemplateArguments) - if (TA.isDependent()) - return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent; - } - return inherited::ComputeLambdaDependency(LSI); - } - ExprResult TransformLambdaExpr(LambdaExpr *E) { LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this); @@ -2081,11 +1976,30 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, "unexpected pack arguments in template rewrite"); Arg = Arg.pack_begin()->getPackExpansionPattern(); } - assert(Arg.getKind() == TemplateArgument::Expression && - "unexpected nontype template argument kind in template rewrite"); - // FIXME: This can lead to the same subexpression appearing multiple times - // in a complete expression. - return Arg.getAsExpr(); + switch (Arg.getKind()) { + case TemplateArgument::Expression: + // FIXME: This can lead to the same subexpression appearing multiple times + // in a complete expression. + return Arg.getAsExpr(); + case TemplateArgument::Integral: { + auto I = Arg.getAsIntegral(); + return IntegerLiteral::Create(getSema().getASTContext(), I, + Arg.getIntegralType(), E->getLocation()); + } + case TemplateArgument::Declaration: + llvm_unreachable("Unimplemented Declaration Kind"); + case TemplateArgument::StructuralValue: + llvm_unreachable("Unimplemented Structural Value Kind"); + case TemplateArgument::Pack: + llvm_unreachable("Handled Above"); + case TemplateArgument::Type: + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + case TemplateArgument::NullPtr: + case TemplateArgument::Null: + llvm_unreachable("Unexpected TemplateArgument Kind"); + } + llvm_unreachable("Unexpected TemplateArgument Kind"); } auto [AssociatedDecl, _] = TemplateArgs.getAssociatedDecl(NTTP->getDepth()); @@ -3102,6 +3016,9 @@ ParmVarDecl *Sema::SubstParmVarDecl( TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = nullptr; + EnterExpressionEvaluationContext EvalContext( + *this, currentEvaluationContext().Context, LazyContextDecl); + TypeLoc OldTL = OldDI->getTypeLoc(); if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) { @@ -3162,14 +3079,14 @@ ParmVarDecl *Sema::SubstParmVarDecl( } } - ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(), - OldParm->getInnerLocStart(), - OldParm->getLocation(), - OldParm->getIdentifier(), - NewDI->getType(), NewDI, - OldParm->getStorageClass()); + ParmVarDecl *NewParm = CheckParameter( + CurContext, OldParm->getInnerLocStart(), OldParm->getLocation(), + OldParm->getIdentifier(), NewDI->getType(), NewDI, + OldParm->getStorageClass(), + OldParm->getTemplateDepth() - TemplateArgs.getNumSubstitutedLevels()); if (!NewParm) return nullptr; + UpdateCurrentContextDecl(NewParm); // Mark the (new) default argument as uninstantiated (if any). if (OldParm->hasUninstantiatedDefaultArg()) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index bb311e3..cd795a7 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1085,16 +1085,24 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, } Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { + EnterExpressionEvaluationContext Eval( + SemaRef, SemaRef.currentEvaluationContext().Context, + Sema::LazyContextDecl); Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false); if (Typedef) Owner->addDecl(Typedef); + SemaRef.UpdateCurrentContextDecl(Typedef); return Typedef; } Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { + EnterExpressionEvaluationContext Eval( + SemaRef, SemaRef.currentEvaluationContext().Context, + Sema::LazyContextDecl); Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true); if (Typedef) Owner->addDecl(Typedef); + SemaRef.UpdateCurrentContextDecl(Typedef); return Typedef; } @@ -1110,13 +1118,8 @@ Decl *TemplateDeclInstantiator::InstantiateTypeAliasTemplateDecl( return nullptr; TypeAliasDecl *Pattern = D->getTemplatedDecl(); - Sema::InstantiatingTemplate InstTemplate( - SemaRef, D->getBeginLoc(), D, - D->getTemplateDepth() >= TemplateArgs.getNumLevels() - ? ArrayRef<TemplateArgument>() - : (TemplateArgs.begin() + TemplateArgs.getNumLevels() - 1 - - D->getTemplateDepth()) - ->Args); + Sema::InstantiatingTemplate InstTemplate(SemaRef, D->getBeginLoc(), D, + /*TemplateArgs=*/std::nullopt); if (InstTemplate.isInvalid()) return nullptr; @@ -1128,6 +1131,10 @@ Decl *TemplateDeclInstantiator::InstantiateTypeAliasTemplateDecl( } } + EnterExpressionEvaluationContext Eval( + SemaRef, SemaRef.currentEvaluationContext().Context, + Sema::LazyContextDecl, /*TemplateArgs=*/std::nullopt); + TypeAliasDecl *AliasInst = cast_or_null<TypeAliasDecl>( InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true)); if (!AliasInst) @@ -1145,6 +1152,7 @@ Decl *TemplateDeclInstantiator::InstantiateTypeAliasTemplateDecl( if (!PrevAliasTemplate) Inst->setInstantiatedFromMemberTemplate(D); + SemaRef.UpdateCurrentContextDecl(AliasInst); return Inst; } @@ -2020,16 +2028,25 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *Record = nullptr; bool IsInjectedClassName = D->isInjectedClassName(); - if (D->isLambda()) + if (D->isLambda()) { + unsigned TemplateDepth = + D->getTemplateDepth() - TemplateArgs.getNumSubstitutedLevels(); + Sema::ContextDeclOrLazy ContextDecl = + SemaRef.currentEvaluationContext().ContextDecl; Record = CXXRecordDecl::CreateLambda( SemaRef.Context, Owner, D->getLambdaTypeInfo(), D->getLocation(), - D->getLambdaDependencyKind(), D->isGenericLambda(), - D->getLambdaCaptureDefault()); - else + D->isGenericLambda(), D->getLambdaCaptureDefault(), + ContextDecl.hasValue() ? *ContextDecl + : ContextDeclOrSentinel(TemplateDepth), + SemaRef.currentEvaluationContext().ContextArgs); + if (!ContextDecl.hasValue()) + SemaRef.PendingLazyContextDecls.push_back(Record); + } else { Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), D->getLocation(), D->getIdentifier(), PrevDecl, /*DelayTypeCreation=*/IsInjectedClassName); + } // Link the type of the injected-class-name to that of the outer class. if (IsInjectedClassName) (void)SemaRef.Context.getTypeDeclType(Record, cast<CXXRecordDecl>(Owner)); @@ -2136,6 +2153,9 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, Decl *TemplateDeclInstantiator::VisitFunctionDecl( FunctionDecl *D, TemplateParameterList *TemplateParams, RewriteKind FunctionRewriteKind) { + EnterExpressionEvaluationContext Eval( + SemaRef, SemaRef.currentEvaluationContext().Context, + Sema::LazyContextDecl); // Check whether there is already a function template specialization for // this declaration. FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); @@ -2245,6 +2265,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( D->FriendConstraintRefersToEnclosingTemplate()); Function->setRangeEnd(D->getSourceRange().getEnd()); } + SemaRef.UpdateCurrentContextDecl(Function); if (D->isInlined()) Function->setImplicitlyInline(); @@ -2527,6 +2548,10 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( else isFriend = (D->getFriendObjectKind() != Decl::FOK_None); + EnterExpressionEvaluationContext Eval( + SemaRef, SemaRef.currentEvaluationContext().Context, + Sema::LazyContextDecl); + bool MergeWithParentScope = (TemplateParams != nullptr) || !(isa<Decl>(Owner) && cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); @@ -2675,6 +2700,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( D->UsesFPIntrin(), D->isInlineSpecified(), D->getConstexprKind(), D->getEndLoc(), TrailingRequiresClause); } + SemaRef.UpdateCurrentContextDecl(Method); if (D->isInlined()) Method->setImplicitlyInline(); @@ -4121,7 +4147,10 @@ Decl *TemplateDeclInstantiator::VisitImplicitConceptSpecializationDecl( Decl * TemplateDeclInstantiator::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { + ContextDeclAndArgs Context = D->getContext(); + // FIXME: Transform the arguments. return RequiresExprBodyDecl::Create(SemaRef.Context, D->getDeclContext(), + Context.CDS, Context.Args, D->getBeginLoc()); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 520dce8..49ac6db 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3093,8 +3093,10 @@ static TypeSourceInfo * GetTypeSourceInfoForDeclarator(TypeProcessingState &State, QualType T, TypeSourceInfo *ReturnTypeInfo); -static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, - TypeSourceInfo *&ReturnTypeInfo) { +static QualType +GetDeclSpecTypeForDeclarator(TypeProcessingState &state, + TypeSourceInfo *&ReturnTypeInfo, + bool *StartImplcitTemplate = nullptr) { Sema &SemaRef = state.getSema(); Declarator &D = state.getDeclarator(); QualType T; @@ -3215,8 +3217,12 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // We'll deal with inventing template parameters for 'auto' in trailing // return types when we pick up the trailing return type when processing // the function chunk. - if (!DeducedIsTrailingReturnType) + if (!DeducedIsTrailingReturnType) { + if (StartImplcitTemplate && Info->NumExplicitTemplateParams == 0 && + Info->TemplateParams.empty()) + *StartImplcitTemplate = true; T = InventTemplateParameter(state, T, nullptr, Auto, *Info).first; + } break; } case DeclaratorContext::Member: { @@ -5666,14 +5672,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, return GetTypeSourceInfoForDeclarator(state, T, TInfo); } -TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D) { +TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, + bool *StartImplcitTemplate) { // Determine the type of the declarator. Not all forms of declarator // have a type. TypeProcessingState state(*this, D); TypeSourceInfo *ReturnTypeInfo = nullptr; - QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo); + QualType T = + GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo, StartImplcitTemplate); if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount) inferARCWriteback(state, T); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 4bbc024..52e672d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -772,12 +772,6 @@ public: /// the body. StmtResult SkipLambdaBody(LambdaExpr *E, Stmt *Body); - CXXRecordDecl::LambdaDependencyKind - ComputeLambdaDependency(LambdaScopeInfo *LSI) { - return static_cast<CXXRecordDecl::LambdaDependencyKind>( - LSI->Lambda->getLambdaDependencyKind()); - } - QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); @@ -5636,7 +5630,8 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB, // Array bounds are constant expressions. EnterExpressionEvaluationContext Unevaluated( - SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); + SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated, + Sema::ReuseLambdaContextDecl); // If we have a VLA then it won't be a constant. SemaRef.ExprEvalContexts.back().InConditionallyConstantEvaluateContext = true; @@ -5971,15 +5966,12 @@ ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam( if (NewDI == OldDI && indexAdjustment == 0) return OldParm; - ParmVarDecl *newParm = ParmVarDecl::Create(SemaRef.Context, - OldParm->getDeclContext(), - OldParm->getInnerLocStart(), - OldParm->getLocation(), - OldParm->getIdentifier(), - NewDI->getType(), - NewDI, - OldParm->getStorageClass(), - /* DefArg */ nullptr); + DeclContext *DC = OldParm->getDeclContext(); + ParmVarDecl *newParm = ParmVarDecl::Create( + SemaRef.Context, DC, OldParm->getInnerLocStart(), OldParm->getLocation(), + OldParm->getIdentifier(), NewDI->getType(), NewDI, + OldParm->getStorageClass(), + /*DefArg=*/nullptr, Decl::castFromDeclContext(DC)->getTemplateDepth()); newParm->setScopeInfo(OldParm->getFunctionScopeDepth(), OldParm->getFunctionScopeIndex() + indexAdjustment); transformedLocalDecl(OldParm, {newParm}); @@ -6641,7 +6633,8 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB, // decltype expressions are not potentially evaluated contexts EnterExpressionEvaluationContext Unevaluated( - SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl, Sema::ExpressionEvaluationContextRecord::EK_Decltype); ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr()); @@ -8098,7 +8091,8 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { if (!ConstexprConditionValue || *ConstexprConditionValue) { EnterExpressionEvaluationContext Ctx( getSema(), Sema::ExpressionEvaluationContext::ImmediateFunctionContext, - nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other, + nullptr, std::nullopt, + Sema::ExpressionEvaluationContextRecord::EK_Other, S->isNonNegatedConsteval()); Then = getDerived().TransformStmt(S->getThen()); @@ -8117,7 +8111,8 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { if (!ConstexprConditionValue || !*ConstexprConditionValue) { EnterExpressionEvaluationContext Ctx( getSema(), Sema::ExpressionEvaluationContext::ImmediateFunctionContext, - nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other, + /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt, + Sema::ExpressionEvaluationContextRecord::EK_Other, S->isNegatedConsteval()); Else = getDerived().TransformStmt(S->getElse()); @@ -8921,7 +8916,7 @@ StmtResult TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { EnterExpressionEvaluationContext ForRangeInitContext( getSema(), Sema::ExpressionEvaluationContext::PotentiallyEvaluated, - /*LambdaContextDecl=*/nullptr, + /*ContextDecl=*/nullptr, /*ContextArgs*/ std::nullopt, Sema::ExpressionEvaluationContextRecord::EK_Other, getSema().getLangOpts().CPlusPlus23); @@ -14067,15 +14062,23 @@ TreeTransform<Derived>::TransformRequiresExpr(RequiresExpr *E) { SmallVector<QualType, 4> TransParamTypes; Sema::ExtParameterInfoBuilder ExtParamInfos; + RequiresExprBodyDecl *OldBody = E->getBody(); + Sema::ContextDeclOrLazy ContextDecl = + getSema().currentEvaluationContext().ContextDecl; + RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create( + getSema().Context, getSema().CurContext, + ContextDecl.hasValue() + ? *ContextDecl + : ContextDeclOrSentinel(getDerived().TransformTemplateDepth( + OldBody->getTemplateDepth())), + getSema().currentEvaluationContext().ContextArgs, OldBody->getBeginLoc()); + if (!ContextDecl.hasValue()) + getSema().PendingLazyContextDecls.push_back(Body); + // C++2a [expr.prim.req]p2 // Expressions appearing within a requirement-body are unevaluated operands. EnterExpressionEvaluationContext Ctx( - SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, - Sema::ReuseLambdaContextDecl); - - RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create( - getSema().Context, getSema().CurContext, - E->getBody()->getBeginLoc()); + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); Sema::ContextRAII SavedContext(getSema(), Body, /*NewThisContext*/false); @@ -14556,42 +14559,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Create the local class that will describe the lambda. - // FIXME: DependencyKind below is wrong when substituting inside a templated - // context that isn't a DeclContext (such as a variable template), or when - // substituting an unevaluated lambda inside of a function's parameter's type - // - as parameter types are not instantiated from within a function's DC. We - // use evaluation contexts to distinguish the function parameter case. - CXXRecordDecl::LambdaDependencyKind DependencyKind = - CXXRecordDecl::LDK_Unknown; - DeclContext *DC = getSema().CurContext; - // A RequiresExprBodyDecl is not interesting for dependencies. - // For the following case, - // - // template <typename> - // concept C = requires { [] {}; }; - // - // template <class F> - // struct Widget; - // - // template <C F> - // struct Widget<F> {}; - // - // While we are substituting Widget<F>, the parent of DC would be - // the template specialization itself. Thus, the lambda expression - // will be deemed as dependent even if there are no dependent template - // arguments. - // (A ClassTemplateSpecializationDecl is always a dependent context.) - while (DC->isRequiresExprBody()) - DC = DC->getParent(); - if ((getSema().isUnevaluatedContext() || - getSema().isConstantEvaluatedContext()) && - (DC->isFileContext() || !DC->getParent()->isDependentContext())) - DependencyKind = CXXRecordDecl::LDK_NeverDependent; - CXXRecordDecl *OldClass = E->getLambdaClass(); CXXRecordDecl *Class = getSema().createLambdaClosureType( - E->getIntroducerRange(), /*Info=*/nullptr, DependencyKind, - E->getCaptureDefault()); + E->getIntroducerRange(), /*Info=*/nullptr, E->getCaptureDefault(), + getDerived().TransformTemplateDepth(OldClass->getTemplateDepth())); getDerived().transformedLocalDecl(OldClass, {Class}); CXXMethodDecl *NewCallOperator = @@ -14605,6 +14576,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Introduce the context of the call operator. Sema::ContextRAII SavedContext(getSema(), NewCallOperator, /*NewThisContext*/false); + std::optional<EnterExpressionEvaluationContext> Eval; + Eval.emplace(getSema(), getSema().currentEvaluationContext().Context, + NewCallOperator); bool Invalid = false; @@ -14795,12 +14769,18 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { NewCallOpType = TransformFunctionProtoTypeLoc(NewCallOpTLBuilder, FPTL); } - if (NewCallOpType.isNull()) - return ExprError(); - LSI->ContainsUnexpandedParameterPack |= - NewCallOpType->containsUnexpandedParameterPack(); - NewCallOpTSI = - NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType); + if (NewCallOpType.isNull()) { + NewCallOpTSI = getSema().Context.getTrivialTypeSourceInfo( + getSema().Context.getFunctionType(getSema().Context.IntTy, + std::nullopt, + FunctionProtoType::ExtProtoInfo())); + Invalid = true; + } else { + LSI->ContainsUnexpandedParameterPack |= + NewCallOpType->containsUnexpandedParameterPack(); + NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, + NewCallOpType); + } } ArrayRef<ParmVarDecl *> Params; @@ -14834,6 +14814,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { getSema().handleLambdaNumbering(Class, NewCallOperator, Numbering); } + Eval.reset(); // FIXME: Sema's lambda-building mechanism expects us to push an expression // evaluation context even if we're not transforming the function body. getSema().PushExpressionEvaluationContext( @@ -14873,41 +14854,6 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { /*IsInstantiation*/ true); SavedContext.pop(); - // Recompute the dependency of the lambda so that we can defer the lambda call - // construction until after we have all the necessary template arguments. For - // example, given - // - // template <class> struct S { - // template <class U> - // using Type = decltype([](U){}(42.0)); - // }; - // void foo() { - // using T = S<int>::Type<float>; - // ^~~~~~ - // } - // - // We would end up here from instantiating S<int> when ensuring its - // completeness. That would transform the lambda call expression regardless of - // the absence of the corresponding argument for U. - // - // Going ahead with unsubstituted type U makes things worse: we would soon - // compare the argument type (which is float) against the parameter U - // somewhere in Sema::BuildCallExpr. Then we would quickly run into a bogus - // error suggesting unmatched types 'U' and 'float'! - // - // That said, everything will be fine if we defer that semantic checking. - // Fortunately, we have such a mechanism that bypasses it if the CallExpr is - // dependent. Since the CallExpr's dependency boils down to the lambda's - // dependency in this case, we can harness that by recomputing the dependency - // from the instantiation arguments. - // - // FIXME: Creating the type of a lambda requires us to have a dependency - // value, which happens before its substitution. We update its dependency - // *after* the substitution in case we can't decide the dependency - // so early, e.g. because we want to see if any of the *substituted* - // parameters are dependent. - DependencyKind = getDerived().ComputeLambdaDependency(&LSICopy); - Class->setLambdaDependencyKind(DependencyKind); // Clean up the type cache created previously. Then, we re-create a type for // such Decl with the new DependencyKind. Class->setTypeForDecl(nullptr); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e5a1e20..7b4f3fd 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8972,12 +8972,15 @@ void ASTReader::ReadLateParsedTemplates( } void ASTReader::AssignedLambdaNumbering(CXXRecordDecl *Lambda) { - if (!Lambda->getLambdaContextDecl()) + auto CDS = Lambda->getLambdaContext().CDS; + if (!CDS.hasValue()) + return; + Decl *ContextDecl = CDS.getValue(); + if (!ContextDecl) return; - auto LambdaInfo = - std::make_pair(Lambda->getLambdaContextDecl()->getCanonicalDecl(), - Lambda->getLambdaIndexInContext()); + auto LambdaInfo = std::make_pair(ContextDecl->getCanonicalDecl(), + Lambda->getLambdaIndexInContext()); // Handle the import and then include case for lambdas. if (auto Iter = LambdaDeclarationsForMerging.find(LambdaInfo); @@ -9843,6 +9846,16 @@ void ASTReader::finishPendingActions() { PendingDeclChains[I].second); PendingDeclChains.clear(); + for (auto &[D, ID] : PendingContextDecls) + switch (D->getKind()) { + case Decl::RequiresExprBody: + cast<RequiresExprBodyDecl>(D)->setContextDecl(GetDecl(ID)); + break; + default: + llvm_unreachable("Unexpected Decl Kind"); + } + PendingContextDecls.clear(); + // Make the most recent of the top-level declarations visible. for (TopLevelDeclsMap::iterator TLD = TopLevelDecls.begin(), TLDEnd = TopLevelDecls.end(); TLD != TLDEnd; ++TLD) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 9272e23..dbe838c 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -205,11 +205,12 @@ class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> { Module *readModule() { return Record.getSubmodule(readSubmoduleID()); } - void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update, - Decl *LambdaContext = nullptr, - unsigned IndexInLambdaContext = 0); + void ReadCXXRecordDefinition( + CXXRecordDecl *D, bool Update, Decl *LambdaContext = nullptr, + ArrayRef<TemplateArgument> LambdaContextArgs = std::nullopt, + unsigned IndexInLambdaContext = 0); void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, - const CXXRecordDecl *D, Decl *LambdaContext, + const CXXRecordDecl *D, bool HasLambdaContext, unsigned IndexInLambdaContext); void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data); void ReadObjCDefinitionData(struct ObjCProtocolDecl::DefinitionData &Data); @@ -600,7 +601,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->FromASTFile = true; if (D->isTemplateParameter() || D->isTemplateParameterPack() || - isa<ParmVarDecl, ObjCTypeParamDecl>(D)) { + isa<ParmVarDecl, ObjCTypeParamDecl, RequiresExprBodyDecl>(D)) { // We don't want to deserialize the DeclContext of a template // parameter or of a parameter of a function template immediately. These // entities might be used in the formulation of its DeclContext (for @@ -1964,7 +1965,7 @@ void ASTDeclReader::VisitUnresolvedUsingIfExistsDecl( void ASTDeclReader::ReadCXXDefinitionData( struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D, - Decl *LambdaContext, unsigned IndexInLambdaContext) { + bool HasLambdaContext, unsigned IndexInLambdaContext) { BitsUnpacker CXXRecordDeclBits = Record.readInt(); @@ -1993,7 +1994,7 @@ void ASTDeclReader::ReadCXXDefinitionData( assert(Data.Definition && "Data.Definition should be already set!"); if (!Data.IsLambda) { - assert(!LambdaContext && !IndexInLambdaContext && + assert(!HasLambdaContext && !IndexInLambdaContext && "given lambda context for non-lambda"); Data.NumBases = Record.readInt(); @@ -2011,18 +2012,17 @@ void ASTDeclReader::ReadCXXDefinitionData( auto &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); BitsUnpacker LambdaBits(Record.readInt()); - Lambda.DependencyKind = LambdaBits.getNextBits(/*Width=*/2); Lambda.IsGenericLambda = LambdaBits.getNextBit(); Lambda.CaptureDefault = LambdaBits.getNextBits(/*Width=*/2); Lambda.NumCaptures = LambdaBits.getNextBits(/*Width=*/15); Lambda.HasKnownInternalLinkage = LambdaBits.getNextBit(); + if (HasLambdaContext) + Lambda.setContextMangling(LambdaBits.getNextBit(), IndexInLambdaContext); Lambda.NumExplicitCaptures = Record.readInt(); Lambda.ManglingNumber = Record.readInt(); if (unsigned DeviceManglingNumber = Record.readInt()) Reader.getContext().DeviceLambdaManglingNumbers[D] = DeviceManglingNumber; - Lambda.IndexInContext = IndexInLambdaContext; - Lambda.ContextDecl = LambdaContext; Capture *ToCapture = nullptr; if (Lambda.NumCaptures) { ToCapture = (Capture *)Reader.getContext().Allocate(sizeof(Capture) * @@ -2119,7 +2119,6 @@ void ASTDeclMerger::MergeDefinitionData( if (DD.IsLambda) { auto &Lambda1 = static_cast<CXXRecordDecl::LambdaDefinitionData &>(DD); auto &Lambda2 = static_cast<CXXRecordDecl::LambdaDefinitionData &>(MergeDD); - DetectedOdrViolation |= Lambda1.DependencyKind != Lambda2.DependencyKind; DetectedOdrViolation |= Lambda1.IsGenericLambda != Lambda2.IsGenericLambda; DetectedOdrViolation |= Lambda1.CaptureDefault != Lambda2.CaptureDefault; DetectedOdrViolation |= Lambda1.NumCaptures != Lambda2.NumCaptures; @@ -2152,9 +2151,10 @@ void ASTDeclMerger::MergeDefinitionData( {MergeDD.Definition, &MergeDD}); } -void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update, - Decl *LambdaContext, - unsigned IndexInLambdaContext) { +void ASTDeclReader::ReadCXXRecordDefinition( + CXXRecordDecl *D, bool Update, Decl *LambdaContext, + ArrayRef<TemplateArgument> LambdaContextArgs, + unsigned IndexInLambdaContext) { struct CXXRecordDecl::DefinitionData *DD; ASTContext &C = Reader.getContext(); @@ -2164,8 +2164,9 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update, assert(!(IsLambda && Update) && "lambda definition should not be added by update record"); if (IsLambda) - DD = new (C) CXXRecordDecl::LambdaDefinitionData( - D, nullptr, CXXRecordDecl::LDK_Unknown, false, LCD_None); + DD = CXXRecordDecl::LambdaDefinitionData::Create( + C, D, /*Info=*/nullptr, /*IsGeneric=*/false, LCD_None, + /*ContextDecl=*/LambdaContext, LambdaContextArgs); else DD = new (C) struct CXXRecordDecl::DefinitionData(D); @@ -2176,7 +2177,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update, if (!Canon->DefinitionData) Canon->DefinitionData = DD; D->DefinitionData = Canon->DefinitionData; - ReadCXXDefinitionData(*DD, D, LambdaContext, IndexInLambdaContext); + ReadCXXDefinitionData(*DD, D, LambdaContext != nullptr, IndexInLambdaContext); // Mark this declaration as being a definition. D->setCompleteDefinition(true); @@ -2210,6 +2211,7 @@ RedeclarableResult ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { Decl *LambdaContext = nullptr; unsigned IndexInLambdaContext = 0; + llvm::SmallVector<TemplateArgument, 4> LambdaContextArgs; switch ((CXXRecKind)Record.readInt()) { case CXXRecNotTemplate: @@ -2244,14 +2246,18 @@ RedeclarableResult ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { } case CXXLambda: { LambdaContext = readDecl(); - if (LambdaContext) + if (LambdaContext) { IndexInLambdaContext = Record.readInt(); - if (LambdaContext) + unsigned NumContextArgs = Record.readInt(); + for (unsigned I = 0; I < NumContextArgs; ++I) + LambdaContextArgs.push_back( + Record.readTemplateArgument(/*Canonicalize=*/false)); MergeImpl.mergeLambda(D, Redecl, *LambdaContext, IndexInLambdaContext); - else + } else { // If we don't have a mangling context, treat this like any other // declaration. mergeRedeclarable(D, Redecl); + } break; } } @@ -2259,7 +2265,7 @@ RedeclarableResult ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { bool WasDefinition = Record.readInt(); if (WasDefinition) ReadCXXRecordDefinition(D, /*Update=*/false, LambdaContext, - IndexInLambdaContext); + LambdaContextArgs, IndexInLambdaContext); else // Propagate DefinitionData pointer from the canonical declaration. D->DefinitionData = D->getCanonicalDecl()->DefinitionData; @@ -2407,6 +2413,15 @@ void ASTDeclReader::VisitImplicitConceptSpecializationDecl( } void ASTDeclReader::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { + VisitDecl(D); + if (D->numTrailingObjects( + RequiresExprBodyDecl::OverloadToken<ContextDeclOrSentinel>())) { + Reader.PendingContextDecls.emplace_back(D, Record.readDeclID()); + llvm::SmallVector<TemplateArgument, 4> Args; + for (unsigned I = 0; I < D->getContextArgs().size(); ++I) + Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/false)); + D->setContextArgs(Args); + } } RedeclarableResult @@ -4008,9 +4023,21 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { case DECL_CONCEPT: D = ConceptDecl::CreateDeserialized(Context, ID); break; - case DECL_REQUIRES_EXPR_BODY: - D = RequiresExprBodyDecl::CreateDeserialized(Context, ID); - break; + case DECL_REQUIRES_EXPR_BODY: { + // FIXME: Add template depth. + unsigned NumContextArgsOrNoContext = Record.readInt(); + bool HasContextDecl = NumContextArgsOrNoContext != 0; + unsigned TemplateDepth = 0; +#ifndef NDEBUG + if (HasContextDecl) { + TemplateDepth = Record.readInt(); + } +#endif + D = RequiresExprBodyDecl::CreateDeserialized( + Context, ID, + HasContextDecl ? ContextDeclOrSentinel(TemplateDepth) : nullptr, + HasContextDecl ? NumContextArgsOrNoContext - 1 : 0); + } break; case DECL_STATIC_ASSERT: D = StaticAssertDecl::CreateDeserialized(Context, ID); break; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index c628949..831b24d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6623,11 +6623,12 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { auto &Lambda = D->getLambdaData(); BitsPacker LambdaBits; - LambdaBits.addBits(Lambda.DependencyKind, /*Width=*/2); LambdaBits.addBit(Lambda.IsGenericLambda); LambdaBits.addBits(Lambda.CaptureDefault, /*Width=*/2); LambdaBits.addBits(Lambda.NumCaptures, /*Width=*/15); LambdaBits.addBit(Lambda.HasKnownInternalLinkage); + if (D->getLambdaContext().CDS) + LambdaBits.addBit(Lambda.getContextIsMangled()); Record->push_back(LambdaBits); Record->push_back(Lambda.NumExplicitCaptures); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 555f632..2fcd882 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1251,6 +1251,8 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { assert(D->getPreviousDecl() == nullptr && "PARM_VAR_DECL can't be redecl"); assert(!D->isStaticDataMember() && "PARM_VAR_DECL can't be static data member"); + // assert(D->getTemplateDepth() == + // Decl::castFromDeclContext(D->getDeclContext())->getTemplateDepth()); } void ASTDeclWriter::VisitDecompositionDecl(DecompositionDecl *D) { @@ -1515,9 +1517,13 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { } else if (D->isLambda()) { // For a lambda, we need some information early for merging. Record.push_back(CXXLambda); - if (auto *Context = D->getLambdaContextDecl()) { - Record.AddDeclRef(Context); + if (auto Context = D->getLambdaContext(); + auto *ContextDecl = Context.CDS.getValue()) { + Record.AddDeclRef(ContextDecl); Record.push_back(D->getLambdaIndexInContext()); + Record.push_back(Context.Args.size()); + for (const TemplateArgument &Arg : Context.Args) + Record.AddTemplateArgument(Arg); } else { Record.push_back(0); } @@ -1701,6 +1707,19 @@ void ASTDeclWriter::VisitImplicitConceptSpecializationDecl( } void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { + Decl *ContextDecl = D->getContext().CDS.getValue(); + Record.push_back(ContextDecl ? D->getContextArgs().size() + 1 : 0); +#ifndef NDEBUG + if (ContextDecl) { + Record.push_back(D->getTemplateDepth(D->getContextArgs())); + } +#endif + VisitDecl(D); + if (ContextDecl) { + Record.AddDeclRef(ContextDecl); + for (const TemplateArgument &Arg : D->getContextArgs()) + Record.AddTemplateArgument(Arg); + } Code = serialization::DECL_REQUIRES_EXPR_BODY; } diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp index a5e0673..fcaa495 100644 --- a/clang/test/AST/ast-dump-concepts.cpp +++ b/clang/test/AST/ast-dump-concepts.cpp @@ -120,3 +120,11 @@ void g(C<T> auto Foo) {} // CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} <col:8, col:11> } + +namespace constructor { + struct A { + template <class> + requires requires { 0; } + A(); + }; +} // namespace constructor diff --git a/clang/test/CodeGenCXX/clang-abi-compat.cpp b/clang/test/CodeGenCXX/clang-abi-compat.cpp index 4d51811..0193c7e5 100644 --- a/clang/test/CodeGenCXX/clang-abi-compat.cpp +++ b/clang/test/CodeGenCXX/clang-abi-compat.cpp @@ -116,7 +116,8 @@ struct B { template<typename T> void test5(typename T::template Y<1.0>) { } template void test5<B>(typename B::Y<1.0>); -// PRE12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIL_ZZNS_5test6EiE1bEEEi +// FIXME: This test case does not look valid. +// PRE12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIL_Z1bEEEi // V12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIXfp_EEEi template<typename T> auto test6(int b) -> typename T::template Y<b> { return {}; } template auto test6<B>(int b) -> B::Y<b>; diff --git a/clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp b/clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp index 9cc6ebe..e931985a 100644 --- a/clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp +++ b/clang/test/CodeGenCXX/cxx20-unevaluated-lambda-crash.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -emit-llvm -o - | FileCheck %s -// CHECK-LABEL: define linkonce_odr void @"_ZN10Issue579601EIiEENS_1FILNS_3$_0EEEEv"() +// FIXME: GCC mangles this as _ZN10Issue579601EIiEENS_1FIXtlNS_UlvE_EEEEEv +// CHECK-LABEL: define linkonce_odr void @_ZN10Issue579601EIiEENS_1FILUlvE_EEEv() namespace Issue57960 { template<auto> class F {}; diff --git a/clang/test/CodeGenCXX/mangle-lambdas-cxx20.cpp b/clang/test/CodeGenCXX/mangle-lambdas-cxx20.cpp index 4871e9d..56b3790 100644 --- a/clang/test/CodeGenCXX/mangle-lambdas-cxx20.cpp +++ b/clang/test/CodeGenCXX/mangle-lambdas-cxx20.cpp @@ -27,3 +27,9 @@ void test_vt1() { // CHECK-LABEL: define linkonce_odr noundef i32 @_ZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_ // CHECK-LABEL: define linkonce_odr noundef i32 @_ZZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_Ed0_NKUlvE_clEv // CHECK-LABEL: define linkonce_odr noundef i32 @_ZZNK3vt1IiEMUlTyiT_E_clIiEEDaiS1_Ed_NKUlvE_clEv + +void f1(decltype([]{})) {} +void test_f1() { + f1({}); +} +// CHECK-LABEL: define internal void @_Z2f1UlvE_( diff --git a/clang/test/CodeGenCXX/mangle-lambdas-tentative.cpp b/clang/test/CodeGenCXX/mangle-lambdas-tentative.cpp new file mode 100644 index 0000000..2d1f37d --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-lambdas-tentative.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-linux -emit-llvm -o - %s -w | FileCheck %s + +namespace declared_on_param { + // CHECK-LABEL: define dso_local void @_ZN17declared_on_param1fEv( + void f() { + struct B { + B(decltype([]{}) = {}) {} + }; + B b; + } + // CHECK: call void @"_ZZN17declared_on_param1fEvEN1BC1ENS0_3$_0E"( +} // namespace declared_on_param diff --git a/clang/test/CodeGenCXX/mangle-requires.cpp b/clang/test/CodeGenCXX/mangle-requires.cpp index 9e2bdde..f8544de 100644 --- a/clang/test/CodeGenCXX/mangle-requires.cpp +++ b/clang/test/CodeGenCXX/mangle-requires.cpp @@ -32,3 +32,8 @@ template <typename T> void g(int n) requires requires (T m) { } {} // CHECK: define {{.*}}@_Z1gIiEviQrQT__XplfL0p_fp_E( template void g<int>(int); + +// FIXME: GCC mangles this as _Z7lambda1IiQrqXcltlUlvE_EEEEvv +template <class T> requires requires { []{}(); } void lambda1() {} +template void lambda1<int>(); +// CHECK: define {{.*}}@_Z7lambda1IiQrqXclLUlvE_EEEEvv diff --git a/clang/test/Index/complete-exprs.m b/clang/test/Index/complete-exprs.m index 16eeda9..555757b 100644 --- a/clang/test/Index/complete-exprs.m +++ b/clang/test/Index/complete-exprs.m @@ -35,7 +35,7 @@ __strong id global; // CHECK-CC2: NotImplemented:{ResultType size_t}{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (40) // RUN: c-index-test -code-completion-at=%s:15:1 -fobjc-arc -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC3 %s // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:15:1 -fobjc-arc -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC3 %s -// CHECK-CC3: FunctionDecl:{ResultType void}{TypedText foo}{LeftParen (}{Placeholder ^bool(id x, A *y)block}{RightParen )} (34) +// CHECK-CC3: FunctionDecl:{ResultType void}{TypedText foo}{LeftParen (}{Placeholder ^bool((id)x, (A *)y)block}{RightParen )} (34) // CHECK-CC3: VarDecl:{ResultType id}{TypedText global} (50) // CHECK-CC3: ParmDecl:{ResultType id}{TypedText param1} (34) diff --git a/clang/test/Modules/requires.cpp b/clang/test/Modules/requires.cpp new file mode 100644 index 0000000..d6ff394 --- /dev/null +++ b/clang/test/Modules/requires.cpp @@ -0,0 +1,15 @@ +// RUN: mkdir -p %t +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s -emit-pch -o %t/foo.pch + +template <class, class> class expected; +template <class _Tp, class _Err> + requires true +class expected<_Tp, _Err> { + friend void swap(expected __x) + requires requires { __x; } + {} +}; + +template <int> + requires requires { 0; } +using iter_rvalue_reference_t = int; diff --git a/clang/test/Parser/backtrack-off-by-one.cpp b/clang/test/Parser/backtrack-off-by-one.cpp index b5c05aee..5a5f28f 100644 --- a/clang/test/Parser/backtrack-off-by-one.cpp +++ b/clang/test/Parser/backtrack-off-by-one.cpp @@ -13,14 +13,7 @@ template <typename T> class A {}; // expected-error@+1 {{expected '{' after base class list}} template <typename T> class B : T // not ',' or '{' -#if __cplusplus < 201103L -// expected-error@+8 {{expected ';' after top level declarator}} -#endif -#if __cplusplus <= 201402L -// expected-error@+5 {{a type specifier is required for all declarations}} -#else -// expected-error@+3 {{expected unqualified-id}} -#endif +// expected-error@+2 {{expected unqualified-id}} // expected-error@+1 {{expected ';' after class}} A<int> { }; diff --git a/clang/test/SemaCXX/lambda-as-default-parameter.cpp b/clang/test/SemaCXX/lambda-as-default-parameter.cpp index 1f07a7f..1c8ceaa 100644 --- a/clang/test/SemaCXX/lambda-as-default-parameter.cpp +++ b/clang/test/SemaCXX/lambda-as-default-parameter.cpp @@ -3,4 +3,9 @@ struct a; // expected-note {{forward declaration of 'a'}} \ expected-note {{forward declaration of 'a'}} void b(a c = [] { return c; }); // expected-error {{initialization of incomplete type 'a'}} \ - expected-error {{variable has incomplete type 'a'}} + expected-error {{variable has incomplete type 'a'}} \ + expected-error {{variable 'c' cannot be implicitly captured in a lambda with no capture-default specified}} \ + expected-note {{'c' declared here}} \ + expected-note {{lambda expression begins here}} \ + expected-note {{capture 'c' by reference}} \ + expected-note {{default capture by reference}} diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp index 39ee89b..41e6978 100644 --- a/clang/test/SemaCXX/lambda-unevaluated.cpp +++ b/clang/test/SemaCXX/lambda-unevaluated.cpp @@ -264,3 +264,15 @@ void func() { } } // namespace GH88081 + +namespace GH97953 { + template<typename T> concept C = true; + + // FIXME: This should be constexpr. + static_assert( + []<int I=0>() -> decltype([]<C auto = 0>{ return true; }) + { return {}; }()()); + // expected-error@-2 {{static assertion expression is not an integral constant expression}} + // expected-note@-3 {{non-constexpr function 'operator()<0>' cannot be used in a constant expression}} + // expected-note@-4 {{declared here}} +} // namespace GH97953 diff --git a/clang/test/SemaTemplate/alias-template-with-lambdas.cpp b/clang/test/SemaTemplate/alias-template-with-lambdas.cpp index 5ec9316..7c71f18 100644 --- a/clang/test/SemaTemplate/alias-template-with-lambdas.cpp +++ b/clang/test/SemaTemplate/alias-template-with-lambdas.cpp @@ -102,15 +102,11 @@ template <typename T> using T15 = T14<T, T>; static_assert(__is_same(T15<char>, int)); -// FIXME: This still crashes because we can't extract template arguments T and U -// outside of the instantiation context of T16. -#if 0 template <typename T, typename... U> using T16 = decltype([](auto Param) requires (sizeof(Param) != 1 && sizeof...(U) > 0) { return Value<T, U...> + sizeof(Param); }); static_assert(T16<int, char, float>()(42) == 2 + sizeof(42)); -#endif } // namespace GH82104 namespace GH89853 { @@ -171,4 +167,12 @@ using T = Result<int, int>; } // namespace GH102760 +namespace var_template_spec { + template <class> int format_kind; + template <class _Rp> requires true + constexpr int format_kind<_Rp> = [] { + return __is_same(_Rp, _Rp); + }(); +} // namespace var_template_spec + } // namespace lambda_calls diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index a98ca39..6c23350 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1151,3 +1151,14 @@ int test() { } } + +namespace deduction_guide { + template <class> struct basic_string_view { + template <class _Range> + requires requires { 0; } + basic_string_view(); + }; + + template <class _It, class _End> + basic_string_view(_It, _End) -> basic_string_view<_It>; +} // namespace deduction_guide diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index e821c5e..065eed6 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -8450,6 +8450,7 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) { if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D)) switch (ND->getLinkageInternal()) { case Linkage::Invalid: + case Linkage::Computing: return CXLinkage_Invalid; case Linkage::None: case Linkage::VisibleNone: diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp index 8d364ed..bca2f71 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -433,6 +433,8 @@ bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) { switch (ND->getFormalLinkage()) { case Linkage::Invalid: llvm_unreachable("Linkage hasn't been computed!"); + case Linkage::Computing: + llvm_unreachable("Linkage is being computed!"); case Linkage::None: case Linkage::Internal: return true; diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index aacecd3..f84f6a61 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -6718,7 +6718,6 @@ TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) { std::distance(FromL->decls().begin(), FromL->decls().end()); EXPECT_NE(ToLSize, 0u); EXPECT_EQ(ToLSize, FromLSize); - EXPECT_FALSE(FromL->isDependentLambda()); } TEST_P(ASTImporterOptionSpecificTestBase, @@ -6772,7 +6771,6 @@ TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) { std::distance(FromL->decls().begin(), FromL->decls().end()); EXPECT_NE(ToLSize, 0u); EXPECT_EQ(ToLSize, FromLSize); - EXPECT_TRUE(FromL->isDependentLambda()); } TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) { diff --git a/clang/unittests/Rename/RenameClassTest.cpp b/clang/unittests/Rename/RenameClassTest.cpp index 24370b5..fb58d11 100644 --- a/clang/unittests/Rename/RenameClassTest.cpp +++ b/clang/unittests/Rename/RenameClassTest.cpp @@ -667,7 +667,7 @@ TEST_F(ClangRenameTest, ReferencesInLambdaFunctionParameters) { namespace ns { class New {}; void f() { - function<void(::new_ns::New)> func; + function<void(New)> func; } } // namespace ns)"; std::string After = runClangRenameOnCode(Before, "ns::Old", "::new_ns::New"); |