[clang] [clang][Sema] Preserve the initializer of invalid VarDecls (PR #88645)
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 23 23:21:48 PDT 2024
https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/88645
>From c24e79da57fc69d2f353a5533a3cc26313301a71 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Sun, 14 Apr 2024 02:41:48 -0400
Subject: [PATCH] [clang][Sema] Preserve the initializer of invalid VarDecls
Fixes https://github.com/clangd/clangd/issues/1821
---
clang/lib/Sema/JumpDiagnostics.cpp | 3 ++-
clang/lib/Sema/SemaDecl.cpp | 16 +++++++++++++---
clang/test/AST/ast-dump-recovery.cpp | 8 ++++++++
3 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp
index ec3892e92f3c3b..27d5284fdb67e7 100644
--- a/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/clang/lib/Sema/JumpDiagnostics.cpp
@@ -179,7 +179,8 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
}
const Expr *Init = VD->getInit();
- if (S.Context.getLangOpts().CPlusPlus && VD->hasLocalStorage() && Init) {
+ if (S.Context.getLangOpts().CPlusPlus && VD->hasLocalStorage() && Init &&
+ !Init->containsErrors()) {
// C++11 [stmt.dcl]p3:
// A program that jumps from a point where a variable with automatic
// storage duration is not in scope to a point where it is in scope
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9fdd8eb236d1ee..e6eaa98bda98e5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13435,15 +13435,16 @@ void Sema::checkNonTrivialCUnion(QualType QT, SourceLocation Loc,
void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
- if (!RealDecl || RealDecl->isInvalidDecl()) {
+ if (!RealDecl) {
CorrectDelayedTyposInExpr(Init, dyn_cast_or_null<VarDecl>(RealDecl));
return;
}
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
+ if (auto *Method = dyn_cast<CXXMethodDecl>(RealDecl);
+ Method && !Method->isInvalidDecl()) {
// Pure-specifiers are handled in ActOnPureSpecifier.
Diag(Method->getLocation(), diag::err_member_function_initialization)
- << Method->getDeclName() << Init->getSourceRange();
+ << Method->getDeclName() << Init->getSourceRange();
Method->setInvalidDecl();
return;
}
@@ -13456,6 +13457,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
return;
}
+ if (VDecl->isInvalidDecl()) {
+ CorrectDelayedTyposInExpr(Init, VDecl);
+ ExprResult Recovery =
+ CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), {Init});
+ if (Expr *E = Recovery.get())
+ VDecl->setInit(E);
+ return;
+ }
+
// WebAssembly tables can't be used to initialise a variable.
if (Init && !Init->getType().isNull() &&
Init->getType()->isWebAssemblyTableType()) {
diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp
index cfb013585ad744..77527743fe8577 100644
--- a/clang/test/AST/ast-dump-recovery.cpp
+++ b/clang/test/AST/ast-dump-recovery.cpp
@@ -413,6 +413,14 @@ void RecoveryExprForInvalidDecls(Unknown InvalidDecl) {
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>'
}
+void InitializerOfInvalidDecl() {
+ int ValidDecl;
+ Unkown InvalidDecl = ValidDecl;
+ // CHECK: VarDecl {{.*}} invalid InvalidDecl
+ // CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors
+ // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'ValidDecl'
+}
+
void RecoverToAnInvalidDecl() {
Unknown* foo; // invalid decl
goo; // the typo was correct to the invalid foo.
More information about the cfe-commits
mailing list