Search code examples
gccclangllvm

using clang to generate .o files for .i files generated by gcc, errors occur


The code example is very simple.

#include <stdio.h>

int main() {
        printf("hello, world");
}
  1. Generate the .i file.

gcc -E test.cpp -o test.cpp.ii

  1. generate .o files for .i files

clang++ -c test.cpp.ii -o test.cpp.o

The following error message is displayed.

In file included from test.cpp:1:
/usr/include/stdio.h:189:48: error: '__malloc__' attribute takes no arguments
  __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (fclose, 1))) ;
                                               ^
/usr/include/stdio.h:201:49: error: '__malloc__' attribute takes no arguments
   __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (fclose, 1))) ;
                                                ^
/usr/include/stdio.h:223:77: error: use of undeclared identifier '__builtin_free'; did you mean '__builtin_frexp'?
   noexcept (true) __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (__builtin_free, 1)));
                                                                            ^
/usr/include/stdio.h:223:77: note: '__builtin_frexp' declared here
/usr/include/stdio.h:223:65: error: '__malloc__' attribute takes no arguments
   noexcept (true) __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (__builtin_free, 1)));

btw, When using gcc to generate .o files from .i files, everything works fine.

  1. attribute ((malloc)) is a feature unique to GCC support?
  2. In this case, how to make clang generate .o files correctly

Solution

  • After a lot of investigation I found this in glibc's stddef.h:

    /* At some point during the gcc 2.96 development the `malloc' attribute
       for functions was introduced.  We don't want to use it unconditionally
       (although this would be possible) since it generates warnings.  */
    #if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__)
    # define __attribute_malloc__ __attribute__ ((__malloc__))
    #else
    # define __attribute_malloc__ /* Ignore */
    #endif
    

    and if you see stdio.h, for example:

    #undef __attr_dealloc_fclose
    #define __attr_dealloc_fclose __attr_dealloc (fclose, 1)
    
    ...
    ...
    ...
    
    extern FILE *fopen (const char *__restrict __filename,
                const char *__restrict __modes)
      __attribute_malloc__ __attr_dealloc_fclose __wur;
    

    So, those attributes in your case, are from glibc, not gcc, and I think it is better to not play with them. So I tested it with musl libc in my arch linux:

    pacman -Sy musl
    

    then

    gcc -ansi -pedantic -nostdinc -I /usr/lib/musl/include/ -E test.cpp -o test.cpp.ii
    clang++ -c test.cpp.ii -o test.cpp.o
    

    at least it worked for me. I hope it will be useful for you.

    You can fill a bug to glibc to not define those attributes at least for -pedantic.