aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Basic/Diagnostic.cpp25
-rw-r--r--lib/Sema/Sema.cpp3
-rw-r--r--lib/Sema/Sema.h18
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp28
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
//===----------------------------------------------------------------------===/