support for parsing more GCC object-size checking builtins

I'm running into problems parsing code that builds with -D_FORTIFY_SOURCE=2 on Mac OS X. Specifically, this causes calls to certain functions to be replacing like so:

[shantonu@shantonu-sens-macbook-2]$ cat test.c
#include <string.h>

extern char *foo;
extern const char *bar;

void * test(void) {
    return stpcpy(foo, bar);
}
[shantonu@shantonu-sens-macbook-2]$ gcc -c test.c -D_FORTIFY_SOURCE=2
[shantonu@shantonu-sens-macbook-2]$ nm test.o | grep " U "
         U ___stpcpy_chk
         U _bar
         U _foo
[shantonu@shantonu-sens-macbook-2]$ gcc -c test.c -D_FORTIFY_SOURCE=0
[shantonu@shantonu-sens-macbook-2]$ nm test.o | grep " U "
         U _bar
         U _foo
         U _stpcpy
[shantonu@shantonu-sens-macbook-2]$ clang -D_FORTIFY_SOURCE=2 -E test.c | tail -4

void * test(void) {
    return ((__builtin_object_size (foo, 0) != (size_t) -1) ? __builtin___stpcpy_chk (foo, bar, __builtin_object_size (foo, 2 > 1)) : __inline_stpcpy_chk (foo, bar));
}

clang does not appear to support all of the builtins documented in the GCC manual at <http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html >. Attempting to use stpcpy (or strncat, etc.), I get:

[shantonu@shantonu-sens-macbook-2]$ clang.orig -D_FORTIFY_SOURCE=2 test.c
test.c:7:12: error: incompatible operand types ('int' and 'char *')
    return stpcpy(foo, bar);
           ^~~~~~
1 diagnostic generated.
[shantonu@shantonu-sens-macbook-2]$ clang.orig -D_FORTIFY_SOURCE=2 test.c -E | clang.orig - -fsyntax-only
<stdin>:273:3: warning: incompatible integer to pointer conversion returning 'int', expected 'char *'
  return __builtin___stpcpy_chk (__dest, __src, __builtin_object_size (__dest, 2 > 1));
  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<stdin>:308:3: warning: incompatible integer to pointer conversion returning 'int', expected 'char *'
  return __builtin___strncat_chk (__dest, __src, __len, __builtin_object_size (__dest, 2 > 1));
  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<stdin>:317:61: error: incompatible operand types ('int' and 'char *')
    return ((__builtin_object_size (foo, 0) != (size_t) -1) ? __builtin___stpcpy_chk (foo, bar, __builtin_object_size (foo, 2 > 1)) : __inline_stpcpy_chk (foo, bar));
                                                            ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 diagnostics generated.

I added the missing builtins to at least the parser, and now I get:

[shantonu@shantonu-sens-macbook-2]$ clang -D_FORTIFY_SOURCE=2 test.c
[shantonu@shantonu-sens-macbook-2]$ clang -D_FORTIFY_SOURCE=2 test.c -E | clang - -fsyntax-only
[shantonu@shantonu-sens-macbook-2]$

This doesn't add codegen support, since there does not appear to be support for any of the other built-in string functions. But this is enough to allow checker to successfully parse my entire project.

The existing prototype for __builtin_memset seemed incorrect, since memset(3) takes an "int" as the pattern. __builtin_strcpy/strncpy also had issues because the destination string was marked as "const" when it shouldn't have been.

builtin-object-size.patch (1.48 KB)

I think the solution for these builtins would be to annotate them with
"F"; gcc seems to be okay with generating calls to __memset_chk.

The patch looks good; if you have commit access, feel free to commit.

-Eli