-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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][Sema] Improve error recovery for id-expressions referencing invalid decls #81662
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang Author: Nathan Ridge (HighCommander4) ChangesPassing AcceptInvalidDecl=true to BuildDeclarationNameExpr() allows the RecoveryExpr that's constructed to retain a DeclRefExpr pointing to the invalid decl as a child, preserving information about the reference for use by tools such as clangd. Fixes clangd/clangd#1820 Full diff: https://github.com/llvm/llvm-project/pull/81662.diff 2 Files Affected:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 4049ab3bf6cafb..3030d388147b24 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2927,7 +2927,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs);
}
- return BuildDeclarationNameExpr(SS, R, ADL);
+ return BuildDeclarationNameExpr(SS, R, ADL, /*AcceptInvalidDecl=*/true);
}
/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp
index cfb013585ad744..f628fa913da1e6 100644
--- a/clang/test/AST/ast-dump-recovery.cpp
+++ b/clang/test/AST/ast-dump-recovery.cpp
@@ -402,6 +402,7 @@ void returnInitListFromVoid() {
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 8
}
+void FuncTakingUnknown(Unknown);
void RecoveryExprForInvalidDecls(Unknown InvalidDecl) {
InvalidDecl + 1;
// CHECK: BinaryOperator {{.*}}
@@ -411,6 +412,11 @@ void RecoveryExprForInvalidDecls(Unknown InvalidDecl) {
InvalidDecl();
// CHECK: CallExpr {{.*}}
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>'
+ FuncTakingUnknown(InvalidDecl);
+ // CHECK: CallExpr {{.*}} '<dependent type>'
+ // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} '<overloaded function type>'
+ // CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>'
+ // CHECK-NEXT: `-DeclRefExpr {{.*}} 'InvalidDecl' 'int'
}
void RecoverToAnInvalidDecl() {
|
Changing to Draft status as CI is showing some test failures that I will need to investigate:
|
The failures are related to new diagnostics that are issued as a side effect of running additional checks in BuildDeclarationNameExpr(). Accepting these additional diagnostics would regress some previous changes such as 1cf4541 and https://reviews.llvm.org/D95928. I think I'll need to find a way to avoid them instead. |
81f473e
to
120bade
Compare
A closer investigation has revealed that this diagnosis wasn't quite accurate. The three In my updated patch, I made an adjustment to this function to behave similarly to the other overload, i.e. wrap the resulting expression in a The |
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.
Minor nit, otherwise LGTM once you fix outstanding issues.
…nvalid decls Passing AcceptInvalidDecl=true to BuildDeclarationNameExpr() allows the RecoveryExpr that's constructed to retain a DeclRefExpr pointing to the invalid decl as a child, preserving information about the reference for use by tools such as clangd. Fixes clangd/clangd#1820
120bade
to
480cabc
Compare
(OpenMP failure still remains to be fixed.) |
Here is a reduced testcase for the OpenMP test failure: #pragma omp declare target
static long double ld_return1e() { return 0; }
void external() {
void *p1 = reinterpret_cast<void*>(&ld_return1e);
}
#pragma omp end declare target When built with the following command:
Here are the diagnostics before this patch: test.cpp:6:39: error: 'ld_return1e' requires 128 bit size 'long double' type support, but target 'nvptx64-unknown-unknown' does not support it
6 | void *p1 = reinterpret_cast<void*>(&ld_return1e);
| ^
test.cpp:3:20: note: 'ld_return1e' defined here
3 | static long double ld_return1e() { return 0; }
| ^
1 error generated and here are the diagnostics after this patch: test.cpp:6:39: error: 'ld_return1e' requires 128 bit size 'long double' type support, but target 'nvptx64-unknown-unknown' does not support it
6 | void *p1 = reinterpret_cast<void*>(&ld_return1e);
| ^
test.cpp:3:20: note: 'ld_return1e' defined here
3 | static long double ld_return1e() { return 0; }
| ^
test.cpp:3:20: error: 'ld_return1e' requires 128 bit size 'long double' type support, but target 'nvptx64-unknown-unknown' does not support it
3 | static long double ld_return1e() { return 0; }
| ^
test.cpp:6:39: note: called by 'external'
6 | void *p1 = reinterpret_cast<void*>(&ld_return1e);
| ^
test.cpp:3:20: note: 'ld_return1e' defined here
3 | static long double ld_return1e() { return 0; }
| ^
2 errors generated. Basically, the patch somehow causes the same diagnostic to be issued a second time at a different location. |
Passing AcceptInvalidDecl=true to BuildDeclarationNameExpr() allows the RecoveryExpr that's constructed to retain a DeclRefExpr pointing to the invalid decl as a child, preserving information about the reference for use by tools such as clangd.
Fixes clangd/clangd#1820