Implict casts disappeared from syntactic init list expressions in C++

Abramo Bagnara via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 12 00:40:58 PDT 2015


Ping...

Il 29/08/2015 10:01, Abramo Bagnara ha scritto:
> Il 28/08/2015 23:27, Richard Smith ha scritto:
>> On Tue, Aug 25, 2015 at 10:27 AM, Abramo Bagnara
>> <abramo.bagnara at bugseng.com <mailto:abramo.bagnara at bugseng.com>> wrote:
>>
>>     Comparing the result of InitListExpr::getSyntacticForm between r224986
>>     and r245836 I've discovered that integer to char implicit cast for
>>     integer literal 3 is no longer added to AST for C++ (while it is present
>>     in C).
>>
>>     This is the source used to test:
>>
>>     char v[10] = { 3 };
>>
>>     Taken in account that:
>>
>>     - implicit cast (and other conversions, constructor calls, etc.) are
>>     very important also for who need to visit the syntactic form (obvious in
>>     *both* C and C++)
>>
>>     - to generate that for the syntactic form permit to increase the
>>     efficiency and the sharing when using designated range extensions (as
>>     the conversion chain don't need to be replicated for each entry)
>>
>>     I think it is a regression. Am I missing something?
>>
>>
>> Why do you expect this semantic information to appear in the syntactic
>> form of the initializer? 
> 
> Compare:
> 
> int x = 2.0;
> 
> with
> 
> struct s {
>   int x;
> } v = { .x = 2.0 };
> 
> For first declaration I have non-syntactic nodes (namely
> ImplicitCastExpr) along with syntactic nodes, while for the second I
> don't have that (for C++). This is an obstacle to write semi-syntactic
> checkers that aims to find e.g. implicit cast from double to int in its
> syntactic context.
> Note that although we might visit the semantic form, we'll lose the
> designators (not present in semantic form).
> 
> To resume, the reason why I would expect that are:
> 
> 1) this is how it always has worked for C (and fortunately still works
> this way)
> 
> 
> 2) this is how it always has worked (although partially, there was some
> bugs) for C++. In past we have had patches to fix the areas where this
> invariant was not respected (see commit 3146766
> http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20111212/050339.html
> as an example).
> 
> This behavior has changed rather recently (if you think it is useful I
> can find the commit that has removed the implicit casts from syntactic
> form in C++)
> 
> Before such commit(s) the only bug I was aware where AST was missing
> conversion chain was the following:
> 
> struct R2 {
>   R2(int) {
>   }
> };
> R2 v2[] = { 1.0 };
> 
> 
> 3) this way it would be congruent with other areas of AST where we have
> non-syntactic nodes along with syntactic ones
> 
> 
> 4) it would permit to share more nodes in semantic form (and avoid to
> rebuild many times the same conversion chain).
> 
> Looking at following typescript you can observe that ImplicitCastExpr is
> shared only for C, but not for C++. I've initialized only two entries,
> but it might be 1000 or 10000000.
> 
> $ cat p.c
> int x[1000000] = { [0 ... 1] = 3.0 };
> $ clang-3.8 -cc1 -ast-dump -x c p.c
> TranslationUnitDecl 0x272de40 <<invalid sloc>> <invalid sloc>
> |-TypedefDecl 0x272e338 <<invalid sloc>> <invalid sloc> implicit
> __int128_t '__int128'
> |-TypedefDecl 0x272e398 <<invalid sloc>> <invalid sloc> implicit
> __uint128_t 'unsigned __int128'
> |-TypedefDecl 0x272e648 <<invalid sloc>> <invalid sloc> implicit
> __builtin_va_list 'struct __va_list_tag [1]'
> `-VarDecl 0x272e718 <p.c:1:1, col:36> col:5 x 'int [1000000]' cinit
>   `-InitListExpr 0x272e8b0 <col:18, col:36> 'int [1000000]'
>     |-array filler
>     | `-ImplicitValueInitExpr 0x272e918 <<invalid sloc>> 'int'
>     |-ImplicitCastExpr 0x272e900 <col:32> 'int' <FloatingToIntegral>
>     | `-FloatingLiteral 0x272e7f8 <col:32> 'double' 3.000000e+00
>     `-ImplicitCastExpr 0x272e900 <col:32> 'int' <FloatingToIntegral>
>       `-FloatingLiteral 0x272e7f8 <col:32> 'double' 3.000000e+00
> $ clang-3.8 -cc1 -ast-dump -x c++ p.c
> TranslationUnitDecl 0x3300e60 <<invalid sloc>> <invalid sloc>
> |-TypedefDecl 0x3301398 <<invalid sloc>> <invalid sloc> implicit
> __int128_t '__int128'
> |-TypedefDecl 0x33013f8 <<invalid sloc>> <invalid sloc> implicit
> __uint128_t 'unsigned __int128'
> |-TypedefDecl 0x3301718 <<invalid sloc>> <invalid sloc> implicit
> __builtin_va_list 'struct __va_list_tag [1]'
> `-VarDecl 0x33017e8 <p.c:1:1, col:36> col:5 x 'int [1000000]' cinit
>   `-InitListExpr 0x3301980 <col:18, col:36> 'int [1000000]'
>     |-array filler
>     | `-ImplicitValueInitExpr 0x3301a00 <<invalid sloc>> 'int'
>     |-ImplicitCastExpr 0x33019d0 <col:32> 'int' <FloatingToIntegral>
>     | `-FloatingLiteral 0x33018c8 <col:32> 'double' 3.000000e+00
>     `-ImplicitCastExpr 0x33019e8 <col:32> 'int' <FloatingToIntegral>
>       `-FloatingLiteral 0x33018c8 <col:32> 'double' 3.000000e+00
> 
> 
> 5) if we would visit semantic form in a checker searching for implicit
> cast from float to int in the C source above we'll find *two* of them,
> while syntactically we have only one. This means that we should be
> forced do some dirty tricks to avoid double reporting.
> 


-- 
Abramo Bagnara

BUGSENG srl - http://bugseng.com
mailto:abramo.bagnara at bugseng.com


More information about the cfe-commits mailing list