Commit
07eea3aa4 `make --shuffle` prevented shuffling prerequisites
that use .SECONDEXPANSION, since shuffle happens before expansion.
This has two problems:
1. No shuffling happens for such prerequisites.
2. Use-after-free when outdated '->shuf' links are used.
Add a reshuffle into expansion phase right after dependency changes.
* src/file.c (expand_deps): Add reshuffle if dependencies change.
* src/shuffle.c (identity_shuffle_array): Fix comment typo.
* tests/scripts/options/shuffle: Add new SECONDEXPANSION test.
#include "variable.h"
#include "debug.h"
#include "hash.h"
+#include "shuffle.h"
/* Remember whether snap_deps has been invoked: we need this to be sure we
struct dep **dp;
const char *fstem;
int initialized = 0;
+ int changed_dep = 0;
if (f->snapped)
return;
if (new == 0)
{
*dp = d->next;
+ changed_dep = 1;
free_dep (d);
d = *dp;
continue;
/* Add newly parsed prerequisites. */
fstem = d->stem;
next = d->next;
+ changed_dep = 1;
free_dep (d);
*dp = new;
for (dp = &new, d = new; d != 0; dp = &d->next, d = d->next)
*dp = next;
d = *dp;
}
+
+ /* Shuffle mode assumes '->next' and '->shuf' links both traverse the same
+ dependencies (in different sequences). Regenerate '->shuf' so we don't
+ refer to stale data. */
+ if (changed_dep)
+ shuffle_deps_recursive (f->deps);
}
/* Add extra prereqs to the file in question. */
/* No-op! */
}
-/* Shuffle list of dependencies by populating '->next'
+/* Shuffle list of dependencies by populating '->shuf'
field in each 'struct dep'. */
static void
shuffle_deps (struct dep *deps)
',
'--shuffle=reverse a_ b_ c_', "a_\nb_\nc_");
+# Check if SECONDEXPANSION targets also get reshuffled.
+run_make_test('
+.SECONDEXPANSION:
+all: $$(var)
+%_: ; @echo $@
+var = a_ b_ c_
+',
+ '--shuffle=reverse', "c_\nb_\na_");
+
1;