Author: Richard Smith Date: 2021-02-03T14:36:49-08:00 New Revision: b15cbaf5a03d0b32dbc32c37766e32ccf66e6c87
URL: https://github.com/llvm/llvm-project/commit/b15cbaf5a03d0b32dbc32c37766e32ccf66e6c87 DIFF: https://github.com/llvm/llvm-project/commit/b15cbaf5a03d0b32dbc32c37766e32ccf66e6c87.diff LOG: PR49020: Diagnose brace elision in designated initializers in C++. This is a corner of the differences between C99 designators and C++20 designators that we'd previously overlooked. As with other such cases, this continues to be permitted as an extension and allowed by default, behind the -Wc99-designators warning flag, except in cases where it leads to a conformance difference (such as in overload resolution and in a SFINAE context). Added: Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaInit.cpp clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d31cc76b04d1..61e8f7f28f1c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -214,6 +214,9 @@ def ext_designated_init_reordered : ExtWarn< SFINAEFailure; def note_previous_field_init : Note< "previous initialization for field %0 is here">; +def ext_designated_init_brace_elision : ExtWarn< + "brace elision for designated initializer is a C99 extension">, + InGroup<C99Designator>, SFINAEFailure; // Declarations. def ext_plain_complex : ExtWarn< diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 4e3547c5121f..640755cec222 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -315,7 +315,8 @@ class InitListChecker { InitListExpr *IList, QualType ElemType, unsigned &Index, InitListExpr *StructuredList, - unsigned &StructuredIndex); + unsigned &StructuredIndex, + bool DirectlyDesignated = false); void CheckComplexType(const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType, unsigned &Index, @@ -1326,7 +1327,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, QualType ElemType, unsigned &Index, InitListExpr *StructuredList, - unsigned &StructuredIndex) { + unsigned &StructuredIndex, + bool DirectlyDesignated) { Expr *expr = IList->getInit(Index); if (ElemType->isReferenceType()) @@ -1462,6 +1464,20 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); ++StructuredIndex; + + // In C++20, brace elision is not permitted for a designated initializer. + if (DirectlyDesignated && SemaRef.getLangOpts().CPlusPlus && !hadError) { + if (InOverloadResolution) + hadError = true; + if (!VerifyOnly) { + SemaRef.Diag(expr->getBeginLoc(), + diag::ext_designated_init_brace_elision) + << expr->getSourceRange() + << FixItHint::CreateInsertion(expr->getBeginLoc(), "{") + << FixItHint::CreateInsertion( + SemaRef.getLocForEndOfToken(expr->getEndLoc()), "}"); + } + } } else { if (!VerifyOnly) { // We cannot initialize this element, so let PerformCopyInitialization @@ -2413,8 +2429,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, unsigned OldIndex = Index; IList->setInit(OldIndex, DIE->getInit()); - CheckSubElementType(Entity, IList, CurrentObjectType, Index, - StructuredList, StructuredIndex); + CheckSubElementType(Entity, IList, CurrentObjectType, Index, StructuredList, + StructuredIndex, /*DirectlyDesignated=*/true); // Restore the designated initializer expression in the syntactic // form of the initializer list. diff --git a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp index 653fcf439c15..c6339116af8b 100644 --- a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp +++ b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp @@ -54,6 +54,10 @@ A a5 = { .y = 1, // override-note {{previous}} .y = 1 // override-error {{overrides prior initialization}} }; +B b2 = {.a = 1}; // pedantic-error {{brace elision for designated initializer is a C99 extension}} +B b3 = {.a = 1, 2}; // pedantic-error {{mixture of designated and non-designated}} pedantic-note {{first non-designated}} pedantic-error {{brace elision}} +B b4 = {.a = 1, 2, 3}; // pedantic-error {{mixture of designated and non-designated}} pedantic-note {{first non-designated}} pedantic-error {{brace elision}} expected-error {{excess elements}} +B b5 = {.a = nullptr}; // expected-error {{cannot initialize}} struct C { int :0, x, :0, y, :0; }; C c = { .x = 1, // override-note {{previous}} @@ -112,6 +116,15 @@ namespace overload_resolution { void k() { j({.x = 1, .y = 2}); // expected-error {{ambiguous}} } + + struct E { A a; }; + struct F { int a; }; + void l(E e); // expected-note {{candidate}} + int &l(F f); // expected-note {{candidate}} + void m() { + int &r = l({.a = 0}); // ok, l(E) is not viable + int &s = l({.a = {0}}); // expected-error {{ambiguous}} + } } namespace deduction { @@ -128,4 +141,18 @@ namespace deduction { void i() { h<A, C>(); // ok, selects C overload by SFINAE } + + struct D { int n; }; + struct E { D n; }; + template<typename T, typename U> void j1(decltype(T{.n = 0})); + template<typename T, typename U> void j1(decltype(U{.n = 0})) = delete; + template<typename T, typename U> void j2(decltype(T{.n = {0}})); // expected-note {{candidate}} + template<typename T, typename U> void j2(decltype(U{.n = {0}})); // expected-note {{candidate}} + template<typename T, typename U> void j3(decltype(T{.n = {{0}}})) = delete; + template<typename T, typename U> void j3(decltype(U{.n = {{0}}})); + void k() { + j1<D, E>({}); // ok, selects D overload by SFINAE (too few braces for E) + j2<D, E>({}); // expected-error {{ambiguous}} + j3<D, E>({}); // ok, selects E overload by SFINAE (too many braces for D) + } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits