clangupc / clang-upc

Clang UPC Front-End
https://clangupc.github.io/
Other
17 stars 5 forks source link

private stdarg.h is "fragile" on Solaris/x86 #75

Open PHHargrove opened 9 years ago

PHHargrove commented 9 years ago

The test code and series of compilation commands below show that on Solaris-11 for x86-64, including stdio.h before stddef.h results in incorrect va_list related definitions IFF on passes -UGNUC to clang. This is true only for the default ILP32 ABI, but not for LP64. The shell command (and output) below show all 8 combinations of (-m64 vs -m32) x (w/ vs w/o -UGNUC) x (w/ stdio.h included before vs after stddef.h).

Note that only one case out of the 8 fail, and when it does the complaint is about clang's private stddef.h header.

$ cat test.c
#if REORDER
  // Works:
  #include <stdarg.h>
  #include <stdio.h>
#else
  // Broken:
  #include <stdio.h>
  #include <stdarg.h>
#endif

static void fatal(const char *s, ...) {
  char msg[255];
  va_list ap;
  va_start(ap, s);
    vsnprintf(msg, sizeof(msg), s, ap);
  va_end(ap);
  fprintf(stderr,"*** Error: %s\n", msg);
}
$ for m in 64 32; do for u in '' '-U__GNUC__'; do for r in 0 1; do cmd="clang -c test.c -
m$m -DREORDER=$r $u"; echo '$' $cmd; eval $cmd && echo PASS || echo FAIL; done; done; done
$ clang -c test.c -m64 -DREORDER=0
PASS
$ clang -c test.c -m64 -DREORDER=1
PASS
$ clang -c test.c -m64 -DREORDER=0 -U__GNUC__
PASS
$ clang -c test.c -m64 -DREORDER=1 -U__GNUC__
PASS
$ clang -c test.c -m32 -DREORDER=0
PASS
$ clang -c test.c -m32 -DREORDER=1
PASS
$ clang -c test.c -m32 -DREORDER=0 -U__GNUC__
test.c:14:12: error: non-const lvalue reference to type '__builtin_va_list' cannot bind to a value of
      unrelated type 'va_list' (aka 'void *')
  va_start(ap, s);
           ^~
/shared/llvm-upc-32/bin/../lib/clang/3.5.1/include/stdarg.h:33:48: note: expanded from macro 'va_start'
#define va_start(ap, param) __builtin_va_start(ap, param)
                                               ^
test.c:16:10: error: non-const lvalue reference to type '__builtin_va_list' cannot bind to a value of
      unrelated type 'va_list' (aka 'void *')
  va_end(ap);
         ^~
/shared/llvm-upc-32/bin/../lib/clang/3.5.1/include/stdarg.h:34:46: note: expanded from macro 'va_end'
#define va_end(ap)          __builtin_va_end(ap)
                                             ^
2 errors generated.
FAIL
$ clang -c test.c -m32 -DREORDER=1 -U__GNUC__
PASS
PHHargrove commented 9 years ago

The conditions to reproduce this issue are identical to those for BUPC bug #3210.

In that case the solution was use of some preprocessor logic in the stdarg.h wrapper (in upcr_geninclude) used in only the first preprocess. It seems likely that such an approach would work here too (since the passes are identical). However, I'd like to avoid adding such a wrapper if this turns out to be something that can/should/will be fixed upstream.