Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Concepts] Traverse the instantiation chain for parameter injection inside a constraint scope #79568

Merged
merged 3 commits into from
Jan 27, 2024

Conversation

zyn0217
Copy link
Contributor

@zyn0217 zyn0217 commented Jan 26, 2024

We preserve the trailing requires-expression during the lambda
expression transformation. In order to get those referenced parameters
inside a requires-expression properly resolved to the instantiated
decls, we intended to inject these 'original' ParmVarDecls to the
current instantiaion scope, at Sema::SetupConstraintScope.

The previous approach seems to overlook nested instantiation chains,
leading to the crash within a nested lambda followed by a requires clause.

This fixes #73418.

…nside a constraint scope

We preserve the trailing requires-expression during the lambda
expression transformation. In order to get those referenced parameters
inside a requires-expression properly resolved to the instantiated
decls, we intended to inject these 'original' ParmVarDecls to the
current instantiaion scope, at `Sema::SetupConstraintScope`.

The previous approach seems to overlook nested instantiation chains,
leading to the crash within a nested lambda followed by a requires clause.

This fixes llvm#73418.
@zyn0217 zyn0217 changed the title [WIP] Try to fix GH73418 [Concepts] Traverse the instantiation chain for parameter injection inside a constraint scope Jan 26, 2024
@zyn0217
Copy link
Contributor Author

zyn0217 commented Jan 26, 2024

In passing, the current strategy of preserving trailing requires expressions in TransformLambdaExpr confuses me:

getSema().CompleteLambdaCallOperator(
NewCallOperator, E->getCallOperator()->getLocation(),
E->getCallOperator()->getInnerLocStart(),
E->getCallOperator()->getTrailingRequiresClause(), NewCallOpTSI,
E->getCallOperator()->getConstexprKind(),
E->getCallOperator()->getStorageClass(), Params,
E->hasExplicitResultType());

Is there a reason why we decided not to perform the requires-expression transformation before this line? Could it be due to some "dependency" issues during the requires-expression evaluation?

Interestingly, this bug could also be resolved by performing additional transformation for such requirements, which is the case since those variables (e.g. params in the reproducer) inside the requires-clause get redirected to the current instantiated lambda Decl that way. But it makes two tests fail, and therefore I doubt if it's that I've missed some hacks, or just because I'm on the wrong direction?

@zyn0217 zyn0217 marked this pull request as ready for review January 26, 2024 17:34
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jan 26, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 26, 2024

@llvm/pr-subscribers-clang

Author: Younan Zhang (zyn0217)

Changes

We preserve the trailing requires-expression during the lambda
expression transformation. In order to get those referenced parameters
inside a requires-expression properly resolved to the instantiated
decls, we intended to inject these 'original' ParmVarDecls to the
current instantiaion scope, at Sema::SetupConstraintScope.

The previous approach seems to overlook nested instantiation chains,
leading to the crash within a nested lambda followed by a requires clause.

This fixes #73418.


Full diff: https://github.com/llvm/llvm-project/pull/79568.diff

3 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+3)
  • (modified) clang/lib/Sema/SemaConcept.cpp (+6-2)
  • (modified) clang/test/SemaTemplate/concepts-lambda.cpp (+18)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 392f694065a242..63b04982629b09 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1025,6 +1025,9 @@ Bug Fixes to AST Handling
 - Fixed a bug where Template Instantiation failed to handle Lambda Expressions
   with certain types of Attributes.
   (`#76521 <https://github.com/llvm/llvm-project/issues/76521>`_)
+- Fixed a bug where variables referenced by requires-clauses inside
+  nested generic lambdas were not properly injected into the constraint scope.
+  (`#73418 <https://github.com/llvm/llvm-project/issues/73418>`_)
 
 Miscellaneous Bug Fixes
 ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index acfc00f4125407..88fc846c89e42c 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -612,8 +612,12 @@ bool Sema::SetupConstraintScope(
 
     // If this is a member function, make sure we get the parameters that
     // reference the original primary template.
-    if (const auto *FromMemTempl =
-            PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
+    // We walk up the instantiated template chain so that nested lambdas get
+    // handled properly.
+    for (FunctionTemplateDecl *FromMemTempl =
+             PrimaryTemplate->getInstantiatedFromMemberTemplate();
+         FromMemTempl;
+         FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate()) {
       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
                                            Scope, MLTAL))
         return true;
diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp
index 7e431529427dff..0b7580f91043c7 100644
--- a/clang/test/SemaTemplate/concepts-lambda.cpp
+++ b/clang/test/SemaTemplate/concepts-lambda.cpp
@@ -149,3 +149,21 @@ void foo() {
   auto caller = make_caller.operator()<&S1::f1>();
 }
 } // namespace ReturnTypeRequirementInLambda
+
+namespace GH73418 {
+void foo() {
+  int x;
+  [&x](auto) {
+    return [](auto y) {
+      return [](auto obj, auto... params)
+        requires requires {
+          sizeof...(params);
+          [](auto... pack) {
+            return sizeof...(pack);
+          }(params...);
+        }
+      { return false; }(y);
+    }(x);
+  }(x);
+}
+} // namespace GH73418

@zyn0217 zyn0217 added concepts C++20 concepts and removed clang Clang issues not falling into any other category labels Jan 26, 2024
Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me.

@llvmbot llvmbot added the clang Clang issues not falling into any other category label Jan 27, 2024
@zyn0217
Copy link
Contributor Author

zyn0217 commented Jan 27, 2024

The failing libcxx test libcxx/gdb/gdb_pretty_printer_test.sh.cpp doesn't appear to relate to this patch, so I'm landing it anyway.

@zyn0217 zyn0217 merged commit 6e6c506 into llvm:main Jan 27, 2024
5 of 6 checks passed
zyn0217 added a commit to zyn0217/llvm-project that referenced this pull request Jan 31, 2024
…nside a constraint scope (llvm#79568)

We preserve the trailing requires-expression during the lambda
expression transformation. In order to get those referenced parameters
inside a requires-expression properly resolved to the instantiated
decls, we intended to inject these 'original' `ParmVarDecls` to the
current instantiaion scope, at `Sema::SetupConstraintScope`.

The previous approach seems to overlook nested instantiation chains,
leading to the crash within a nested lambda followed by a requires
clause.

This fixes llvm#73418.
tstellar pushed a commit that referenced this pull request Feb 7, 2024
Backporting #79568 to clang 18.
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
Backporting llvm#79568 to clang 18.
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
Backporting llvm#79568 to clang 18.
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
Backporting llvm#79568 to clang 18.
tstellar pushed a commit to tstellar/llvm-project that referenced this pull request Feb 14, 2024
Backporting llvm#79568 to clang 18.
@pointhex pointhex mentioned this pull request May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category concepts C++20 concepts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ICE due to pack expansion in requires of nested lambda
4 participants