[cfe-dev] 'braces around scalar initializer' warning, should be error?

will wray via cfe-dev cfe-dev at lists.llvm.org
Fri Dec 21 06:29:57 PST 2018


Your fix is live on compiler explorer already - an early present delivered
in time for xmas.

And, of course, it does allow to distinguish scalar member from
array-of-one-scalar,
just by testing one more set of braces.

Excellent service, thanks.

I'll take a look at gcc bugzilla today and see about reporting that
braced-scalar error as a bug.


On Thu, Dec 20, 2018 at 4:04 PM Richard Smith <richard at metafoo.co.uk> wrote:

> On Thu, 20 Dec 2018 at 12:22, will wray via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
>> Ah, so same issue for actual scalars as for scalar members of aggregates.
>>
>> This bug prevents a port of my lib* to Clang, so I'd like to see it
>> addressed.
>> There's no related bug report in Clang bugzilla AFAICT.
>>
>> Shall I report?
>>
>
> Should be fixed in r349820. (Our "extension" diagnostics should probably
> cause SFINAE failures by default, but for now I've just marked this
> particular one as doing so.)
>
>
>> Will
>>
>> * The lib extends magic_get to support array type aggregate members
>>  as described here https://github.com/apolukhin/magic_get/issues/20
>>  - it relies on a sfinae / requires error to catch 'too-many-braces'.
>> This is a valuable niche use case, at least until static reflection
>> arrives.
>>
>> Oddly, the GCC bug that gives an error on single-brace-init of a scalar
>> member
>> allows to discriminate a scalar member from an array-of-one-scalar member
>> -
>> it seems a conforming implementation can't distinguish, say, int from
>> int[1] -
>> but this ability comes at a cost of awkward non-uniform initialization
>> syntax.
>>
>
> Clang trunk accepts:
>
> valid a = braces1<int[1]>(0);
> valid b = braces2<int[1]>(0);
> invalid c = braces3<int[1]>(0);
>
> struct X { int n[1]; };
> valid d = braces1<X>(0);
> valid e = braces2<X>(0);
> valid f = braces3<X>(0);
>
> ... which I believe is correct. (int[1] allows one more set of braces than
> int.)
>
>
>> On Thu, Dec 20, 2018 at 2:09 PM Richard Smith <richard at metafoo.co.uk>
>> wrote:
>>
>>> [Adding back cfe-dev]
>>>
>>> On Wed, 19 Dec 2018 at 08:11, will wray <wjwray at gmail.com> wrote:
>>>
>>>> Thanks, as ever, for your detailed explanation and for clarifying my
>>>> question as C++ related.
>>>>
>>>> Here's a Christmas tree (in concept):
>>>> https://concept.godbolt.org/z/aFoGUL
>>>>
>>>> template <class T> concept braces0 = requires {    T{0};    };
>>>> template <class T> concept braces1 = requires {   T{{0}};   };
>>>> template <class T> concept braces2 = requires {  T{{{0}}};  };
>>>> template <class T> concept braces3 = requires { T{{{{0}}}}; };
>>>>
>>>> So, for our class S with single scalar member we'd expect braces2<S>
>>>> and on to evaluate false.
>>>> But Clang evaluates all as true - it doesn't catch the error in the
>>>> expression (well, declaration statement)
>>>> in this unevaluated context (same in conventional sfinae attempts).
>>>>
>>>> Is this expected behaviour?
>>>>
>>>
>>> No, that looks like a bug. Here's a testcase against clang trunk:
>>> https://gcc.godbolt.org/z/wLXqPD
>>>
>>> ICC and MSVC get this right; GCC and Clang get it wrong in two different
>>> ways.
>>>
>>>
>>>> On Tue, Dec 18, 2018 at 8:35 PM Richard Smith <richard at metafoo.co.uk>
>>>> wrote:
>>>>
>>>>> (For clarity, since you didn't say, I'm assuming this is a question
>>>>> about C++, and I'm going to assume you mean Clang's default C++ mode,
>>>>> C++14.)
>>>>>
>>>>> On Tue, 18 Dec 2018 at 12:17, will wray via cfe-dev <
>>>>> cfe-dev at lists.llvm.org> wrote:
>>>>>
>>>>>> *    struct S { int i; };*
>>>>>>
>>>>>> *    S s{{0}};*
>>>>>> *Clang*: `*warning*: braces around scalar initializer
>>>>>> [-Wbraced-scalar-init]`
>>>>>>
>>>>>> or, with more braces:
>>>>>>
>>>>>>  `*warning*: too many braces around scalar initializer
>>>>>> [-Wmany-braces-around-scalar-init]
>>>>>> (consistent as a warning since at least clang 3.0.0)
>>>>>>
>>>>>> *GCC*: `*error*: braces around scalar initializer for type 'int'`
>>>>>>
>>>>>> (consistent as an error since ~gcc 4.4.7)
>>>>>>
>>>>>> *MSVC*: no warning (with \Wall)
>>>>>> *Intel*: warning #1119: extra braces are nonstandard
>>>>>>
>>>>>> I believe that this is a non-standard extension in Clang. Can anyone
>>>>>> confirm?
>>>>>>
>>>>>
>>>>> Nope, this is valid, and I'm frankly stunned that GCC rejects.
>>>>>
>>>>> C++14 [dcl.init.aggr]/2 says: "Each member is copy-initialized from
>>>>> the corresponding initializer-clause. [...] [ Note: If an
>>>>> initializer-clause is itself an initializer list, the member is
>>>>> list-initialized, which will result in a recursive application of the rules
>>>>> in this section if the member is an aggregate.  — end note ]"
>>>>> C++14 [dcl.init.list]/3.5: "Otherwise, if the initializer list has a
>>>>> single element of type E and either T is not a reference type or its
>>>>> referenced type is reference-related to E, the object or reference is
>>>>> initialized from that element;"
>>>>>
>>>>> In fact, it's valid in every revision of C++ since C++11. (It was
>>>>> ill-formed in C++98, which allowed int n = {0}, but not S s = {{0}};, but
>>>>> the syntax you used was added in C++11.)
>>>>>
>>>>> The fact that clang accepts
>>>>>
>>>>> struct S { int i; };
>>>>> S s = {{0}};
>>>>>
>>>>> in C++98 mode under -pedantic-errors is a (minor) bug.
>>>>>
>>>>> Does the standard does mandate an error here?
>>>>>> If so then is there any flag to make this an error in Clang?
>>>>>> (-pedantic-errors flag makes no difference, for gcc or for clang.)
>>>>>> Maybe it's for MSVC / EDG compatibility? Or C compatibility? What
>>>>>> reason?
>>>>>>
>>>>>> An error allows compile-time code to distinguish between scalar and
>>>>>> non-scalar,
>>>>>> to count the number of allowable braces and so to detect array rank &
>>>>>> dims.
>>>>>>
>>>>>> On the other hand, an error forces different syntax for initializing
>>>>>> scalar and non-scalar
>>>>>> so disallows generic 'uniform' braced-init syntax where there may be
>>>>>> scalars.
>>>>>>
>>>>>> Thanks for any thoughts,
>>>>>> Will
>>>>>>
>>>>>> Here are some issues/DRs & commits that may or may not be relevant
>>>>>> An old pre-11 issue
>>>>>> 632. Brace-enclosed initializer for scalar member of aggregate
>>>>>> <http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#632>
>>>>>> explains that this was a C/C++ incompatibility, says it was resolved
>>>>>> by Initializer Lists
>>>>>> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm>
>>>>>> (LOL) (I can't see how or where it is resolved)
>>>>>>
>>>>>
>>>>> See above.
>>>>>
>>>>>
>>>>>> h1501. Nested braces in list-initialization
>>>>>> <http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1501>
>>>>>>
>>>>>
>>>>> As noted here, one set of braces around a scalar initialization is
>>>>> permitted, and two or more sets is invalid. So:
>>>>>
>>>>> S s = {{{0}}}; // error
>>>>>
>>>>> and indeed for that Clang reports
>>>>>
>>>>> error: too many braces around scalar initializer
>>>>> [-Werror,-Wmany-braces-around-scalar-init]
>>>>> S s = {{{0}}};
>>>>>         ^~~
>>>>>
>>>>> As part of changes for DR1467 List-initialization of aggregate from
>>>>>> same-type object
>>>>>> <http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467>
>>>>>> this Clang commit
>>>>>> r228896
>>>>>> <http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20150209/123171.html>-
>>>>>> Improve the "braces around scalar init" warning to determine whether to warn
>>>>>> _______________________________________________
>>>>>> cfe-dev mailing list
>>>>>> cfe-dev at lists.llvm.org
>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>>>>
>>>>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20181221/6f445fb3/attachment.html>


More information about the cfe-dev mailing list