[clang] [clang][Sema] Fix a bug when instantiating a lambda with requires clause (PR #65193)

2023-10-03 Thread via cfe-commits

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)

2023-10-03 Thread via cfe-commits

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)

2023-10-03 Thread via cfe-commits

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)

2023-10-03 Thread via cfe-commits

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)

2023-10-03 Thread via cfe-commits

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)

2023-10-03 Thread via cfe-commits

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)

2023-10-03 Thread via cfe-commits

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)

2023-10-02 Thread Erich Keane via cfe-commits


@@ -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)

2023-10-02 Thread Erich Keane via cfe-commits


@@ -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)

2023-10-02 Thread Erich Keane via cfe-commits

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)

2023-10-02 Thread Erich Keane via cfe-commits

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)

2023-10-02 Thread via cfe-commits


@@ -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)

2023-10-02 Thread via cfe-commits

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)

2023-10-02 Thread via cfe-commits

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)

2023-10-02 Thread via cfe-commits


@@ -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)

2023-09-15 Thread via cfe-commits


@@ -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)

2023-09-15 Thread via cfe-commits

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)

2023-09-15 Thread via cfe-commits

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)

2023-09-15 Thread via cfe-commits

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)

2023-09-15 Thread via cfe-commits

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)

2023-09-15 Thread via cfe-commits


@@ -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)

2023-09-15 Thread via cfe-commits

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)

2023-09-15 Thread via cfe-commits

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)

2023-09-13 Thread via cfe-commits

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)

2023-09-12 Thread via cfe-commits

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)

2023-09-12 Thread via cfe-commits

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)

2023-09-12 Thread Erich Keane via cfe-commits

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)

2023-09-12 Thread via cfe-commits


@@ -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)

2023-09-12 Thread via cfe-commits

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)

2023-09-12 Thread via cfe-commits

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)

2023-09-12 Thread via cfe-commits


@@ -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)

2023-09-12 Thread via cfe-commits


@@ -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)

2023-09-12 Thread via cfe-commits


@@ -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)

2023-09-12 Thread via cfe-commits

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)

2023-09-12 Thread via cfe-commits

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)

2023-09-12 Thread via cfe-commits

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)

2023-09-12 Thread via cfe-commits

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)

2023-09-12 Thread Jay Foad via cfe-commits

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)

2023-09-12 Thread via cfe-commits

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)

2023-09-11 Thread via cfe-commits

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)

2023-09-02 Thread via cfe-commits

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)

2023-09-02 Thread via cfe-commits

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)

2023-09-01 Thread via cfe-commits

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)

2023-09-01 Thread via cfe-commits

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)

2023-09-01 Thread via cfe-commits

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)

2023-09-01 Thread via cfe-commits

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)

2023-09-01 Thread via cfe-commits

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)

2023-09-01 Thread via cfe-commits

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)

2023-09-01 Thread via cfe-commits

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)

2023-09-01 Thread via cfe-commits

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