[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 15 18:37:03 PDT 2023
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193
>From 3eafb85ff74271456cba24ea5892dd5660c1d332 Mon Sep 17 00:00:00 2001
From: Sheng <ox59616e at gmail.com>
Date: Wed, 30 Aug 2023 11:44:23 +0800
Subject: [PATCH 1/3] [clang][Sema] Fix a bug when instantiating a lambda with
requires clause
Instantiating a lambda at a scope different from its definition
scope will paralyze clang if the trailing require clause
refers to local variables of that definition scope.
This patch fixes this by re-adding the local variables to
`LocalInstantiationScope`.
Fixes #64462
---
clang/lib/Sema/SemaConcept.cpp | 59 ++++++++++++++++++++++++++++++++++
clang/test/SemaCXX/pr64462.cpp | 20 ++++++++++++
2 files changed, 79 insertions(+)
create mode 100644 clang/test/SemaCXX/pr64462.cpp
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index d1fa8e7831225b7..e48e0f743927a17 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -567,6 +567,58 @@ bool Sema::addInstantiatedCapturesToScope(
return false;
}
+static void addDeclsFromParentScope(Sema &S, FunctionDecl *FD,
+ LocalInstantiationScope &Scope) {
+ assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator");
+
+ LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(S.getFunctionScopes().back());
+
+ auto captureVar = [&](VarDecl *VD) {
+ LSI->addCapture(VD, /*isBlock=*/false, /*isByref=*/false,
+ /*isNested=*/false, VD->getBeginLoc(), SourceLocation(),
+ VD->getType(), /*Invalid=*/false);
+ };
+
+ FD = dyn_cast<FunctionDecl>(FD->getParent()->getParent());
+
+ if (!FD || !FD->isTemplateInstantiation())
+ return;
+
+ FunctionDecl *Pattern = FD->getPrimaryTemplate()->getTemplatedDecl();
+
+ for (unsigned I = 0; I < Pattern->getNumParams(); ++I) {
+ ParmVarDecl *PVD = Pattern->getParamDecl(I);
+ if (!PVD->isParameterPack()) {
+ Scope.InstantiatedLocal(PVD, FD->getParamDecl(I));
+ captureVar(FD->getParamDecl(I));
+ continue;
+ }
+
+ Scope.MakeInstantiatedLocalArgPack(PVD);
+
+ for (ParmVarDecl *Inst : FD->parameters().drop_front(I)) {
+ Scope.InstantiatedLocalPackArg(PVD, Inst);
+ captureVar(Inst);
+ }
+ }
+
+ for (auto *decl : Pattern->decls()) {
+ if (!isa<VarDecl>(decl) || isa<ParmVarDecl>(decl))
+ continue;
+
+ IdentifierInfo *II = cast<NamedDecl>(decl)->getIdentifier();
+ auto it = llvm::find_if(FD->decls(), [&](Decl *inst) {
+ VarDecl *VD = dyn_cast<VarDecl>(inst);
+ return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II;
+ });
+
+ assert(it != FD->decls().end() && "Cannot find the instantiated variable.");
+
+ Scope.InstantiatedLocal(decl, *it);
+ captureVar(cast<VarDecl>(*it));
+ }
+}
+
bool Sema::SetupConstraintScope(
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
@@ -684,6 +736,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
CtxToSave = CtxToSave->getNonTransparentContext();
}
+ const bool shouldAddDeclsFromParentScope = !CtxToSave->Encloses(CurContext);
ContextRAII SavedContext{*this, CtxToSave};
LocalInstantiationScope Scope(*this, !ForOverloadResolution ||
isLambdaCallOperator(FD));
@@ -705,6 +758,9 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
*this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope);
+ if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope)
+ addDeclsFromParentScope(*this, const_cast<FunctionDecl *>(FD), Scope);
+
return CheckConstraintSatisfaction(
FD, {FD->getTrailingRequiresClause()}, *MLTAL,
SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
@@ -896,6 +952,9 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
*this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
+ if (isLambdaCallOperator(Decl))
+ addDeclsFromParentScope(*this, Decl, Scope);
+
llvm::SmallVector<Expr *, 1> Converted;
return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
PointOfInstantiation, Satisfaction);
diff --git a/clang/test/SemaCXX/pr64462.cpp b/clang/test/SemaCXX/pr64462.cpp
new file mode 100644
index 000000000000000..cc8b5510d1a823a
--- /dev/null
+++ b/clang/test/SemaCXX/pr64462.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s
+
+auto c1(auto f, auto ...fs) {
+ constexpr bool a = true;
+ // expected-note at +2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}}
+ // expected-note at +1{{candidate template ignored: constraints not satisfied [with auto:1 = bool}}
+ return [](auto) requires a && (c1(fs...)) {};
+}
+
+auto c2(auto f, auto ...fs) {
+ constexpr bool a = true;
+ // expected-note at +2{{because substituted constraint expression is ill-formed: no matching function for call to 'c2'}}
+ // expected-note at +1{{candidate function not viable: constraints not satisfied}}
+ return []() requires a && (c2(fs...)) {};
+}
+
+void foo() {
+ c1(true)(true); // expected-error {{no matching function for call to object of type}}
+ c2(true)(); // expected-error {{no matching function for call to object of type}}
+}
>From 68912e0a88fc38cc5467c52f305e3c693f310dba Mon Sep 17 00:00:00 2001
From: Sheng <ox59616e at gmail.com>
Date: Fri, 15 Sep 2023 02:02:34 +0800
Subject: [PATCH 2/3] Add support for nested lambda.
---
clang/lib/Sema/SemaConcept.cpp | 78 ++++++++++++++++++++--------------
clang/test/SemaCXX/pr64462.cpp | 25 +++++------
2 files changed, 59 insertions(+), 44 deletions(-)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index e48e0f743927a17..dbe7a05660decf0 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -567,6 +567,20 @@ bool Sema::addInstantiatedCapturesToScope(
return false;
}
+static FunctionDecl *getPatternFunctionDecl(FunctionDecl *FD) {
+ if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) {
+ while (FD->getInstantiatedFromMemberFunction())
+ FD = FD->getInstantiatedFromMemberFunction();
+ return FD;
+ }
+
+ FunctionTemplateDecl *FTD = FD->getPrimaryTemplate();
+ while (FTD->getInstantiatedFromMemberTemplate())
+ FTD = FTD->getInstantiatedFromMemberTemplate();
+
+ return FTD->getTemplatedDecl();
+}
+
static void addDeclsFromParentScope(Sema &S, FunctionDecl *FD,
LocalInstantiationScope &Scope) {
assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator");
@@ -579,43 +593,45 @@ static void addDeclsFromParentScope(Sema &S, FunctionDecl *FD,
VD->getType(), /*Invalid=*/false);
};
- FD = dyn_cast<FunctionDecl>(FD->getParent()->getParent());
-
- if (!FD || !FD->isTemplateInstantiation())
- return;
+ while (true) {
+ FD = dyn_cast_or_null<FunctionDecl>(FD->getParent()->getParent());
+ if (!FD || !FD->isTemplateInstantiation())
+ return;
- FunctionDecl *Pattern = FD->getPrimaryTemplate()->getTemplatedDecl();
+ FunctionDecl *Pattern = getPatternFunctionDecl(FD);
- for (unsigned I = 0; I < Pattern->getNumParams(); ++I) {
- ParmVarDecl *PVD = Pattern->getParamDecl(I);
- if (!PVD->isParameterPack()) {
- Scope.InstantiatedLocal(PVD, FD->getParamDecl(I));
- captureVar(FD->getParamDecl(I));
- continue;
- }
+ for (unsigned I = 0; I < Pattern->getNumParams(); ++I) {
+ ParmVarDecl *PVD = Pattern->getParamDecl(I);
+ if (!PVD->isParameterPack()) {
+ Scope.InstantiatedLocal(PVD, FD->getParamDecl(I));
+ captureVar(FD->getParamDecl(I));
+ continue;
+ }
- Scope.MakeInstantiatedLocalArgPack(PVD);
+ Scope.MakeInstantiatedLocalArgPack(PVD);
- for (ParmVarDecl *Inst : FD->parameters().drop_front(I)) {
- Scope.InstantiatedLocalPackArg(PVD, Inst);
- captureVar(Inst);
+ for (ParmVarDecl *Inst : FD->parameters().drop_front(I)) {
+ Scope.InstantiatedLocalPackArg(PVD, Inst);
+ captureVar(Inst);
+ }
}
- }
- for (auto *decl : Pattern->decls()) {
- if (!isa<VarDecl>(decl) || isa<ParmVarDecl>(decl))
- continue;
+ for (auto *decl : Pattern->decls()) {
+ if (!isa<VarDecl>(decl) || isa<ParmVarDecl>(decl))
+ continue;
- IdentifierInfo *II = cast<NamedDecl>(decl)->getIdentifier();
- auto it = llvm::find_if(FD->decls(), [&](Decl *inst) {
- VarDecl *VD = dyn_cast<VarDecl>(inst);
- return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II;
- });
+ IdentifierInfo *II = cast<NamedDecl>(decl)->getIdentifier();
+ auto it = llvm::find_if(FD->decls(), [&](Decl *inst) {
+ VarDecl *VD = dyn_cast<VarDecl>(inst);
+ return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II;
+ });
- assert(it != FD->decls().end() && "Cannot find the instantiated variable.");
+ if (it == FD->decls().end())
+ continue;
- Scope.InstantiatedLocal(decl, *it);
- captureVar(cast<VarDecl>(*it));
+ Scope.InstantiatedLocal(decl, *it);
+ captureVar(cast<VarDecl>(*it));
+ }
}
}
@@ -736,10 +752,8 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
CtxToSave = CtxToSave->getNonTransparentContext();
}
- const bool shouldAddDeclsFromParentScope = !CtxToSave->Encloses(CurContext);
ContextRAII SavedContext{*this, CtxToSave};
- LocalInstantiationScope Scope(*this, !ForOverloadResolution ||
- isLambdaCallOperator(FD));
+ LocalInstantiationScope Scope(*this, !ForOverloadResolution);
std::optional<MultiLevelTemplateArgumentList> MLTAL =
SetupConstraintCheckingTemplateArgumentsAndScope(
const_cast<FunctionDecl *>(FD), {}, Scope);
@@ -758,7 +772,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
*this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope);
- if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope)
+ if (isLambdaCallOperator(FD) && ForOverloadResolution)
addDeclsFromParentScope(*this, const_cast<FunctionDecl *>(FD), Scope);
return CheckConstraintSatisfaction(
diff --git a/clang/test/SemaCXX/pr64462.cpp b/clang/test/SemaCXX/pr64462.cpp
index cc8b5510d1a823a..7cffb3583dcd408 100644
--- a/clang/test/SemaCXX/pr64462.cpp
+++ b/clang/test/SemaCXX/pr64462.cpp
@@ -2,19 +2,20 @@
auto c1(auto f, auto ...fs) {
constexpr bool a = true;
- // expected-note at +2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}}
- // expected-note at +1{{candidate template ignored: constraints not satisfied [with auto:1 = bool}}
- return [](auto) requires a && (c1(fs...)) {};
-}
-
-auto c2(auto f, auto ...fs) {
- constexpr bool a = true;
- // expected-note at +2{{because substituted constraint expression is ill-formed: no matching function for call to 'c2'}}
- // expected-note at +1{{candidate function not viable: constraints not satisfied}}
- return []() requires a && (c2(fs...)) {};
+ return [](auto) requires a {
+ constexpr bool b = true;
+ return []() requires a && b {
+ constexpr bool c = true;
+ return [](auto) requires a && b && c {
+ constexpr bool d = true;
+ // expected-note at +2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}}
+ // expected-note at +1{{candidate function not viable: constraints not satisfied}}
+ return []() requires a && b && c && d && (c1(fs...)) {};
+ };
+ }();
+ }(1);
}
void foo() {
- c1(true)(true); // expected-error {{no matching function for call to object of type}}
- c2(true)(); // expected-error {{no matching function for call to object of type}}
+ c1(true)(1.0)(); // expected-error{{no matching function for call to object of type}}
}
>From 1aff72f446c6febee0bce9ef3199a9c66bf16b75 Mon Sep 17 00:00:00 2001
From: Sheng <ox59616e at gmail.com>
Date: Sat, 16 Sep 2023 09:36:08 +0800
Subject: [PATCH 3/3] Move the implementation into
LambdaScopeForCallOperatorInstantiationRAII
---
clang/include/clang/Sema/Sema.h | 8 +-
clang/lib/Sema/SemaConcept.cpp | 77 +------------------
clang/lib/Sema/SemaLambda.cpp | 62 ++++++++++-----
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 30 ++++++++
4 files changed, 81 insertions(+), 96 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 304108df9f8d029..bd72da0da2425b2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7370,7 +7370,8 @@ class Sema final {
public:
LambdaScopeForCallOperatorInstantiationRAII(
Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
- LocalInstantiationScope &Scope);
+ LocalInstantiationScope &Scope,
+ bool shouldAddDeclsFromParentScope = true);
};
/// Check whether the given expression is a valid constraint expression.
@@ -7396,6 +7397,11 @@ class Sema final {
llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
SatisfactionCache;
+ /// Intorduce the instantiated local variables into the local
+ /// instantiation scope.
+ void addInstantiatedLocalVarsToScope(FunctionDecl *Function,
+ const FunctionDecl *PatternDecl,
+ LocalInstantiationScope &Scope);
/// Introduce the instantiated function parameters into the local
/// instantiation scope, and set the parameter names to those used
/// in the template.
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index dbe7a05660decf0..a0cf69cd8f1b57c 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -567,74 +567,6 @@ bool Sema::addInstantiatedCapturesToScope(
return false;
}
-static FunctionDecl *getPatternFunctionDecl(FunctionDecl *FD) {
- if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) {
- while (FD->getInstantiatedFromMemberFunction())
- FD = FD->getInstantiatedFromMemberFunction();
- return FD;
- }
-
- FunctionTemplateDecl *FTD = FD->getPrimaryTemplate();
- while (FTD->getInstantiatedFromMemberTemplate())
- FTD = FTD->getInstantiatedFromMemberTemplate();
-
- return FTD->getTemplatedDecl();
-}
-
-static void addDeclsFromParentScope(Sema &S, FunctionDecl *FD,
- LocalInstantiationScope &Scope) {
- assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator");
-
- LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(S.getFunctionScopes().back());
-
- auto captureVar = [&](VarDecl *VD) {
- LSI->addCapture(VD, /*isBlock=*/false, /*isByref=*/false,
- /*isNested=*/false, VD->getBeginLoc(), SourceLocation(),
- VD->getType(), /*Invalid=*/false);
- };
-
- while (true) {
- FD = dyn_cast_or_null<FunctionDecl>(FD->getParent()->getParent());
- if (!FD || !FD->isTemplateInstantiation())
- return;
-
- FunctionDecl *Pattern = getPatternFunctionDecl(FD);
-
- for (unsigned I = 0; I < Pattern->getNumParams(); ++I) {
- ParmVarDecl *PVD = Pattern->getParamDecl(I);
- if (!PVD->isParameterPack()) {
- Scope.InstantiatedLocal(PVD, FD->getParamDecl(I));
- captureVar(FD->getParamDecl(I));
- continue;
- }
-
- Scope.MakeInstantiatedLocalArgPack(PVD);
-
- for (ParmVarDecl *Inst : FD->parameters().drop_front(I)) {
- Scope.InstantiatedLocalPackArg(PVD, Inst);
- captureVar(Inst);
- }
- }
-
- for (auto *decl : Pattern->decls()) {
- if (!isa<VarDecl>(decl) || isa<ParmVarDecl>(decl))
- continue;
-
- IdentifierInfo *II = cast<NamedDecl>(decl)->getIdentifier();
- auto it = llvm::find_if(FD->decls(), [&](Decl *inst) {
- VarDecl *VD = dyn_cast<VarDecl>(inst);
- return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II;
- });
-
- if (it == FD->decls().end())
- continue;
-
- Scope.InstantiatedLocal(decl, *it);
- captureVar(cast<VarDecl>(*it));
- }
- }
-}
-
bool Sema::SetupConstraintScope(
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
@@ -770,10 +702,8 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
- *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope);
-
- if (isLambdaCallOperator(FD) && ForOverloadResolution)
- addDeclsFromParentScope(*this, const_cast<FunctionDecl *>(FD), Scope);
+ *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
+ ForOverloadResolution);
return CheckConstraintSatisfaction(
FD, {FD->getTrailingRequiresClause()}, *MLTAL,
@@ -966,9 +896,6 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
*this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
- if (isLambdaCallOperator(Decl))
- addDeclsFromParentScope(*this, Decl, Scope);
-
llvm::SmallVector<Expr *, 1> Converted;
return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
PointOfInstantiation, Satisfaction);
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 1702ddb3ee0fbf0..96d02c5a2f137ed 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -2256,33 +2256,55 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
return BuildBlock;
}
+static FunctionDecl *getPatternFunctionDecl(FunctionDecl *FD) {
+ if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) {
+ while (FD->getInstantiatedFromMemberFunction())
+ FD = FD->getInstantiatedFromMemberFunction();
+ return FD;
+ }
+
+ if (FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate)
+ return FD->getInstantiatedFromDecl();
+
+ FunctionTemplateDecl *FTD = FD->getPrimaryTemplate();
+ if (!FTD)
+ return nullptr;
+
+ while (FTD->getInstantiatedFromMemberTemplate())
+ FTD = FTD->getInstantiatedFromMemberTemplate();
+
+ return FTD->getTemplatedDecl();
+}
+
Sema::LambdaScopeForCallOperatorInstantiationRAII::
LambdaScopeForCallOperatorInstantiationRAII(
- Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
- LocalInstantiationScope &Scope)
- : FunctionScopeRAII(SemasRef) {
+ Sema &SemaRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
+ LocalInstantiationScope &Scope, bool shouldAddDeclsFromParentScope)
+ : FunctionScopeRAII(SemaRef) {
if (!isLambdaCallOperator(FD)) {
FunctionScopeRAII::disable();
return;
}
- if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
- FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
- if (const auto *FromMemTempl =
- PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
- SemasRef.addInstantiatedCapturesToScope(
- FD, FromMemTempl->getTemplatedDecl(), Scope, MLTAL);
- }
- }
+ SemaRef.RebuildLambdaScopeInfo(cast<CXXMethodDecl>(FD));
- else if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
- FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
- FunctionDecl *InstantiatedFrom =
- FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
- ? FD->getInstantiatedFromMemberFunction()
- : FD->getInstantiatedFromDecl();
- SemasRef.addInstantiatedCapturesToScope(FD, InstantiatedFrom, Scope, MLTAL);
- }
+ FunctionDecl *Pattern = getPatternFunctionDecl(FD);
+ if (Pattern) {
+ SemaRef.addInstantiatedCapturesToScope(FD, Pattern, Scope, MLTAL);
+
+ FunctionDecl *ParentFD = FD;
+ while (shouldAddDeclsFromParentScope) {
+
+ ParentFD =
+ dyn_cast<FunctionDecl>(getLambdaAwareParentOfDeclContext(ParentFD));
+ Pattern =
+ dyn_cast<FunctionDecl>(getLambdaAwareParentOfDeclContext(Pattern));
- SemasRef.RebuildLambdaScopeInfo(cast<CXXMethodDecl>(FD));
+ if (!FD || !Pattern)
+ break;
+
+ SemaRef.addInstantiatedParametersToScope(ParentFD, Pattern, Scope, MLTAL);
+ SemaRef.addInstantiatedLocalVarsToScope(ParentFD, Pattern, Scope);
+ }
+ }
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 37a7d6204413a38..eac599143ec9a0e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4515,6 +4515,36 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
return NewTInfo;
}
+/// Intorduce the instantiated local variables into the local
+/// instantiation scope.
+void Sema::addInstantiatedLocalVarsToScope(FunctionDecl *Function,
+ const FunctionDecl *PatternDecl,
+ LocalInstantiationScope &Scope) {
+ LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(getFunctionScopes().back());
+
+ for (auto *decl : PatternDecl->decls()) {
+ if (!isa<VarDecl>(decl) || isa<ParmVarDecl>(decl))
+ continue;
+
+ VarDecl *VD = cast<VarDecl>(decl);
+ IdentifierInfo *II = VD->getIdentifier();
+
+ auto it = llvm::find_if(Function->decls(), [&](Decl *inst) {
+ VarDecl *InstVD = dyn_cast<VarDecl>(inst);
+ return InstVD && InstVD->isLocalVarDecl() &&
+ InstVD->getIdentifier() == II;
+ });
+
+ if (it == Function->decls().end())
+ continue;
+
+ Scope.InstantiatedLocal(VD, *it);
+ LSI->addCapture(cast<VarDecl>(*it), /*isBlock=*/false, /*isByref=*/false,
+ /*isNested=*/false, VD->getLocation(), SourceLocation(),
+ VD->getType(), /*Invalid=*/false);
+ }
+}
+
/// Introduce the instantiated function parameters into the local
/// instantiation scope, and set the parameter names to those used
/// in the template.
More information about the cfe-commits
mailing list