diff options
author | Ben Boeckel <ben.boeckel@kitware.com> | 2019-11-20 21:00:37 (GMT) |
---|---|---|
committer | Ben Boeckel <ben.boeckel@kitware.com> | 2019-11-20 21:00:37 (GMT) |
commit | ebbb9e2fdb0746e2125013e29a334efc8c0331b6 (patch) | |
tree | 5b01bde0221830090dd6aaf986142c71835ab341 /src | |
parent | 1daa7470ab7ed147726b560d0bc55327fff3482f (diff) | |
download | Ninja-ebbb9e2fdb0746e2125013e29a334efc8c0331b6.zip Ninja-ebbb9e2fdb0746e2125013e29a334efc8c0331b6.tar.gz Ninja-ebbb9e2fdb0746e2125013e29a334efc8c0331b6.tar.bz2 |
depfile_parser_test: test buggy -MP behavior
This ensures the current behavior of rejecting this case due to `x`
being reused as an input.
Diffstat (limited to 'src')
-rw-r--r-- | src/depfile_parser.cc | 12 | ||||
-rw-r--r-- | src/depfile_parser.in.cc | 12 | ||||
-rw-r--r-- | src/depfile_parser_test.cc | 9 |
3 files changed, 31 insertions, 2 deletions
diff --git a/src/depfile_parser.cc b/src/depfile_parser.cc index e92584e..90d4a8a 100644 --- a/src/depfile_parser.cc +++ b/src/depfile_parser.cc @@ -51,6 +51,7 @@ bool DepfileParser::Parse(string* content, string* err) { char* end = in + content->size(); bool have_target = false; bool parsing_targets = true; + bool poisoned_input = false; while (in < end) { bool have_newline = false; // out: current output point (typically same as in, but can fall behind @@ -295,8 +296,13 @@ yy28: if (len > 0) { StringPiece piece = StringPiece(filename, len); // If we've seen this as an input before, skip it. - if (std::find(ins_.begin(), ins_.end(), piece) == ins_.end()) { + std::vector<StringPiece>::iterator pos = std::find(ins_.begin(), ins_.end(), piece); + if (pos == ins_.end()) { if (is_dependency) { + if (poisoned_input) { + *err = "inputs may not also have inputs"; + return false; + } // New input. ins_.push_back(piece); } else { @@ -304,12 +310,16 @@ yy28: if (std::find(outs_.begin(), outs_.end(), piece) == outs_.end()) outs_.push_back(piece); } + } else if (!is_dependency) { + // We've passed an input on the left side; reject new inputs. + poisoned_input = true; } } if (have_newline) { // A newline ends a rule so the next filename will be a new target. parsing_targets = true; + poisoned_input = false; } } if (!have_target) { diff --git a/src/depfile_parser.in.cc b/src/depfile_parser.in.cc index eba892f..b32b942 100644 --- a/src/depfile_parser.in.cc +++ b/src/depfile_parser.in.cc @@ -50,6 +50,7 @@ bool DepfileParser::Parse(string* content, string* err) { char* end = in + content->size(); bool have_target = false; bool parsing_targets = true; + bool poisoned_input = false; while (in < end) { bool have_newline = false; // out: current output point (typically same as in, but can fall behind @@ -147,8 +148,13 @@ bool DepfileParser::Parse(string* content, string* err) { if (len > 0) { StringPiece piece = StringPiece(filename, len); // If we've seen this as an input before, skip it. - if (std::find(ins_.begin(), ins_.end(), piece) == ins_.end()) { + std::vector<StringPiece>::iterator pos = std::find(ins_.begin(), ins_.end(), piece); + if (pos == ins_.end()) { if (is_dependency) { + if (poisoned_input) { + *err = "inputs may not also have inputs"; + return false; + } // New input. ins_.push_back(piece); } else { @@ -156,12 +162,16 @@ bool DepfileParser::Parse(string* content, string* err) { if (std::find(outs_.begin(), outs_.end(), piece) == outs_.end()) outs_.push_back(piece); } + } else if (!is_dependency) { + // We've passed an input on the left side; reject new inputs. + poisoned_input = true; } } if (have_newline) { // A newline ends a rule so the next filename will be a new target. parsing_targets = true; + poisoned_input = false; } } if (!have_target) { diff --git a/src/depfile_parser_test.cc b/src/depfile_parser_test.cc index e5e3038..bf1a0bc 100644 --- a/src/depfile_parser_test.cc +++ b/src/depfile_parser_test.cc @@ -332,3 +332,12 @@ TEST_F(DepfileParserTest, MultipleRulesDifferentOutputs) { EXPECT_EQ("y", parser_.ins_[1].AsString()); EXPECT_EQ("z", parser_.ins_[2].AsString()); } + +TEST_F(DepfileParserTest, BuggyMP) { + std::string err; + EXPECT_FALSE(Parse("foo: x y z\n" + "x: alsoin\n" + "y:\n" + "z:\n", &err)); + ASSERT_EQ("inputs may not also have inputs", err); +} |