diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Basic/Diagnostic.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 18 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 28 |
4 files changed, 65 insertions, 9 deletions
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 3b3d61b08d..323f7a7d4a 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -46,6 +46,7 @@ struct StaticDiagInfoRec { unsigned short DiagID; unsigned Mapping : 3; unsigned Class : 3; + bool SFINAE : 1; const char *Description; const char *OptionGroup; @@ -58,8 +59,8 @@ struct StaticDiagInfoRec { }; static const StaticDiagInfoRec StaticDiagInfo[] = { -#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP) \ - { diag::ENUM, DEFAULT_MAPPING, CLASS, DESC, GROUP }, +#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) \ + { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, DESC, GROUP }, #include "clang/Basic/DiagnosticCommonKinds.inc" #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" @@ -68,7 +69,7 @@ static const StaticDiagInfoRec StaticDiagInfo[] = { #include "clang/Basic/DiagnosticASTKinds.inc" #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" -{ 0, 0, 0, 0, 0 } + { 0, 0, 0, 0, 0, 0} }; #undef DIAG @@ -89,7 +90,7 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { #endif // Search the diagnostic table with a binary search. - StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0 }; + StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0 }; const StaticDiagInfoRec *Found = std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find); @@ -115,6 +116,12 @@ const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) { return 0; } +bool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->SFINAE && Info->Class != CLASS_NOTE; + return false; +} + /// getDiagClass - Return the class field of the diagnostic. /// static unsigned getBuiltinDiagClass(unsigned DiagID) { @@ -399,7 +406,7 @@ bool Diagnostic::setDiagnosticGroupMapping(const char *Group, /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. -void Diagnostic::ProcessDiag() { +bool Diagnostic::ProcessDiag() { DiagnosticInfo Info(this); // Figure out the diagnostic level of this message. @@ -449,13 +456,13 @@ void Diagnostic::ProcessDiag() { // If a fatal error has already been emitted, silence all subsequent // diagnostics. if (FatalErrorOccurred) - return; + return false; // If the client doesn't care about this message, don't issue it. If this is // a note and the last real diagnostic was ignored, ignore it too. if (DiagLevel == Diagnostic::Ignored || (DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored)) - return; + return false; // If this diagnostic is in a system header and is not a clang error, suppress // it. @@ -464,7 +471,7 @@ void Diagnostic::ProcessDiag() { Info.getLocation().getSpellingLoc().isInSystemHeader() && (DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) { LastDiagLevel = Diagnostic::Ignored; - return; + return false; } if (DiagLevel >= Diagnostic::Error) { @@ -477,6 +484,8 @@ void Diagnostic::ProcessDiag() { if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics; CurDiagID = ~0U; + + return true; } 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 //===----------------------------------------------------------------------===/ |