[clang] Set the error-bit for ill-formed semantic InitListExpr.
authorHaojian Wu <hokein.wu@gmail.com>
Tue, 21 Jul 2020 07:39:44 +0000 (09:39 +0200)
committerHaojian Wu <hokein.wu@gmail.com>
Tue, 21 Jul 2020 07:39:44 +0000 (09:39 +0200)
When a semantic checking fails on a syntactic InitListExpr, we will
get an ill-formed semantic InitListExpr (e.g. some inits are nullptr),
using this semantic InitListExpr in clang (without setting the err-bits) is crashy.

Differential Revision: https://reviews.llvm.org/D84140

clang-tools-extra/clangd/unittests/HoverTests.cpp
clang/include/clang/AST/DependenceFlags.h
clang/include/clang/AST/Expr.h
clang/lib/AST/ComputeDependence.cpp
clang/lib/Sema/SemaInit.cpp

index 19ab6d6..636e5d9 100644 (file)
@@ -957,6 +957,16 @@ TEST(Hover, NoHover) {
           template <typename T> 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';",
index 14a7ffa..ca96b65 100644 (file)
@@ -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)
   };
index c13b971..ea8f688 100644 (file)
@@ -4690,6 +4690,13 @@ public:
       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);
 
index 2333993..c3a2090 100644 (file)
@@ -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())
index eb07de6..e2f67e9 100644 (file)
@@ -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) {