]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Fix out-of-order expansion with expand-before-require.
authorEric Blake <ebb9@byu.net>
Tue, 20 Jan 2009 21:22:41 +0000 (14:22 -0700)
committerEric Blake <ebb9@byu.net>
Wed, 21 Jan 2009 15:57:42 +0000 (08:57 -0700)
* lib/m4sugar/m4sugar.m4 (m4_require): Redundantly expand a
required macro when issuing expand-before-require warning.
* doc/autoconf.texi (Prerequisite Macros): Adjust documentation.
(Expanded Before Required): New node.
* tests/m4sugar.at (m4@&t@_require: nested): Adjust test.
* NEWS: Mention this fix.
Suggested by Bruno Haible.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
NEWS
doc/autoconf.texi
lib/m4sugar/m4sugar.m4
tests/m4sugar.at

index f03804cced4bb00972c0f088499137ff27a4549e..4ac83f5631a6095e8c4741ff0249e3a71777e083 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2009-01-21  Eric Blake  <ebb9@byu.net>
 
+       Fix out-of-order expansion with expand-before-require.
+       * lib/m4sugar/m4sugar.m4 (m4_require): Redundantly expand a
+       required macro when issuing expand-before-require warning.
+       * doc/autoconf.texi (Prerequisite Macros): Adjust documentation.
+       (Expanded Before Required): New node.
+       * tests/m4sugar.at (m4@&t@_require: nested): Adjust test.
+       * NEWS: Mention this fix.
+       Suggested by Bruno Haible.
+
        Warn if macro is provided before indirectly required.
        * lib/m4sugar/m4sugar.m4 (m4_provide): Track the set of all macros
        provided since last outermost defun.
diff --git a/NEWS b/NEWS
index 7eff140bbc3957f7b29a0af8f81ba1225e2797fc..5e43abcda41157d2ecc4686ec523a2ba997dc499 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,15 @@ GNU Autoconf NEWS - User visible changes.
 
 ** The manual is now shipped under the terms of the GNU FDL 1.3.
 
+** AC_REQUIRE now detects the case of an outer macro which first expands
+   then later indirectly requires the same inner macro.  Previously,
+   this case led to silent out-of-order expansion (bug present since
+   2.50); it now issues a syntax warning, and duplicates the expansion
+   of the inner macro to guarantee dependencies have been met.  See
+   the manual for advice on how to refactor macros in order to avoid
+   the bug in earlier autoconf versions and avoid increased script
+   size in the current version.
+
 ** AC_LANG_ERLANG works once again (regression introduced in 2.61a).
 
 ** AC_HEADER_ASSERT is fixed so that './configure --enable-assert' no
index 69d5085dff0c40fa3f33845a7cb28d6a759e4919..b7e63fc132532ee6ea0fdbfed40c2d24d8df966a 100644 (file)
@@ -617,6 +617,7 @@ Frequent Autoconf Questions, with answers
 * Defining Directories::        Passing @code{datadir} to program
 * Autom4te Cache::              What is it?  Can I remove it?
 * Present But Cannot Be Compiled::  Compiler and Preprocessor Disagree
+* Expanded Before Required::    Expanded Before Required
 
 History of Autoconf
 
@@ -13119,61 +13120,87 @@ SOME_CHECK
 @end example
 
 However, this implementation can lead to another class of problems.
-Since dependencies are hoisted prior to the outermost @code{AC_DEFUN}
-body, but only if they have not been previously seen, it is still
-possible to encounter out-of-order expansion.  Given this example:
+Consider the case where an outer macro first expands, then indirectly
+requires, an inner macro:
 
 @example
