r228896 - Improve the "braces around scalar init" warning to determine whether to warn

Richard Smith richard-llvm at metafoo.co.uk
Wed Feb 11 17:50:06 PST 2015


Author: rsmith
Date: Wed Feb 11 19:50:05 2015
New Revision: 228896

URL: http://llvm.org/viewvc/llvm-project?rev=228896&view=rev
Log:
Improve the "braces around scalar init" warning to determine whether to warn
based on whether "redundant" braces are ever reasonable as part of the
initialization of the entity, rather than whether the initialization is
"top-level". In passing, add a warning flag for it.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CXX/drs/dr16xx.cpp
    cfe/trunk/test/Misc/warning-flags.c
    cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
    cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp
    cfe/trunk/test/SemaCXX/cxx98-compat.cpp
    cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 11 19:50:05 2015
@@ -4171,9 +4171,10 @@ def warn_missing_field_initializers : Wa
   "missing field %0 initializer">,
   InGroup<MissingFieldInitializers>, DefaultIgnore;
 def warn_braces_around_scalar_init : Warning<
-  "braces around scalar initializer">;
+  "braces around scalar initializer">, InGroup<DiagGroup<"braced-scalar-init">>;
 def ext_many_braces_around_scalar_init : ExtWarn<
-  "too many braces around scalar initializer">;
+  "too many braces around scalar initializer">,
+  InGroup<DiagGroup<"many-braces-around-scalar-init">>;
 def ext_complex_component_init : Extension<
   "complex initialization specifying real and imaginary components "
   "is an extension">, InGroup<DiagGroup<"complex-component-init">>;

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Feb 11 19:50:05 2015
@@ -754,6 +754,68 @@ void InitListChecker::CheckImplicitInitL
   }
 }
 
+/// Warn that \p Entity was of scalar type and was initialized by a
+/// single-element braced initializer list.
+static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
+                                 SourceRange Braces) {
+  // Don't warn during template instantiation. If the initialization was
+  // non-dependent, we warned during the initial parse; otherwise, the
+  // type might not be scalar in some uses of the template.
+  if (!S.ActiveTemplateInstantiations.empty())
+    return;
+
+  unsigned DiagID = 0;
+
+  switch (Entity.getKind()) {
+  case InitializedEntity::EK_VectorElement:
+  case InitializedEntity::EK_ComplexElement:
+  case InitializedEntity::EK_ArrayElement:
+  case InitializedEntity::EK_Parameter:
+  case InitializedEntity::EK_Parameter_CF_Audited:
+  case InitializedEntity::EK_Result:
+    // Extra braces here are suspicious.
+    DiagID = diag::warn_braces_around_scalar_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;
+    break;
+
+  case InitializedEntity::EK_Variable:
+  case InitializedEntity::EK_LambdaCapture:
+    // No warning, might be direct-list-initialization.
+    // FIXME: Should we warn for copy-list-initialization in these cases?
+    break;
+
+  case InitializedEntity::EK_New:
+  case InitializedEntity::EK_Temporary:
+  case InitializedEntity::EK_CompoundLiteralInit:
+    // No warning, braces are part of the syntax of the underlying construct.
+    break;
+
+  case InitializedEntity::EK_RelatedResult:
+    // No warning, we already warned when initializing the result.
+    break;
+
+  case InitializedEntity::EK_Exception:
+  case InitializedEntity::EK_Base:
+  case InitializedEntity::EK_Delegating:
+  case InitializedEntity::EK_BlockElement:
+    llvm_unreachable("unexpected braced scalar init");
+  }
+
+  if (DiagID) {
+    S.Diag(Braces.getBegin(), DiagID)
+      << Braces
+      << FixItHint::CreateRemoval(Braces.getBegin())
+      << FixItHint::CreateRemoval(Braces.getEnd());
+  }
+}
+
+
 /// Check whether the initializer \p IList (that was written with explicit
 /// braces) can be used to initialize an object of type \p T.
 ///
@@ -829,12 +891,9 @@ void InitListChecker::CheckExplicitInitL
     }
   }
 
-  if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 &&
-      !TopLevelObject)
-    SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
-      << IList->getSourceRange()
-      << FixItHint::CreateRemoval(IList->getLocStart())
-      << FixItHint::CreateRemoval(IList->getLocEnd());
+  if (!VerifyOnly && T->isScalarType() &&
+      IList->getNumInits() == 1 && !isa<InitListExpr>(IList->getInit(0)))
+    warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange());
 }
 
 void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,

