[clang] WIP: Improved Context Declaration tracking
This patch aims to improve how parenting relationships
are represented in the AST.
Currently regular declarations can only be children of
special AST nodes which inherit from DeclContext, except
for a few special cases which are required by itanium mangling.
Having this parenting relationship well described helps
in tracking which entities are dependent, and an improvement
here would allow us to drop a lot of workarounds and to
get some difficult cases right.
This patch extends the ContextDecl tracking which currently
is used for mangling, in order to cover almost needed cases.
Template type aliases represent a specially difficult case
which is addressed by this patch.
They can be contexts for other declarations, but besides not
being DeclContexts, they also lack a declaration which
represents their specialization.
This patch addresses the type alias context problem by
storing the specialization arguments along with the ContextDecl
for entities declared in their context.
TODO:
* Move away from using ExpressionEvaluationContexts, and use the same
stack used for tracking the CurContext. Remove the separate ContextDecl
field, and have that functionally built in to the base Decl class,
so that we don't separatelly treack both a parent Decl and a parent
DeclContext.
* A function type has ParmVarDecls, and these can appear inside
aliases and template type aliases in particular, so a ParmvarDecl
needs a ContextDecl too.
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 @@
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 @@
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 @@
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 @@
};
/// 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 @@
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 @@
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 @@
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 @@
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 @@
/// 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 @@
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 @@
ObjCContainerDeclBitfields ObjCContainerDeclBits;
LinkageSpecDeclBitfields LinkageSpecDeclBits;
BlockDeclBitfields BlockDeclBits;
+ RequiresExprBodyDeclBitfields RequiresExprBodyDeclBits;
static_assert(sizeof(DeclContextBitfields) <= 8,
"DeclContextBitfields is larger than 8 bytes!");
@@ -2053,6 +2065,8 @@
"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 252e6e9..1a780e7 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -254,6 +254,33 @@
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 @@
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,20 +399,31 @@
struct DefinitionData *DefinitionData;
- /// Describes a C++ closure type (generated by a lambda expression).
- struct LambdaDefinitionData : public DefinitionData {
- using Capture = LambdaCapture;
+ 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;
- /// 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;
+ /// 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 final
+ : public DefinitionData,
+ private llvm::TrailingObjects<LambdaDefinitionData, LambdaContext,
+ TemplateArgument> {
+ using Capture = LambdaCapture;
/// Whether this lambda is a generic lambda.
LLVM_PREFERRED_TYPE(bool)
@@ -411,21 +441,15 @@
/// 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 @@
/// 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;
+ LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool IsGeneric,
+ LambdaCaptureDefault CaptureDefault,
+ ContextDeclOrSentinel ContextDecl,
+ ArrayRef<TemplateArgument> ContextArgs);
- // C++1z [expr.prim.lambda]p4:
- // This class type is not an aggregate type.
- Aggregate = false;
- PlainOldData = false;
- }
+ 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 @@
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 @@
/// 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 @@
// 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 @@
/// 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 @@
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 @@
/// 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 @@
// 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 @@
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 @@
// 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 @@
};
/// 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 @@
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 @@
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 @@
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 @@
/// 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 @@
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 @@
};
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 @@
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 @@
/// 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 @@
/// 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 @@
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 @@
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 @@
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 @@
ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
ExpressionEvaluationContextRecord::ExpressionKind Type =
ExpressionEvaluationContextRecord::EK_Other);
+ void UpdateCurrentContextDecl(Decl *ContextDecl);
void PopExpressionEvaluationContext();
void DiscardCleanupsInEvaluationContext();
@@ -7946,6 +7980,8 @@
/// 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 @@
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 @@
/// 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 @@
/// 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 @@
///
/// \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 @@
/// "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 @@
///
/// 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 @@
/// 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 @@
/// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// - 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 @@
// 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 @@
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 @@
// 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 @@
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::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 @@
return LinkageInfo::internal();
}
- return getLVForClosure(
- Record->getDeclContext()->getRedeclContext(),
- Record->getLambdaContextDecl(), computation);
+ return getLVForClosure(Record->getDeclContext()->getRedeclContext(),
+ Record->getLambdaManglingContextDecl(),
+ computation);
}
break;
@@ -1534,7 +1526,7 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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::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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// ::= <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 @@
return;
}
+ if (Decl::castFromDeclContext(DC) == Structor) {
+ mangleUnqualifiedName(GD, DC, AdditionalAbiTags);
+ return;
+ }
+
if (isLocalContainerContext(DC)) {
mangleLocalName(GD, AdditionalAbiTags);
return;
@@ -1462,13 +1468,12 @@
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 @@
// -- 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::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 @@
if (DC->isTranslationUnit())
return;
+ while (DC->isRequiresExprBody())
+ DC = DC->getParent();
+
if (NoFunction && isLocalContainerContext(DC))
return;
@@ -2290,7 +2298,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
Actions,
Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
: Sema::ExpressionEvaluationContext::ConstantEvaluated,
- nullptr,
+ /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt,
Sema::ExpressionEvaluationContextRecord::EK_AttrArgument);
ExprResult ArgExpr(
@@ -646,7 +646,7 @@
Actions,
Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
: Sema::ExpressionEvaluationContext::ConstantEvaluated,
- nullptr,
+ /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt,
Sema::ExpressionEvaluationContextRecord::ExpressionKind::
EK_AttrArgument);
@@ -2075,6 +2075,9 @@
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 @@
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 @@
TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);
- ParseDeclarator(D);
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+ ParseDeclarator(D, &CurTemplateDepthTracker);
if (IsTemplateSpecOrInst)
SAC.done();
@@ -2362,8 +2370,12 @@
// 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 @@
}
// 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 @@
TheDecl =
ParseFunctionDefinition(D, TemplateInfo, &LateParsedAttrs);
}
-
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -2503,7 +2514,7 @@
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 @@
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 @@
}
break;
}
- }
+ }
SemaCUDA::CUDATargetContextRAII X(Actions.CUDA(),
SemaCUDA::CTCK_InitGlobalVar, ThisDecl);
@@ -3424,7 +3439,8 @@
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::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 @@
}
/// 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 @@
/// [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 @@
AnnotateScopeToken(SS, true);
if (DirectDeclParser)
- (this->*DirectDeclParser)(D);
+ (this->*DirectDeclParser)(D, CurTemplateDepthTracker);
return;
}
}
@@ -6775,7 +6795,7 @@
// 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 @@
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 @@
}
// 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 @@
///
/// 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 @@
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 @@
break;
}
}
-}
+ }
void Parser::ParseDecompositionDeclarator(Declarator &D) {
assert(Tok.is(tok::l_square));
@@ -7486,7 +7510,10 @@
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 @@
/// 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 @@
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::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 @@
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 @@
: DeclaratorCtx == DeclaratorContext::LambdaExpr
? DeclaratorContext::LambdaExprParameter
: DeclaratorContext::Prototype);
+
ParseDeclarator(ParmDeclarator);
if (ThisLoc.isValid())
@@ -8065,8 +8101,18 @@
// 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 @@
// 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 @@
// 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 @@
//
// 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 @@
// 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 @@
<< 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 @@
return nullptr;
}
ParsedTemplateInfo TemplateInfo;
+ EnterExpressionEvaluationContext Eval(
+ Actions, Actions.currentEvaluationContext().Context,
+ Sema::LazyContextDecl);
return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo);
}
}
@@ -5327,6 +5337,9 @@
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::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 @@
/// \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::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 @@
Scope::FunctionPrototypeScope);
Actions.PushLambdaScope();
- Actions.ActOnLambdaExpressionAfterIntroducer(Intro, getCurScope());
+ Actions.ActOnLambdaExpressionAfterIntroducer(Intro, getCurScope(),
+ TemplateParameterDepth);
ParsedAttributes Attributes(AttrFactory);
if (getLangOpts().CUDA) {
@@ -1465,15 +1467,8 @@
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 @@
Scope::CompoundStmtScope;
ParseScope BodyScope(this, ScopeFlags);
+ // ActOnStartOfLambdaDefinition reintroduces the context
+ Actions.PopExpressionEvaluationContext();
Actions.ActOnStartOfLambdaDefinition(Intro, D, DS);
// Parse compound-statement.
@@ -2081,6 +2078,10 @@
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 @@
// 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 @@
/// '[' 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 @@
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 @@
// 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 @@
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 @@
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 @@
}
EnterExpressionEvaluationContext PotentiallyDiscarded(
- Actions, Context, nullptr,
+ Actions, Context, /*ContextDecl=*/nullptr, /*ContextArgs=*/std::nullopt,
Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
}
@@ -1657,7 +1657,7 @@
}
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 @@
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 @@
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 @@
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 @@
.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 @@
// 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 @@
}
// 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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
}
// 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 @@
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 @@
// 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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
- // 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 @@
/* 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 @@
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 *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 @@
}
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 @@
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 @@
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 @@
// 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 @@
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 @@
NonTemplateMember = FunTmpl->getTemplatedDecl();
else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
NonTemplateMember = VarTmpl->getTemplatedDecl();
+ UpdateCurrentContextDecl(NonTemplateMember);
Member->setAccess(AS);
@@ -13520,6 +13521,7 @@
NewND = NewTD;
}
+ UpdateCurrentContextDecl(NewTD);
PushOnScopeChains(NewND, S);
ActOnDocumentableDecl(NewND);
return NewND;
@@ -14009,7 +14011,8 @@
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 @@
/* 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 @@
/* 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 @@
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 @@
/* 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 @@
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 @@
? 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 @@
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 @@
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 @@
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 @@
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 @@
}
}
+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 @@
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 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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
/*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 @@
/*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 @@
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 @@
/*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 @@
/*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 @@
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 @@
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 @@
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 @@
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 @@
return std::make_tuple(
&Context.getManglingNumberContext(ASTContext::NeedExtraManglingDecl,
ManglingContextDecl),
- ManglingContextDecl);
+ true);
}
llvm_unreachable("unexpected context");
@@ -455,7 +454,8 @@
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 @@
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 @@
// 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::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
- Scope *CurrentScope) {
+ Scope *CurrentScope,
+ unsigned TemplateDepth) {
LambdaScopeInfo *LSI = getCurLambda();
assert(LSI && "LambdaScopeInfo should be on stack!");
@@ -1075,35 +1082,8 @@
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 @@
Method->setLexicalDeclContext(CurContext);
PushDeclContext(CurScope, Method);
+ PushExpressionEvaluationContext(currentEvaluationContext().Context, Method);
bool ContainsUnexpandedParameterPack = false;
@@ -1549,7 +1530,8 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
/*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 @@
/*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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
/*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 @@
// 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 @@
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 @@
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 @@
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 @@
}
}
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 @@
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 c42cc250..6bb36ea 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -84,93 +84,6 @@
}
};
-// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
"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 @@
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 *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::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 @@
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 @@
}
}
+ 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 @@
if (!PrevAliasTemplate)
Inst->setInstantiatedFromMemberTemplate(D);
+ SemaRef.UpdateCurrentContextDecl(AliasInst);
return Inst;
}
@@ -2020,16 +2028,25 @@
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 @@
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 @@
D->FriendConstraintRefersToEnclosingTemplate());
Function->setRangeEnd(D->getSourceRange().getEnd());
}
+ SemaRef.UpdateCurrentContextDecl(Function);
if (D->isInlined())
Function->setImplicitlyInline();
@@ -2527,6 +2548,10 @@
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 @@
D->UsesFPIntrin(), D->isInlineSpecified(), D->getConstexprKind(),
D->getEndLoc(), TrailingRequiresClause);
}
+ SemaRef.UpdateCurrentContextDecl(Method);
if (D->isInlined())
Method->setImplicitlyInline();
@@ -4121,7 +4147,10 @@
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 @@
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 @@
// 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 @@
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 @@
/// 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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
/*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::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 @@
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 @@
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 @@
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::ReadCXXDefinitionData(
struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D,
- Decl *LambdaContext, unsigned IndexInLambdaContext) {
+ bool HasLambdaContext, unsigned IndexInLambdaContext) {
BitsUnpacker CXXRecordDeclBits = Record.readInt();
@@ -1993,7 +1994,7 @@
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 @@
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 @@
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 @@
{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 @@
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 @@
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 @@
Decl *LambdaContext = nullptr;
unsigned IndexInLambdaContext = 0;
+ llvm::SmallVector<TemplateArgument, 4> LambdaContextArgs;
switch ((CXXRecKind)Record.readInt()) {
case CXXRecNotTemplate:
@@ -2244,14 +2246,18 @@
}
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 @@
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::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 @@
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 @@
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 @@
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 @@
} 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::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 @@
// 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 @@
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 @@
// 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 @@
} {}
// 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 @@
// 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 @@
// 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 @@
}
} // 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 @@
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 @@
} // 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 @@
}
}
+
+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 @@
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 @@
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 @@
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 @@
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 @@
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");