"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">>;
}
}
+/// 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.
///
}
}
- 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,
void f(int, A);
void test() {
- f({0}, {{1}});
+ f({0}, {{1}}); // expected-warning {{braces around scalar init}}
}
namespace with_error {
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
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
one ov2(int);
two ov2(F<3>);
+ // expected-warning@+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
}
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}}
-// 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]; };
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() {
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}}
// 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>
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}}
}
};
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}}