[cfe-dev] 'braces around scalar initializer' warning, should be error?
Richard Smith via cfe-dev
cfe-dev at lists.llvm.org
Thu Dec 20 13:04:23 PST 2018
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/20181220/293feafe/attachment.html>
More information about the cfe-dev
mailing list