[llvm-bugs] [Bug 24754] New: Possible defect in implementation of clang compiler headers, vis-a-vis include_next

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Sep 8 18:20:17 PDT 2015


https://llvm.org/bugs/show_bug.cgi?id=24754

            Bug ID: 24754
           Summary: Possible defect in implementation of clang compiler
                    headers, vis-a-vis include_next
           Product: new-bugs
           Version: unspecified
          Hardware: PC
                OS: MacOS X
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: nikkoara at hates.ms
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

My platform is Mac OSX, stock clang. Taking the case of the header stdint.h:

$ cat t.cpp
#include <stdint.h>

int main () {
    return uint8_t ();
}

Notice the way the compiler internal stdint.h header includes the system
stdint.h which, in turn, includes the other relevant headers:

$ clang -E t.cpp
# 1 "t.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 326 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "t.cpp" 2
# 1
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h"
1 3 4
# 63
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h"
3 4
# 1 "/usr/include/stdint.h" 1 3 4
# 18 "/usr/include/stdint.h" 3 4
# 1 "/usr/include/sys/_types/_int8_t.h" 1 3 4
# 30 "/usr/include/sys/_types/_int8_t.h" 3 4
typedef __signed char int8_t;
[...]
$

This is accomplished through the following steps:

1. First include finds and includes the compiler internal as a system include
2. That header include_next the same header, search finds system header

However, including directly the compiler header:

$ cat t.cpp
#include
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h"

int main () {
    return uint8_t ();
}

does not result in the inclusion of the system header and the compilation
fails:

$ clang -c -v t.cpp
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"
[...] -o t.o -x c++ t.cpp
clang -cc1 version 6.1.0 based upon LLVM 3.6.0svn default target
x86_64-apple-darwin14.5.0
ignoring nonexistent directory "/usr/include/c++/v1"
ignoring nonexistent directory "/usr/local/include"
#include "..." search starts here:
#include <...> search starts here:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
In file included from t.cpp:1:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h:31:24:
warning:
[...]
t.cpp:4:12: error: use of undeclared identifier 'uint8_t'
    return uint8_t ();
           ^
2 warnings and 1 error generated.

Notice how the compiler header includes itself, recursively, via the
include_next at line 63:

$ clang -E t.cpp
# 1 "t.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 326 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "t.cpp" 2
# 1
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h"
1
In file included from t.cpp:1:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h:31:24:
warning:
      #include_next with absolute path
#if __STDC_HOSTED__ && __has_include_next(<stdint.h>)
                       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h:63:3:
warning:
      #include_next with absolute path
# include_next <stdint.h>
  ^
# 63
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h"
# 1
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h"
1 3 4
# 64
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.1.0/include/stdint.h"
2
# 2 "t.cpp" 2

int main () {
    return uint8_t ();
}
2 warnings generated.

Here is the thing.

The compiler stdint.h is guarded in a classical manner, which prevents
recursive includes. This prevents the including of the system header when the
compiler header is included directly. Such a direct inclusion would be used,
e.g., by an alternative implementation of the C++ Standard Library. Regardless,
the direct inclusion of the compiler header should not result in a different
behavior.

Contrast this implementation of stdint.h with the GNU Linux/GCC stdint.h, for
the same headers:

$ cat t.cpp
#include "/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h"

int main () {
    return uint8_t ();
}

$ gcc -E t.cpp
# 1 "t.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "t.cpp"
# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h" 1
# 9 "/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h"
# 1 "/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h" 1 3 4
# 9 "/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h" 3 4
# 1 "/usr/include/stdint.h" 1 3 4
# 25 "/usr/include/stdint.h" 3 4
[...]
$

Notice the recursive include above. The structure of the compiler internal is:

$ cat /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h
#ifndef _GCC_WRAP_STDINT_H
#if __STDC_HOSTED__
# if defined __cplusplus && __cplusplus >= 201103L
#  undef __STDC_LIMIT_MACROS
#  define __STDC_LIMIT_MACROS
#  undef __STDC_CONSTANT_MACROS
#  define __STDC_CONSTANT_MACROS
# endif
# include_next <stdint.h>
#else
# include "stdint-gcc.h"
#endif
#define _GCC_WRAP_STDINT_H
#endif

Notice the different guarding which does not prevent a recursive include in the
scenario detailed above. It seems that the gcc header implementation explicitly
addresses this situation.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20150909/295d7ba4/attachment-0001.html>


More information about the llvm-bugs mailing list