[PATCH] Improve error reporting for SFINAE

Paul Fultz II pfultz2 at yahoo.com
Mon Apr 6 13:37:50 PDT 2015


Added tests


REPOSITORY
  rL LLVM

http://reviews.llvm.org/D8309

Files:
  include/clang/Sema/TemplateDeduction.h
  lib/Sema/SemaOverload.cpp
  test/SemaCXX/sfinae-error-overload.cpp
  test/SemaCXX/sfinae-error.cpp

Index: include/clang/Sema/TemplateDeduction.h
===================================================================
--- include/clang/Sema/TemplateDeduction.h
+++ include/clang/Sema/TemplateDeduction.h
@@ -68,8 +68,10 @@
   /// \brief Take ownership of the SFINAE diagnostic.
   void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
     assert(HasSFINAEDiagnostic);
-    PD.first = SuppressedDiagnostics.front().first;
-    PD.second.swap(SuppressedDiagnostics.front().second);
+    unsigned NumberOfDiagnostics = SuppressedDiagnostics.size();
+    PartialDiagnosticAt &PDiag = SuppressedDiagnostics[((NumberOfDiagnostics == 2) ? 1 : 0)];
+    PD.first = PDiag.first;
+    PD.second.swap(PDiag.second);
     SuppressedDiagnostics.clear();
     HasSFINAEDiagnostic = false;
   }
@@ -98,8 +100,6 @@
   /// \brief Add a new diagnostic to the set of diagnostics
   void addSuppressedDiagnostic(SourceLocation Loc,
                                PartialDiagnostic PD) {
-    if (HasSFINAEDiagnostic)
-      return;
     SuppressedDiagnostics.emplace_back(Loc, std::move(PD));
   }
 
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -9105,6 +9105,16 @@
       return;
     }
 
+    // If the diagnsotics is already for overload candidate substitution
+    // failure, then just emit the diagnostics as is.
+    if (PDiag && (PDiag->second.getDiagID() ==
+                      diag::note_ovl_candidate_substitution_failure ||
+                  PDiag->second.getDiagID() ==
+                      diag::note_ovl_candidate_disabled_by_enable_if)) {
+      S.Diag(PDiag->first, PDiag->second);
+      return;
+    }
+
     // Format the SFINAE diagnostic into the argument string.
     // FIXME: Add a general mechanism to include a PartialDiagnostic *'s
     //        formatted message in another diagnostic.
@@ -9116,7 +9126,7 @@
       PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
     }
 
-    S.Diag(Templated->getLocation(),
+    S.Diag(PDiag->first,
            diag::note_ovl_candidate_substitution_failure)
         << TemplateArgString << SFINAEArgString << R;
     MaybeEmitInheritedConstructorNote(S, Templated);
Index: test/SemaCXX/sfinae-error-overload.cpp
===================================================================
--- test/SemaCXX/sfinae-error-overload.cpp
+++ test/SemaCXX/sfinae-error-overload.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 2>&1 | FileCheck %s
+template<class T> auto h(T x)->decltype(x.smurf()){return x.smurf();}
+void h() {}
+template<class T> auto g(T x)->decltype(h(x)){return h(x);}
+template<class T> auto f(T x)->decltype(g(x)){return g(x);}
+int main(){
+  f(3);
+}
+
+// CHECK: sfinae-error-overload.cpp:7:3: error: no matching function for call to 'f'
+// CHECK-NEXT:   f(3);
+// CHECK: sfinae-error-overload.cpp:4:41: note: candidate template ignored: substitution failure [with T = int]: no matching function for call to 'h'
+// CHECK-NEXT: template<class T> auto g(T x)->decltype(h(x)){return h(x);}
+
Index: test/SemaCXX/sfinae-error.cpp
===================================================================
--- test/SemaCXX/sfinae-error.cpp
+++ test/SemaCXX/sfinae-error.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 2>&1 | FileCheck --check-prefix=CHECK1 %s
+template<class T> auto h(T x)->decltype(x.smurf()){return x.smurf();}
+template<class T> auto g(T x)->decltype(h(x)){return h(x);}
+template<class T> auto f(T x)->decltype(g(x)){return g(x);}
+int main(){
+  f(3);
+}
+
+// CHECK1: sfinae-error.cpp:6:3: error: no matching function for call to 'f'
+// CHECK1:   f(3);
+// CHECK1: sfinae-error.cpp:2:42: note: candidate template ignored: substitution failure [with T = int]: member reference base type 'int' is not a structure or union
+// CHECK1-NEXT: template<class T> auto h(T x)->decltype(x.smurf()){return x.smurf();}
+

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D8309.23290.patch
Type: text/x-patch
Size: 3963 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150406/10f04e27/attachment.bin>


More information about the cfe-commits mailing list