blob: a2d86c3f95a7ea5187f60e3b3332fa4d8a44bf6d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
#!/bin/sh
set -eu
base="${TMPDIR-/tmp}/mcpu-cpp-include-next-$$"
mkdir -p "$base/wrapper" "$base/system" "$base/after" "$base/local"
trap 'rm -rf "$base"' EXIT HUP INT TERM
cat > "$base/config" <<EOT
MCPU_CPP_SYSTEM_INCLUDE_PATH = $base/system;
EOT
cat > "$base/main.c" <<'EOT'
#include <wrapped.h>
#include "local/local.h"
#if 0
#include_next <never.h>
#endif
EOT
cat > "$base/wrapper/wrapped.h" <<'EOT'
wrapper_begin
#line 500 "virtual/wrapped.h"
#define NEXT_WRAPPED <wrapped.h>
#include_next NEXT_WRAPPED
wrapper_end
EOT
cat > "$base/system/wrapped.h" <<'EOT'
system_begin
#include_next "wrapped.h"
system_end
EOT
cat > "$base/after/wrapped.h" <<'EOT'
after_header
EOT
cat > "$base/local/local.h" <<'EOT'
local_header
#include_next <from_chain.h>
EOT
cat > "$base/wrapper/from_chain.h" <<'EOT'
from_chain_wrapper
EOT
"$MCPU_CPP" --config-file "$base/config" \
-isystem "$base/wrapper" -idirafter "$base/after" \
"$base/main.c" -o "$base/out"
# The wrapper header found through -isystem continues into the configured
# system include root, then that header continues into -idirafter. The quote
# form of #include_next must not re-search the current source directory.
awk '
/wrapper_begin/ { a = NR }
/system_begin/ { b = NR }
/after_header/ { c = NR }
/system_end/ { d = NR }
/wrapper_end/ { e = NR }
END { exit !(a && a < b && b < c && c < d && d < e) }
' "$base/out"
# A header found by ordinary quoted-source-directory lookup has no configured
# search entry to skip, so include_next begins with the configured chain.
grep '^local_header$' "$base/out" >/dev/null
grep '^from_chain_wrapper$' "$base/out" >/dev/null
# Macro-expanded include_next operands use the same include operand parser.
grep '^system_begin$' "$base/out" >/dev/null
# Inactive conditional branches must not execute include_next.
! grep 'never.h' "$base/out" >/dev/null
# If no later search entry contains the file, include_next is an error rather
# than falling back to the directory that supplied the current header.
cat > "$base/wrapper/last.h" <<'EOT'
#include_next <last.h>
EOT
cat > "$base/last-main.c" <<'EOT'
#include <last.h>
EOT
if "$MCPU_CPP" --config-file "$base/config" \
-isystem "$base/wrapper" "$base/last-main.c" \
-o "$base/last.out" 2>"$base/last.err"; then
echo '#include_next unexpectedly found the current header again' >&2
exit 1
fi
grep "cannot find include_next file 'last.h'" "$base/last.err" >/dev/null
|