aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.cpp2
-rw-r--r--lib/Sema/Sema.h42
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp4
3 files changed, 45 insertions, 3 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 4dc5222072..a5f243816a 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -183,7 +183,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
- CurrentInstantiationScope(0) {
+ NumSFINAEErrors(0), CurrentInstantiationScope(0) {
StdNamespace = 0;
TUScope = 0;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index b310568740..0607a893da 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -256,6 +256,9 @@ public:
/// unit.
bool CompleteTranslationUnit;
+ /// \brief The number of SFINAE diagnostics that have been trapped.
+ unsigned NumSFINAEErrors;
+
typedef llvm::DenseMap<Selector, ObjCMethodList> MethodPool;
/// Instance/Factory Method Pools - allows efficient lookup when typechecking
@@ -308,8 +311,25 @@ public:
if (isSFINAEContext() && Diagnostic::isBuiltinSFINAEDiag(DiagID)) {
// If we encountered an error during template argument
// deduction, and that error is one of the SFINAE errors,
- // supress the diagnostic.
- return SemaDiagnosticBuilder(*this);
+ // suppress the diagnostic.
+ bool Fatal = false;
+ switch (Diags.getDiagnosticLevel(DiagID)) {
+ case Diagnostic::Ignored:
+ case Diagnostic::Note:
+ case Diagnostic::Warning:
+ break;
+
+ case Diagnostic::Error:
+ ++NumSFINAEErrors;
+ break;
+
+ case Diagnostic::Fatal:
+ Fatal = true;
+ break;
+ }
+
+ if (!Fatal)
+ return SemaDiagnosticBuilder(*this);
}
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
@@ -2340,6 +2360,24 @@ public:
/// will be suppressed and there will be no local error recovery.
bool isSFINAEContext() const;
+ /// \brief RAII class used to determine whether SFINAE has
+ /// trapped any errors that occur during template argument
+ /// deduction.
+ class SFINAETrap {
+ Sema &SemaRef;
+ unsigned PrevSFINAEErrors;
+ public:
+ explicit SFINAETrap(Sema &SemaRef)
+ : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors) { }
+
+ ~SFINAETrap() { SemaRef.NumSFINAEErrors = PrevSFINAEErrors; }
+
+ /// \brief Determine whether any SFINAE errors have been trapped.
+ bool hasErrorOccurred() const {
+ return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
+ }
+ };
+
/// \brief A stack-allocated class that identifies which local
/// variable declaration instantiations are present in this scope.
///
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 2cab07ee19..84d802d1bf 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -632,6 +632,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
// argument list if the template arguments of the partial
// specialization can be deduced from the actual template argument
// list (14.8.2).
+ SFINAETrap Trap(*this);
llvm::SmallVector<TemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result
@@ -735,6 +736,9 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
// FIXME: Check template template arguments?
}
+ if (Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+
return TDK_Success;
}