This is to help improve error reporting with SFINAE as part of the bug report here:
http://llvm.org/bugs/show_bug.cgi?id=13309 So now when this program compiles: 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); } Clang will report back this error with the true diagnostics: smurf.cpp:5:3: error: no matching function for call to 'f' f(3); ^ smurf.cpp:1:42: note: candidate template ignored: substitution failure [with T = int]: member reference base type 'int' is not a structure or union template<class T> auto h(T x)->decltype(x.smurf()){return x.smurf();} ^ Now this only does this when there is single overloads involved. If we change the example to add an extra overload for `h`, like this: 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); } Then we get an error like this instead: smurf.cpp:6:3: error: no matching function for call to 'f' f(3); ^ smurf.cpp:3:41: note: candidate template ignored: substitution failure [with T = int]: no matching function for call to 'h' template<class T> auto g(T x)->decltype(h(x)){return h(x);} ^ So clang basically stops when there is multiple overloads. If the user needs to see more detail for this, we could look at adding an option for a full backtrace in the future. Either way, I think this is very useful to have, and improves the error reporting in clang immensely. I would like to get this patch merged into clang. Index: include/clang/Sema/TemplateDeduction.h =================================================================== --- include/clang/Sema/TemplateDeduction.h (revision 230275) +++ include/clang/Sema/TemplateDeduction.h (working copy) @@ -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 (revision 230275) +++ lib/Sema/SemaOverload.cpp (working copy) @@ -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); _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
