-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
[clang] Fix a crash when a variable is captured by a block nested inside a lambda #93749
Conversation
`Eval->Value.get` returns a null pointer when the variable doesn't have an initializer. This fixes llvm#93625. rdar://128482541
@llvm/pr-subscribers-clang Author: Akira Hatanaka (ahatanak) Changes
This fixes #93625. rdar://128482541 Full diff: https://github.com/llvm/llvm-project/pull/93749.diff 2 Files Affected:
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 41fbfe281ef65..4940a787e7d30 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2408,9 +2408,11 @@ Expr *VarDecl::getInit() {
return cast<Expr>(S);
auto *Eval = getEvaluatedStmt();
- return cast<Expr>(Eval->Value.isOffset()
- ? Eval->Value.get(getASTContext().getExternalSource())
- : Eval->Value.get(nullptr));
+
+ return cast_or_null<Expr>(
+ Eval->Value.isOffset()
+ ? Eval->Value.get(getASTContext().getExternalSource())
+ : Eval->Value.get(nullptr));
}
Stmt **VarDecl::getInitAddress() {
diff --git a/clang/test/SemaObjCXX/block-capture.mm b/clang/test/SemaObjCXX/block-capture.mm
index 8ba02f919e015..231aef33f2c7e 100644
--- a/clang/test/SemaObjCXX/block-capture.mm
+++ b/clang/test/SemaObjCXX/block-capture.mm
@@ -83,3 +83,21 @@
SubMove(SubSubMove &&);
};
TEST(SubMove);
+
+
+#if __cplusplus >= 202302L
+// clang used to crash compiling this code.
+namespace BlockInLambda {
+ struct S {
+ constexpr ~S();
+ };
+
+ void func(S const &a) {
+ [a](auto b) {
+ ^{
+ (void)a;
+ }();
+ }(12);
+ }
+}
+#endif
|
Note that the call to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
clang/lib/AST/Decl.cpp
Outdated
? Eval->Value.get(getASTContext().getExternalSource()) | ||
: Eval->Value.get(nullptr)); | ||
|
||
return cast_or_null<Expr>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Prefer cast_if_present
.
Can you provide a better description for the PR (such as "[clang] fix a crash with block captures inside a lambda" ) and an entry in clang/docs/ReleaseNotes.rst referencing the fixed issue? Thanks! The change itself looks good except modulo @zyn0217's feedback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for the fix!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see it stops crashing, but is it actually working now?
Why hasInit
returns true, but the variable doesn't actually have an initializer?
Shouldn't the fix go there?
llvm-project/clang/lib/AST/Decl.cpp Line 2541 in 3af717d
|
I see. It sounds like it would be less confusing if |
I can see if we can make |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, we can finish in post.
…ide a lambda (llvm#93749) `Eval->Value.get` returns a null pointer when the variable doesn't have an initializer. Use `cast_if_present` instead of `cast`. This fixes llvm#93625. rdar://128482541 (cherry picked from commit e1c3e16) Conflicts: clang/docs/ReleaseNotes.rst
…ide a lambda (llvm#93749) `Eval->Value.get` returns a null pointer when the variable doesn't have an initializer. Use `cast_if_present` instead of `cast`. This fixes llvm#93625. rdar://128482541 (cherry picked from commit e1c3e16) Conflicts: clang/docs/ReleaseNotes.rst
VarDecl::isNull() doesn't tell whether the VarDecl has an initializer as methods like ensureEvaluatedStmt can create an EvaluatedStmt even when there isn't an initializer. Revert e1c3e16 as the change isn't needed anymore with this change. See the discussion in llvm#93749.
Eval->Value.get
returns a null pointer when the variable doesn't have an initializer.This fixes #93625.
rdar://128482541