diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 19ab6d63947b78..636e5d99be5227 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -957,6 +957,16 @@ TEST(Hover, NoHover) { template void foo() { (void)[[size^of]](T); })cpp", + R"cpp(// should not crash on invalid semantic form of init-list-expr. + /*error-ok*/ + struct Foo { + int xyz = 0; + }; + class Bar {}; + constexpr Foo s = ^{ + .xyz = Bar(), + }; + )cpp", // literals "auto x = t^rue;", "auto x = '^A';", diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h index 14a7ffaecb2b04..ca96b65574bdd1 100644 --- a/clang/include/clang/AST/DependenceFlags.h +++ b/clang/include/clang/AST/DependenceFlags.h @@ -41,6 +41,7 @@ struct ExprDependenceScope { TypeInstantiation = Type | Instantiation, ValueInstantiation = Value | Instantiation, TypeValueInstantiation = Type | Value | Instantiation, + ErrorDependent = Error | ValueInstantiation, LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) }; diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index c13b9711928505..ea8f688452eba5 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4690,6 +4690,13 @@ class InitListExpr : public Expr { setDependence(getDependence() | expr->getDependence()); } + /// Mark the semantic form of the InitListExpr as error when the semantic + /// analysis fails. + void markError() { + assert(isSemanticForm()); + setDependence(getDependence() | ExprDependence::ErrorDependent); + } + /// Reserve space for some number of initializers. void reserveInits(const ASTContext &C, unsigned NumInits); diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 2333993dbeb40d..c3a2090266621b 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -502,7 +502,7 @@ ExprDependence clang::computeDependence(RecoveryExpr *E) { // dependent type), or the type is known and dependent, or it has // type-dependent subexpressions. auto D = toExprDependence(E->getType()->getDependence()) | - ExprDependence::ValueInstantiation | ExprDependence::Error; + ExprDependence::ErrorDependent; // FIXME: remove the type-dependent bit from subexpressions, if the // RecoveryExpr has a non-dependent type. for (auto *S : E->subExpressions()) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index eb07de65d26680..e2f67e9fd59bc7 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -962,6 +962,8 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass, nullptr, 0); } + if (hadError && FullyStructuredList) + FullyStructuredList->markError(); } int InitListChecker::numArrayElements(QualType DeclType) {