summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2016-04-27 01:55:20 (GMT)
committerNico Weber <nicolasweber@gmx.de>2016-04-27 13:36:42 (GMT)
commit29f373a66bb9d3c56a1d4cf476832c12b7e2e1ad (patch)
tree01ef2ee7a18ca8aa2c22cdfbe5e5e264f81b176b
parentaa79fbe25f55e4eeac384d322df8a44bbeb4fe23 (diff)
downloadNinja-29f373a66bb9d3c56a1d4cf476832c12b7e2e1ad.zip
Ninja-29f373a66bb9d3c56a1d4cf476832c12b7e2e1ad.tar.gz
Ninja-29f373a66bb9d3c56a1d4cf476832c12b7e2e1ad.tar.bz2
Fix crash with duplicate implicit outputs.
Sadly, duplicate outputs aren't an error by default in Ninja (see also a new edge has no effect. Remember to decrement the "number of implicit outputs" counter for the new edge when this happens. Fixes #1136.
-rw-r--r--src/manifest_parser.cc18
-rw-r--r--src/manifest_parser_test.cc24
2 files changed, 35 insertions, 7 deletions
diff --git a/src/manifest_parser.cc b/src/manifest_parser.cc
index be267a3..a4f489e 100644
--- a/src/manifest_parser.cc
+++ b/src/manifest_parser.cc
@@ -339,8 +339,8 @@ bool ManifestParser::ParseEdge(string* err) {
}
edge->outputs_.reserve(outs.size());
- for (vector<EvalString>::iterator i = outs.begin(); i != outs.end(); ++i) {
- string path = i->Evaluate(env);
+ for (size_t i = 0, e = outs.size(); i != e; ++i) {
+ string path = outs[i].Evaluate(env);
string path_err;
unsigned int slash_bits;
if (!CanonicalizePath(&path, &slash_bits, &path_err))
@@ -350,11 +350,15 @@ bool ManifestParser::ParseEdge(string* err) {
lexer_.Error("multiple rules generate " + path + " [-w dupbuild=err]",
err);
return false;
- } else if (!quiet_) {
- Warning("multiple rules generate %s. "
- "builds involving this target will not be correct; "
- "continuing anyway [-w dupbuild=warn]",
- path.c_str());
+ } else {
+ if (!quiet_) {
+ Warning("multiple rules generate %s. "
+ "builds involving this target will not be correct; "
+ "continuing anyway [-w dupbuild=warn]",
+ path.c_str());
+ }
+ if (e - i <= static_cast<size_t>(implicit_outs))
+ --implicit_outs;
}
}
}
diff --git a/src/manifest_parser_test.cc b/src/manifest_parser_test.cc
index ba83a67..1312d26 100644
--- a/src/manifest_parser_test.cc
+++ b/src/manifest_parser_test.cc
@@ -949,6 +949,30 @@ TEST_F(ParserTest, ImplicitOutputEmpty) {
EXPECT_FALSE(edge->is_implicit_out(0));
}
+TEST_F(ParserTest, ImplicitOutputDupe) {
+ ASSERT_NO_FATAL_FAILURE(AssertParse(
+"rule cat\n"
+" command = cat $in > $out\n"
+"build foo baz | foo baq foo: cat bar\n"));
+
+ Edge* edge = state.LookupNode("foo")->in_edge();
+ ASSERT_EQ(edge->outputs_.size(), 3);
+ EXPECT_FALSE(edge->is_implicit_out(0));
+ EXPECT_FALSE(edge->is_implicit_out(1));
+ EXPECT_TRUE(edge->is_implicit_out(2));
+}
+
+TEST_F(ParserTest, ImplicitOutputDupes) {
+ ASSERT_NO_FATAL_FAILURE(AssertParse(
+"rule cat\n"
+" command = cat $in > $out\n"
+"build foo foo foo | foo foo foo foo: cat bar\n"));
+
+ Edge* edge = state.LookupNode("foo")->in_edge();
+ ASSERT_EQ(edge->outputs_.size(), 1);
+ EXPECT_FALSE(edge->is_implicit_out(0));
+}
+
TEST_F(ParserTest, NoExplicitOutput) {
ManifestParser parser(&state, NULL, kDupeEdgeActionWarn);
string err;