<html>
<head>
<base href="https://llvm.org/bugs/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - Possible defect in implementation of clang compiler headers, vis-a-vis include_next"
href="https://llvm.org/bugs/show_bug.cgi?id=24754">24754</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Possible defect in implementation of clang compiler headers, vis-a-vis include_next
</td>
</tr>
<tr>
<th>Product</th>
<td>new-bugs
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>MacOS X
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>new bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>nikkoara@hates.ms
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr></table>
<p>
<div>
<pre>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.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>