Skip to content

[clang] reject to capture variable in RequiresExprBodyDecl #78598

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

Conversation

HerrCai0907
Copy link
Contributor

@HerrCai0907 HerrCai0907 commented Jan 18, 2024

RequiresExprBodyDecl will be in CurContext. Then is will cause mismatch between CurContext and FunctionScopes.
This patch wants to ignore RequiresExprBodyDecl in CurContext.
Fixes: #69307, #76593.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jan 18, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 18, 2024

@llvm/pr-subscribers-clang

Author: Congcong Cai (HerrCai0907)

Changes

Expression in RequiresExprBodyDecl is resolved as constants and should not be captured.
Fixes: #69307, #76593.


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

2 Files Affected:

  • (modified) clang/lib/Sema/SemaExpr.cpp (+3-1)
  • (added) clang/test/SemaCXX/requires-expression-with-capture-variable.cpp (+25)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6413a48f809ac9..767fc3787cb22f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19719,7 +19719,9 @@ bool Sema::tryCaptureVariable(
   // we can bailout early.
   if (CapturingFunctionScopes == 0 && (!BuildAndDiagnose || VarDC == DC))
     return true;
-
+  // Expression in `RequiresExprBodyDecl` should not be captured.
+  if (isa<RequiresExprBodyDecl>(CurContext))
+    return true;
   const auto *VD = dyn_cast<VarDecl>(Var);
   if (VD) {
     if (VD->isInitCapture())
diff --git a/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp b/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp
new file mode 100644
index 00000000000000..d01a54133f6c39
--- /dev/null
+++ b/clang/test/SemaCXX/requires-expression-with-capture-variable.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang -fsyntax-only -std=c++20 -Xclang -verify %s
+
+// expected-no-diagnostics
+
+auto GH69307_Func_1() {
+  constexpr auto b = 1;
+  return [&](auto c) -> int
+           requires requires { b + c; }
+  { return 1; };
+};
+auto GH69307_Func_Ret = GH69307_Func_1()(1);
+
+auto GH69307_Lambda_1 = []() {
+  return [&](auto c) -> int
+           requires requires { c; }
+  { return 1; };
+};
+auto GH69307_Lambda_1_Ret = GH69307_Lambda_1()(1);
+
+auto GH69307_Lambda_2 = [](auto c) {
+  return [&]() -> int
+           requires requires { c; }
+  { return 1; };
+};
+auto GH69307_Lambda_2_Ret = GH69307_Lambda_2(1)();

@cor3ntin
Copy link
Contributor

Thanks for the patch!

Requires Expressions should be in an unevaluated context, so we should never try to capture variables they mentioned.

Maybe we need to test the evaluation context in either tryCaptureVariable or NeedToCaptureVariable, rather than a specific handling for requires expressions

https://eel.is/c++draft/expr.prim.lambda.capture#7.sentence-2

WDYT?

@erichkeane

@zyn0217
Copy link
Contributor

zyn0217 commented Jan 18, 2024

I think this also fixes #63845 and the example in #41751 (comment), and even #67260!

Expression in `RequiresExprBodyDecl` is resolved as constants and should not be captured.
Fixes: #69307, #76593.
@HerrCai0907 HerrCai0907 force-pushed the users/ccc/69307-clang-ice-when-dealing-with-some-certain-requires-clauses-in-calculateconstraintsatisfaction branch from 33db497 to a99f16f Compare January 20, 2024 05:46
Copy link

github-actions bot commented Jan 20, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@HerrCai0907 HerrCai0907 requested a review from cor3ntin January 20, 2024 05:56
@HerrCai0907
Copy link
Contributor Author

Thanks for the patch!

Requires Expressions should be in an unevaluated context, so we should never try to capture variables they mentioned.

Maybe we need to test the evaluation context in either tryCaptureVariable or NeedToCaptureVariable, rather than a specific handling for requires expressions

https://eel.is/c++draft/expr.prim.lambda.capture#7.sentence-2

WDYT?

@erichkeane

We will use tryCaptureVariable to diagnose -Wunused-lambda-capture. So simply ignoring them in an unevaluated context is not a good idea. I have changed the PR to match this function work even for RequiresExprBodyDecl.

…some-certain-requires-clauses-in-calculateconstraintsatisfaction
@HerrCai0907
Copy link
Contributor Author

ping @erichkeane @cor3ntin

@cor3ntin
Copy link
Contributor

cor3ntin commented Feb 4, 2024

Thanks for the patch!
Requires Expressions should be in an unevaluated context, so we should never try to capture variables they mentioned.
Maybe we need to test the evaluation context in either tryCaptureVariable or NeedToCaptureVariable, rather than a specific handling for requires expressions
https://eel.is/c++draft/expr.prim.lambda.capture#7.sentence-2
WDYT?
@erichkeane

We will use tryCaptureVariable to diagnose -Wunused-lambda-capture. So simply ignoring them in an unevaluated context is not a good idea. I have changed the PR to match this function work even for RequiresExprBodyDecl.

You have an example of that? There may be further bugs there.
id-expression that appear in any unevaluated context should not be captured ( typeid being an exception
https://eel.is/c++draft/expr.prim.lambda.capture#7.sentence-2 )

@HerrCai0907
Copy link
Contributor Author

HerrCai0907 commented Feb 4, 2024

You have an example of that? There may be further bugs there.
id-expression that appear in any unevaluated context should not be captured ( typeid being an exception

I think it is from standard, but from user-friendly site. Now clang will hint user some variables is not need to capture in unevaluated context. The current implement is clang will try to capture it and then throw a diagnose and then give up to capture.
https://godbolt.org/z/9jnx93r6e

auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; };

@@ -19706,22 +19706,29 @@ static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI,
}
}

static DeclContext *ignoreReuquiresBodyDecl(DeclContext *DC) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
static DeclContext *ignoreReuquiresBodyDecl(DeclContext *DC) {
static DeclContext *ignoreRequiresBodyDecl(DeclContext *DC) {

Copy link
Collaborator

Choose a reason for hiding this comment

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

Name here doesn't match what you're doing here. Perhaps something closer to getParentIgnoringRequiresBodyDecl? Not a great name either, but better I think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think inline it will be better since we only call it once.


auto GH69307_Func_1() {
constexpr auto b = 1;
return [&](auto c) -> int
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you do a similar test with NO capture here? To show that they aren't needed.


void test() {
int i;
auto explicit_by_value_unused_requires = [i] (auto) requires requires { i; } {}; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be PARTICULARLY good if we could 'remember' that it was 'used' in the requires clause so we can add a note that says something like (please consider wording and write better:)), note: use in requires expr doesn't use captures because they are special.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would be interesting. I will try to do it later in festival.

@LYP951018
Copy link
Contributor

This PR should also be able to fix #63972.

@HerrCai0907 HerrCai0907 deleted the users/ccc/69307-clang-ice-when-dealing-with-some-certain-requires-clauses-in-calculateconstraintsatisfaction branch February 27, 2024 01:36
@zyn0217
Copy link
Contributor

zyn0217 commented Feb 27, 2024

Could you please explain why you're closing the PR?

@cor3ntin
Copy link
Contributor

If @HerrCai0907 doesn't reply, we should take over
@shafik @erichkeane @Endilll

@l1nxy
Copy link

l1nxy commented Apr 21, 2024

@cor3ntin @shafik Hi, I want to take charge of this issue and submit a PR for the fix.

@shafik
Copy link
Collaborator

shafik commented May 1, 2024

@cor3ntin @shafik Hi, I want to take charge of this issue and submit a PR for the fix.

I would open a new PR and reference this one in the summary for completeness. It looks like this one is not going to picked up by the author and so if you can take it over and finish it that would be very much appreciated.

There are a lot of issues that crash similarly and so we likely have plenty of tests to try against a fix :-)

zyn0217 added a commit to zyn0217/llvm-project that referenced this pull request May 24, 2024
This patch picks up llvm#78598 with the hope that we can address such
crashes in tryCaptureVariable for unevaluated lambdas.

In addition to tryCaptureVariable, this also contains several other
fixes on e.g. lambda parsing/dependencies.
zyn0217 added a commit that referenced this pull request Jun 4, 2024
This patch picks up #78598 with the hope that we can address such
crashes in `tryCaptureVariable()` for unevaluated lambdas.

In addition to `tryCaptureVariable()`, this also contains several other
fixes on e.g. lambda parsing/dependencies.

Fixes #63845
Fixes #67260
Fixes #69307
Fixes #88081
Fixes #89496
Fixes #90669
Fixes #91633
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang] ICE when dealing with some certain requires clauses in calculateConstraintSatisfaction
8 participants