llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Haojian Wu (hokein) <details> <summary>Changes</summary> 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 nodes. We should use the one after the typo correction. This is spotted by a clangd hover crash on the testcase. --- Full diff: https://github.com/llvm/llvm-project/pull/90948.diff 3 Files Affected: - (modified) clang-tools-extra/clangd/unittests/HoverTests.cpp (+13) - (modified) clang/lib/Sema/SemaDecl.cpp (+5-2) - (modified) clang/test/AST/ast-dump-recovery.cpp (+5) ``````````diff 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..169df60b56bb4b 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); + std::vector<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() { `````````` </details> https://github.com/llvm/llvm-project/pull/90948 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits