[C++] Handle multiple implicit patterns properly

When there are multiple implicit patterns in a rule, recipe
should be used only once.
diff --git a/dep.cc b/dep.cc
index 40f9a1f..45f9584 100644
--- a/dep.cc
+++ b/dep.cc
@@ -45,10 +45,10 @@
 
 class RuleTrie {
   struct Entry {
-    Entry(shared_ptr<Rule> r, StringPiece s)
+    Entry(const Rule* r, StringPiece s)
         : rule(r), suffix(s) {
     }
-    shared_ptr<Rule> rule;
+    const Rule* rule;
     StringPiece suffix;
   };
 
@@ -59,7 +59,7 @@
       delete p.second;
   }
 
-  void Add(StringPiece name, shared_ptr<Rule> rule) {
+  void Add(StringPiece name, const Rule* rule) {
     if (name.empty() || name[0] == '%') {
       rules_.push_back(Entry(rule, name));
       return;
@@ -72,7 +72,7 @@
     p.first->second->Add(name.substr(1), rule);
   }
 
-  void Get(StringPiece name, vector<shared_ptr<Rule>>* rules) const {
+  void Get(StringPiece name, vector<const Rule*>* rules) const {
     for (const Entry& ent : rules_) {
       if ((ent.suffix.empty() && name.empty()) ||
           HasSuffix(name, ent.suffix.substr(1))) {
@@ -360,10 +360,7 @@
 
   void PopulateImplicitRule(shared_ptr<Rule> rule) {
     for (Symbol output_pattern : rule->output_patterns) {
-      shared_ptr<Rule> r = make_shared<Rule>(*rule);
-      r->output_patterns.clear();
-      r->output_patterns.push_back(output_pattern);
-      implicit_rules_->Add(output_pattern.str(), r);
+      implicit_rules_->Add(output_pattern.str(), rule.get());
     }
   }
 
@@ -381,18 +378,46 @@
     return NULL;
   }
 
-  bool CanPickImplicitRule(shared_ptr<Rule> rule, Symbol output) {
-    CHECK(rule->output_patterns.size() == 1);
-    Pattern pat(rule->output_patterns[0].str());
-    if (!pat.Match(output.str())) {
+  bool CanPickImplicitRule(const Rule* rule, Symbol output, DepNode* n,
+                           shared_ptr<Rule>* out_rule) {
+    Symbol matched(Symbol::IsUninitialized{});
+    for (Symbol output_pattern : rule->output_patterns) {
+      Pattern pat(output_pattern.str());
+      if (pat.Match(output.str())) {
+        bool ok = true;
+        for (Symbol input : rule->inputs) {
+          string buf;
+          pat.AppendSubst(output.str(), input.str(), &buf);
+          if (!Exists(Intern(buf))) {
+            ok = false;
+            break;
+          }
+        }
+
+        if (ok) {
+          matched = output_pattern;
+          break;
+        }
+      }
+    }
+    if (!matched.IsValid())
       return false;
+
+    *out_rule = make_shared<Rule>(*rule);
+    if ((*out_rule)->output_patterns.size() > 1) {
+      // We should mark all other output patterns as used.
+      Pattern pat(matched.str());
+      for (Symbol output_pattern : rule->output_patterns) {
+        if (output_pattern == matched)
+          continue;
+        string buf;
+        pat.AppendSubst(output.str(), output_pattern.str(), &buf);
+        done_[Intern(buf)] = n;
+      }
+      (*out_rule)->output_patterns.clear();
+      (*out_rule)->output_patterns.push_back(matched);
     }
-    for (Symbol input : rule->inputs) {
-      string buf;
-      pat.AppendSubst(output.str(), input.str(), &buf);
-      if (!Exists(Intern(buf)))
-        return false;
-    }
+
     return true;
   }
 
@@ -410,7 +435,7 @@
     return r;
   }
 
-  bool PickRule(Symbol output,
+  bool PickRule(Symbol output, DepNode* n,
                 shared_ptr<Rule>* out_rule, Vars** out_var) {
     shared_ptr<Rule> rule = LookupRule(output);
     Vars* vars = LookupRuleVars(output);
@@ -422,11 +447,11 @@
       }
     }
 
-    vector<shared_ptr<Rule>> irules;
+    vector<const Rule*> irules;
     implicit_rules_->Get(output.str(), &irules);
     for (auto iter = irules.rbegin(); iter != irules.rend(); ++iter) {
-      shared_ptr<Rule> irule = *iter;
-      if (!CanPickImplicitRule(irule, output))
+      shared_ptr<Rule> irule;
+      if (!CanPickImplicitRule(*iter, output, n, &irule))
         continue;
       if (rule) {
         shared_ptr<Rule> r = make_shared<Rule>(*rule);
@@ -445,7 +470,7 @@
       CHECK(irule->output_patterns.size() == 1);
       vars = MergeImplicitRuleVars(irule->output_patterns[0], vars);
       *out_var = vars;
-      *out_rule = irule;
+      *out_rule = make_shared<Rule>(*irule);
       return true;
     }
 
@@ -503,14 +528,11 @@
 
     shared_ptr<Rule> rule;
     Vars* vars;
-    if (!PickRule(output, &rule, &vars)) {
+    if (!PickRule(output, n, &rule, &vars)) {
       return n;
     }
 
     if (rule->output_patterns.size() >= 1) {
-      if (rule->output_patterns.size() != 1) {
-        fprintf(stderr, "hmm %s\n", rule->DebugString().c_str());
-      }
       CHECK(rule->output_patterns.size() == 1);
       n->output_pattern = rule->output_patterns[0];
     }