Author: Haojian Wu Date: 2024-05-07T09:10:29+02:00 New Revision: fc866fd2a2cfca6d62f48dcf83778959fd24f559
URL: https://github.com/llvm/llvm-project/commit/fc866fd2a2cfca6d62f48dcf83778959fd24f559 DIFF: https://github.com/llvm/llvm-project/commit/fc866fd2a2cfca6d62f48dcf83778959fd24f559.diff LOG: [clang] Don't preserve the typo expr in the recovery expr for invalid VarDecls (#90948) With the commit d5308949cf884d8e4b971d51a8b4f73584c4adec, we now preserve the initializer for invalid decls with the recovery-expr. However there is a chance that the original init expr is a typo-expr, we should not preserve it in the final AST, as typo-expr is an internal AST node. We should use the one after the typo correction. This is spotted by a clangd hover crash on the testcase. Added: Modified: clang-tools-extra/clangd/unittests/HoverTests.cpp clang/lib/Sema/SemaDecl.cpp clang/test/AST/ast-dump-recovery.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 5ead74748f550c..28df24f34827c0 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -965,6 +965,19 @@ class Foo final {})cpp"; // Bindings are in theory public members of an anonymous struct. HI.AccessSpecifier = "public"; }}, + {// Don't crash on invalid decl with invalid init expr. + R"cpp( + Unknown [[^abc]] = invalid; + // error-ok + )cpp", + [](HoverInfo &HI) { + HI.Name = "abc"; + HI.Kind = index::SymbolKind::Variable; + HI.NamespaceScope = ""; + HI.Definition = "int abc = <recovery - expr>()"; + HI.Type = "int"; + HI.AccessSpecifier = "public"; + }}, {// Extra info for function call. R"cpp( void fun(int arg_a, int &arg_b) {}; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 19968452f0d566..590f37837eb2df 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13530,9 +13530,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } if (VDecl->isInvalidDecl()) { - CorrectDelayedTyposInExpr(Init, VDecl); + ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl); + SmallVector<Expr *> SubExprs; + if (Res.isUsable()) + SubExprs.push_back(Res.get()); ExprResult Recovery = - CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), {Init}); + CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), SubExprs); if (Expr *E = Recovery.get()) VDecl->setInit(E); return; diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp index 77527743fe8577..a88dff471d9f04 100644 --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -419,6 +419,11 @@ void InitializerOfInvalidDecl() { // CHECK: VarDecl {{.*}} invalid InvalidDecl // CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'ValidDecl' + + Unknown InvalidDeclWithInvalidInit = Invalid; + // CHECK: VarDecl {{.*}} invalid InvalidDeclWithInvalidInit + // CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors + // CHECK-NOT: `-TypoExpr } void RecoverToAnInvalidDecl() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits