summaryrefslogtreecommitdiff
path: root/tests/t0043-include-next.sh
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