diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 18 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 28 |
3 files changed, 48 insertions, 1 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index e3cea5be42..4dc5222072 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -316,7 +316,8 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() { } Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { - this->Emit(); + if (!this->Emit()) + return; // If this is not a note, and we're in a template instantiation // that is different from the last template instantiation where diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 169ce8216c..b310568740 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -297,11 +297,21 @@ public: SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID) : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { } + explicit SemaDiagnosticBuilder(Sema &SemaRef) + : DiagnosticBuilder(DiagnosticBuilder::Suppress), SemaRef(SemaRef) { } + ~SemaDiagnosticBuilder(); }; /// \brief Emit a diagnostic. SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { + 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); + } + DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID); return SemaDiagnosticBuilder(DB, *this, DiagID); } @@ -2322,6 +2332,14 @@ public: void PrintInstantiationStack(); + /// \brief Determines whether we are currently in a context where + /// template argument substitution failures are not considered + /// errors. + /// + /// When this routine returns true, the emission of most diagnostics + /// will be suppressed and there will be no local error recovery. + bool isSFINAEContext() const; + /// \brief A stack-allocated class that identifies which local /// variable declaration instantiations are present in this scope. /// diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 4d03e79c65..18b2d75acc 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -199,6 +199,34 @@ void Sema::PrintInstantiationStack() { } } +bool Sema::isSFINAEContext() const { + using llvm::SmallVector; + for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator + Active = ActiveTemplateInstantiations.rbegin(), + ActiveEnd = ActiveTemplateInstantiations.rend(); + Active != ActiveEnd; + ++Active) { + + switch(Active->Kind) { + case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation: + // We're in a template argument deduction context, so SFINAE + // applies. + return true; + + case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: + // A default template argument instantiation may or may not be a + // SFINAE context; look further up the stack. + break; + + case ActiveTemplateInstantiation::TemplateInstantiation: + // This is a template instantiation, so there is no SFINAE. + return false; + } + } + + return false; +} + //===----------------------------------------------------------------------===/ // Template Instantiation for Types //===----------------------------------------------------------------------===/ |