]> granicus.if.org Git - clang/commitdiff
Fix PR15634, better error message for template deduction failure.
authorRichard Trieu <rtrieu@google.com>
Mon, 8 Apr 2013 21:11:40 +0000 (21:11 +0000)
committerRichard Trieu <rtrieu@google.com>
Mon, 8 Apr 2013 21:11:40 +0000 (21:11 +0000)
When two template decls with the same name are used in this diagnostic,
force them to print their qualified names.  This changes the bad message of:

candidate template ignored: could not match 'array' against 'array'

to the better message of:

candidate template ignored: could not match 'NS2::array' against 'NS1::array'

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179056 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOverload.cpp
test/SemaTemplate/overload-candidates.cpp

index 95c9c804f39334b07884eec5718a1a08d092fb0f..d93de39f14d7dbf8c3939240da3de3399a8a2b17 100644 (file)
@@ -2370,6 +2370,11 @@ def note_ovl_candidate_failed_overload_resolution : Note<
     "function %0">;
 def note_ovl_candidate_non_deduced_mismatch : Note<
     "candidate template ignored: could not match %diff{$ against $|types}0,1">;
+// This note is needed because the above note would sometimes print two
+// different types with the same name.  Remove this note when the above note
+// can handle that case properly.
+def note_ovl_candidate_non_deduced_mismatch_qualified : Note<
+    "candidate template ignored: could not match %q0 against %q1">;
     
 // Note that we don't treat templates differently for this diagnostic.
 def note_ovl_candidate_arity : Note<"candidate "
index 89d495ddc197f2e0251e7450ab4188d185f25d1e..805fdd8b578f8c1526adbfe0ec04fca59ecf5655 100644 (file)
@@ -8508,13 +8508,35 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
     return;
   }
 
-  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_NonDeducedMismatch: {
     // FIXME: Provide a source location to indicate what we couldn't match.
+    TemplateArgument FirstTA = *Cand->DeductionFailure.getFirstArg();
+    TemplateArgument SecondTA = *Cand->DeductionFailure.getSecondArg();
+    if (FirstTA.getKind() == TemplateArgument::Template &&
+        SecondTA.getKind() == TemplateArgument::Template) {
+      TemplateName FirstTN = FirstTA.getAsTemplate();
+      TemplateName SecondTN = SecondTA.getAsTemplate();
+      if (FirstTN.getKind() == TemplateName::Template &&
+          SecondTN.getKind() == TemplateName::Template) {
+        if (FirstTN.getAsTemplateDecl()->getName() ==
+            SecondTN.getAsTemplateDecl()->getName()) {
+          // FIXME: This fixes a bad diagnostic where both templates are named
+          // the same.  This particular case is a bit difficult since:
+          // 1) It is passed as a string to the diagnostic printer.
+          // 2) The diagnostic printer only attempts to find a better
+          //    name for types, not decls.
+          // Ideally, this should folded into the diagnostic printer.
+          S.Diag(Fn->getLocation(),
+                 diag::note_ovl_candidate_non_deduced_mismatch_qualified)
+              << FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl();
+          return;
+        }
+      }
+    }
     S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch)
-      << *Cand->DeductionFailure.getFirstArg()
-      << *Cand->DeductionFailure.getSecondArg();
+      << FirstTA << SecondTA;
     return;
-
+  }
   // TODO: diagnose these individually, then kill off
   // note_ovl_candidate_bad_deduction, which is uselessly vague.
   case Sema::TDK_MiscellaneousDeductionFailure:
index dc6d2a51ec2efed860a92b7c1b541d20d9c8dfcd..ad65397865ad08c591c4c7f0ec942e0c34f850e2 100644 (file)
@@ -62,3 +62,20 @@ template<typename T> struct NonTemplateFunction {
   typename boost::enable_if<sizeof(T) == 4, int>::type f(); // expected-error{{no type named 'type' in 'boost::enable_if<false, int>'; 'enable_if' cannot be used to disable this declaration}}
 };
 NonTemplateFunction<char> NTFC; // expected-note{{here}}
+
+namespace NS1 {
+  template <class A>
+  class array {};
+}
+
+namespace NS2 {
+  template <class A>
+  class array {};
+}
+
+template <class A>
+void foo(NS2::array<A>); // expected-note{{candidate template ignored: could not match 'NS2::array' against 'NS1::array'}}
+
+void test() {
+  foo(NS1::array<int>()); // expected-error{{no matching function for call to 'foo'}}
+}