Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make tests/make: demonstrate edge case that evaluate...



details:   https://anonhg.NetBSD.org/src/rev/ca2f7157d2b1
branches:  trunk
changeset: 1029286:ca2f7157d2b1
user:      rillig <rillig%NetBSD.org@localhost>
date:      Thu Dec 30 02:14:55 2021 +0000

description:
tests/make: demonstrate edge case that evaluates an expression twice

diffstat:

 usr.bin/make/cond.c                          |   8 ++--
 usr.bin/make/unit-tests/cond-token-plain.exp |   1 +
 usr.bin/make/unit-tests/cond-token-plain.mk  |  49 ++++++++++++++++++++++++++-
 3 files changed, 51 insertions(+), 7 deletions(-)

diffs (100 lines):

diff -r c8942620c29f -r ca2f7157d2b1 usr.bin/make/cond.c
--- a/usr.bin/make/cond.c       Thu Dec 30 01:34:26 2021 +0000
+++ b/usr.bin/make/cond.c       Thu Dec 30 02:14:55 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cond.c,v 1.320 2021/12/30 01:34:26 rillig Exp $        */
+/*     $NetBSD: cond.c,v 1.321 2021/12/30 02:14:55 rillig Exp $        */
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -95,7 +95,7 @@
 #include "dir.h"
 
 /*     "@(#)cond.c     8.2 (Berkeley) 1/2/94"  */
-MAKE_RCSID("$NetBSD: cond.c,v 1.320 2021/12/30 01:34:26 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.321 2021/12/30 02:14:55 rillig Exp $");
 
 /*
  * The parsing of conditional expressions is based on this grammar:
@@ -793,8 +793,8 @@
         * as an expression.
         */
        /*
-        * XXX: Is it possible to have a variable expression evaluated twice
-        *  at this point?
+        * XXX: In edge cases, a variable expression may be evaluated twice,
+        *  see cond-token-plain.mk, keyword 'twice'.
         */
        arg = ParseWord(&cp, doEval);
        assert(arg[0] != '\0');
diff -r c8942620c29f -r ca2f7157d2b1 usr.bin/make/unit-tests/cond-token-plain.exp
--- a/usr.bin/make/unit-tests/cond-token-plain.exp      Thu Dec 30 01:34:26 2021 +0000
+++ b/usr.bin/make/unit-tests/cond-token-plain.exp      Thu Dec 30 02:14:55 2021 +0000
@@ -56,6 +56,7 @@
 make: "cond-token-plain.mk" line 201: Malformed conditional (${0:?:} || left == right)
 CondParser_Eval: left == right || ${0:?:}
 make: "cond-token-plain.mk" line 206: Malformed conditional (left == right || ${0:?:})
+make: "cond-token-plain.mk" line 225: Malformed conditional (VAR.${IF_COUNT::+=1} != "")
 make: Fatal errors encountered -- cannot continue
 make: stopped in unit-tests
 exit status 1
diff -r c8942620c29f -r ca2f7157d2b1 usr.bin/make/unit-tests/cond-token-plain.mk
--- a/usr.bin/make/unit-tests/cond-token-plain.mk       Thu Dec 30 01:34:26 2021 +0000
+++ b/usr.bin/make/unit-tests/cond-token-plain.mk       Thu Dec 30 02:14:55 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-plain.mk,v 1.14 2021/12/12 09:36:00 rillig Exp $
+# $NetBSD: cond-token-plain.mk,v 1.15 2021/12/30 02:14:55 rillig Exp $
 #
 # Tests for plain tokens (that is, string literals without quotes)
 # in .if conditions.  These are also called bare words.
@@ -209,5 +209,48 @@
 # See cond-token-string.mk for similar tests where the condition is enclosed
 # in "quotes".
 
-all:
-       @:;
+.MAKEFLAGS: -d0
+
+
+# As of cond.c 1.320 from 2021-12-30, the code in CondParser_ComparisonOrLeaf
+# looks suspicious of evaluating the expression twice: first for parsing a
+# bare word and second for parsing the left-hand side of a comparison.
+#
+# In '.if' directives, the left-hand side of a comparison must not be a bare
+# word though, and this keeps CondParser_Leaf from evaluating the expression
+# for the second time.  The right-hand side of a comparison may be a bare
+# word, but that side has no risk of being parsed more than once.
+#
+# expect+1: Malformed conditional (VAR.${IF_COUNT::+=1} != "")
+.if VAR.${IF_COUNT::+=1} != ""
+.  error
+.else
+.  error
+.endif
+.if ${IF_COUNT} != "1"
+.  error
+.endif
+
+# A different situation is when CondParser.leftUnquotedOK is true.  This
+# situation arises in expressions of the form ${cond:?yes:no}.  As of
+# 2021-12-30, the condition in such an expression is evaluated before parsing
+# the condition, see varmod-ifelse.mk.  To pass a variable expression to the
+# condition parser, it needs to be escaped.  This rarely happens in practice,
+# in most cases the conditions are simple enough that it doesn't matter
+# whether the condition is first evaluated and then parsed, or vice versa.
+# A half-baked attempt at hiding this implementation detail is
+# CondParser.leftUnquotedOK, but that is a rather leaky abstraction.
+
+#.MAKEFLAGS: -dcv
+COND=  VAR.$${MOD_COUNT::+=1}
+.if ${${COND} == "VAR.":?yes:no} != "yes"
+.  error
+.endif
+
+# The value "1 1" demonstrates that the expression ${MOD_COUNT::+=1} was
+# evaluated twice.  In practice, expressions that occur in conditions do not
+# have side effects, making this problem rather academic, but it is there.
+.if ${MOD_COUNT} != "1 1"
+.  error
+.endif
+#.MAKEFLAGS: -d0



Home | Main Index | Thread Index | Old Index