[cfe-dev] clang initializer elements that are pointers to other global variables

Török Edvin edwintorok at gmail.com
Fri Oct 19 03:41:49 PDT 2007


Hi,

I run clang -fsyntax-only on x.i. Everything is ok. I use llvm-gcc to
generate bitcode, and llc to generate C code again. clang fails to
compile it.
It says that the initializer is not constant, and that the variable
was redeclared.
gcc and llvm-gcc say the generated C code is ok.

Original x.i:
const char* wordlist[] = {
        "word1",
        "word2"
};

$ clang x.i
$ echo $?
0
$ llvm-gcc -emit-llvm -c x.i -o x.bc && llc -march=c x.bc -o x.cbe.c
$ clang -I/usr/lib/gcc/x86_64-linux-gnu/4.2.1/include/  x.cbe.c
x.cbe.c:124:35: error: initializer element is not constant
unsigned char *wordlist[2] = { (&(_2E_str[((signed int )((unsigned int
)0))])), (&(_2E_str1[((signed int )((unsigned int )0))])) };
                               ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x.cbe.c:124:84: error: initializer element is not constant
unsigned char *wordlist[2] = { (&(_2E_str[((signed int )((unsigned int
)0))])), (&(_2E_str1[((signed int )((unsigned int )0))])) };

         ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x.cbe.c:125:22: error: redefinition of '_2E_str'
static unsigned char _2E_str[6] = "word1";
                     ^
x.cbe.c:119:22: error: previous definition is here
static unsigned char _2E_str[6];
                     ^
x.cbe.c:126:22: error: redefinition of '_2E_str1'
static unsigned char _2E_str1[6] = "word2";
                     ^
x.cbe.c:120:22: error: previous definition is here
static unsigned char _2E_str1[6];
                     ^
x.cbe.c:130:64: warning: comparing floating point with == or != is unsafe
static inline int llvm_fcmp_ord(double X, double Y) { return X == X && Y == Y; }
[... more of these ...., however gcc agrees, see below]


Here is the part of x.cbe.c that comes from the original x.i, lets call it y.c:
static unsigned char _2E_str[6] = "word1";
static unsigned char _2E_str1[6] = "word2";
unsigned char *wordlist[2] = { (&(_2E_str[((signed int )((unsigned int
)0))])), (&(_2E_str1[((signed int )((unsigned int )0))])) };

$ clang y.c
$ clang y.c
y.c:3:35: error: initializer element is not constant
unsigned char *wordlist[2] = { (&(_2E_str[((signed int )((unsigned int
)0))])), (&(_2E_str1[((signed int )((unsigned int )0))])) };
                               ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
y.c:3:84: error: initializer element is not constant
unsigned char *wordlist[2] = { (&(_2E_str[((signed int )((unsigned int
)0))])), (&(_2E_str1[((signed int )((unsigned int )0))])) };

         ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 diagnostics generated.

However using gcc/llvm-gcc I get no significant warnings:
$ gcc -Wall -W -c x.cbe.c
x.cbe.c:112: warning: conflicting types for built-in function 'malloc'
$ llvm-gcc -Wall -W -c x.cbe.c
x.cbe.c:112: warning: conflicting types for built-in function 'malloc'

[malloc is declared as returning unsigned char*, whereas in standard
headers it returns void*. In practice this doesn't cause problems, so
I'll ignore this warning.]

But where are the float comparison warnings? Lets try more flags:

$gcc -c -pedantic -Wextra -Wall -Wbad-function-cast -Wcast-align
-Wcast-qual -Wdisabled-optimization -Wendif-labels -Wfloat-equal
-Wformat=2 -Wformat-nonliteral -Winline -Wmissing-declarations
-Wmissing-prototypes -Wnested-externs -Wno-unused-parameter
-Wpointer-arith -Wshadow -Wstrict-prototypes -Wswitch -Wundef
-Wwrite-strings x.cbe.c
x.cbe.c:90: warning: ISO C90 does not support 'long long'
x.cbe.c:92: warning: ISO C90 does not support 'long long'
x.cbe.c:93: warning: ISO C90 does not support 'long long'
x.cbe.c:93: warning: ISO C90 does not support 'long long'
x.cbe.c:100: warning: ISO C90 does not support 'long long'
x.cbe.c:112: warning: function declaration isn't a prototype
x.cbe.c:112: warning: conflicting types for built-in function 'malloc'
x.cbe.c: In function 'llvm_fcmp_ord':
x.cbe.c:130: warning: comparing floating point with == or != is unsafe
[... more of these....]

The functions are:
static inline int llvm_fcmp_ord(double X, double Y) { return X == X && Y == Y; }
static inline int llvm_fcmp_uno(double X, double Y) { return X != X || Y != Y; }

I'll discuss these in a separate mail, this one is getting too long.

Best regards,
--Edwin



More information about the cfe-dev mailing list