clang vs. gcc

Hi,

clang doesn't compile the following code:

Hi,

clang doesn't compile the following code:
---------------------------
[filcab@farnsworth ~] $ cat a.c
#include <stdio.h>

extern void a;

int main ()
{
  printf("%p\n", &a);
  return 0;
}
---------------------------

[filcab@farnsworth ~] $ gcc -c a.c
[filcab@farnsworth ~] $ clang -c a.c
a.c:7:18: error: address expression must be an lvalue or a function
designator
  printf("%p\n", &a);
                 ^~
1 diagnostic generated.

Should I file a bug report or is it intended?

Both! :wink:

If you want to know, it's
from valgrind's source code. The symbol acts as a marker and is defined
in a .S file.

This isn't valid C89 or C99, but it's a GNU extension and it seems reasonable. Please file a bug report and we'll add it as a GNU extension.

  - Doug

There's already a bug on file: http://llvm.org/bugs/show_bug.cgi?id=2524 .

-Eli

Filipe Cabecinhas wrote:-

Hi,

clang doesn't compile the following code:
---------------------------
[filcab@farnsworth ~] $ cat a.c
#include <stdio.h>

extern void a;

int main ()
{
   printf("%p\n", &a);
   return 0;
}
---------------------------

[filcab@farnsworth ~] $ gcc -c a.c
[filcab@farnsworth ~] $ clang -c a.c
a.c:7:18: error: address expression must be an lvalue or a function
designator
   printf("%p\n", &a);
                  ^~
1 diagnostic generated.

Should I file a bug report or is it intended? If you want to know, it's
from valgrind's source code. The symbol acts as a marker and is defined
in a .S file.

If you declare it instead as

  extern const void a;

the code is valid C.

Neil.

Hi,

Neil Booth wrote:

If you declare it instead as

  extern const void a;

the code is valid C.

Neil.

Thanks. "const void" is a type that's different from "void"... I wouldn't get there by myself :slight_smile:

Also, I'm trying to compile valgrind using clang. valgrind doesn't use any libc functions (due to possible false warnings) so it uses GCC's __builtin_{set,long}jmp(...). I noticed they're not implemented in clang (and may never be... even in GCC's docs I didn't find anything about those builtins (only that the ADA backend uses them).

How could I get this to work? Is there any other way short of building (with GCC) a *.o file that exports those definitions or implementing it myself?

Regards,

   Filipe

The only way to safely do setjmp/longjmp in LLVM is to call external
functions called "setjmp" and "longjmp".

-Eli

Are you saying that inline asms are unsafe?

You aren't allowed to have control flow into or out of an inline asm, so an inline asm for setjmp/longjmp is not safe.

-Chris

So... There's no way I can use a setjmp/longjmp (or something that has the same effect) without using libc? or I can just use setjmp/longjmp happily (when compiling with clang) and it will get translated to something other than the call to libc?

Regards,

   Filipe

Chris Lattner wrote:

Are you experiencing an actual problem here? While C doesn't specify that this is legal, you can probably get away with it. Just mark any local variables as volatile.

-Chris

I'm just trying to compile valgrind. But valgrind is using __builtin_longjmp because it can't use libc. This doesn't compile because clang doesn't define that function. How could I pass this problem?

Chris Lattner wrote:

I'm just trying to compile valgrind. But valgrind is using __builtin_longjmp because it can't use libc. This doesn't compile because clang doesn't define that function. How could I pass this problem?

The best way is to implement __builtin_longjmp in clang!

-Chris

Unfortunately, that would require rather extensive changes to LLVM...
we would need real intrinsics to support it. We could make
__builtin_setjmp and __builtin_longjmp compile to setjmp and longjmp
calls, but that doesn't seem like it would help much.

-Eli

That is what llvm-gcc does, and it appears to work.

-Chris

No, llvm-gcc simply ignores __builtin_longjmp (!). Take a look at the
output for "int a(void* x) { __builtin_longjmp(x,1); }" to see what I
mean. The only reason it "works" is that __builtin_longjmp is very
rarely used.

-Eli

Correction: we can't. This would silently miscompile
__builtin_setjmp/longjmp because the caller won't allocate a large
enough buffer for setjmp/longjmp.

-Eli