[clang] 57acbae - Improve diagnostic when constant-evaluating a std::initializer_list with

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 15 13:28:33 PDT 2020


Author: Richard Smith
Date: 2020-04-15T13:28:24-07:00
New Revision: 57acbaece1ace979e6a9382d9d517d48895b9ef7

URL: https://github.com/llvm/llvm-project/commit/57acbaece1ace979e6a9382d9d517d48895b9ef7
DIFF: https://github.com/llvm/llvm-project/commit/57acbaece1ace979e6a9382d9d517d48895b9ef7.diff

LOG: Improve diagnostic when constant-evaluating a std::initializer_list with
an unexpected form.

Added: 
    

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 2eabf59acb94..5b3866d0a471 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9338,24 +9338,30 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
   // Get a pointer to the first element of the array.
   Array.addArray(Info, E, ArrayType);
 
+  auto InvalidType = [&] {
+    Info.FFDiag(E, diag::note_constexpr_unsupported_layout)
+      << E->getType();
+    return false;
+  };
+
   // FIXME: Perform the checks on the field types in SemaInit.
   RecordDecl *Record = E->getType()->castAs<RecordType>()->getDecl();
   RecordDecl::field_iterator Field = Record->field_begin();
   if (Field == Record->field_end())
-    return Error(E);
+    return InvalidType();
 
   // Start pointer.
   if (!Field->getType()->isPointerType() ||
       !Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
                             ArrayType->getElementType()))
-    return Error(E);
+    return InvalidType();
 
   // FIXME: What if the initializer_list type has base classes, etc?
   Result = APValue(APValue::UninitStruct(), 0, 2);
   Array.moveInto(Result.getStructField(0));
 
   if (++Field == Record->field_end())
-    return Error(E);
+    return InvalidType();
 
   if (Field->getType()->isPointerType() &&
       Info.Ctx.hasSameType(Field->getType()->getPointeeType(),
@@ -9370,10 +9376,10 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
     // Length.
     Result.getStructField(1) = APValue(APSInt(ArrayType->getSize()));
   else
-    return Error(E);
+    return InvalidType();
 
   if (++Field != Record->field_end())
-    return Error(E);
+    return InvalidType();
 
   return true;
 }

diff  --git a/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
index b5d6bd68f1fb..9380330b41f3 100644
--- a/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -365,3 +365,14 @@ namespace designated_init {
   static_assert(c.size() == 5, "");
   static_assert(d.size() == 1, "");
 }
+
+namespace weird_initlist {
+  struct weird {};
+}
+template<> struct std::initializer_list<weird_initlist::weird> { int a, b, c; };
+namespace weird_initlist {
+  // We don't check the struct layout in Sema.
+  auto x = {weird{}, weird{}, weird{}, weird{}, weird{}};
+  // ... but we do in constant evaluation.
+  constexpr auto y = {weird{}, weird{}, weird{}, weird{}, weird{}}; // expected-error {{constant}} expected-note {{type 'const std::initializer_list<weird_initlist::weird>' has unexpected layout}}
+}


        


More information about the cfe-commits mailing list