make/tests/scripts/features/conditionals
Paul Smith c59cc4f932 [SV 64185] Clarify handling of directive lines starting with TAB
It's clear that this change causes too many problems to be made
without warning.  Revert the change disallowing conditional lines to
start with TAB.

Instead, generate warnings whenever a directive line begins with a
TAB character.  Make this change for all directives, not just
conditional directives: define, undefine, export, unexport, vpath,
load, include, etc.

* NEWS: Update the backward-compatibility warning.
* src/read.c (eval): Track whether the line starts with a TAB.
If so then whenever we recognize a directive, emit a warning.
Revert the previous change for this bug.
(parse_var_assignment): Accept a file location if the line begins
with TAB; show a warning if we discover a directive.
(conditional_line): Warn about lines starting with TAB.
* tests/scripts/...: Add tests to verify warnings for initial TAB.
2025-08-26 08:13:55 -04:00

313 lines
5.4 KiB
Perl

# -*-perl-*-
$description = "Check GNU Make conditionals.";
$details = "Attempt various different flavors of GNU Make conditionals.";
run_make_test(q!
arg1 = first
arg2 = second
arg3 = third
arg4 = cc
arg5 = second
all:
ifeq ($(arg1),$(arg2))
#TAB#@echo arg1 equals arg2
else
#TAB#@echo arg1 NOT equal arg2
endif
ifeq '$(arg2)' "$(arg5)"
#TAB#@echo arg2 equals arg5
else
#TAB#@echo arg2 NOT equal arg5
endif
ifneq '$(arg3)' '$(arg4)'
#TAB#@echo arg3 NOT equal arg4
else
#TAB#@echo arg3 equal arg4
endif
ifndef undefined
#TAB#@echo variable is undefined
else
#TAB#@echo variable undefined is defined
endif
ifdef arg4
#TAB#@echo arg4 is defined
else
#TAB#@echo arg4 is NOT defined
endif!,
'',
'arg1 NOT equal arg2
arg2 equals arg5
arg3 NOT equal arg4
variable is undefined
arg4 is defined');
# Test expansion of variables inside ifdef.
run_make_test(q!
foo = 1
FOO = foo
F = f
DEF = no
DEF2 = no
ifdef $(FOO)
DEF = yes
endif
ifdef $(F)oo
DEF2 = yes
endif
DEF3 = no
FUNC = $1
ifdef $(call FUNC,DEF)3
DEF3 = yes
endif
all:; @echo DEF=$(DEF) DEF2=$(DEF2) DEF3=$(DEF3)!,
'',
'DEF=yes DEF2=yes DEF3=yes');
# Test all the different "else if..." constructs
run_make_test(q!
arg1 = first
arg2 = second
arg3 = third
arg4 = cc
arg5 = fifth
result =
ifeq ($(arg1),$(arg2))
result += arg1 equals arg2
else ifeq '$(arg2)' "$(arg5)"
result += arg2 equals arg5
else ifneq '$(arg3)' '$(arg3)'
result += arg3 NOT equal arg4
else ifndef arg5
result += variable is undefined
else ifdef undefined
result += arg4 is defined
else
result += success
endif
all: ; @echo $(result)!,
'',
'success');
# Test some random "else if..." construct nesting
run_make_test(q!
arg1 = first
arg2 = second
arg3 = third
arg4 = cc
arg5 = second
ifeq ($(arg1),$(arg2))
$(info failed 1)
else ifeq '$(arg2)' "$(arg2)"
ifdef undefined
$(info failed 2)
else
$(info success)
endif
else ifneq '$(arg3)' '$(arg3)'
$(info failed 3)
else ifdef arg5
$(info failed 4)
else ifdef undefined
$(info failed 5)
else
$(info failed 6)
endif
.PHONY: all
all: ; @:!,
'',
'success');
# SV 47960 : ensure variable assignments in non-taken legs don't cause problems
run_make_test(q!
ifneq ($(FOO),yes)
target:
else
BAR = bar
target:
endif
#TAB#@echo one
!,
'', "one\n");
# SV 64085: Ensure tab-prefixed conditional directives are warned about
# In a future release these will become errors: according to the docs this
# was never allowed, but unfortunately the code didn't check for it.
my @defcond = ('ifdef', 'ifndef');
my @eqcond = ('ifeq', 'ifneq');
for my $d (@defcond) {
run_make_test(qq!
blah=1
#TAB#$d blah
endif
all:;
!,
'', "#MAKEFILE#:3: warning: conditional directive lines cannot start with TAB\n#MAKE#: 'all' is up to date.");
}
for my $d (@eqcond) {
run_make_test(qq!
blah=1
#TAB#$d (a,b)
endif
all:;
!,
'', "#MAKEFILE#:3: warning: conditional directive lines cannot start with TAB\n#MAKE#: 'all' is up to date.");
}
run_make_test(q!
ifeq (a, b)
#TAB## noop
else
#TAB#ifeq (a, b)
#TAB##TAB## noop
#TAB#endif
endif
all:
#TAB#@echo foo
!,
'', "#MAKEFILE#:5: warning: conditional directive lines cannot start with TAB\n#MAKEFILE#:7: warning: conditional directive lines cannot start with TAB\nfoo");
run_make_test(q!
all:
$(info hello)
ifdef blah
junk:
#TAB#else
else
endif
!,
'', "hello\n#MAKEFILE#:7: warning: conditional directive lines cannot start with TAB\n#MAKEFILE#:8: *** only one 'else' per conditional. Stop.",
512);
run_make_test(q!
blah=1
ifdef blah
else
#TAB#else
endif
all:;
!,
'', "#MAKEFILE#:5: warning: conditional directive lines cannot start with TAB\n#MAKEFILE#:5: *** only one 'else' per conditional. Stop.",
512);
run_make_test(q!
blah=1
ifdef blah
else
#TAB#endif
endif
all:;
!,
'', "#MAKEFILE#:5: warning: conditional directive lines cannot start with TAB\n#MAKEFILE#:6: *** extraneous 'endif'. Stop.",
512);
run_make_test(q!
blah=1
ifdef blah
else
#TAB#ifdef blah
endif
all:;
!,
'', "#MAKEFILE#:5: warning: conditional directive lines cannot start with TAB\n#MAKEFILE#:8: *** missing 'endif'. Stop.",
512);
run_make_test(q!
blah=1
all:;
foo:
ifdef blah
#TAB#ifdef blah
endif
!,
'', "#MAKE#: 'all' is up to date.");
run_make_test(q!
blah=1
all:;
foo:
ifdef blah
#TAB#endif
endif
!,
'', "#MAKE#: 'all' is up to date.");
run_make_test(q!
blah=1
all:;
foo:
ifdef blah
#TAB#else
else
endif
!,
'', "#MAKE#: 'all' is up to date.");
# SV 64402: parse braces in ifeq/ifneq properly
run_make_test(q!
ifeq ($(and a,b),)
endif
ifeq (${and a,b},)
endif
ifeq (${and $(x),${or $(z),${q}}},)
endif
ifeq (${and ),(},)
endif
ifeq ($(and },{),)
endif
# We can hide the comma in a variable
C = ,
ifeq ((and a$Cb),)
endif
all:;
!,
'', "#MAKE#: 'all' is up to date.");
# The "," in "$," is a variable name not a comma
run_make_test(q!
ifeq ($,,)
$(info ok)
endif
all:;
!,
'', "ok\n#MAKE#: 'all' is up to date.");
# Without variable references we don't do anything special with parens
run_make_test(q!
ifeq ((and a,b),)
endif
all:;
!,
'', "#MAKEFILE#:2: extraneous text after 'ifeq' directive\n#MAKE#: 'all' is up to date.");
# This tells the test driver that the perl test script executed properly.
1;