[clang] 69ab8b4 - [Sema][SVE] Fix handling of initialisers for built-in SVE types

Richard Sandiford via cfe-commits cfe-commits at lists.llvm.org
Wed May 6 04:31:12 PDT 2020


Author: Richard Sandiford
Date: 2020-05-06T12:24:27+01:00
New Revision: 69ab8b46b84daa42f334ea2dc7a097f7b81bae77

URL: https://github.com/llvm/llvm-project/commit/69ab8b46b84daa42f334ea2dc7a097f7b81bae77
DIFF: https://github.com/llvm/llvm-project/commit/69ab8b46b84daa42f334ea2dc7a097f7b81bae77.diff

LOG: [Sema][SVE] Fix handling of initialisers for built-in SVE types

The built-in SVE types are supposed to be treated as opaque types.
This means that for initialisation purposes they should be treated
as a single unit, much like a scalar type.

However, as Eli pointed out, actually using "scalar" in the diagnostics
is likely to cause confusion, given the types are logically vectors.
The patch therefore uses custom diagnostics or generalises existing
ones.  Some of the messages use the word "indivisible" to try to make
it clear(er) that these types can't be initialised elementwise.

I don't think it's possible to trigger warn_braces_around_(scalar_)init
for sizeless types as things stand, since the types can't be used as
members or elements of more complex types.  But it seemed better to be
consistent with ext_many_braces_around_(scalar_)init, so the patch
changes it anyway.

Differential Revision: https://reviews.llvm.org/D76689

Added: 
    

Modified: 
    clang/docs/DiagnosticsReference.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaInit.cpp
    clang/test/Sema/sizeless-1.c
    clang/test/SemaCXX/sizeless-1.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/DiagnosticsReference.rst b/clang/docs/DiagnosticsReference.rst
index 38618f453027..402ec9d4eba6 100644
--- a/clang/docs/DiagnosticsReference.rst
+++ b/clang/docs/DiagnosticsReference.rst
@@ -1032,9 +1032,13 @@ This diagnostic is enabled by default.
 
 **Diagnostic text:**
 
-+-----------------------------------------------------------------------+
-|:warning:`warning:` |nbsp| :diagtext:`braces around scalar initializer`|
-+-----------------------------------------------------------------------+
++------------------------------------------------------------+----------------------------+-----------------------+
+|:warning:`warning:` |nbsp| :diagtext:`braces around` |nbsp| |+--------------------------+|:diagtext:`initializer`|
+|                                                            ||:diagtext:`scalar` |nbsp| ||                       |
+|                                                            |+--------------------------+|                       |
+|                                                            ||                          ||                       |
+|                                                            |+--------------------------+|                       |
++------------------------------------------------------------+----------------------------+-----------------------+
 
 
 -Wbridge-cast
