hintonda created this revision.
hintonda added reviewers: rsmith, xbolva00.
Herald added a project: clang.

Basic designator initializers are allowed in c++2a, so only
issue warnings for the extended ones that aren't allowed:

  - out of order
- nested
- arrays
- mixed


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D59754

Files:
  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,20 @@
   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; };
+
+// out of order designators
+A a1 = {.y = 1, .x = 2}; // expected-warning {{designated initializers are a C99 feature}}
+
+// array designator
+int arr[3] = {[1] = 5}; // expected-warning {{designated initializers are a C99 feature}}
+
+// nested designator
+B b = {.a.x = 0}; // expected-warning {{designated initializers are a C99 feature}}
+
+// mixed designator and non-designator
+A a2 = {.x = 1, 2}; // expected-warning {{designated initializers are a C99 feature}}
+}
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 HasNonDesginatedInit = false;
 
   while (Index < IList->getNumInits()) {
     Expr *Init = IList->getInit(Index);
@@ -2013,6 +2014,10 @@
 
       HasDesignatedInit = true;
 
+      auto 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,15 @@
         }
       }
 
+      // Warn on out of order and mixed designators in C++20.
+      auto NextIdx = Field != FieldEnd
+                         ? Field->getFieldIndex()
+                         : std::distance(RD->field_begin(), RD->field_end());
+      if (VerifyOnly && (LastIdx >= NextIdx || HasNonDesginatedInit) &&
+          SemaRef.getLangOpts().CPlusPlus2a)
+        SemaRef.Diag(Init->getBeginLoc(), diag::ext_designated_init)
+            << Init->getSourceRange();
+
       InitializedSomething = true;
 
       // Disable check for missing fields when designators are used.
@@ -2045,6 +2059,11 @@
       break;
     }
 
+    // Warn on mixed designators in C++20
+    if (VerifyOnly && HasDesignatedInit && SemaRef.getLangOpts().CPlusPlus2a)
+      SemaRef.Diag(Init->getBeginLoc(), diag::ext_designated_init)
+          << Init->getSourceRange();
+
     // We've already initialized a member of a union. We're done.
     if (InitializedSomething && DeclType->isUnionType())
       break;
@@ -2976,6 +2995,7 @@
   bool Invalid = false;
   SmallVector<ASTDesignator, 32> Designators;
   SmallVector<Expr *, 32> InitExpressions;
+  bool HaveArrayDesignator = false;
 
   // Build designators and check array designator expressions.
   for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
@@ -2999,6 +3019,7 @@
                                             D.getRBracketLoc()));
         InitExpressions.push_back(Index);
       }
+      HaveArrayDesignator = true;
       break;
     }
 
@@ -3042,6 +3063,7 @@
           InitExpressions.push_back(EndIndex);
         }
       }
+      HaveArrayDesignator = true;
       break;
     }
     }
@@ -3060,8 +3082,11 @@
                                  Init.getAs<Expr>());
 
   if (!getLangOpts().C99)
-    Diag(DIE->getBeginLoc(), diag::ext_designated_init)
-        << DIE->getSourceRange();
+    // Warn on nested and array designators in C++20
+    if (!getLangOpts().CPlusPlus2a || Desig.getNumDesignators() > 1 ||
+        HaveArrayDesignator)
+      Diag(DIE->getBeginLoc(), diag::ext_designated_init)
+          << DIE->getSourceRange();
 
   return DIE;
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to