erik.pilkington created this revision.
erik.pilkington added reviewers: rsmith, faisalv.
erik.pilkington added a subscriber: cfe-commits.
Previously, clang would give a terrible diagnostic for the following:
```
template <int N> struct B {};
struct D : B<0>, B<1> {};
template <int N> int f(B<N>) { return 0; } // error, ambiguous bases of 'D' 
could be deduced.
int main() { f(D()); }
```
This patch just introduces a new deduction failure kind: 
`TDK_AmbiguousBaseClasses`, and uses it to emit a better diagnostic.

Thanks!

http://reviews.llvm.org/D22311

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaOverload.cpp
  lib/Sema/SemaTemplateDeduction.cpp
  test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp

Index: test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
===================================================================
--- test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
+++ test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
@@ -166,7 +166,7 @@
 template<int N> struct B {};
 struct D : B<0>, B<1> {};
 
-template<int N> int callee(B<N>); // expected-note{{failed template argument deduction}}
+template<int N> int callee(B<N>); // expected-note{{candidate template ignored: ambiguous base classes of 'PR28195::D' match 'B<N>'}}
 
 int caller() {
   callee(D()); // expected-error{{no matching function}}
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp
+++ lib/Sema/SemaTemplateDeduction.cpp
@@ -1483,8 +1483,11 @@
           if (BaseResult == Sema::TDK_Success) {
             // If we've already seen some success, then deduction fails due to
             // an ambiguity (temp.deduct.call p5).
-            if (Successful)
-              return Sema::TDK_MiscellaneousDeductionFailure;
+            if (Successful) {
+              Info.FirstArg = TemplateArgument(ParamIn);
+              Info.SecondArg = TemplateArgument(ArgIn);
+              return Sema::TDK_AmbiguousBaseClasses;
+            }
 
             Successful = true;
             std::swap(SuccessfulDeduced, Deduced);
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -594,6 +594,7 @@
     break;
   }
 
+  case Sema::TDK_AmbiguousBaseClasses:
   case Sema::TDK_NonDeducedMismatch: {
     // FIXME: Should allocate from normal heap so that we can free this later.
     DFIArguments *Saved = new (Context) DFIArguments;
@@ -648,6 +649,7 @@
   case Sema::TDK_Underqualified:
   case Sema::TDK_DeducedMismatch:
   case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_AmbiguousBaseClasses:
     // FIXME: Destroy the data?
     Data = nullptr;
     break;
@@ -684,6 +686,7 @@
   case Sema::TDK_DeducedMismatch:
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
+  case Sema::TDK_AmbiguousBaseClasses:
     return TemplateParameter();
 
   case Sema::TDK_Incomplete:
@@ -715,6 +718,7 @@
   case Sema::TDK_Underqualified:
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
+  case Sema::TDK_AmbiguousBaseClasses:
     return nullptr;
 
   case Sema::TDK_DeducedMismatch:
@@ -748,6 +752,7 @@
   case Sema::TDK_Underqualified:
   case Sema::TDK_DeducedMismatch:
   case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_AmbiguousBaseClasses:
     return &static_cast<DFIArguments*>(Data)->FirstArg;
 
   // Unhandled
@@ -775,6 +780,7 @@
   case Sema::TDK_Underqualified:
   case Sema::TDK_DeducedMismatch:
   case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_AmbiguousBaseClasses:
     return &static_cast<DFIArguments*>(Data)->SecondArg;
 
   // Unhandled
@@ -9582,6 +9588,13 @@
         << FirstTA << SecondTA;
     return;
   }
+
+  case Sema::TDK_AmbiguousBaseClasses:
+    S.Diag(Templated->getLocation(),
+           diag::note_ovl_candidate_ambiguous_base_classes)
+        << *DeductionFailure.getSecondArg() << *DeductionFailure.getFirstArg();
+    return;
+
   // TODO: diagnose these individually, then kill off
   // note_ovl_candidate_bad_deduction, which is uselessly vague.
   case Sema::TDK_MiscellaneousDeductionFailure:
@@ -9843,6 +9856,7 @@
   case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_DeducedMismatch:
   case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_AmbiguousBaseClasses:
   case Sema::TDK_MiscellaneousDeductionFailure:
     return 3;
 
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -6446,6 +6446,8 @@
     /// \brief The arguments included an overloaded function name that could
     /// not be resolved to a suitable function.
     TDK_FailedOverloadResolution,
+    /// \brief Multiple base classes could have been successfully deduced.
+    TDK_AmbiguousBaseClasses,
     /// \brief Deduction failed; that's all we know.
     TDK_MiscellaneousDeductionFailure
   };
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3223,6 +3223,8 @@
 // can handle that case properly.
 def note_ovl_candidate_non_deduced_mismatch_qualified : Note<
     "candidate template ignored: could not match %q0 against %q1">;
+def note_ovl_candidate_ambiguous_base_classes : Note<
+    "candidate template ignored: ambiguous base classes of %0 match %1">;
 
 // Note that we don't treat templates differently for this diagnostic.
 def note_ovl_candidate_arity : Note<"candidate "
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to