summaryrefslogtreecommitdiff
path: root/tests/t0057-missing-generated-dependencies.sh
diff options
context:
space:
mode:
Diffstat (limited to 'tests/t0057-missing-generated-dependencies.sh')
-rwxr-xr-xtests/t0057-missing-generated-dependencies.sh166
1 files changed, 166 insertions, 0 deletions
diff --git a/tests/t0057-missing-generated-dependencies.sh b/tests/t0057-missing-generated-dependencies.sh
new file mode 100755
index 0000000..7ad5001
--- /dev/null
+++ b/tests/t0057-missing-generated-dependencies.sh
@@ -0,0 +1,166 @@
+#!/bin/sh
+set -eu
+
+base="${TMPDIR-/tmp}/mcpu-cpp-missing-generated-deps-$$"
+mkdir -p "$base/user" "$base/sys"
+trap 'rm -rf "$base"' EXIT HUP INT TERM
+
+cd "$base"
+
+cat > main.c <<'EOT'
+#include "generated-user.h"
+#include <generated-system.h>
+#define GENERATED_MACRO_HEADER "generated-macro.h"
+#include GENERATED_MACRO_HEADER
+EOT
+
+# Without -MG, the first unresolved include remains a hard error.
+if "$MCPU_CPP" --no-config -M main.c > no-mg.out 2> no-mg.err; then
+ echo "missing include unexpectedly succeeded without -MG" >&2
+ exit 1
+fi
+grep "cannot find include file 'generated-user.h'" no-mg.err >/dev/null
+
+# -M -MG records unresolved operands exactly as written and does not diagnose
+# them as missing files. Macro-expanded include operands use their expanded
+# filename.
+"$MCPU_CPP" --no-config -M -MG main.c > M.d 2> M.err
+test ! -s M.err
+grep '^main\.o:' M.d >/dev/null
+for f in main.c generated-user.h generated-system.h generated-macro.h
+do
+ grep -F "$f" M.d >/dev/null || {
+ echo "-M -MG omitted unresolved dependency: $f" >&2
+ exit 1
+ }
+done
+
+# -MM retains unresolved quoted/user includes but filters unresolved angle
+# includes as system-class dependencies.
+"$MCPU_CPP" --no-config -MM -MG main.c > MM.d
+grep -F 'generated-user.h' MM.d >/dev/null
+grep -F 'generated-macro.h' MM.d >/dev/null
+if grep -F 'generated-system.h' MM.d >/dev/null; then
+ echo "-MM -MG kept unresolved angle/system dependency" >&2
+ exit 1
+fi
+
+# Missing dependencies reached from a real system header inherit system
+# context, even when the nested directive uses quotes. User-header quoted
+# descendants remain user dependencies.
+cat > sys/system-parent.h <<'EOT'
+#include "generated-from-system.h"
+EOT
+cat > user/user-parent.h <<'EOT'
+#include "generated-from-user.h"
+EOT
+cat > nested.c <<'EOT'
+#include <system-parent.h>
+#include <user-parent.h>
+EOT
+
+"$MCPU_CPP" --no-config -MM -MG -I user -isystem sys nested.c > nested-MM.d
+grep -F 'user/user-parent.h' nested-MM.d >/dev/null
+grep -F 'generated-from-user.h' nested-MM.d >/dev/null
+if grep -F 'sys/system-parent.h' nested-MM.d >/dev/null ||
+ grep -F 'generated-from-system.h' nested-MM.d >/dev/null; then
+ echo "-MM -MG kept system-context dependency" >&2
+ exit 1
+fi
+
+"$MCPU_CPP" --no-config -M -MG -I user -isystem sys nested.c > nested-M.d
+grep -F 'sys/system-parent.h' nested-M.d >/dev/null
+grep -F 'generated-from-system.h' nested-M.d >/dev/null
+
+# Unresolved dependency identity is textual and separate from physical
+# st_dev/st_ino identity. shadow.h exists in CWD, but <shadow.h> is not found
+# through the angle search chain under --no-config; a later quoted ./shadow.h
+# resolves that physical file. Both registry entries must survive under -M.
+cat > shadow.h <<'EOT'
+#define SHADOW_VALUE 1
+EOT
+cat > identity.c <<'EOT'
+#include <shadow.h>
+#include "./shadow.h"
+EOT
+"$MCPU_CPP" --no-config -M -MG identity.c > identity-M.d
+grep '^identity\.o: identity\.c shadow\.h \./\./shadow\.h$' identity-M.d >/dev/null || {
+ echo "unresolved and physical dependency identities were incorrectly merged" >&2
+ cat identity-M.d >&2
+ exit 1
+}
+
+# In -MM the unresolved angle entry is filtered, while the resolved quoted
+# physical dependency remains.
+"$MCPU_CPP" --no-config -MM -MG identity.c > identity-MM.d
+grep -F '././shadow.h' identity-MM.d >/dev/null
+case "$(cat identity-MM.d)" in
+ *' shadow.h '*)
+ echo "-MM kept the unresolved angle dependency" >&2
+ exit 1
+ ;;
+esac
+
+# Repeated unresolved operands are deduplicated textually. Their first
+# classification is retained, matching GNU CPP: angle-first stays system-only,
+# while quote-first stays visible to -MM.
+cat > first-system.c <<'EOT'
+#include <same-missing.h>
+#include "same-missing.h"
+EOT
+"$MCPU_CPP" --no-config -MM -MG first-system.c > first-system.d
+if grep -F 'same-missing.h' first-system.d >/dev/null; then
+ echo "angle-first unresolved dependency lost its first classification" >&2
+ exit 1
+fi
+
+cat > first-user.c <<'EOT'
+#include "same-missing.h"
+#include <same-missing.h>
+EOT
+"$MCPU_CPP" --no-config -MM -MG first-user.c > first-user.d
+grep -F 'same-missing.h' first-user.d >/dev/null
+
+# Different unresolved spellings are distinct because no physical identity is
+# available to canonicalize them.
+cat > spelling.c <<'EOT'
+#include "generated.h"
+#include "./generated.h"
+EOT
+"$MCPU_CPP" --no-config -M -MG spelling.c > spelling.d
+grep -F ' generated.h' spelling.d >/dev/null
+grep -F ' ./generated.h' spelling.d >/dev/null
+
+# -MG also applies to missing command-line forced files. They enter the same
+# unresolved registry as user dependencies and preserve the command-line
+# operand; no synthetic path is prepended.
+: > forced.c
+"$MCPU_CPP" --no-config -M -MG \
+ -imacros missing-macros.h -include missing-include.h forced.c > forced-M.d
+grep -F 'missing-macros.h' forced-M.d >/dev/null
+grep -F 'missing-include.h' forced-M.d >/dev/null
+
+"$MCPU_CPP" --no-config -MM -MG \
+ -imacros missing-macros.h -include missing-include.h forced.c > forced-MM.d
+grep -F 'missing-macros.h' forced-MM.d >/dev/null
+grep -F 'missing-include.h' forced-MM.d >/dev/null
+
+# -MG is dependency-only: GNU permits it with -M/-MM, not side-effect -MD/-MMD
+# and not without dependency generation.
+for opts in '-MG' '-MD -MG' '-MMD -MG'
+do
+ if "$MCPU_CPP" --no-config $opts forced.c > invalid.out 2> invalid.err; then
+ echo "$opts unexpectedly accepted" >&2
+ exit 1
+ fi
+ grep -- '-MG may only be used with -M or -MM' invalid.err >/dev/null
+done
+
+# Explicit dependency targets continue to compose with -MG.
+"$MCPU_CPP" --no-config -M -MG -MT generated-target.o main.c > target.d
+grep '^generated-target\.o:' target.d >/dev/null
+grep -F 'generated-user.h' target.d >/dev/null
+
+# Public help exposes the implemented option.
+"$MCPU_CPP" --help > help.out
+grep '^ -MG treat missing headers as generated dependencies$' help.out >/dev/null