Author: Nathan Ridge Date: 2024-04-24T20:31:18-04:00 New Revision: d5308949cf884d8e4b971d51a8b4f73584c4adec
URL: https://github.com/llvm/llvm-project/commit/d5308949cf884d8e4b971d51a8b4f73584c4adec DIFF: https://github.com/llvm/llvm-project/commit/d5308949cf884d8e4b971d51a8b4f73584c4adec.diff LOG: [clang][Sema] Preserve the initializer of invalid VarDecls (#88645) Fixes https://github.com/clangd/clangd/issues/1821 Added: Modified: clang/lib/Sema/JumpDiagnostics.cpp clang/lib/Sema/SemaDecl.cpp clang/test/AST/ast-dump-recovery.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp index ce6211c23218bb..8af36d5c24e3d2 100644 --- a/clang/lib/Sema/JumpDiagnostics.cpp +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -180,7 +180,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 378615497b13cf..e0745fe9a45367 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13502,16 +13502,18 @@ 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)) { - // Pure-specifiers are handled in ActOnPureSpecifier. - Diag(Method->getLocation(), diag::err_member_function_initialization) - << Method->getDeclName() << Init->getSourceRange(); - Method->setInvalidDecl(); + if (auto *Method = dyn_cast<CXXMethodDecl>(RealDecl)) { + if (!Method->isInvalidDecl()) { + // Pure-specifiers are handled in ActOnPureSpecifier. + Diag(Method->getLocation(), diag::err_member_function_initialization) + << Method->getDeclName() << Init->getSourceRange(); + Method->setInvalidDecl(); + } return; } @@ -13523,6 +13525,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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits