diff options
-rw-r--r-- | lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 42 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 4 |
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; } |