hintonda updated this revision to Diff 195611.
hintonda added a comment.

- Fix typo.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59754/new/

https://reviews.llvm.org/D59754

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaInit.cpp
  clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp

Index: clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
===================================================================
--- clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
+++ clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++2a %s -verify
+// RUN: %clang_cc1 -std=c++2a %s -verify -pedantic
 
 namespace class_with_ctor {
   struct A { // expected-note 6{{candidate}}
@@ -21,3 +21,14 @@
   C c1 = {{}, {}}; // ok, call default ctor twice
   C c2 = {{1, 2}, {3, 4}}; // expected-error 2{{no matching constructor}}
 }
+
+namespace designator {
+struct A { int x, y; };
+struct B { A a; };
+
+A a1 = {.y = 1, .x = 2}; // expected-warning {{C99 out of order designated initializers are a C++20 extension}}
+int arr[3] = {[1] = 5}; // expected-warning {{C99 array designated initializers are a C++20 extension}}
+B b = {.a.x = 0}; // expected-warning {{C99 nested designated initializers are a C++20 extension}}
+A a2 = {.x = 1, 2}; // expected-warning {{C99 mixed designated initializers are a C++20 extension}}
+A a3 = {1, .y = 2}; // expected-warning {{C99 mixed designated initializers are a C++20 extension}}
+}
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -1999,6 +1999,7 @@
   bool CheckForMissingFields =
     !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
+  bool HasNonDesignatedInit = false;
 
   while (Index < IList->getNumInits()) {
     Expr *Init = IList->getInit(Index);
@@ -2013,6 +2014,10 @@
 
       HasDesignatedInit = true;
 
+      unsigned LastIdx =
+          Field != FieldEnd ? Field->getFieldIndex()
+                            : std::distance(RD->field_begin(), RD->field_end());
+
       // Handle this designated initializer. Field will be updated to
       // the next field that we'll be initializing.
       if (CheckDesignatedInitializer(Entity, IList, DIE, 0,
@@ -2032,6 +2037,20 @@
         }
       }
 
+      unsigned NextIdx =
+          Field != FieldEnd ? Field->getFieldIndex()
+                            : std::distance(RD->field_begin(), RD->field_end());
+      if (!VerifyOnly && SemaRef.getLangOpts().CPlusPlus2a) {
+        if (LastIdx >= NextIdx) {
+          SemaRef.Diag(Init->getBeginLoc(), diag::ext_c20_designated_init)
+              << "out of order" << Init->getSourceRange();
+        }
+        if (HasNonDesignatedInit) {
+          SemaRef.Diag(Init->getBeginLoc(), diag::ext_c20_designated_init)
+              << "mixed" << Init->getSourceRange();
+        }
+      }
+
       InitializedSomething = true;
 
       // Disable check for missing fields when designators are used.
@@ -2045,6 +2064,13 @@
       break;
     }
 
+    HasNonDesignatedInit = true;
+
+    if (!VerifyOnly && HasDesignatedInit && SemaRef.getLangOpts().CPlusPlus2a) {
+      SemaRef.Diag(Init->getBeginLoc(), diag::ext_c20_designated_init)
+          << "mixed" << Init->getSourceRange();
+    }
+
     // We've already initialized a member of a union. We're done.
     if (InitializedSomething && DeclType->isUnionType())
       break;
@@ -2980,6 +3006,7 @@
   bool Invalid = false;
   SmallVector<ASTDesignator, 32> Designators;
   SmallVector<Expr *, 32> InitExpressions;
+  bool HasArrayDesignator = false;
 
   // Build designators and check array designator expressions.
   for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
@@ -3003,6 +3030,7 @@
                                             D.getRBracketLoc()));
         InitExpressions.push_back(Index);
       }
+      HasArrayDesignator = true;
       break;
     }
 
@@ -3046,6 +3074,7 @@
           InitExpressions.push_back(EndIndex);
         }
       }
+      HasArrayDesignator = true;
       break;
     }
     }
@@ -3063,9 +3092,19 @@
                                  InitExpressions, Loc, GNUSyntax,
                                  Init.getAs<Expr>());
 
-  if (!getLangOpts().C99)
+  if (!getLangOpts().C99 && !getLangOpts().CPlusPlus2a) {
     Diag(DIE->getBeginLoc(), diag::ext_designated_init)
         << DIE->getSourceRange();
+  } else if (getLangOpts().CPlusPlus2a) {
+    if (Desig.getNumDesignators() > 1) {
+      Diag(DIE->getBeginLoc(), diag::ext_c20_designated_init)
+          << "nested" << DIE->getSourceRange();
+    }
+    if (HasArrayDesignator) {
+      Diag(DIE->getBeginLoc(), diag::ext_c20_designated_init)
+          << "array" << DIE->getSourceRange();
+    }
+  }
 
   return DIE;
 }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -154,6 +154,8 @@
   "'new' cannot allocate object of variably modified type %0">;
 
 // C99 Designated Initializers
+def ext_c20_designated_init : Extension<
+  "C99 %0 designated initializers are a C++20 extension">, InGroup<C99>;
 def ext_designated_init : Extension<
   "designated initializers are a C99 feature">, InGroup<C99>;
 def err_array_designator_negative : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to