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

Abramo Bagnara via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 7 23:54:31 PDT 2015


Ping^2

Il 12/09/2015 09:40, Abramo Bagnara ha scritto:
> 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