From 2611e1991fabe2a3ae929c6ebd4afbd4f550f306 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Sun, 26 Feb 2023 18:04:14 -0500 Subject: Introduce a --warn command line option Replace the singleton --warn-undefined-variables with infrastructure to manage multiple warnings: the --warn option can take an action "ignore", "warn", or "error" (which will apply to all warnings), or a specific warning type and an action for that type. Multiple options can be provided and are consolidated. * NEWS: Announce the new option. * doc/make.1: Document in the man page. * doc/make.texi (Warnings): Document in the user's manual. * Makefile.am: Add new header warning.h. * src/warning.h: Define enum for actions and warning types, and macros to test whether they are set. Keep the default settings separate so that we can correctly reconstruct MAKEFLAGS. * src/makeint.h: Remove deprecated warn_undefined_variables_flag. * src/main.c: Create global variables to hold warning settings. (switches): Add a new switch for --warn. (initialize_warnings): Set the default warning actions. (main): Call initialize_warnings(). (encode_warning_state, decode_warning_state): Convert warning states between strings and enums. (encode_warning_name, decode_warning_name): Convert warning names between strings and enums. (decode_warn_flags): Convert a --warn option into enum values. If deprecated warn_undefined_variables_flag is set convert it to --warn. (decode_switches): Don't remove duplicates of --warn since order matters. Call decode_warn_flags() to handle --warn. (define_makeflags): Special-case handling of --warn options written to MAKEFLAGS: write out the current settings. * src/read.c (tilde_expand): Use new warning control macros. * src/variable.c (warn_undefined): Ditto. * src/job.c (construct_command_argv): Ditto. * tests/scripts/options/warn: Rename from warn-undefined-variables and add tests for --warn. * tests/scripts/variables/MAKEFLAGS: Expect the new behavior. --- tests/scripts/options/warn | 86 ++++++++++++++++++++++++++ tests/scripts/options/warn-undefined-variables | 49 --------------- tests/scripts/variables/MAKEFLAGS | 14 ++--- 3 files changed, 93 insertions(+), 56 deletions(-) create mode 100644 tests/scripts/options/warn delete mode 100644 tests/scripts/options/warn-undefined-variables (limited to 'tests') diff --git a/tests/scripts/options/warn b/tests/scripts/options/warn new file mode 100644 index 00000000..98155d46 --- /dev/null +++ b/tests/scripts/options/warn @@ -0,0 +1,86 @@ +# -*-perl-*- + +$description = "Test the --warn option."; + +my %warn_test = ( + '--warn' => '', '--warn=warn' => '', '--warn=error --warn=warn' => '', + '--warn --warn=error' => '=error', + '--warn=ignore --warn=error --warn=ignore --warn=undefined-var' => '=ignore,undefined-var', + '--warn=undefined-var:error --warn' => '=warn,undefined-var:error' +); + +# Verify the deprecated --warn-undefined-variables option +run_make_test(q! +$(info MF=$(MAKEFLAGS)) +all:; @#HELPER# env MAKEFLAGS +!, + '--warn-undefined-variables', "MF= --warn=undefined-var\nMAKEFLAGS= --warn=undefined-var"); + +# Verify parsing of --warn in various forms. + +while (my ($f, $r) = each %warn_test) { + run_make_test(undef, $f, "MF= --warn$r\nMAKEFLAGS= --warn$r"); +} + +# Verify that values set in MAKEFLAGS take effect + +while (my ($f, $r) = each %warn_test) { + run_make_test(qq! +MAKEFLAGS += $f +\$(info MF=\$(MAKEFLAGS)) +all:; \@#HELPER# env MAKEFLAGS +!, + '', "MF= --warn$r\nMAKEFLAGS= --warn$r"); +} + +# Verify that make's special variables don't warn even if they're not set +run_make_test(q! +vars := $(.VARIABLES) $(MAKECMDGOALS) $(MAKE_RESTARTS) $(CURDIR) +vars += $(GNUMAKEFLAGS) $(MAKEFLAGS) $(MFLAGS) $(MAKE_COMMAND) $(MAKE) +vars += $(MAKEFILE_LIST) $(MAKEOVERRIDES) $(-*-command-variables-*-) +vars += $(.RECIPEPREFIX) $(.LOADED) $(.FEATURES) +vars += $(SHELL) $(.SHELLFLAGS) $(MAKE_TERMOUT) $(MAKE_TERMERR) +vars += $(.DEFAULT) $(.DEFAULT_GOAL) $(-*-eval-flags-*-) $(SUFFIXES) +vars += $(VPATH) $(GPATH) +all:; +!, + '--warn=undefined-var', "#MAKE#: 'all' is up to date."); + +# sv 63609. +# Test for buffer overrun in warn_undefined. +run_make_test(q! +all:; +X := $(averyveryveryloooooooooooooooooooooooooooongvariablename) +!, + '--warn=undefined-var', + "#MAKEFILE#:3: reference to undefined variable 'averyveryveryloooooooooooooooooooooooooooongvariablename' +#MAKE#: 'all' is up to date.\n" +); + +# Check undefined variable warnings + +# With no options or with ignore, nothing should happen +run_make_test(' +EMPTY = +EREF = $(EMPTY) +UREF = $(UNDEFINED) + +SEREF := $(EREF) +SUREF := $(UREF) + +all: ; @echo ref $(EREF) $(UREF)', + '', 'ref'); + +run_make_test(undef, '--warn=undefined-var:ignore', 'ref'); + +# Check warnings +run_make_test(undef, '--warn=undefined-var', + "#MAKEFILE#:7: reference to undefined variable 'UNDEFINED' +#MAKEFILE#:9: reference to undefined variable 'UNDEFINED' +ref"); + +# Check and errors +run_make_test(undef, '--warn=undefined-var:error', + "#MAKEFILE#:7: *** reference to undefined variable 'UNDEFINED'. Stop.", 512); + +1; diff --git a/tests/scripts/options/warn-undefined-variables b/tests/scripts/options/warn-undefined-variables deleted file mode 100644 index d9653d2c..00000000 --- a/tests/scripts/options/warn-undefined-variables +++ /dev/null @@ -1,49 +0,0 @@ -# -*-perl-*- - -$description = "Test the --warn-undefined-variables option."; - -$details = "Verify that warnings are printed for referencing undefined variables."; - -# Verify that make's special variables don't warn even if they're not set -run_make_test(q! -vars := $(.VARIABLES) $(MAKECMDGOALS) $(MAKE_RESTARTS) $(CURDIR) -vars += $(GNUMAKEFLAGS) $(MAKEFLAGS) $(MFLAGS) $(MAKE_COMMAND) $(MAKE) -vars += $(MAKEFILE_LIST) $(MAKEOVERRIDES) $(-*-command-variables-*-) -vars += $(.RECIPEPREFIX) $(.LOADED) $(.FEATURES) -vars += $(SHELL) $(.SHELLFLAGS) $(MAKE_TERMOUT) $(MAKE_TERMERR) -vars += $(.DEFAULT) $(.DEFAULT_GOAL) $(-*-eval-flags-*-) $(SUFFIXES) -vars += $(VPATH) $(GPATH) -all:; -!, - '--warn-undefined-variables', "#MAKE#: 'all' is up to date."); - -# Without --warn-undefined-variables, nothing should happen -run_make_test(' -EMPTY = -EREF = $(EMPTY) -UREF = $(UNDEFINED) - -SEREF := $(EREF) -SUREF := $(UREF) - -all: ; @echo ref $(EREF) $(UREF)', - '', 'ref'); - -# With --warn-undefined-variables, it should warn me -run_make_test(undef, '--warn-undefined-variables', - "#MAKEFILE#:7: warning: undefined variable 'UNDEFINED' -#MAKEFILE#:9: warning: undefined variable 'UNDEFINED' -ref"); - -# sv 63609. -# Test for buffer overrun in warn_undefined. -run_make_test(q! -all:; -X := $(averyveryverylongvariablename) -!, - '--warn-undefined-variables', - "#MAKEFILE#:3: warning: undefined variable 'averyveryverylongvariablename' -#MAKE#: 'all' is up to date.\n" -); - -1; diff --git a/tests/scripts/variables/MAKEFLAGS b/tests/scripts/variables/MAKEFLAGS index 32c2ede8..fc18d650 100644 --- a/tests/scripts/variables/MAKEFLAGS +++ b/tests/scripts/variables/MAKEFLAGS @@ -99,7 +99,7 @@ all:; \$(info makeflags='\$(MAKEFLAGS)') # Long options which take no arguments. # sv 62514. -@opts = (' --no-print-directory', ' --warn-undefined-variables', ' --trace'); +@opts = (' --no-print-directory', ' --warn=undefined-var', ' --trace'); for my $fl (@flavors) { for my $opt (@opts) { run_make_test(" @@ -139,19 +139,19 @@ all:; \$(info makeflags='\$(MAKEFLAGS)') # A mix of multiple flags from env, the makefile and command line. # Skip -L since it's not available everywhere for my $fl (@flavors) { -$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn-undefined-variables --trace'; +$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn=undefined-var --trace'; run_make_test(" MAKEFLAGS${fl}iknqrswd -Ilocaltmp -Ilocaltmp -Onone -Onone -l2.5 -l2.5 all:; \$(info makeflags='\$(MAKEFLAGS)') ", '-Onone -l2.5 -l2.5 -Onone -Ilocaltmp -iknqrswd -i -n -s -k -Ilocaltmp', -"/makeflags='Bdiknqrsw -Ilocaltmp -l2.5 -Onone --trace --warn-undefined-variables'/"); +"/makeflags='Bdiknqrsw -Ilocaltmp -l2.5 -Onone --trace --warn=undefined-var'/"); } # Verify MAKEFLAGS are all available to shell function at parse time. for my $fl (@flavors) { -my $answer = 'Biknqrs -Ilocaltmp -l2.5 -Onone --no-print-directory --warn-undefined-variables'; -$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn-undefined-variables'; +my $answer = 'Biknqrs -Ilocaltmp -l2.5 -Onone --no-print-directory --warn=undefined-var'; +$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn=undefined-var'; run_make_test(" MAKEFLAGS${fl}iknqrsw -Ilocaltmp -Ilocaltmp -Onone -Onone -l2.5 -l2.5 --no-print-directory \$(info at parse time '\$(MAKEFLAGS)') @@ -165,8 +165,8 @@ at build time makeflags='$answer'"); # Verify MAKEFLAGS and command line definitions are all available to shell function at parse time. for my $fl (@flavors) { -$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn-undefined-variables'; -my $answer = 'Biknqrs -Ilocaltmp -l2.5 -Onone --no-print-directory --warn-undefined-variables -- hello=world'; +$ENV{'MAKEFLAGS'} = 'ikB --no-print-directory --warn=undefined-var'; +my $answer = 'Biknqrs -Ilocaltmp -l2.5 -Onone --no-print-directory --warn=undefined-var -- hello=world'; run_make_test(" MAKEFLAGS${fl}iknqrsw -Ilocaltmp -Ilocaltmp -Onone -Onone -l2.5 -l2.5 --no-print-directory \$(info at parse time '\$(MAKEFLAGS)') -- cgit v1.2.1