diff options
Diffstat (limited to 'tests/t0058-variadic-macros.sh')
| -rwxr-xr-x | tests/t0058-variadic-macros.sh | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/tests/t0058-variadic-macros.sh b/tests/t0058-variadic-macros.sh new file mode 100755 index 0000000..584e980 --- /dev/null +++ b/tests/t0058-variadic-macros.sh @@ -0,0 +1,135 @@ +#!/bin/sh +set -eu +base="${TMPDIR-/tmp}/mcpu-cpp-variadic-$$" +mkdir -p "$base" +trap 'rm -rf "$base"' EXIT HUP INT TERM + +cat > "$base/main.c" <<'EOT' +#define A 7 +#define SUM(X, Y) X + Y +#define V(...) <__VA_ARGS__> +#define F(first, ...) first | __VA_ARGS__ +#define STRV(...) #__VA_ARGS__ +#define LEFT(...) pre ## __VA_ARGS__ +#define RIGHT(...) __VA_ARGS__ ## post +#define CALL(FN, ...) FN(__VA_ARGS__) +#define WRAP(...) V(__VA_ARGS__) +#define ID(X) X +#define РУССКИЙ(первый, ...) первый : __VA_ARGS__ + +V(alpha, beta, gamma) +V() +F(one, two, three) +F(one) +F(one,) +F(A, SUM(1, 2)) +STRV(A, b + c) +LEFT(fix) +LEFT() +RIGHT(fix) +RIGHT() +CALL(ID, A) +WRAP(A, SUM(3, 4)) +РУССКИЙ(один, два, три) +EOT + +"$MCPU_CPP" --no-config "$base/main.c" -o "$base/out" + +grep -Fx '<alpha, beta, gamma>' "$base/out" >/dev/null +grep -Fx '<>' "$base/out" >/dev/null +grep -Fx 'one | two, three' "$base/out" >/dev/null +# Both an omitted variadic tail and an explicitly empty one expand to no tokens. +test "$(grep -Fxc 'one | ' "$base/out")" -eq 2 +grep -Fx '7 | 1 + 2' "$base/out" >/dev/null +grep -Fx '"A, b + c"' "$base/out" >/dev/null +grep -Fx 'prefix' "$base/out" >/dev/null +grep -Fx 'pre' "$base/out" >/dev/null +grep -Fx 'fixpost' "$base/out" >/dev/null +grep -Fx 'post' "$base/out" >/dev/null +grep -Fx '7' "$base/out" >/dev/null +grep -Fx '<7, 3 + 4>' "$base/out" >/dev/null +grep -Fx 'один : два, три' "$base/out" >/dev/null + +# The variable argument is preserved as such when macro definitions are dumped. +"$MCPU_CPP" --no-config -dM "$base/main.c" > "$base/dump" +grep -Fx '#define V(...) <__VA_ARGS__>' "$base/dump" >/dev/null +grep -Fx '#define F(first,...) first | __VA_ARGS__' "$base/dump" >/dev/null +grep -Fx '#define STRV(...) #__VA_ARGS__' "$base/dump" >/dev/null +grep -Fx '#define РУССКИЙ(первый,...) первый : __VA_ARGS__' "$base/dump" >/dev/null + + +# Variadic-ness is part of a macro definition. Repeating the same variadic +# definition is harmless, while changing a non-variadic definition into a +# variadic one is a real redefinition and therefore participates in -Werror. +cat > "$base/redefine-same.c" <<'EOT' +#define SAME(x, ...) x | __VA_ARGS__ +#define SAME(x, ...) x | __VA_ARGS__ +SAME(1, 2) +EOT +"$MCPU_CPP" --no-config "$base/redefine-same.c" \ + -o "$base/redefine-same.out" 2>"$base/redefine-same.err" +test ! -s "$base/redefine-same.err" +grep -Fx '1 | 2' "$base/redefine-same.out" >/dev/null + +cat > "$base/redefine-kind.c" <<'EOT' +#define CHANGE(x) x +#define CHANGE(x, ...) x | __VA_ARGS__ +EOT +if "$MCPU_CPP" --no-config -Werror "$base/redefine-kind.c" \ + -o "$base/redefine-kind.out" 2>"$base/redefine-kind.err"; then + echo 'variadic/non-variadic redefinition escaped -Werror' >&2 + exit 1 +fi +grep "error: macro 'CHANGE' redefined" "$base/redefine-kind.err" >/dev/null + +# A variadic macro may have fixed parameters, but those fixed parameters are +# still required. An empty spelling counts as an argument, just as it does +# for ordinary function-like macros. +cat > "$base/few.c" <<'EOT' +#define NEEDS_TWO(a, b, ...) a + b + __VA_ARGS__ +NEEDS_TWO(1) +EOT +if "$MCPU_CPP" --no-config "$base/few.c" -o "$base/few.out" 2>"$base/few.err"; then + echo 'variadic macro accepted too few fixed arguments' >&2 + exit 1 +fi +grep "macro 'NEEDS_TWO' used with too few arguments" "$base/few.err" >/dev/null + +# The old GNU named variadic form is deliberately outside the 0.0.46 +# contract. Only the C99-style ... + __VA_ARGS__ form is accepted. +cat > "$base/named.c" <<'EOT' +#define OLD(args...) args +EOT +if "$MCPU_CPP" --no-config "$base/named.c" -o "$base/named.out" 2>"$base/named.err"; then + echo 'GNU named variadic macro form unexpectedly accepted' >&2 + exit 1 +fi +grep 'badly punctuated parameter list in #define' "$base/named.err" >/dev/null + +cat > "$base/malformed.c" <<'EOT' +#define BAD(..., x) x +EOT +if "$MCPU_CPP" --no-config "$base/malformed.c" -o "$base/malformed.out" 2>"$base/malformed.err"; then + echo 'parameters after ... unexpectedly accepted' >&2 + exit 1 +fi +grep 'badly punctuated parameter list in #define' "$base/malformed.err" >/dev/null + +cat > "$base/reserved.c" <<'EOT' +#define BAD(__VA_ARGS__) __VA_ARGS__ +EOT +if "$MCPU_CPP" --no-config "$base/reserved.c" -o "$base/reserved.out" 2>"$base/reserved.err"; then + echo '__VA_ARGS__ unexpectedly accepted as an ordinary parameter name' >&2 + exit 1 +fi +grep "'__VA_ARGS__' cannot be used as a macro parameter name" "$base/reserved.err" >/dev/null + +# A replacement using #__VA_ARGS__ is valid only for a variadic macro. +cat > "$base/not-variadic.c" <<'EOT' +#define BAD(x) #__VA_ARGS__ +EOT +if "$MCPU_CPP" --no-config "$base/not-variadic.c" -o "$base/not-variadic.out" 2>"$base/not-variadic.err"; then + echo '#__VA_ARGS__ unexpectedly accepted in a non-variadic macro' >&2 + exit 1 +fi +grep "'#' operator should be followed by a macro argument name" "$base/not-variadic.err" >/dev/null |
