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 = ()"; + 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 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 {{.*}} '' contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'ValidDecl' + + Unknown InvalidDeclWithInvalidInit = Invalid; + // CHECK: VarDecl {{.*}} invalid InvalidDeclWithInvalidInit + // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors + // CHECK-NOT: `-TypoExpr } void RecoverToAnInvalidDecl() {