cgccexpressioncompile-time-constantcomma-operator

Apparent GCC bug with comma operator in constant initializer


I was messing around with C and discovered an apparent bug in GCC:

#include <stdio.h>

int y = (1, 2);
int main()
{
  return 0;
}

in gcc gives error: initializer element is not constant while it works fine in clang. And as expected, putting the declaration inside the main() function also works with both compilers.

The parentheses are necessary, as otherwise gcc would be correct in disallowing the comma operator.

Despite the gcc code snippet looking like this:

    3 | int y = (1, 2);
      |         ^

the parentheses are not the problem. int y = (1 + 2); works fine.

I know that the comma operator is never necessary in constant expressions, as there should never be any side effects, but it's still odd that GCC sees it as an error instead of just printing warning: expression result unused (which it also does).

Is this a bug?


Solution

  • Per the standard, comma operator is not allowed in constant expressions, but clang admits it in most (but not all) contexts. For example:

    int a = (1,2); //accepts
    
    int b[(1,2)]; // warns: VLA folded to constant size array
    
    _Static_assert((1,2), "oops!"); // fails
    
    struct 
    {
       int c : (1,2); // accepts
       int d [(1,2)]; // warns: VLA folded to constant size array
    
    } e;
    
    enum { FOO = (1,2) }; //accepts
    
    int _Alignas((2,16)) f; // fails
    
    int* g = (1,0); // warns: integer to pointer conversion
                    // so this is not a null pointer constant,
                    // but still a constant expression (because the 
                    // initialisation is accepted)!
    

    Live

    gcc rejects all of these constructs.

    The standard does allow an implementation to accept other forms of constant expressions though, but it isn't clear if these other forms should be documented or how they should be admitted in different contexts.

    There is a clang bug about clang sometimes treating comma as allowed in constant expressions.