Modified: cfe/trunk/test/CXX/drs/dr16xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr16xx.cpp?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr16xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr16xx.cpp Wed Feb 11 19:50:05 2015
@@ -29,7 +29,7 @@ namespace dr1631 {  // dr1631: 3.7 c++11
   void f(int, A);
 
   void test() {
-    f({0}, {{1}});
+    f({0}, {{1}}); // expected-warning {{braces around scalar init}}
   }
 
   namespace with_error {

Modified: cfe/trunk/test/Misc/warning-flags.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/warning-flags.c?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/test/Misc/warning-flags.c (original)
+++ cfe/trunk/test/Misc/warning-flags.c Wed Feb 11 19:50:05 2015
@@ -18,14 +18,13 @@ This test serves two purposes:
 
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
-CHECK: Warnings without flags (96):
+CHECK: Warnings without flags (94):
 CHECK-NEXT:   ext_excess_initializers
 CHECK-NEXT:   ext_excess_initializers_in_char_array_initializer
 CHECK-NEXT:   ext_expected_semi_decl_list
 CHECK-NEXT:   ext_explicit_specialization_storage_class
 CHECK-NEXT:   ext_implicit_lib_function_decl
 CHECK-NEXT:   ext_initializer_string_for_char_array_too_long
-CHECK-NEXT:   ext_many_braces_around_scalar_init
 CHECK-NEXT:   ext_missing_declspec
 CHECK-NEXT:   ext_missing_whitespace_after_macro_name
 CHECK-NEXT:   ext_new_paren_array_nonconst
@@ -50,7 +49,6 @@ CHECK-NEXT:   warn_anon_bitfield_width_e
 CHECK-NEXT:   warn_arcmt_nsalloc_realloc
 CHECK-NEXT:   warn_asm_label_on_auto_decl
 CHECK-NEXT:   warn_bitfield_width_exceeds_type_size
-CHECK-NEXT:   warn_braces_around_scalar_init
 CHECK-NEXT:   warn_c_kext
 CHECK-NEXT:   warn_call_to_pure_virtual_member_function_from_ctor_dtor
 CHECK-NEXT:   warn_call_wrong_number_of_arguments

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Wed Feb 11 19:50:05 2015
@@ -142,6 +142,7 @@ namespace objects {
 
     one ov2(int);
     two ov2(F<3>);
+    // expected-warning at +1 {{braces around scalar initializer}}
     static_assert(sizeof(ov2({1})) == sizeof(one), "bad overload"); // list -> int ranks as identity
     static_assert(sizeof(ov2({1, 2, 3})) == sizeof(two), "bad overload"); // list -> F only viable
   }

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp Wed Feb 11 19:50:05 2015
@@ -110,7 +110,7 @@ namespace inner_init {
   struct D { C &&r; };
   D d1 { 0 }; // ok, 0 implicitly converts to C
   D d2 { { 0 } }; // ok, { 0 } calls C(0)
-  D d3 { { { 0 } } }; // ok, { { 0 } } calls C({ 0 })
+  D d3 { { { 0 } } }; // ok, { { 0 } } calls C({ 0 }), expected-warning {{braces around scalar init}}
   D d4 { { { { 0 } } } }; // expected-error {{no matching constructor for initialization of 'inner_init::C &&'}}
 
   struct E { explicit E(int); }; // expected-note 2{{here}}

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Wed Feb 11 19:50:05 2015
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -pedantic-errors
 
 struct one { char c[1]; };
 struct two { char c[2]; };
@@ -55,7 +55,7 @@ namespace integral {
     int ar[10];
     (void) ar[{1}]; // expected-error {{array subscript is not an integer}}
 
-    return {1};
+    return {1}; // expected-warning {{braces around scalar init}}
   }
 
   void inline_init() {
@@ -70,15 +70,15 @@ namespace integral {
 
   void function_call() {
     void takes_int(int);
-    takes_int({1});
+    takes_int({1}); // expected-warning {{braces around scalar init}}
   }
 
   void overloaded_call() {
     one overloaded(int);
     two overloaded(double);
 
-    static_assert(sizeof(overloaded({0})) == sizeof(one), "bad overload");
-    static_assert(sizeof(overloaded({0.0})) == sizeof(two), "bad overload");
+    static_assert(sizeof(overloaded({0})) == sizeof(one), "bad overload"); // expected-warning {{braces around scalar init}}
+    static_assert(sizeof(overloaded({0.0})) == sizeof(two), "bad overload"); // expected-warning {{braces around scalar init}}
 
     void ambiguous(int, double); // expected-note {{candidate}}
     void ambiguous(double, int); // expected-note {{candidate}}

Modified: cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-return-init-list.cpp Wed Feb 11 19:50:05 2015
@@ -4,7 +4,7 @@
 // required for libstdc++ 4.5) is supported in C++98.
 
 int test0(int i) {
-  return { i }; // expected-warning{{generalized initializer lists are a C++11 extension}}
+  return { i }; // expected-warning{{generalized initializer lists are a C++11 extension}} expected-warning {{scalar}}
 }
 
 template<typename T, typename U>

Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Wed Feb 11 19:50:05 2015
@@ -74,10 +74,10 @@ int InitList(int i = {}) { // expected-w
   InitListCtor ilc = { true, false }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}}
   const int &r = { 0 }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}}
   struct { int a; const int &r; } rr = { 0, {0} }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}}
-  return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
+  return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} expected-warning {{scalar}}
 }
 struct DelayedDefaultArgumentParseInitList {
-  void f(int i = {1}) { // expected-warning {{generalized initializer lists are incompatible with C++98}}
+  void f(int i = {1}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} expected-warning {{scalar}}
   }
 };
 

Modified: cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp?rev=228896&r1=228895&r2=228896&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/microsoft-new-delete.cpp Wed Feb 11 19:50:05 2015
@@ -31,4 +31,4 @@ struct explicit_ctor_tag {} ect;
 void *operator new[](size_t, explicit_ctor_tag, explicit_ctor);
 void *operator new(size_t, explicit_ctor_tag, int);
 void *t = new (ect, 0) int[4];
-void *u = new (ect, {0}) int[4];
+void *u = new (ect, {0}) int[4]; // expected-warning {{braces around scalar init}}





More information about the cfe-commits mailing list