- Fix broken handling of order-only prereqs in secondary expansion

of implicit rules.
- Fix leaked memory when dealing with implicit rule chains that
  have file variables or pattern variables.
This commit is contained in:
Paul Smith 2009-09-24 20:59:22 +00:00
parent 0afbbf8595
commit d65b267e4a
4 changed files with 260 additions and 221 deletions

View File

@ -1,4 +1,14 @@
2009-09-23 Paul <psmith@gnu.org>
2009-09-24 Paul Smith <psmith@gnu.org>
* implicit.c (pattern_search): Add back support for order-only
prerequisites for secondary expansion implicit rules, that were
accidentally dropped. If we find a "|", enable order-only mode
and set IGNORE_MTIME on all deps that are seen afterward.
(pattern_search): Fix memory leaks: for intermediate files where
we've already set the file variable and pattern variable sets, be
sure to either save or free them as appropriate.
2009-09-23 Paul Smith <psmith@gnu.org>
Rework the way secondary expansion is stored, for efficiency.
This changes secondary expansion so that ONLY WHEN we know we have

View File

@ -1,7 +1,7 @@
/* Implicit rule searching for GNU Make.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software
Foundation, Inc.
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 Free
Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@ -145,7 +145,7 @@ get_next_word (const char *buffer, unsigned int *length)
}
/* This structure stores information about the expanded prerequisites for a
pattern rule. NAME is always set, to the strcache'd name of the prereq.
pattern rule. NAME is always set to the strcache'd name of the prereq.
FILE and PATTERN will be set for intermediate files only. IGNORE_MTIME is
copied from the prerequisite we expanded.
*/
@ -230,7 +230,7 @@ pattern_search (struct file *file, int archive,
that is not just `%'. */
int specific_rule_matched = 0;
struct nameseq ns_simple;
struct dep dep_simple;
unsigned int ri; /* uninit checks OK */
struct rule *rule;
@ -273,8 +273,6 @@ pattern_search (struct file *file, int archive,
pathlen = lastslash - filename + 1;
ns_simple.next = 0;
/* First see which pattern rules match this target and may be considered.
Put them in TRYRULES. */
@ -415,12 +413,14 @@ pattern_search (struct file *file, int archive,
for (ri = 0; ri < nrules; ri++)
{
struct dep *dep;
unsigned int failed = 0;
int check_lastslash;
unsigned int failed = 0;
int file_variables_set = 0;
unsigned int deps_found = 0;
/* NPTR points to the part of the prereq we haven't processed. */
const char *nptr = 0;
const char *dir = NULL;
int order_only = 0;
rule = tryrules[ri];
@ -444,6 +444,15 @@ pattern_search (struct file *file, int archive,
{
stem += pathlen;
stemlen -= pathlen;
/* We need to add the directory prefix, so set it up. */
if (! pathdir)
{
pathdir = alloca (pathlen + 1);
memcpy (pathdir, filename, pathlen);
pathdir[pathlen] = '\0';
}
dir = pathdir;
}
DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"),
@ -473,22 +482,9 @@ pattern_search (struct file *file, int archive,
nptr = dep_name (dep);
while (1)
{
const char *dir = NULL;
struct nameseq *ns, *n;
struct dep *dl, *d;
char *p;
/* If we need to add the directory prefix set it up. */
if (check_lastslash)
{
if (! pathdir)
{
pathdir = alloca (pathlen + 1);
memcpy (pathdir, filename, pathlen);
pathdir[pathlen] = '\0';
}
dir = pathdir;
}
/* If we're out of name to parse, start the next prereq. */
if (! nptr)
{
@ -501,9 +497,11 @@ pattern_search (struct file *file, int archive,
/* If we don't need a second expansion, just replace the %. */
if (! dep->need_2nd_expansion)
{
dep_simple = *dep;
dep_simple.next = 0;
p = strchr (nptr, '%');
if (p == 0)
ns_simple.name = nptr;
dep_simple.name = nptr;
else
{
char *o = depname;
@ -517,9 +515,9 @@ pattern_search (struct file *file, int archive,
memcpy (o, stem_str, stemlen);
o += stemlen;
strcpy (o, p + 1);
ns_simple.name = strcache_add (depname);
dep_simple.name = strcache_add (depname);
}
ns = &ns_simple;
dl = &dep_simple;
/* We've used up this dep, so next time get a new one. */
nptr = 0;
@ -537,7 +535,6 @@ pattern_search (struct file *file, int archive,
resulting prerequisite. */
else
{
int order_only = 0;
int add_dir = 0;
unsigned int len;
@ -545,6 +542,14 @@ pattern_search (struct file *file, int archive,
if (nptr == 0)
continue;
/* See this is a transition to order-only prereqs. */
if (! order_only && len == 1 && nptr[0] == '|')
{
order_only = 1;
nptr += len;
continue;
}
/* If the dependency name has %, substitute the stem. If we
just replace % with the stem value then later, when we do
the 2nd expansion, we will re-expand this stem value
@ -587,12 +592,15 @@ pattern_search (struct file *file, int archive,
p = variable_expand_for_file (depname, file);
/* Parse the expanded string. */
ns = parse_file_seq (&p, sizeof (struct dep),
order_only ? '\0' : '|',
dl = PARSE_FILE_SEQ (&p, struct dep, order_only ? '\0' : '|',
add_dir ? dir : NULL, 0);
for (n = ns; n != NULL; n = n->next)
for (d = dl; d != NULL; d = d->next)
{
++deps_found;
if (order_only)
d->ignore_mtime = 1;
}
/* Set up for the next word. */
nptr += len;
@ -611,12 +619,12 @@ pattern_search (struct file *file, int archive,
}
/* Go through the nameseq and handle each as a prereq name. */
for (n = ns; n != 0; n = n->next)
for (d = dl; d != 0; d = d->next)
{
struct dep *expl_d;
int is_rule = n->name == dep_name (dep);
int is_rule = d->name == dep_name (dep);
if (file_impossible_p (n->name))
if (file_impossible_p (d->name))
{
/* If this prereq has already been ruled "impossible",
then the rule fails. Don't bother trying it on the
@ -625,7 +633,7 @@ pattern_search (struct file *file, int archive,
(is_rule
? _("Rejecting impossible rule prerequisite `%s'.\n")
: _("Rejecting impossible implicit prerequisite `%s'.\n"),
n->name));
d->name));
tryrules[ri] = 0;
failed = 1;
@ -633,23 +641,23 @@ pattern_search (struct file *file, int archive,
}
memset (pat, '\0', sizeof (struct patdeps));
pat->ignore_mtime = dep->ignore_mtime;
pat->ignore_mtime = d->ignore_mtime;
DBS (DB_IMPLICIT,
(is_rule
? _("Trying rule prerequisite `%s'.\n")
: _("Trying implicit prerequisite `%s'.\n"), n->name));
: _("Trying implicit prerequisite `%s'.\n"), d->name));
/* If this prereq is also explicitly mentioned for FILE,
skip all tests below since it must be built no matter
which implicit rule we choose. */
for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next)
if (streq (dep_name (expl_d), n->name))
if (streq (dep_name (expl_d), d->name))
break;
if (expl_d != 0)
{
(pat++)->name = n->name;
(pat++)->name = d->name;
continue;
}
@ -661,11 +669,11 @@ pattern_search (struct file *file, int archive,
FILENAME's directory), so it might actually exist. */
/* @@ dep->changed check is disabled. */
if (lookup_file (n->name) != 0
if (lookup_file (d->name) != 0
/*|| ((!dep->changed || check_lastslash) && */
|| file_exists_p (n->name))
|| file_exists_p (d->name))
{
(pat++)->name = n->name;
(pat++)->name = d->name;
continue;
}
@ -673,13 +681,13 @@ pattern_search (struct file *file, int archive,
"lib/foo.c", and VPATH=src, searches for
"src/lib/foo.c". */
{
const char *vname = vpath_search (n->name, 0);
const char *vname = vpath_search (d->name, 0);
if (vname)
{
DBS (DB_IMPLICIT,
(_("Found prerequisite `%s' as VPATH `%s'\n"),
n->name, vname));
(pat++)->name = n->name;
d->name, vname));
(pat++)->name = d->name;
continue;
}
}
@ -692,12 +700,12 @@ pattern_search (struct file *file, int archive,
{
DBS (DB_IMPLICIT,
(_("Looking for a rule with intermediate file `%s'.\n"),
n->name));
d->name));
if (int_file == 0)
int_file = alloca (sizeof (struct file));
memset (int_file, '\0', sizeof (struct file));
int_file->name = n->name;
int_file->name = d->name;
if (pattern_search (int_file,
0,
@ -705,9 +713,9 @@ pattern_search (struct file *file, int archive,
recursions + 1))
{
pat->pattern = int_file->name;
int_file->name = n->name;
int_file->name = d->name;
pat->file = int_file;
(pat++)->name = n->name;
(pat++)->name = d->name;
int_file = 0;
continue;
}
@ -717,7 +725,9 @@ pattern_search (struct file *file, int archive,
go through the search again later. */
if (int_file->variables)
free_variable_set (int_file->variables);
file_impossible (n->name);
if (int_file->pat_variables)
free_variable_set (int_file->pat_variables);
file_impossible (d->name);
}
/* A dependency of this rule does not exist. Therefore, this
@ -727,8 +737,8 @@ pattern_search (struct file *file, int archive,
}
/* Free the ns chain. */
if (ns != &ns_simple)
free_ns_chain (ns);
if (dl != &dep_simple)
free_dep_chain (dl);
if (failed)
break;
@ -803,6 +813,9 @@ pattern_search (struct file *file, int archive,
f->deps = imf->deps;
f->cmds = imf->cmds;
f->stem = imf->stem;
f->variables = imf->variables;
f->pat_variables = imf->pat_variables;
f->pat_searched = imf->pat_searched;
f->also_make = imf->also_make;
f->is_target = 1;
f->intermediate = 1;

View File

@ -1,4 +1,9 @@
2009-09-23 Paul <psmith@gnu.org>
2009-09-24 Paul Smith <psmith@gnu.org>
* scripts/features/se_implicit: Add a test for order-only
secondary expansion prerequisites.
2009-09-23 Paul Smith <psmith@gnu.org>
* scripts/features/patternrules: Test that we can remove pattern
rules, both single and multiple prerequisites. Savannah bug #18622.

View File

@ -210,6 +210,17 @@ oo$ba.1
oo$ba
');
# Test #9: Check the value of $^
run_make_test(q!
.SECONDEXPANSION:
%.so: | $$(extra) ; @echo $^
foo.so: extra := foo.o
foo.so:
foo.o:
!,
'', "\n");
# This tells the test driver that the perl test script executed properly.
1;