aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.cpp30
-rw-r--r--lib/Sema/SemaOverload.cpp50
2 files changed, 66 insertions, 14 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 5017c2cdf5..9f2880fb4e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -698,6 +698,15 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
// Count this failure so that we know that template argument deduction
// has failed.
++NumSFINAEErrors;
+
+ // Make a copy of this suppressed diagnostic and store it with the
+ // template-deduction information.
+ if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
+ Diagnostic DiagInfo(&Diags);
+ (*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
+ PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
+ }
+
Diags.setLastDiagnosticIgnored();
Diags.Clear();
return;
@@ -714,6 +723,15 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
// Suppress this diagnostic.
++NumSFINAEErrors;
+
+ // Make a copy of this suppressed diagnostic and store it with the
+ // template-deduction information.
+ if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
+ Diagnostic DiagInfo(&Diags);
+ (*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
+ PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
+ }
+
Diags.setLastDiagnosticIgnored();
Diags.Clear();
@@ -730,13 +748,13 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
case DiagnosticIDs::SFINAE_Suppress:
// Make a copy of this suppressed diagnostic and store it with the
// template-deduction information;
- Diagnostic DiagInfo(&Diags);
-
- if (*Info)
+ if (*Info) {
+ Diagnostic DiagInfo(&Diags);
(*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(),
- PartialDiagnostic(DiagInfo,Context.getDiagAllocator()));
-
- // Suppress this diagnostic.
+ PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
+ }
+
+ // Suppress this diagnostic.
Diags.setLastDiagnosticIgnored();
Diags.Clear();
return;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 007ea0fdcd..f065d38d92 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -28,6 +28,7 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
@@ -541,6 +542,7 @@ static MakeDeductionFailureInfo(ASTContext &Context,
TemplateDeductionInfo &Info) {
OverloadCandidate::DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
+ Result.HasDiagnostic = false;
Result.Data = 0;
switch (TDK) {
case Sema::TDK_Success:
@@ -567,6 +569,12 @@ static MakeDeductionFailureInfo(ASTContext &Context,
case Sema::TDK_SubstitutionFailure:
Result.Data = Info.take();
+ if (Info.hasSFINAEDiagnostic()) {
+ PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt(
+ SourceLocation(), PartialDiagnostic::NullDiagnostic());
+ Info.takeSFINAEDiagnostic(*Diag);
+ Result.HasDiagnostic = true;
+ }
break;
case Sema::TDK_NonDeducedMismatch:
@@ -594,8 +602,12 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
break;
case Sema::TDK_SubstitutionFailure:
- // FIXME: Destroy the template arugment list?
+ // FIXME: Destroy the template argument list?
Data = 0;
+ if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) {
+ Diag->~PartialDiagnosticAt();
+ HasDiagnostic = false;
+ }
break;
// Unhandled
@@ -605,6 +617,13 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
}
}
+PartialDiagnosticAt *
+OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() {
+ if (HasDiagnostic)
+ return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic));
+ return 0;
+}
+
TemplateParameter
OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
@@ -8235,14 +8254,29 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
return;
case Sema::TDK_SubstitutionFailure: {
- std::string ArgString;
- if (TemplateArgumentList *Args
- = Cand->DeductionFailure.getTemplateArgumentList())
- ArgString = S.getTemplateArgumentBindingsText(
- Fn->getDescribedFunctionTemplate()->getTemplateParameters(),
- *Args);
+ // Format the template argument list into the argument string.
+ llvm::SmallString<128> TemplateArgString;
+ if (TemplateArgumentList *Args =
+ Cand->DeductionFailure.getTemplateArgumentList()) {
+ TemplateArgString = " ";
+ TemplateArgString += S.getTemplateArgumentBindingsText(
+ Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args);
+ }
+
+ // Format the SFINAE diagnostic into the argument string.
+ // FIXME: Add a general mechanism to include a PartialDiagnostic *'s
+ // formatted message in another diagnostic.
+ llvm::SmallString<128> SFINAEArgString;
+ SourceRange R;
+ if (PartialDiagnosticAt *PDiag =
+ Cand->DeductionFailure.getSFINAEDiagnostic()) {
+ SFINAEArgString = ": ";
+ R = SourceRange(PDiag->first, PDiag->first);
+ PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
+ }
+
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
- << ArgString;
+ << TemplateArgString << SFINAEArgString << R;
MaybeEmitInheritedConstructorNote(S, Fn);
return;
}