@@ -2151,6 +2155,10 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_
 |:warning:`warning:` |nbsp| :diagtext:`scalar initialized from empty initializer list is incompatible with C++98`|
 +----------------------------------------------------------------------------------------------------------------+
 
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initializing` |nbsp| :placeholder:`A` |nbsp| :diagtext:`from an empty initializer list is incompatible with C++98`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
 +-----------------------------------------------------------------------------------------------------------------+
 |:warning:`warning:` |nbsp| :diagtext:`enumeration types with a fixed underlying type are incompatible with C++98`|
 +-----------------------------------------------------------------------------------------------------------------+
@@ -4501,6 +4509,10 @@ This diagnostic is enabled by default.
 |                                                                 |+------------------+|                               |
 +-----------------------------------------------------------------+--------------------+-------------------------------+
 
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`excess elements in initializer for indivisible sizeless type` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------------------------------------------------+
+
 +--------------------------------------------------------------------------------+
 |:warning:`warning:` |nbsp| :diagtext:`excess elements in char array initializer`|
 +--------------------------------------------------------------------------------+
@@ -7429,9 +7441,13 @@ This diagnostic is enabled by default.
 
 **Diagnostic text:**
 
-+--------------------------------------------------------------------------------+
-|:warning:`warning:` |nbsp| :diagtext:`too many braces around scalar initializer`|
-+--------------------------------------------------------------------------------+
++---------------------------------------------------------------------+----------------------------+-----------------------+
+|:warning:`warning:` |nbsp| :diagtext:`too many braces around` |nbsp| |+--------------------------+|:diagtext:`initializer`|
+|                                                                     ||:diagtext:`scalar` |nbsp| ||                       |
+|                                                                     |+--------------------------+|                       |
+|                                                                     ||                          ||                       |
+|                                                                     |+--------------------------+|                       |
++---------------------------------------------------------------------+----------------------------+-----------------------+
 
 
 -Wmax-tokens

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7624fd7107c8..b3f6f66a8c56 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -171,8 +171,9 @@ def err_field_designator_unknown : Error<
 def err_field_designator_nonfield : Error<
   "field designator %0 does not refer to a non-static data member">;
 def note_field_designator_found : Note<"field designator refers here">;
-def err_designator_for_scalar_init : Error<
-  "designator in initializer for scalar type %0">;
+def err_designator_for_scalar_or_sizeless_init : Error<
+  "designator in initializer for %select{scalar|indivisible sizeless}0 "
+  "type %1">;
 def warn_initializer_overrides : Warning<
   "initializer %select{partially |}0overrides prior initialization of "
   "this subobject">, InGroup<InitializerOverrides>;
@@ -5398,6 +5399,11 @@ def err_excess_initializers : Error<
 def ext_excess_initializers : ExtWarn<
   "excess elements in %select{array|vector|scalar|union|struct}0 initializer">,
   InGroup<ExcessInitializers>;
+def err_excess_initializers_for_sizeless_type : Error<
+  "excess elements in initializer for indivisible sizeless type %0">;
+def ext_excess_initializers_for_sizeless_type : ExtWarn<
+  "excess elements in initializer for indivisible sizeless type %0">,
+  InGroup<ExcessInitializers>;
 def err_excess_initializers_in_char_array_initializer : Error<
   "excess elements in char array initializer">;
 def ext_excess_initializers_in_char_array_initializer : ExtWarn<
@@ -5411,18 +5417,24 @@ def ext_initializer_string_for_char_array_too_long : ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup<MissingFieldInitializers>, DefaultIgnore;
-def warn_braces_around_scalar_init : Warning<
-  "braces around scalar initializer">, InGroup<DiagGroup<"braced-scalar-init">>;
-def ext_many_braces_around_scalar_init : ExtWarn<
-  "too many braces around scalar initializer">,
+def warn_braces_around_init : Warning<
+  "braces around %select{scalar |}0initializer">,
+  InGroup<DiagGroup<"braced-scalar-init">>;
+def ext_many_braces_around_init : ExtWarn<
+  "too many braces around %select{scalar |}0initializer">,
   InGroup<DiagGroup<"many-braces-around-scalar-init">>, SFINAEFailure;
 def ext_complex_component_init : Extension<
   "complex initialization specifying real and imaginary components "
   "is an extension">, InGroup<DiagGroup<"complex-component-init">>;
 def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
+def err_empty_sizeless_initializer : Error<
+  "initializer for sizeless type %0 cannot be empty">;
 def warn_cxx98_compat_empty_scalar_initializer : Warning<
   "scalar initialized from empty initializer list is incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_empty_sizeless_initializer : Warning<
+  "initializing %0 from an empty initializer list is incompatible with C++98">,
+  InGroup<CXX98Compat>, DefaultIgnore;
 def warn_cxx98_compat_reference_list_init : Warning<
   "reference initialized from initializer list is incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 9c6c9f103af2..e64b6d64f632 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -1119,14 +1119,14 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
   case InitializedEntity::EK_Parameter_CF_Audited:
   case InitializedEntity::EK_Result:
     // Extra braces here are suspicious.
-    DiagID = diag::warn_braces_around_scalar_init;
+    DiagID = diag::warn_braces_around_init;
     break;
 
   case InitializedEntity::EK_Member:
     // Warn on aggregate initialization but not on ctor init list or
     // default member initializer.
     if (Entity.getParent())
-      DiagID = diag::warn_braces_around_scalar_init;
+      DiagID = diag::warn_braces_around_init;
     break;
 
   case InitializedEntity::EK_Variable:
@@ -1157,9 +1157,9 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
 
   if (DiagID) {
     S.Diag(Braces.getBegin(), DiagID)
-      << Braces
-      << FixItHint::CreateRemoval(Braces.getBegin())
-      << FixItHint::CreateRemoval(Braces.getEnd());
+        << Entity.getType()->isSizelessBuiltinType() << Braces
+        << FixItHint::CreateRemoval(Braces.getBegin())
+        << FixItHint::CreateRemoval(Braces.getEnd());
   }
 }
 
@@ -1203,6 +1203,12 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
               : diag::ext_excess_initializers_in_char_array_initializer;
       SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
           << IList->getInit(Index)->getSourceRange();
+    } else if (T->isSizelessBuiltinType()) {
+      unsigned DK = ExtraInitsIsError
+                        ? diag::err_excess_initializers_for_sizeless_type
+                        : diag::ext_excess_initializers_for_sizeless_type;
+      SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK)
+          << T << IList->getInit(Index)->getSourceRange();
     } else {
       int initKind = T->isArrayType() ? 0 :
                      T->isVectorType() ? 1 :
@@ -1295,7 +1301,8 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
     if (!VerifyOnly)
       SemaRef.Diag(IList->getBeginLoc(), diag::err_init_objc_class) << DeclType;
     hadError = true;
-  } else if (DeclType->isOCLIntelSubgroupAVCType()) {
+  } else if (DeclType->isOCLIntelSubgroupAVCType() ||
+             DeclType->isSizelessBuiltinType()) {
     // Checks for scalar type are sufficient for these types too.
     CheckScalarType(Entity, IList, DeclType, Index, StructuredList,
                     StructuredIndex);
@@ -1508,12 +1515,20 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
                                       InitListExpr *StructuredList,
                                       unsigned &StructuredIndex) {
   if (Index >= IList->getNumInits()) {
-    if (!VerifyOnly)
-      SemaRef.Diag(IList->getBeginLoc(),
-                   SemaRef.getLangOpts().CPlusPlus11
-                       ? diag::warn_cxx98_compat_empty_scalar_initializer
-                       : diag::err_empty_scalar_initializer)
-          << IList->getSourceRange();
+    if (!VerifyOnly) {
+      if (DeclType->isSizelessBuiltinType())
+        SemaRef.Diag(IList->getBeginLoc(),
+                     SemaRef.getLangOpts().CPlusPlus11
+                         ? diag::warn_cxx98_compat_empty_sizeless_initializer
+                         : diag::err_empty_sizeless_initializer)
+            << DeclType << IList->getSourceRange();
+      else
+        SemaRef.Diag(IList->getBeginLoc(),
+                     SemaRef.getLangOpts().CPlusPlus11
+                         ? diag::warn_cxx98_compat_empty_scalar_initializer
+                         : diag::err_empty_scalar_initializer)
+            << IList->getSourceRange();
+    }
     hadError = !SemaRef.getLangOpts().CPlusPlus11;
     ++Index;
     ++StructuredIndex;
@@ -1525,17 +1540,18 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
     // FIXME: This is invalid, and accepting it causes overload resolution
     // to pick the wrong overload in some corner cases.
     if (!VerifyOnly)
-      SemaRef.Diag(SubIList->getBeginLoc(),
-                   diag::ext_many_braces_around_scalar_init)
-          << SubIList->getSourceRange();
+      SemaRef.Diag(SubIList->getBeginLoc(), diag::ext_many_braces_around_init)
+          << DeclType->isSizelessBuiltinType() << SubIList->getSourceRange();
 
     CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
                     StructuredIndex);
     return;
   } else if (isa<DesignatedInitExpr>(expr)) {
     if (!VerifyOnly)
-      SemaRef.Diag(expr->getBeginLoc(), diag::err_designator_for_scalar_init)
-          << DeclType << expr->getSourceRange();
+      SemaRef.Diag(expr->getBeginLoc(),
+                   diag::err_designator_for_scalar_or_sizeless_init)
+          << DeclType->isSizelessBuiltinType() << DeclType
+          << expr->getSourceRange();
     hadError = true;
     ++Index;
     ++StructuredIndex;

diff  --git a/clang/test/Sema/sizeless-1.c b/clang/test/Sema/sizeless-1.c
index 8fe8e7b30cf6..dd6492c44b62 100644
--- a/clang/test/Sema/sizeless-1.c
+++ b/clang/test/Sema/sizeless-1.c
@@ -83,6 +83,14 @@ void func(int sel) {
   svint8_t bad_init_int8 = for; // expected-error {{expected expression}}
 
   int empty_brace_init_int = {}; // expected-error {{scalar initializer cannot be empty}}
+  svint8_t empty_brace_init_int8 = {}; // expected-error {{initializer for sizeless type 'svint8_t' (aka '__SVInt8_t') cannot be empty}}
+  svint8_t brace_init_int8 = {local_int8};
+  svint8_t bad_brace_init_int8_1 = {local_int8, 0};    // expected-warning {{excess elements in initializer for indivisible sizeless type 'svint8_t'}}
+  svint8_t bad_brace_init_int8_2 = {0};                // expected-error {{incompatible type 'int'}}
+  svint8_t bad_brace_init_int8_3 = {local_int16};      // expected-error {{incompatible type 'svint16_t'}}
+  svint8_t bad_brace_init_int8_4 = {[0] = local_int8}; // expected-error {{designator in initializer for indivisible sizeless type 'svint8_t'}}
+  svint8_t bad_brace_init_int8_5 = {{local_int8}};     // expected-warning {{too many braces around initializer}}
+  svint8_t bad_brace_init_int8_6 = {{local_int8, 0}};  // expected-warning {{too many braces around initializer}}
 
   const svint8_t const_int8 = local_int8; // expected-note {{declared const here}}
   const svint8_t uninit_const_int8;

diff  --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp
index a7c02343cb48..46a183f7ad0c 100644
--- a/clang/test/SemaCXX/sizeless-1.cpp
+++ b/clang/test/SemaCXX/sizeless-1.cpp
@@ -94,9 +94,18 @@ void func(int sel) {
 
 #if __cplusplus >= 201103L
   int empty_brace_init_int = {};
+  svint8_t empty_brace_init_int8 = {};
 #else
   int empty_brace_init_int = {}; // expected-error {{scalar initializer cannot be empty}}
+  svint8_t empty_brace_init_int8 = {}; // expected-error {{initializer for sizeless type 'svint8_t' (aka '__SVInt8_t') cannot be empty}}
 #endif
+  svint8_t brace_init_int8 = {local_int8};
+  svint8_t bad_brace_init_int8_1 = {local_int8, 0};    // expected-error {{excess elements in initializer for indivisible sizeless type 'svint8_t'}}
+  svint8_t bad_brace_init_int8_2 = {0};                // expected-error {{rvalue of type 'int'}}
+  svint8_t bad_brace_init_int8_3 = {local_int16};      // expected-error {{lvalue of type 'svint16_t'}}
+  svint8_t bad_brace_init_int8_4 = {[0] = local_int8}; // expected-error {{designator in initializer for indivisible sizeless type 'svint8_t'}} expected-warning {{array designators are a C99 extension}}
+  svint8_t bad_brace_init_int8_5 = {{local_int8}};     // expected-warning {{too many braces around initializer}}
+  svint8_t bad_brace_init_int8_6 = {{local_int8, 0}};  // expected-warning {{too many braces around initializer}}
 
   const svint8_t const_int8 = local_int8; // expected-note {{declared const here}}
   const svint8_t uninit_const_int8;       // expected-error {{default initialization of an object of const type 'const svint8_t'}}
@@ -455,6 +464,14 @@ void cxx_only(int sel) {
   local_int8 = ref_int8;
 
 #if __cplusplus >= 201103L
+  svint8_t zero_init_int8{};
+  svint8_t init_int8{local_int8};
+  svint8_t bad_brace_init_int8_1{local_int8, 0};    // expected-error {{excess elements in initializer for indivisible sizeless type 'svint8_t'}}
+  svint8_t bad_brace_init_int8_2{0};                // expected-error {{rvalue of type 'int'}}
+  svint8_t bad_brace_init_int8_3{local_int16};      // expected-error {{lvalue of type 'svint16_t'}}
+  svint8_t bad_brace_init_int8_4{[0] = local_int8}; // expected-error {{designator in initializer for indivisible sizeless type 'svint8_t'}} expected-warning {{array designators are a C99 extension}}
+  svint8_t bad_brace_init_int8_5{{local_int8}};     // expected-warning {{too many braces around initializer}}
+  svint8_t bad_brace_init_int8_6{{local_int8, 0}};  // expected-warning {{too many braces around initializer}}
   svint8_t wrapper_init_int8{wrapper<svint8_t>()};
   svint8_t &ref_init_int8{local_int8};
 
@@ -601,4 +618,9 @@ void cxx_only(int sel) {
 
 #if __cplusplus >= 201103L
 svint8_t ret_bad_conv() { return explicit_conv(); } // expected-error {{no viable conversion from returned value of type 'explicit_conv' to function return type 'svint8_t'}}
+
+#pragma clang diagnostic warning "-Wc++98-compat"
+
+void incompat_init() { __attribute__((unused)) svint8_t foo = {}; } // expected-warning {{initializing 'svint8_t' (aka '__SVInt8_t') from an empty initializer list is incompatible with C++98}}
+
 #endif


        


More information about the cfe-commits mailing list