]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bmake/unit-tests/varname-empty.mk
Update to bmake-20201101
[FreeBSD/FreeBSD.git] / contrib / bmake / unit-tests / varname-empty.mk
1 # $NetBSD: varname-empty.mk,v 1.7 2020/10/23 17:53:01 rillig Exp $
2 #
3 # Tests for the special variable with the empty name.
4 #
5 # There is no variable named "" at all, and this fact is used a lot in
6 # variable expressions of the form ${:Ufallback}.  These expressions are
7 # based on the variable named "" and use the :U modifier to assign a
8 # fallback value to the expression (but not to the variable).
9 #
10 # This form of expressions is used to implement value substitution in the
11 # .for loops.  Another use case is in a variable assignment of the form
12 # ${:Uvarname}=value, which allows for characters in the variable name that
13 # would otherwise be interpreted by the parser, such as whitespace, ':',
14 # '=', '$', backslash.
15 #
16 # The only places where a variable is assigned a value are Var_Set and
17 # Var_Append, and these places protect the variable named "" from being
18 # defined.  This is different from read-only variables, as that flag can
19 # only apply to variables that are defined.  The variable named "" must
20 # never be defined though.
21 #
22 # See also:
23 #       The special variables @F or ^D, in var-class-local.mk
24
25 # Until 2020-08-22 it was possible to assign a value to the variable with
26 # the empty name, leading to all kinds of unexpected effects in .for loops
27 # and other places that assume that ${:Ufallback} expands to "fallback".
28 # The bug in Var_Set was that only expanded variables had been checked for
29 # the empty name, but not the direct assignments with an empty name.
30 ?=      default
31 =       assigned        # undefined behavior until 2020-08-22
32 +=      appended
33 :=      subst
34 !=      echo 'shell-output'
35 .if ${:Ufallback} != "fallback"
36 .  error
37 .endif
38
39 ${:U}=  assigned indirectly
40 .if ${:Ufallback} != "fallback"
41 .  error
42 .endif
43
44 # Before 2020-08-22, the simple assignment operator '=' after an empty
45 # variable name had an off-by-one bug in Parse_DoVar.  The code that was
46 # supposed to "skip to operator character" started its search _after_ the
47 # assignment operator, assuming that the variable name would be at least
48 # one character long.  It then looked for the next occurrence of a '=', which
49 # could be several lines away or not occur at all.  While looking for the
50 # '=', some whitespace was nulled out, leading to out-of-bounds write.
51 =       assigned        # undefined behavior until 2020-08-22
52
53 # The .for loop expands the expression ${i} to ${:U1}, ${:U2} and so on.
54 # This only works if the variable with the empty name is guaranteed to
55 # be undefined.
56 .for i in 1 2 3
57 NUMBERS+=       ${i}
58 .endfor
59
60 all:
61         @echo out: ${:Ufallback}
62         @echo out: ${NUMBERS}