hintonda updated this revision to Diff 195610.
hintonda added a comment.
- Removed auto and added specific warnings.
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 extention}}
+int arr[3] = {[1] = 5}; // expected-warning {{C99 array designated initializers are a C++20 extention}}
+B b = {.a.x = 0}; // expected-warning {{C99 nested designated initializers are a C++20 extention}}
+A a2 = {.x = 1, 2}; // expected-warning {{C99 mixed designated initializers are a C++20 extention}}
+A a3 = {1, .y = 2}; // expected-warning {{C99 mixed designated initializers are a C++20 extention}}
+}
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 extention">, 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits