Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which C99-compiler (Clang vs. GCC) is closer to standard on const structure fields?

I have code like this:

$ cat test.c 
#include <stdio.h>
typedef struct
{
    const int x;
} SX;

static SX mksx(void)
{
    return (SX) { .x = 10 };
}

void fn(void)
{
    SX sx;
    while((sx = mksx()).x != 20)
    {
        printf("stupid code!");
    }
}

And 2 opinions about its correctness:

$ for i in gcc clang; do echo "$i SAYS:"; $i -c -std=c99 -pedantic -Werror test.c; done
gcc SAYS:
test.c: In function ‘fn’:
test.c:15:2: error: assignment of read-only variable ‘sx’
  while((sx = mksx()).x != 20)
  ^
clang SAYS:

Which compiler is right?

like image 286
M.Bakhterev Avatar asked Aug 30 '13 08:08

M.Bakhterev


People also ask

Which is better Clang or GCC?

Clang is much faster and uses far less memory than GCC. Clang aims to provide extremely clear and concise diagnostics (error and warning messages), and includes support for expressive diagnostics. GCC's warnings are sometimes acceptable, but are often confusing and it does not support expressive diagnostics.

What is difference between clang and clang ++?

clang and clang++ on most systems are the same executable. One is merely a symbolic link to the other. The program checks to see what name it is invoked under, and: for clang , compiles code as C.

Does clang use GCC?

Clang is compatible with GCC. Its command-line interface shares many of GCC's flags and options. Clang implements many GNU language extensions and compiler intrinsics, some of which are purely for compatibility.

Does clang support c11?

C++11 implementation statusYou can use Clang in C++11 mode with the -std=c++11 option. Clang's C++11 mode can be used with libc++ or with gcc's libstdc++.


2 Answers

The C99 standard says in 6.5.16:2:

An assignment operator shall have a modifiable lvalue as its left operand.

and in 6.3.2.1:1:

A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.

So GCC is right to warn.

In addition, the clause 6.5.16:2 is in a “Constraints” section of the C99 standard, so a conforming compiler is required to emit a diagnostic for a program that breaks the clause. It is still undefined behavior: the compiler can still do what it wants after the diagnostic is emitted. But there has to be a message. In consequence, Clang is behaving in a non-conforming manner here.

like image 146
Pascal Cuoq Avatar answered Sep 23 '22 17:09

Pascal Cuoq


const variable can't be modified after initialization, otherwise it's undefined behavior.

Since it is undefined behavior, I think one can say both gcc and clang follow the standard. (Although gcc's choice seems better, it deserves a warning) (See EDIT below)

The only way to give the variable x a value with defined behavior is to initialize it:

SX sx = { .x = 10 };

EDIT: As @Keith Thompson comments below, it's more than just undefined behavior in this case:

C99 §6.5.16 Assignment operators

Constraints

An assignment operator shall have a modifiable lvalue as its left operand.

This is a constraint, and according to:

C99 §5.1.1.3 Diagnostics

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances.

A compiler must issue a diagnostic for any program that violates a constraint.

Back to the question, gcc is correct is generate a warning, while clang fails to do so.

like image 30
Yu Hao Avatar answered Sep 22 '22 17:09

Yu Hao