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