[cfe-dev] Cast to type with side effects

Abramo Bagnara abramo.bagnara at gmail.com
Wed Sep 22 09:08:15 PDT 2010


Il 22/09/2010 17:55, Douglas Gregor ha scritto:
> 
> On Sep 22, 2010, at 8:13 AM, Abramo Bagnara wrote:
> 
>>
>> int g();
>>
>> int main() {
>>  //  enum { x = (g(), 0) };
>>  enum { x = (int)(int(*)[g()])0 };
>>  return 0;
>> }
>>
>> Constant expression evaluator seems to (wrongly IMHO) believe that types
>> cannot have side effects.
>>
>> Do you confirm we have a bug here?
> 
> I don't think this was meant to be well-formed C99, although it seems like there is a gap in the C99 standard here. In particular, C99 6.7.5.2p2 says:
> 
>   An ordinary identifier (as defined in 6.2.3) that has a variably modified type shall have either block scope and no linkage or function prototype scope.
> 
> Now, we're in a type-name (C99 6.7.6), so there is no identifier... however, the general view of type-names is that they are declarators without the identifier, which implies that C99 6.7.5p2 applies in this case. C99 6.7.7p3 strengthens our case somewhat, even though it is about typedefs, because it says:
> 
> 	Any array size expressions associated with variable length array declarators are evaluated each time the declaration of the typedef name is reached in the order of execution.
> 
> There is no way to reach an enumerator constant in the order of execution, so it doesn't make sense to have a VLA there.
> 
> Oh, and EDG rejects this code in C99 mode.
> 
> Long story short: yes, there is a bug here, which is that Clang accepts this ill-formed program. It should reject the use of a variably-modified type in a cast.

I believe this conclusion is far too strict:

int x = (int)(int(*)[g()])0;

I think this is perfectly ok and it has side effects that have to be
executed (and clang behave as expected).

The clang problem is *not* to accept VM types in cast, but it is to
ignore their inner side effects in constant evaluation.

I'm missing something?




More information about the cfe-dev mailing list