]> granicus.if.org Git - clang/commitdiff
Diagnose when omitting braces in direct list-initialization in C++0x.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 16 Oct 2011 18:19:28 +0000 (18:19 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 16 Oct 2011 18:19:28 +0000 (18:19 +0000)
This also applies to C99-style aggregate literals, should they be used in C++11, since they are effectively identical to constructor call list-initialization syntax.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142147 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaInit.cpp
test/SemaCXX/cxx0x-initializer-aggregates.cpp [new file with mode: 0644]
test/SemaCXX/generalized-initializers.cpp

index 1fb8fb8b9750433a9a44e764981a92dbb02deac9..2662a19691023abc2fd364393e1281e4f312bb1d 100644 (file)
@@ -2798,6 +2798,9 @@ def warn_anon_bitfield_width_exceeds_type_size : Warning<
 def warn_missing_braces : Warning<
   "suggest braces around initialization of subobject">,
   InGroup<DiagGroup<"missing-braces">>, DefaultIgnore;
+def err_missing_braces : Error<
+  "cannot omit braces around initialization of subobject when using direct "
+  "list-initialization">;
 
 def err_redefinition_of_label : Error<"redefinition of label %0">;
 def err_undeclared_label_use : Error<"use of undeclared label %0">;
index cef4870638f9ca66de28577e6705351f13e3670b..c566b236e4fe26607874a56610c16d21bd470151 100644 (file)
@@ -170,6 +170,7 @@ class InitListChecker {
   Sema &SemaRef;
   bool hadError;
   bool VerifyOnly; // no diagnostics, no structure building
+  bool AllowBraceElision;
   std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
   InitListExpr *FullyStructuredList;
 
@@ -260,7 +261,8 @@ class InitListChecker {
 
 public:
   InitListChecker(Sema &S, const InitializedEntity &Entity,
-                  InitListExpr *IL, QualType &T, bool VerifyOnly);
+                  InitListExpr *IL, QualType &T, bool VerifyOnly,
+                  bool AllowBraceElision);
   bool HadError() { return hadError; }
 
   // @brief Retrieves the fully-structured initializer list used for
@@ -466,8 +468,8 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
 
 InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
                                  InitListExpr *IL, QualType &T,
-                                 bool VerifyOnly)
-  : SemaRef(S), VerifyOnly(VerifyOnly) {
+                                 bool VerifyOnly, bool AllowBraceElision)
+  : SemaRef(S), VerifyOnly(VerifyOnly), AllowBraceElision(AllowBraceElision) {
   hadError = false;
 
   unsigned newIndex = 0;
@@ -551,10 +553,14 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
                         /*SubobjectIsDesignatorContext=*/false, Index,
                         StructuredSubobjectInitList,
                         StructuredSubobjectInitIndex);
-  unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
-  if (!VerifyOnly) {
+
+  if (VerifyOnly) {
+    if (!AllowBraceElision && (T->isArrayType() || T->isRecordType()))
+      hadError = true;
+  } else {
     StructuredSubobjectInitList->setType(T);
 
+    unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
     // Update the structured sub-object initializer so that it's ending
     // range corresponds with the end of the last initializer it used.
     if (EndIndex < ParentIList->getNumInits()) {
@@ -563,10 +569,11 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
       StructuredSubobjectInitList->setRBraceLoc(EndLoc);
     }
 
-    // Warn about missing braces.
+    // Complain about missing braces.
     if (T->isArrayType() || T->isRecordType()) {
       SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
-                   diag::warn_missing_braces)
+                    AllowBraceElision ? diag::warn_missing_braces :
+                                        diag::err_missing_braces)
         << StructuredSubobjectInitList->getSourceRange()
         << FixItHint::CreateInsertion(
               StructuredSubobjectInitList->getLocStart(), "{")
@@ -574,6 +581,8 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
               SemaRef.PP.getLocForEndOfToken(
                                       StructuredSubobjectInitList->getLocEnd()),
               "}");
+      if (!AllowBraceElision)
+        hadError = true;
     }
   }
 }
@@ -2808,7 +2817,9 @@ static void TryListInitialization(Sema &S,
   }
 
   InitListChecker CheckInitList(S, Entity, InitList,
-          DestType, /*VerifyOnly=*/true);
+          DestType, /*VerifyOnly=*/true,
+          Kind.getKind() != InitializationKind::IK_Direct ||
+            !S.getLangOptions().CPlusPlus0x);
   if (CheckInitList.HadError()) {
     Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
     return;
@@ -4654,7 +4665,9 @@ InitializationSequence::Perform(Sema &S,
       InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
       QualType Ty = Step->Type;
       InitListChecker PerformInitList(S, Entity, InitList,
-          ResultType ? *ResultType : Ty, /*VerifyOnly=*/false);
+          ResultType ? *ResultType : Ty, /*VerifyOnly=*/false,
+          Kind.getKind() != InitializationKind::IK_Direct ||
+            !S.getLangOptions().CPlusPlus0x);
       if (PerformInitList.HadError())
         return ExprError();
 
@@ -5180,7 +5193,9 @@ bool InitializationSequence::Diagnose(Sema &S,
     InitListExpr* InitList = cast<InitListExpr>(Args[0]);
     QualType DestType = Entity.getType();
     InitListChecker DiagnoseInitList(S, Entity, InitList,
-            DestType, /*VerifyOnly=*/false);
+            DestType, /*VerifyOnly=*/false,
+            Kind.getKind() != InitializationKind::IK_Direct ||
+              !S.getLangOptions().CPlusPlus0x);
     assert(DiagnoseInitList.HadError() &&
            "Inconsistent init list check result.");
     break;
diff --git a/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/test/SemaCXX/cxx0x-initializer-aggregates.cpp
new file mode 100644 (file)
index 0000000..687d272
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+namespace aggregate {
+  // Direct list initialization does NOT allow braces to be elided!
+  struct S {
+    int ar[2];
+    struct T {
+      int i1;
+      int i2;
+    } t;
+    struct U {
+      int i1;
+    } u[2];
+    struct V {
+      int var[2];
+    } v;
+  };
+
+  void test() {
+    S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error
+    S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
+    S s3{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
+    S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
+    S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
+  }
+}
index a1891c9c322e39325aebf9b84d713ea3e8252692..9e11e267f1dd65a1426a816416a98fd5e48d475b 100644 (file)
@@ -40,16 +40,6 @@ namespace std {
 
 namespace integral {
 
-  int function_call() {
-    void takes_int(int);
-    takes_int({1});
-  }
-
-  void inline_init() {
-    (void) int{1};
-    (void) new int{1};
-  }
-
   void initializer_list() {
     std::initializer_list<int> il = { 1, 2, 3 };
     std::initializer_list<double> dl = { 1.0, 2.0, 3 };
@@ -180,28 +170,3 @@ namespace litb {
   B g({1, 2, 3});
 
 }
-
-namespace aggregate {
-  // Direct list initialization does NOT allow braces to be elided!
-  struct S {
-    int ar[2];
-    struct T {
-      int i1;
-      int i2;
-    } t;
-    struct U {
-      int i1;
-    } u[2];
-    struct V {
-      int var[2];
-    } v;
-  };
-
-  void test() {
-    S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error
-    S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
-    S s3{ 1, 2, 3, 4, 5, 6 }; // xpected-error
-    S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // xpected-error
-    S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // xpected-error
-  }
-}