[clang] [clang-tools-extra] [llvm] [clang] WIP: Improved Context Declaration tracking (PR #107942)
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 9 17:38:26 PDT 2024
https://github.com/mizvekov created https://github.com/llvm/llvm-project/pull/107942
This patch aims to improve how parenting relationships are represented in the AST.
Currently regular declarations can only be children of special AST nodes which inherit from DeclContext, except for a few special cases which are required by itanium mangling.
Having this parenting relationship well described helps in tracking which entities are dependent, and an improvement here would allow us to drop a lot of workarounds and to get some difficult cases right.
This patch extends the ContextDecl tracking which currently is used for mangling, in order to cover almost needed cases.
Template type aliases represent a specially difficult case which is addressed by this patch.
They can be contexts for other declarations, but besides not being DeclContexts, they also lack a declaration which represents their specialization.
This patch addresses the type alias context problem by storing the specialization arguments along with the ContextDecl for entities declared in their context.
TODO:
* Move away from using ExpressionEvaluationContexts, and use the same stack used for tracking the CurContext. Remove the separate ContextDecl field, and have that functionally built in to the base Decl class, so that we don't separatelly treack both a parent Decl and a parent DeclContext.
* A function type has ParmVarDecls, and these can appear inside aliases and template type aliases in particular, so a ParmvarDecl needs a ContextDecl too.
>From 77a8e95f6cc7395a1fd5c345479181d9ec692769 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Sat, 10 Aug 2024 23:43:27 -0300
Subject: [PATCH] [clang] WIP: Improved Context Declaration tracking
This patch aims to improve how parenting relationships
are represented in the AST.
Currently regular declarations can only be children of
special AST nodes which inherit from DeclContext, except
for a few special cases which are required by itanium mangling.
Having this parenting relationship well described helps
in tracking which entities are dependent, and an improvement
here would allow us to drop a lot of workarounds and to
get some difficult cases right.
This patch extends the ContextDecl tracking which currently
is used for mangling, in order to cover almost needed cases.
Template type aliases represent a specially difficult case
which is addressed by this patch.
They can be contexts for other declarations, but besides not
being DeclContexts, they also lack a declaration which
represents their specialization.
This patch addresses the type alias context problem by
storing the specialization arguments along with the ContextDecl
for entities declared in their context.
TODO:
* Move away from using ExpressionEvaluationContexts, and use the same
stack used for tracking the CurContext. Remove the separate ContextDecl
field, and have that functionally built in to the base Decl class,
so that we don't separatelly treack both a parent Decl and a parent
DeclContext.
* A function type has ParmVarDecls, and these can appear inside
aliases and template type aliases in particular, so a ParmvarDecl
needs a ContextDecl too.
---
benchmark.txt | 91 ++++++
.../lambda-function.cpp | 4 +-
clang/include/clang/AST/ASTLambda.h | 11 -
clang/include/clang/AST/Decl.h | 31 +-
clang/include/clang/AST/DeclBase.h | 16 +-
clang/include/clang/AST/DeclCXX.h | 269 ++++++++++++------
clang/include/clang/Basic/Linkage.h | 5 +
clang/include/clang/Parse/Parser.h | 37 ++-
.../Sema/EnterExpressionEvaluationContext.h | 7 +-
clang/include/clang/Sema/Sema.h | 77 +++--
clang/include/clang/Sema/Template.h | 2 +
clang/include/clang/Serialization/ASTReader.h | 3 +
clang/lib/AST/ASTContext.cpp | 2 +-
clang/lib/AST/ASTImporter.cpp | 40 ++-
clang/lib/AST/Decl.cpp | 78 ++---
clang/lib/AST/DeclBase.cpp | 93 +++---
clang/lib/AST/DeclCXX.cpp | 157 ++++++++--
clang/lib/AST/ItaniumMangle.cpp | 38 ++-
clang/lib/AST/Linkage.h | 9 +-
clang/lib/AST/MicrosoftMangle.cpp | 6 +-
.../FlowSensitive/DataflowEnvironment.cpp | 4 +-
clang/lib/CodeGen/CGObjC.cpp | 8 +-
clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 3 +-
clang/lib/CodeGen/CGStmtOpenMP.cpp | 3 +-
clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 +
clang/lib/CodeGen/MicrosoftCXXABI.cpp | 2 +
clang/lib/Index/IndexSymbol.cpp | 2 +
clang/lib/Parse/ParseDecl.cpp | 121 +++++---
clang/lib/Parse/ParseDeclCXX.cpp | 41 ++-
clang/lib/Parse/ParseExpr.cpp | 9 +-
clang/lib/Parse/ParseExprCXX.cpp | 51 ++--
clang/lib/Parse/ParseObjc.cpp | 12 +-
clang/lib/Parse/ParseStmt.cpp | 4 +-
clang/lib/Parse/ParseTemplate.cpp | 42 ++-
clang/lib/Parse/Parser.cpp | 25 +-
clang/lib/Sema/HLSLExternalSemaSource.cpp | 2 +-
clang/lib/Sema/Sema.cpp | 4 +-
clang/lib/Sema/SemaCXXScopeSpec.cpp | 7 +-
clang/lib/Sema/SemaConcept.cpp | 1 +
clang/lib/Sema/SemaDecl.cpp | 87 +++---
clang/lib/Sema/SemaDeclCXX.cpp | 48 ++--
clang/lib/Sema/SemaDeclObjC.cpp | 6 +-
clang/lib/Sema/SemaExpr.cpp | 114 ++++++--
clang/lib/Sema/SemaExprCXX.cpp | 15 +-
clang/lib/Sema/SemaExprObjC.cpp | 99 +++----
clang/lib/Sema/SemaLambda.cpp | 92 +++---
clang/lib/Sema/SemaLookup.cpp | 3 +-
clang/lib/Sema/SemaObjCProperty.cpp | 11 +-
clang/lib/Sema/SemaOpenMP.cpp | 3 +-
clang/lib/Sema/SemaOverload.cpp | 6 +
clang/lib/Sema/SemaPseudoObject.cpp | 41 ++-
clang/lib/Sema/SemaRISCV.cpp | 6 +-
clang/lib/Sema/SemaTemplate.cpp | 36 ++-
clang/lib/Sema/SemaTemplateDeduction.cpp | 3 +-
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 38 ++-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 211 +++++---------
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 51 +++-
clang/lib/Sema/SemaType.cpp | 18 +-
clang/lib/Sema/TreeTransform.h | 148 +++-------
clang/lib/Serialization/ASTReader.cpp | 21 +-
clang/lib/Serialization/ASTReaderDecl.cpp | 75 +++--
clang/lib/Serialization/ASTWriter.cpp | 3 +-
clang/lib/Serialization/ASTWriterDecl.cpp | 23 +-
clang/test/AST/ast-dump-concepts.cpp | 8 +
clang/test/CodeGenCXX/clang-abi-compat.cpp | 3 +-
.../cxx20-unevaluated-lambda-crash.cpp | 3 +-
.../test/CodeGenCXX/mangle-lambdas-cxx20.cpp | 6 +
.../CodeGenCXX/mangle-lambdas-tentative.cpp | 12 +
clang/test/CodeGenCXX/mangle-requires.cpp | 5 +
clang/test/Index/complete-exprs.m | 2 +-
clang/test/Modules/requires.cpp | 15 +
clang/test/Parser/backtrack-off-by-one.cpp | 9 +-
.../SemaCXX/lambda-as-default-parameter.cpp | 7 +-
clang/test/SemaCXX/lambda-unevaluated.cpp | 12 +
.../alias-template-with-lambdas.cpp | 12 +-
clang/test/SemaTemplate/concepts.cpp | 11 +
clang/tools/libclang/CIndex.cpp | 1 +
clang/tools/libclang/CXIndexDataConsumer.cpp | 2 +
clang/unittests/AST/ASTImporterTest.cpp | 2 -
clang/unittests/Rename/RenameClassTest.cpp | 2 +-
80 files changed, 1600 insertions(+), 989 deletions(-)
create mode 100644 benchmark.txt
create mode 100644 clang/test/CodeGenCXX/mangle-lambdas-tentative.cpp
create mode 100644 clang/test/Modules/requires.cpp
diff --git a/benchmark.txt b/benchmark.txt
new file mode 100644
index 00000000000000..428114a17346ec
--- /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 452983ea9c4184..9fd6c5e60e4e22 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 646cb574847fe2..ae38e57365233d 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 0600ecc4d14a18..8f7b6205505982 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -986,6 +986,11 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
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 @@ class ImplicitParamDecl : public VarDecl {
};
/// 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 @@ class ParmVarDecl : public VarDecl {
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 @@ class ParmVarDecl : public VarDecl {
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 @@ class ParmVarDecl : public VarDecl {
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 @@ class ParmVarDecl : public VarDecl {
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 ee662ed73d7e0e..4b4fd5ae731779 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -930,7 +930,8 @@ class alignas(8) Decl {
/// 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 @@ class DeclContext {
ObjCContainerDeclBitfields ObjCContainerDeclBits;
LinkageSpecDeclBitfields LinkageSpecDeclBits;
BlockDeclBitfields BlockDeclBits;
+ RequiresExprBodyDeclBitfields RequiresExprBodyDeclBits;
static_assert(sizeof(DeclContextBitfields) <= 8,
"DeclContextBitfields is larger than 8 bytes!");
@@ -2053,6 +2065,8 @@ class DeclContext {
"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 252e6e92564142..1a780e798b8268 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -254,6 +254,33 @@ class CXXBaseSpecifier {
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 @@ class CXXRecordDecl : public RecordDecl {
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;
@@ -409,23 +439,17 @@ class CXXRecordDecl : public RecordDecl {
/// The number of explicit captures in this lambda.
unsigned NumExplicitCaptures : 12;
+ /// 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 @@ class CXXRecordDecl : public RecordDecl {
/// 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 @@ class CXXRecordDecl : public RecordDecl {
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 @@ class CXXRecordDecl : public RecordDecl {
/// 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 @@ class CXXRecordDecl : public RecordDecl {
// 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 @@ class CXXRecordDecl : public RecordDecl {
/// 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 @@ class CXXRecordDecl : public RecordDecl {
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 @@ class CXXDeductionGuideDecl : public FunctionDecl {
/// 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 fcf56b93b9781d..dc1522b5eeb024 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 47f72135c97cff..442db14c837d75 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2080,7 +2080,9 @@ class Parser : public CodeCompletionHandler {
// 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 @@ class Parser : public CodeCompletionHandler {
};
/// 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 @@ class Parser : public CodeCompletionHandler {
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 @@ class Parser : public CodeCompletionHandler {
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 5eca797b8842b5..bc15739f6465cd 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 ac4c11964b126f..d022625104c14f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3639,8 +3639,10 @@ class Sema final : public SemaBase {
/// 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 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
};
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 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
/// 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 @@ class Sema final : public SemaBase {
/// 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 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
ExpressionEvaluationContextRecord::ExpressionKind Type =
ExpressionEvaluationContextRecord::EK_Other);
+ void UpdateCurrentContextDecl(Decl *ContextDecl);
void PopExpressionEvaluationContext();
void DiscardCleanupsInEvaluationContext();
@@ -7946,6 +7980,8 @@ class Sema final : public SemaBase {
/// 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 @@ class Sema final : public SemaBase {
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 @@ class Sema final : public SemaBase {
/// 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 @@ class Sema final : public SemaBase {
/// 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 @@ class Sema final : public SemaBase {
///
/// \param DC - The DeclContext containing the lambda expression or
/// block literal.
- std::tuple<MangleNumberingContext *, Decl *>
- getCurrentMangleNumberContext(const DeclContext *DC);
+ std::tuple<MangleNumberingContext *, bool>
+ getCurrentMangleNumberContext(const DeclContext *DC,
+ Decl *ManglingContextDecl,
+ bool InSignature = false);
///@}
@@ -11217,8 +11257,6 @@ class Sema final : public SemaBase {
/// "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 @@ class Sema final : public SemaBase {
///
/// 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 0340c23fd170d6..52028540c9c855 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 898f4392465fdf..9a04127e5421c9 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -1148,6 +1148,9 @@ class ASTReader
/// 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 fa9cc38efc4662..c49b172133c1f1 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 c2fb7dddcfc637..b2cd022a514b46 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 a14b1b33d35efc..6e9fad420022d0 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 f42857f20efc44..20e536421e098a 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 01143391edab40..88944bada5d491 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 7d638befcbd3f1..101a364df96c98 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -173,7 +173,7 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
// 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 e4dcb5e53261ce..25a310b624b3c3 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 018ab617a0ecee..736c675f71ae18 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 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
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 e1f68e493f3553..1ac9f3b08099a2 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 a73a71f2d26889..22900b3d182744 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 9e095a37552196..d53e88fc00453f 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 8afe2abf2cc494..d70f641321f8ef 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 fb1eb72d9f3404..ea36035f3714fa 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 76d0191a7e63ad..cd138311714773 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 419ff79a5cbab0..5cbc7a6695e974 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 1f56884be392d6..dcb1d8ac3164f9 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 6370da1fab0042..f761fc4b541727 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 64f284d78b24db..4d2f311bd256b0 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 9bb0fff329d728..db08d44c7dd501 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 dad39d8dc736de..3b4add86f317fd 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 bdb3fc051d0b35..7d232e09f769bc 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 de29652abbfd95..9399e9d7f930e7 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 04c2f1d380bc48..67d538814ea6c3 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 071e64fe56d48a..4102258e0b57ac 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 46ddd360870b4f..545244e89a2097 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 5b2d65247e72e5..4414b36edc29ce 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 6a1b32598bb4a6..f8902f381cdd20 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 3c6a0dff798ff6..64194a5bf0484c 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 6b6fa98bf394ca..e79c204b775733 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 807453400abdd0..bc0832760b6591 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 30e5fe4543bcaa..818bb7a0d5e81b 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 e086c601107041..7ee9f3e5d16890 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 2f914ddc22a38b..89ca8dff60b127 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 15ed8572e60844..7dbdc1d950a3c3 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 d3d4bf27ae7283..1a41a428c82bd1 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 031f2a6af87744..1c61fa274e3594 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 b952ffbd69f5d5..3403da12e29c50 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 861b0a91240b3b..bfa417719ef881 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 30ed47e6e56ec9..69b81a573a657c 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 56d6f12fbc6e4a..bebef1c273c90a 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 513f83146fb59e..084a5f0e4bb06e 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 4c88159ea4cedf..129ff665771a96 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 545da21183c3c4..47cde6e8c8133e 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 @@ struct ConvertConstructorToDeductionGuideTransform {
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 c42cc250bb904a..6bb36ea92729c9 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 bb311e38409280..cd795a756216e7 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 520dce870b7b78..49ac6dbac27e2c 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 4bbc024587915c..52e672d7149483 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -772,12 +772,6 @@ class TreeTransform {
/// 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 e5a1e20a265616..7b4f3fdd52a115 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 9272e23c7da3fc..dbe838cca369dd 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 c6289493fce1de..831b24d8b68fe2 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 555f6325da646b..2fcd8826cd0589 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 a5e0673c241ef4..fcaa4958b5bfdb 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 4d518116f0a70c..0193c7e51d2a9a 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 9cc6ebe93af489..e931985af838de 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 4871e9d00e73f9..56b3790eb56f3c 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 00000000000000..2d1f37dce468d3
--- /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 9e2bdde03407a9..f8544dec76a279 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 16eeda9bff4b6c..555757b3ec7939 100644
--- a/clang/test/Index/complete-exprs.m
+++ b/clang/test/Index/complete-exprs.m
@@ -35,7 +35,7 @@ - (int)method:(id)param1 {
// 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 00000000000000..d6ff3947799d58
--- /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 b5c05aeee9d933..5a5f28f844a489 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 at +1 {{expected '{' after base class list}}
template <typename T> class B : T // not ',' or '{'
-#if __cplusplus < 201103L
-// expected-error at +8 {{expected ';' after top level declarator}}
-#endif
-#if __cplusplus <= 201402L
-// expected-error at +5 {{a type specifier is required for all declarations}}
-#else
-// expected-error at +3 {{expected unqualified-id}}
-#endif
+// expected-error at +2 {{expected unqualified-id}}
// expected-error at +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 1f07a7f5644b7c..1c8ceaa806c60f 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 39ee89bc797f84..41e697892efd56 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 at -2 {{static assertion expression is not an integral constant expression}}
+ // expected-note at -3 {{non-constexpr function 'operator()<0>' cannot be used in a constant expression}}
+ // expected-note at -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 5ec93163e4d188..7c71f186e71e23 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 a98ca3939222bd..6c2335015a0a4e 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 e821c5e4c588b6..065eed68192677 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 8d364ed8876a12..bca2f71da3a61f 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 aacecd3fbcd902..f84f6a6197bbe1 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 24370b5795e942..fb58d117d25390 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");
More information about the cfe-commits
mailing list