-AC_DEFUN([A], [[in A]])
-AC_DEFUN([B], [AC_REQUIRE([A])[in B]])
-AC_DEFUN([C], [AC_REQUIRE([B])[in C]])
-AC_DEFUN([OUTER], [[in OUTER]
+AC_DEFUN([TESTA], [[echo in A
+if test -n "$SEEN_A" ; then echo duplicate ; fi
+SEEN_A=:]])
+AC_DEFUN([TESTB], [AC_REQUIRE([TESTA])[echo in B
+if test -z "$SEEN_A" ; then echo bug ; fi]])
+AC_DEFUN([TESTC], [AC_REQUIRE([TESTB])[echo in C]])
+AC_DEFUN([OUTER], [[echo in OUTER]
 A
 C])
 OUTER
 @end example
 
 @noindent
-observe that the expansion of @code{B} occurred prior to the expansion
-of @code{OUTER}, but because the requirement for @code{B} was not
-encountered until after @code{A} had already been directly expanded,
-there was no reason to hoist @code{A}.  Or, put another way, the fact
-that @code{B} was hoisted but not @code{A} means that @code{B} occurs
-before its prerequisite:
+Prior to Autoconf 2.64, the implementation of @code{AC_REQUIRE}
+recognized that @code{TESTB} needed to be hoisted prior to the expansion
+of @code{OUTER}, but because @code{TESTA} had already been directly
+expanded, it failed to hoist @code{TESTA}.  Therefore, the expansion of
+@code{TESTB} occurs prior to its prerequisites, leading to the following
+output:
 
 @example
 in B
+bug
 in OUTER
 in A
 in C
 @end example
 
+@noindent
+Newer Autoconf is smart enough to recognize this situation, and hoists
+@code{TESTA} even though it has already been expanded, but issues a
+syntax warning in the process.  This is because the hoisted expansion of
+@code{TESTA} defeats the purpose of using @code{AC_REQUIRE} to avoid
+redundant code, and causes its own set of problems if the hoisted macro
+is not idempotent:
+
+@example
+in A
+in B
+in OUTER
+in A
+duplicate
+in C
+@end example
+
 The bug is not in Autoconf, but in the macro definitions.  If you ever
 pass a particular macro name to @code{AC_REQUIRE}, then you are implying
 that the macro only needs to be expanded once.  But to enforce this, all
 uses of that macro should be through @code{AC_REQUIRE}; directly
 expanding the macro defeats the point of using @code{AC_REQUIRE} to
 eliminate redundant expansion.  In the example, this rule of thumb was
-violated because @code{B} requires @code{A} while @code{OUTER} directly
-expands it.  One way of fixing the bug is to factor @code{A} into two
-macros, the portion designed for direct and repeated use (here, named
-@code{A}), and the portion designed for one-shot output and used only
-inside @code{AC_REQUIRE} (here, named @code{A_PREREQ}).  Then, by fixing
-all clients to use the correct macro according to their needs:
-
-@example
-AC_DEFUN([A], [AC_REQUIRE([A_PREREQ])[in A]])
-AC_DEFUN([A_PREREQ], [[in A_PREREQ]])
-AC_DEFUN([B], [AC_REQUIRE([A_PREREQ])[in B]])
-AC_DEFUN([C], [AC_REQUIRE([B])[in C]])
-AC_DEFUN([OUTER], [[in OUTER]
-A
-C])
+violated because @code{TESTB} requires @code{TESTA} while @code{OUTER}
+directly expands it.  One way of fixing the bug is to factor
+@code{TESTA} into two macros, the portion designed for direct and
+repeated use (here, named @code{TESTA}), and the portion designed for
+one-shot output and used only inside @code{AC_REQUIRE} (here, named
+@code{TESTA_PREREQ}).  Then, by fixing all clients to use the correct
+calling convention according to their needs:
+
+@example
+AC_DEFUN([TESTA], [AC_REQUIRE([TESTA_PREREQ])[echo in A]])
+AC_DEFUN([TESTA_PREREQ], [[echo in A_PREREQ
+if test -n "$SEEN_A" ; then echo duplicate ; fi
+SEEN_A=:]])
+AC_DEFUN([TESTB], [AC_REQUIRE([TESTA_PREREQ])[echo in B
+if test -z "$SEEN_A" ; then echo bug ; fi]])
+AC_DEFUN([TESTC], [AC_REQUIRE([TESTB])[echo in C]])
+AC_DEFUN([OUTER], [[echo in OUTER]
+TESTA
+TESTC])
 OUTER
 @end example
 
 @noindent
-the resulting output will then obey all dependency rules:
+the resulting output will then obey all dependency rules and avoid any
+syntax warnings, whether the script is built with old or new Autoconf
+versions:
 
 @example
 in A_PREREQ
@@ -22415,6 +22442,7 @@ are addressed.
 * Defining Directories::        Passing @code{datadir} to program
 * Autom4te Cache::              What is it?  Can I remove it?
 * Present But Cannot Be Compiled::  Compiler and Preprocessor Disagree
+* Expanded Before Required::    Expanded Before Required
 @end menu
 
 @node Distributing
@@ -22803,6 +22831,48 @@ checking for pi.h... yes
 See @ref{Particular Headers}, for a list of headers with their
 prerequisites.
 
+@node Expanded Before Required
+@section Expanded Before Required
+
+@cindex expanded before required
+Older versions of Autoconf silently built files with incorrect ordering
+between dependent macros if an outer macro first expanded, then later
+indirectly required, an inner macro.  Starting with Autoconf 2.64, this
+situation no longer generates out-of-order code, but results in
+duplicate output and a diagnosis of a syntax warning:
+
+@example
+$ @kbd{cat configure.ac}
+@result{}AC_DEFUN([TESTA], [[echo in A
+@result{}if test -n "$SEEN_A" ; then echo duplicate ; fi
+@result{}SEEN_A=:]])
+@result{}AC_DEFUN([TESTB], [AC_REQUIRE([TESTA])[echo in B
+@result{}if test -z "$SEEN_A" ; then echo bug ; fi]])
+@result{}AC_DEFUN([TESTC], [AC_REQUIRE([TESTB])[echo in C]])
+@result{}AC_DEFUN([OUTER], [[echo in OUTER]
+@result{}TESTA
+@result{}TESTC])
+@result{}AC_INIT
+@result{}OUTER
+@result{}AC_OUTPUT
+$ @kbd{autoconf}
+@result{}configure.ac:11: warning: AC_REQUIRE:
+@result{} `TESTA' was expanded before it was required
+@result{}configure.ac:4: TESTB is expanded from...
+@result{}configure.ac:6: TESTC is expanded from...
+@result{}configure.ac:7: OUTER is expanded from...
+@result{}configure.ac:11: the top level
+@end example
+
+To avoid this warning, decide what purpose the macro in question serves.
+If it only needs to be expanded once (for example, if it provides
+initialization text used by later macros), then the fix is to change all
+instance of direct calls to instead go through @code{AC_REQUIRE}
+(@pxref{Prerequisite Macros}).  If, instead, the macro is parameterized
+by arguments or by the current definition of other macros in the m4
+environment, then the macro should always be directly expanded instead
+of required.
+
 @c ===================================================== History of Autoconf.
 
 @node History
index 1457aefee74c8a2adf0b88fb92f9ea0f71f95519..3a5ce49a1529334b682cbb7f42fc952661b69e86 100644 (file)
@@ -1728,8 +1728,8 @@ m4_define([m4_undivert],
 # inside a context that will be hoisted in front of the outermost
 # defun'd macro.  In other words, we must be careful not to warn on:
 #
-# | m4_defun([TEST1], [1])
-# | m4_defun([TEST2], [TEST1 REQUIRE([TEST1])])
+# | m4_defun([TEST4], [4])
+# | m4_defun([TEST5], [TEST4 REQUIRE([TEST5])])
 #
 # The implementation of the warning involves tracking the set of
 # macros which have been provided since the start of the outermost
@@ -1739,9 +1739,12 @@ m4_define([m4_undivert],
 # removed from the set; and when a macro is indirectly required (that
 # is, when m4_require detects a nested call), the set is checked.  If
 # a macro is in the set, then it has been provided before it was
-# required, and a warning is issued because the output will be out of
-# order and the user must fix her macros to reflect the true
-# dependencies.
+# required, and we satisfy dependencies by expanding the macro as if
+# it had never been provided; in the example given above, this means
+# we now output `1 2 3 1'.  Meanwhile, a warning is issued to inform
+# the user that her macros trigger the bug in older autoconf versions,
+# and that her outupt file now contains redundant contents (and
+# possibly new problems, if the repeated macro was not idempotent).
 #
 #
 # 2. Keeping track of the expansion stack
@@ -1984,9 +1987,10 @@ m4_define([m4_require],
   [m4_fatal([$0($1): cannot be used outside of an ]dnl
 m4_if([$0], [m4_require], [[m4_defun]], [[AC_DEFUN]])['d macro])])]dnl
 [m4_provide_if([$1], [m4_ifdef([_m4_require],
-  [m4_set_contains([_m4_provide], [$1],
-    [m4_warn([syntax], [$0: `$1' was expanded before it was required])])])],
-  [_m4_require_call([$1], [$2], _m4_divert_dump)])])
+  [m4_set_contains([_m4_provide], [$1], [m4_warn([syntax],
+      [$0: `$1' was expanded before it was required])_m4_require_call],
+    [m4_ignore])], [m4_ignore])],
+  [_m4_require_call])([$1], [$2], _m4_divert_dump)])
 
 
 # _m4_require_call(NAME-TO-CHECK, [BODY-TO-EXPAND = NAME-TO-CHECK],
index a6739cf10aed92c1b0fce66ded52bc895d19a7f9..613a3c9b426481f8051b0dbaeeea4b3d8932c674 100644 (file)
@@ -545,7 +545,8 @@ c
 post])dnl
 outer
 ]],
-[[b
+[[a
+b
 pre
 a
 c