-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][AST] Invalidate DecompositionDecl if it has invalid initializer. #72428
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
@llvm/pr-subscribers-clang Author: Haojian Wu (hokein) ChangesFix #67495, #72198 CC @ADKaster, @ecnelises Full diff: https://github.com/llvm/llvm-project/pull/72428.diff 2 Files Affected:
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3876eb501083acb..b89031425e4b5ac 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13540,6 +13540,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), Args);
if (RecoveryExpr.get())
VDecl->setInit(RecoveryExpr.get());
+ // In general, for error recovery purposes, the initalizer doesn't play
+ // part in the valid bit of the declaration. There are a few exceptions:
+ // 1) if the var decl has a deduced auto type, and the type cannot be
+ // deduced by an invalid initializer;
+ // 2) if the var decl is decompsition decl with a concrete type (e.g.
+ // `int [a, b] = 1;`), and the initializer is invalid;
+ // Case 1) is already handled earlier in this function.
+ if (llvm::isa<DecompositionDecl>(VDecl)) // Case 2)
+ VDecl->setInvalidDecl();
return;
}
diff --git a/clang/test/AST/ast-dump-invalid-initialized.cpp b/clang/test/AST/ast-dump-invalid-initialized.cpp
index 1c374ae716a9db5..a71a02f0f60039e 100644
--- a/clang/test/AST/ast-dump-invalid-initialized.cpp
+++ b/clang/test/AST/ast-dump-invalid-initialized.cpp
@@ -24,4 +24,17 @@ void test() {
auto b4 = A(1);
// CHECK: `-VarDecl {{.*}} invalid b5 'auto'
auto b5 = A{1};
-}
\ No newline at end of file
+}
+
+void pr72198() {
+ // CHECK: DecompositionDecl {{.*}} invalid 'int'
+ int [_, b] = {0, 0};
+ [b]{};
+}
+
+int get_point();
+void pr67495() {
+ // CHECK: DecompositionDecl {{.*}} invalid 'int &'
+ auto& [x, y] = get_point();
+ [x, y] {};
+}
|
What differentiates the DecompositionDecl such that we need to mark the decl invalid when there's an error in the RHS, while for other decls we don't? It seems inconsistent. |
// `int [a, b] = 1;`), and the initializer is invalid; | ||
// Case 1) is already handled earlier in this function. | ||
if (llvm::isa<DecompositionDecl>(VDecl)) // Case 2) | ||
VDecl->setInvalidDecl(); |
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.
Maybe we should move the 1)
part of the comment line 13496, or just remove it entirely.
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.
We should have the comment in both places. This is very helpful to understanding the code.
I agree that having the comment far away from the code that it is commenting on is less useful. The code could easily be moved in a refactor or in other ways and become completely disconnected.
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 think this comment is helpful (especially the context is not obvious here). I'd like to keep it.
The code handling the case 1)
is https://github.com/llvm/llvm-project/blob/1c05fe350064aa3a1784bb09829a07d501842d97/clang/lib/Sema/SemaDecl.cpp#L13363C3-L13384, and it is easier to understand the purpose by reading the code. I'd avoid having two similar comments in the codebase.
13b97a2
to
067a93a
Compare
DecompositionDecl (aka structure binding) is special here, a legal DecompositionDecl must be declared with a deduced |
Ah that makes sense then. I didn't realise it had to be |
Friendly ping. |
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.
We need a release note and please add a more detailed summary. A description of the problem being solved and the solution to the fix provides.
067a93a
to
ff9d909
Compare
Done. |
ff9d909
to
7ecf5d7
Compare
7ecf5d7
to
9eb93e9
Compare
Friendly ping. |
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 with a tiny nit.
9eb93e9
to
a0ad535
Compare
…er. (llvm#72428) Fix llvm#67495, llvm#72198 We build ill-formed AST nodes for invalid structured binding. For case `int [_, b] = {0, 0};`, the `DecompositionDecl` is valid, and its children `BindingDecl`s are valid but with a NULL type, this breaks clang invariants in many places, and using these `BindingDecl`s can lead to crashes. This patch fixes them by marking the DecompositionDecl and its children invalid.
Fix #67495, #72198
We build ill-formed AST nodes for invalid structured binding. For case
int [_, b] = {0, 0};
, theDecompositionDecl
is valid, and its childrenBindingDecl
s are valid but with a NULL type, this breaks clang invariants in many places, and using theseBindingDecl
s can lead to crashes. This patch fixes them by marking the DecompositionDecl and its children invalid.CC @ADKaster, @ecnelises