[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e closed https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
0x59616e wrote: Thank you for your review. I appreciate your feedback ;) https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/cor3ntin approved this pull request. LGTM, thanks! (Feel free to squash-merge yourself) https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193 >From 8abb437d97382f517bcbf0b5c4a542172c5ae144 Mon Sep 17 00:00:00 2001 From: Sheng Date: Wed, 30 Aug 2023 11:44:23 +0800 Subject: [PATCH 1/6] [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 036548b68247bfa..41af513969c6615 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -584,6 +584,58 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -701,6 +753,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)); @@ -722,6 +775,9 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, LambdaScopeForCallOperatorInstantiationRAII LambdaScope( *this, const_cast(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(FD), Scope); + return CheckConstraintSatisfaction( FD, {FD->getTrailingRequiresClause()}, *MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), @@ -913,6 +969,9 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints( LambdaScopeForCallOperatorInstantiationRAII LambdaScope( *this, const_cast(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+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@+2{{because substituted constraint expression is ill-formed: no matching
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
0x59616e wrote: The typo and the style issues have been fixed. Thank you. Now I'm going to rebase to main and add release note. https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193 >From 3eafb85ff74271456cba24ea5892dd5660c1d332 Mon Sep 17 00:00:00 2001 From: Sheng Date: Wed, 30 Aug 2023 11:44:23 +0800 Subject: [PATCH 1/5] [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 , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -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(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(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(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+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@+2{{because substituted constraint expression is ill-formed: no matching
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193 >From 3eafb85ff74271456cba24ea5892dd5660c1d332 Mon Sep 17 00:00:00 2001 From: Sheng Date: Wed, 30 Aug 2023 11:44:23 +0800 Subject: [PATCH 1/5] [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 , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -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(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(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(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+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@+2{{because substituted constraint expression is ill-formed: no matching
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -7370,7 +7370,8 @@ class Sema final { public: LambdaScopeForCallOperatorInstantiationRAII( Sema , FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, -LocalInstantiationScope ); +LocalInstantiationScope , +bool shouldAddDeclsFromParentScope = true); erichkeane wrote: ```suggestion bool ShouldAddDeclsFromParentScope = true); ``` https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -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 , FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, -LocalInstantiationScope ) -: FunctionScopeRAII(SemasRef) { +Sema , FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, +LocalInstantiationScope , bool shouldAddDeclsFromParentScope) erichkeane wrote: ```suggestion LocalInstantiationScope , bool ShouldAddDeclsFromParentScope) ``` https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/erichkeane commented: Just a pair of nits based on the style guide, else LGTM. https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/erichkeane edited https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -7396,6 +7397,11 @@ class Sema final { llvm::ContextualFoldingSet SatisfactionCache; + /// Intorduce the instantiated local variables into the local + /// instantiation scope. cor3ntin wrote: ```suggestion /// Introduce the instantiated local variables into the local /// instantiation scope. ``` https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/cor3ntin commented: I found a couple of typos, and this needs a release note to indicate https://github.com/llvm/llvm-project/issues/64462 was fixed. I'd like @erichkeane to take a last look but otherwise I think this looks reasonable (Sorry for the delay) https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -4515,6 +4515,36 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, return NewTInfo; } +/// Intorduce the instantiated local variables into the local cor3ntin wrote: ```suggestion /// Introduce the instantiated local variables into the local ``` https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -567,6 +567,58 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); 0x59616e wrote: I'm having difficulty understanding the problem. Is there anything incorrect here ? It would be great if more context could be provided. Thanks. https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e resolved https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e resolved https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193 >From 3eafb85ff74271456cba24ea5892dd5660c1d332 Mon Sep 17 00:00:00 2001 From: Sheng 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 , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -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(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(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(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+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@+2{{because substituted constraint expression is ill-formed: no matching
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e edited https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -567,6 +567,58 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(S.getFunctionScopes().back()); + + auto captureVar = [&](VarDecl *VD) { +LSI->addCapture(VD, /*isBlock=*/false, /*isByref=*/false, +/*isNested=*/false, VD->getBeginLoc(), SourceLocation(), +VD->getType(), /*Invalid=*/false); + }; + 0x59616e wrote: I couldn't find where the logic is in `LambdaScopeForCallOperatorInstantiationRAII`. Would you mind giving more hints ? Thanks. https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
0x59616e wrote: Support for nested lambda has been added. I will address your kindly feedbacks later. https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193 >From 3eafb85ff74271456cba24ea5892dd5660c1d332 Mon Sep 17 00:00:00 2001 From: Sheng Date: Wed, 30 Aug 2023 11:44:23 +0800 Subject: [PATCH 1/2] [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 , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -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(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(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(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+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@+2{{because substituted constraint expression is ill-formed: no matching
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
0x59616e wrote: > There is also the question of what happen in the deeply nested case > > ```c++ > int foo(auto...); > auto f(auto... a) { >return [] { >return [] () requires requires { foo(a...) ;} {}; >}(); > } > > auto g = f()(); > ``` > > we may have to visit all functions recursively from the bottom up to add > their locals / parameters / captures How deep the nested level should we support ? Support for two levels is easy, but three (or more) levels is complicated. I wonder whether the three (or more) nested levels is common enough that deserves the support. Any thought ? https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
cor3ntin wrote: There is also the question of what happen in the deeply nested case ```cpp void f(auto a) { [] { [] () requires requires foo(a) {}(); }(); } ``` we may have to visit all functions recursively from the bottom up to add their locals / parameters / captures https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
erichkeane wrote: > We have `addInstantiatedParametersToScope` - Which we use in > SetupConstraints`for example We could reuse that to add the parameter of the > enclosing function. We could similarly add > an`addInstantiatedLocalVarsToScope` method doing the same thing. > > And the logic could be moved to `LambdaScopeForCallOperatorInstantiationRAII` > > @erichkeane for additional feedback That sounds like a really good idea to me. We seem to be messing with this sort of thing all over the place, so having it all in 1 place seems beneficial. https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -567,6 +567,58 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(FD->getParent()->getParent()); cor3ntin wrote: you could use `getLambdaAwareParentOfDeclContext(FD)` here https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/cor3ntin commented: We have `addInstantiatedParametersToScope` - Which we use in SetupConstraints` for example We could reuse that to add the parameter of the enclosing function. We could similarly add an `addInstantiatedLocalVarsToScope` method doing the same thing. And the logic could be moved to `LambdaScopeForCallOperatorInstantiationRAII` @erichkeane for additional feedback https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/cor3ntin edited https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -567,6 +567,58 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); cor3ntin wrote: A I understand, this is the important bit, we don't care they are captures, all captures are added unconditionally https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -567,6 +567,58 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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)); cor3ntin wrote: These are not captures, adding them to the instantiation scope should be enough https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
@@ -567,6 +567,58 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(S.getFunctionScopes().back()); + + auto captureVar = [&](VarDecl *VD) { +LSI->addCapture(VD, /*isBlock=*/false, /*isByref=*/false, +/*isNested=*/false, VD->getBeginLoc(), SourceLocation(), +VD->getType(), /*Invalid=*/false); + }; + cor3ntin wrote: That logic is already in `LambdaScopeForCallOperatorInstantiationRAII`, you need to add it again https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e ready_for_review https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193: >From 3eafb85ff74271456cba24ea5892dd5660c1d332 Mon Sep 17 00:00:00 2001 From: Sheng Date: Wed, 30 Aug 2023 11:44:23 +0800 Subject: [PATCH] [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 , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -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(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(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(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+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@+2{{because substituted constraint expression is ill-formed: no matching
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
llvmbot wrote: @llvm/pr-subscribers-clang Changes Instantiating a lambda at a scope different from where it is defined will paralyze clang if the trailing require clause refers to local variables. This patch fixes this by re-adding the local variables to `LocalInstantiationScope`. Fixes #64462 -- Full diff: https://github.com/llvm/llvm-project/pull/65193.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaConcept.cpp (+61) - (added) clang/test/SemaCXX/pr64462.cpp (+20) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index d1fa8e7831225b7..45a25cdcb88c8d3 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -567,6 +567,59 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(FD->getParent()->getParent()); + FunctionDecl *Pattern = nullptr; + + if (!FD || !FD->isTemplateInstantiation()) +return; + + 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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -684,9 +737,11 @@ 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)); + std::optional MLTAL = SetupConstraintCheckingTemplateArgumentsAndScope( const_cast(FD), {}, Scope); @@ -705,6 +760,9 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, LambdaScopeForCallOperatorInstantiationRAII LambdaScope( *this, const_cast(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(FD), Scope); + return CheckConstraintSatisfaction( FD, {FD->getTrailingRequiresClause()}, *MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), @@ -896,6 +954,9 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints( LambdaScopeForCallOperatorInstantiationRAII LambdaScope( *this, const_cast(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c2'}} + // expected-note@+1{{candidate function not viable: constraints not satisfied}} + return []() requires a && (c2(fs...)) {};
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/llvmbot labeled https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/jayfoad updated https://github.com/llvm/llvm-project/pull/65193: >From 0da34437a4ec6604d27808a020f56c6cf3615b21 Mon Sep 17 00:00:00 2001 From: Sheng Date: Wed, 30 Aug 2023 11:44:23 +0800 Subject: [PATCH] [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 | 61 ++ clang/test/SemaCXX/pr64462.cpp | 20 +++ 2 files changed, 81 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..45a25cdcb88c8d3 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -567,6 +567,59 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(FD->getParent()->getParent()); + FunctionDecl *Pattern = nullptr; + + if (!FD || !FD->isTemplateInstantiation()) +return; + + 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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -684,9 +737,11 @@ 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)); + std::optional MLTAL = SetupConstraintCheckingTemplateArgumentsAndScope( const_cast(FD), {}, Scope); @@ -705,6 +760,9 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, LambdaScopeForCallOperatorInstantiationRAII LambdaScope( *this, const_cast(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(FD), Scope); + return CheckConstraintSatisfaction( FD, {FD->getTrailingRequiresClause()}, *MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), @@ -896,6 +954,9 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints( LambdaScopeForCallOperatorInstantiationRAII LambdaScope( *this, const_cast(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+1{{candidate template ignored: constraints not satisfied [with auto:1 = bool}} + return [](auto) requires a && (c1(fs...)) {}; +} + +auto c2(auto
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193: >From 0da34437a4ec6604d27808a020f56c6cf3615b21 Mon Sep 17 00:00:00 2001 From: Sheng Date: Wed, 30 Aug 2023 11:44:23 +0800 Subject: [PATCH] [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 | 61 ++ clang/test/SemaCXX/pr64462.cpp | 20 +++ 2 files changed, 81 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..45a25cdcb88c8d3 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -567,6 +567,59 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +LocalInstantiationScope ) { + assert(isLambdaCallOperator(FD) && "FD must be a lambda call operator"); + + LambdaScopeInfo *LSI = cast(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(FD->getParent()->getParent()); + FunctionDecl *Pattern = nullptr; + + if (!FD || !FD->isTemplateInstantiation()) +return; + + 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(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVar(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { @@ -684,9 +737,11 @@ 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)); + std::optional MLTAL = SetupConstraintCheckingTemplateArgumentsAndScope( const_cast(FD), {}, Scope); @@ -705,6 +760,9 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, LambdaScopeForCallOperatorInstantiationRAII LambdaScope( *this, const_cast(FD), *MLTAL, Scope); + if (isLambdaCallOperator(FD) && shouldAddDeclsFromParentScope) +addDeclsFromParentScope(*this, const_cast(FD), Scope); + return CheckConstraintSatisfaction( FD, {FD->getTrailingRequiresClause()}, *MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), @@ -896,6 +954,9 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints( LambdaScopeForCallOperatorInstantiationRAII LambdaScope( *this, const_cast(Decl), *MLTAL, Scope); + if (isLambdaCallOperator(Decl)) +addDeclsFromParentScope(*this, Decl, Scope); + llvm::SmallVector 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 000..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@+2{{because substituted constraint expression is ill-formed: no matching function for call to 'c1'}} + // expected-note@+1{{candidate template ignored: constraints not satisfied [with auto:1 = bool}} + return [](auto) requires a && (c1(fs...)) {}; +} + +auto c2(auto
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
cor3ntin wrote: Could you rebase on top of main? There have been a few changes to lambda that i think address part of the issues here, but this patch is still very much needed. We add a bug when referring to a capture in a decltype or a require would cause a crash, and that is fixed. I suspect the salient part of your patch is the addition of the parameters of the enclosing function. https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/cor3ntin labeled https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/cor3ntin labeled https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
cor3ntin wrote: Just to note that this has some overlap with https://reviews.llvm.org/D159126 https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e ready_for_review https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e updated https://github.com/llvm/llvm-project/pull/65193: >From a65cb213b6ea24a04e170a7cc210ed9d2d00a9ac Mon Sep 17 00:00:00 2001 From: Sheng Date: Wed, 30 Aug 2023 11:44:23 +0800 Subject: [PATCH] [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/include/clang/Sema/Sema.h | 5 +- clang/lib/Sema/SemaConcept.cpp | 136 clang/test/SemaCXX/pr64462.cpp | 20 + 3 files changed, 125 insertions(+), 36 deletions(-) create mode 100644 clang/test/SemaCXX/pr64462.cpp diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1980571e6656f9..d33af3d113b90c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7394,7 +7394,8 @@ class Sema final { /// function. bool SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, - MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ); + MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope , + const bool shouldAddDeclsFromParentScope); /// Used during constraint checking, sets up the constraint template argument /// lists, and calls SetupConstraintScope to set up the @@ -7402,7 +7403,7 @@ class Sema final { std::optional SetupConstraintCheckingTemplateArgumentsAndScope( FunctionDecl *FD, std::optional> TemplateArgs, - LocalInstantiationScope ); + LocalInstantiationScope , const bool shouldAddDeclsFromParentScope); private: // The current stack of constraint satisfactions, so we can exit-early. diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index fa3dadf68229ee..a15324f2424265 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -567,9 +567,65 @@ bool Sema::addInstantiatedCapturesToScope( return false; } +static void addDeclsFromParentScope(Sema , FunctionDecl *FD, +FunctionDecl *Pattern, +LocalInstantiationScope ) { + LambdaScopeInfo *LSI = nullptr; + if (!S.getFunctionScopes().empty()) +LSI = dyn_cast(S.getFunctionScopes().back()); + + auto captureVarIfNeeded = [&](VarDecl *VD) { +if (!LSI) + return; + +LSI->addCapture(VD, /*isBlock=*/false, /*isByref=*/false, +/*isNested=*/false, VD->getBeginLoc(), SourceLocation(), +VD->getType(), /*Invalid=*/false); + }; + + FD = dyn_cast(FD->getParent()->getParent()); + Pattern = dyn_cast(Pattern->getParent()->getParent()); + + if (!FD || !Pattern) +return; + + for (unsigned I = 0; I < Pattern->getNumParams(); ++I) { +ParmVarDecl *PVD = Pattern->getParamDecl(I); +if (!PVD->isParameterPack()) { + Scope.InstantiatedLocal(PVD, FD->getParamDecl(I)); + captureVarIfNeeded(FD->getParamDecl(I)); + continue; +} + +Scope.MakeInstantiatedLocalArgPack(PVD); + +for (ParmVarDecl *Inst : FD->parameters().drop_front(I)) { + Scope.InstantiatedLocalPackArg(PVD, Inst); + captureVarIfNeeded(Inst); +} + } + + for (auto *decl : Pattern->decls()) { +if (!isa(decl) || isa(decl)) + continue; + +IdentifierInfo *II = cast(decl)->getIdentifier(); +auto it = llvm::find_if(FD->decls(), [&](Decl *inst) { + VarDecl *VD = dyn_cast(inst); + return VD && VD->isLocalVarDecl() && VD->getIdentifier() == II; +}); + +assert(it != FD->decls().end() && "Cannot find the instantiated variable."); + +Scope.InstantiatedLocal(decl, *it); +captureVarIfNeeded(cast(*it)); + } +} + bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional> TemplateArgs, -MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope ) { +MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope , +const bool shouldAddDeclsFromParentScope) { if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); InstantiatingTemplate Inst( @@ -601,10 +657,14 @@ bool Sema::SetupConstraintScope( Scope, MLTAL)) return true; // Make sure the captures are also added to the instantiation scope. - if (isLambdaCallOperator(FD) && - addInstantiatedCapturesToScope(FD, FromMemTempl->getTemplatedDecl(), - Scope, MLTAL)) -return true; + if (isLambdaCallOperator(FD)) { +if (addInstantiatedCapturesToScope(FD, FromMemTempl->getTemplatedDecl(), + Scope, MLTAL)) + return true; +if
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e converted_to_draft https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e review_requested https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e review_requested https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e opened https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)
https://github.com/0x59616e review_requested https://github.com/llvm/llvm-project/pull/65193 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits