Rejigger how -pedantic and -pedantic-errors work and their interaction
with other diagnostic mapping. In the new scheme, -Wfoo or -Wno-foo or
-Werror=foo all override the -pedantic options, and __extension__
robustly silences all extension diagnostics in their scope.
An added bonus of this change is that MAP_DEFAULT goes away, meaning that
per-diagnostic mapping information can now be stored in 2 bits, doubling
the density of the Diagnostic::DiagMapping array. This also
substantially simplifies Diagnostic::getDiagnosticLevel.
OTOH, this temporarily introduces some "macro intensive" code in
Diagnostic.cpp. This will be addressed in a later patch.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69154 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 8c393c5..4dcd7c3 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -12,6 +12,15 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/Diagnostic.h"
+
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Analysis/AnalysisDiagnostic.h"
+#include "clang/Driver/DriverDiagnostic.h"
+
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/SmallVector.h"
@@ -25,50 +34,85 @@
// Builtin Diagnostic information
//===----------------------------------------------------------------------===//
-/// Flag values for diagnostics.
+// DefaultDiagnosticMappings - This specifies the default mapping for each diag,
+// based on its kind. Yay for macros?
+
+struct DefaultMappingInfo {
+ unsigned DiagID : 14;
+ unsigned Mapping : 2;
+};
+
+#define NOTE diag::MAP_IGNORE
+#define WARNING diag::MAP_WARNING
+#define EXTENSION diag::MAP_IGNORE
+#define EXTWARN diag::MAP_WARNING
+#define ERROR diag::MAP_ERROR
+#define FATAL diag::MAP_FATAL
+
+static const DefaultMappingInfo DefaultMappings[] = {
+#define DIAG(ENUM,CLASS,DESC) { diag::ENUM, CLASS },
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+{ 0, 0 }
+};
+
+#undef DIAG
+#undef NOTE
+#undef WARNING
+#undef EXTENSION
+#undef EXTWARN
+#undef ERROR
+#undef FATAL
+
+
+
+// Diagnostic classes.
enum {
- // Diagnostic classes.
NOTE = 0x01,
WARNING = 0x02,
EXTENSION = 0x03,
EXTWARN = 0x04,
ERROR = 0x05,
- FATAL = 0x06,
- class_mask = 0x07
+ FATAL = 0x06
};
-/// DiagnosticFlags - A set of flags, or'd together, that describe the
-/// diagnostic.
-#define DIAG(ENUM,FLAGS,DESC) FLAGS,
-static unsigned char DiagnosticFlagsCommon[] = {
+/// DiagnosticClasses - The class for each diagnostic.
+#define DIAG(ENUM,CLASS,DESC) CLASS,
+static unsigned char DiagnosticClassesCommon[] = {
#include "clang/Basic/DiagnosticCommonKinds.inc"
0
};
-static unsigned char DiagnosticFlagsDriver[] = {
+static unsigned char DiagnosticClassesDriver[] = {
#include "clang/Basic/DiagnosticDriverKinds.inc"
0
};
-static unsigned char DiagnosticFlagsFrontend[] = {
+static unsigned char DiagnosticClassesFrontend[] = {
#include "clang/Basic/DiagnosticFrontendKinds.inc"
0
};
-static unsigned char DiagnosticFlagsLex[] = {
+static unsigned char DiagnosticClassesLex[] = {
#include "clang/Basic/DiagnosticLexKinds.inc"
0
};
-static unsigned char DiagnosticFlagsParse[] = {
+static unsigned char DiagnosticClassesParse[] = {
#include "clang/Basic/DiagnosticParseKinds.inc"
0
};
-static unsigned char DiagnosticFlagsAST[] = {
+static unsigned char DiagnosticClassesAST[] = {
#include "clang/Basic/DiagnosticASTKinds.inc"
0
};
-static unsigned char DiagnosticFlagsSema[] = {
+static unsigned char DiagnosticClassesSema[] = {
#include "clang/Basic/DiagnosticSemaKinds.inc"
0
};
-static unsigned char DiagnosticFlagsAnalysis[] = {
+static unsigned char DiagnosticClassesAnalysis[] = {
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
0
};
@@ -81,27 +125,27 @@
"Diagnostic ID out of range!");
unsigned res;
if (DiagID < diag::DIAG_START_DRIVER)
- res = DiagnosticFlagsCommon[DiagID];
+ res = DiagnosticClassesCommon[DiagID];
else if (DiagID < diag::DIAG_START_FRONTEND)
- res = DiagnosticFlagsDriver[DiagID - diag::DIAG_START_DRIVER - 1];
+ res = DiagnosticClassesDriver[DiagID - diag::DIAG_START_DRIVER - 1];
else if (DiagID < diag::DIAG_START_LEX)
- res = DiagnosticFlagsFrontend[DiagID - diag::DIAG_START_FRONTEND - 1];
+ res = DiagnosticClassesFrontend[DiagID - diag::DIAG_START_FRONTEND - 1];
else if (DiagID < diag::DIAG_START_PARSE)
- res = DiagnosticFlagsLex[DiagID - diag::DIAG_START_LEX - 1];
+ res = DiagnosticClassesLex[DiagID - diag::DIAG_START_LEX - 1];
else if (DiagID < diag::DIAG_START_AST)
- res = DiagnosticFlagsParse[DiagID - diag::DIAG_START_PARSE - 1];
+ res = DiagnosticClassesParse[DiagID - diag::DIAG_START_PARSE - 1];
else if (DiagID < diag::DIAG_START_SEMA)
- res = DiagnosticFlagsAST[DiagID - diag::DIAG_START_AST - 1];
+ res = DiagnosticClassesAST[DiagID - diag::DIAG_START_AST - 1];
else if (DiagID < diag::DIAG_START_ANALYSIS)
- res = DiagnosticFlagsSema[DiagID - diag::DIAG_START_SEMA - 1];
+ res = DiagnosticClassesSema[DiagID - diag::DIAG_START_SEMA - 1];
else
- res = DiagnosticFlagsAnalysis[DiagID - diag::DIAG_START_ANALYSIS - 1];
- return res & class_mask;
+ res = DiagnosticClassesAnalysis[DiagID - diag::DIAG_START_ANALYSIS - 1];
+ return res;
}
/// DiagnosticText - An english message to print for the diagnostic. These
/// should be localized.
-#define DIAG(ENUM,FLAGS,DESC) DESC,
+#define DIAG(ENUM,CLASS,DESC) DESC,
static const char * const DiagnosticTextCommon[] = {
#include "clang/Basic/DiagnosticCommonKinds.inc"
0
@@ -203,13 +247,10 @@
Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
+ AllExtensionsSilenced = 0;
IgnoreAllWarnings = false;
WarningsAsErrors = false;
- WarnOnExtensions = false;
- ErrorOnExtensions = false;
SuppressSystemWarnings = false;
- // Clear all mappings, setting them to MAP_DEFAULT.
- memset(DiagMappings, 0, sizeof(DiagMappings));
ErrorOccurred = false;
FatalErrorOccurred = false;
@@ -221,6 +262,12 @@
ArgToStringFn = DummyArgToStringFn;
ArgToStringCookie = 0;
+
+ // Set all mappings to their default.
+ for (unsigned i = 0, e = sizeof(DefaultMappings)/sizeof(DefaultMappings[0]);
+ i != e; ++i)
+ setDiagnosticMappingInternal(DefaultMappings[i].DiagID,
+ DefaultMappings[i].Mapping);
}
Diagnostic::~Diagnostic() {
@@ -251,6 +298,17 @@
return DiagID < diag::DIAG_UPPER_LIMIT && getBuiltinDiagClass(DiagID) == NOTE;
}
+/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+/// ID is for an extension of some sort.
+///
+bool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID) {
+ if (DiagID < diag::DIAG_UPPER_LIMIT) {
+ unsigned Class = getBuiltinDiagClass(DiagID);
+ return Class == EXTENSION || Class == EXTWARN;
+ }
+ return false;
+}
+
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
@@ -294,40 +352,31 @@
Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
// Specific non-error diagnostics may be mapped to various levels from ignored
// to error. Errors can only be mapped to fatal.
+ Diagnostic::Level Result = Diagnostic::Fatal;
switch (getDiagnosticMapping((diag::kind)DiagID)) {
- case diag::MAP_DEFAULT: break;
- case diag::MAP_IGNORE: return Diagnostic::Ignored;
- case diag::MAP_WARNING: DiagClass = WARNING; break;
- case diag::MAP_ERROR: DiagClass = ERROR; break;
- case diag::MAP_FATAL: DiagClass = FATAL; break;
- }
-
- // Map diagnostic classes based on command line argument settings.
- if (DiagClass == EXTENSION) {
- if (ErrorOnExtensions)
- DiagClass = ERROR;
- else if (WarnOnExtensions)
- DiagClass = WARNING;
- else
- return Ignored;
- } else if (DiagClass == EXTWARN) {
- DiagClass = ErrorOnExtensions ? ERROR : WARNING;
- }
-
- // If warnings are globally mapped to ignore or error, do it.
- if (DiagClass == WARNING) {
+ case diag::MAP_IGNORE:
+ return Diagnostic::Ignored;
+ case diag::MAP_ERROR:
+ Result = Diagnostic::Error;
+ break;
+ case diag::MAP_FATAL:
+ Result = Diagnostic::Fatal;
+ break;
+ case diag::MAP_WARNING:
+ // If warnings are globally mapped to ignore or error, do it.
if (IgnoreAllWarnings)
return Diagnostic::Ignored;
- if (WarningsAsErrors)
- DiagClass = ERROR;
+ Result = WarningsAsErrors ? Diagnostic::Error : Diagnostic::Warning;
+ break;
}
+
+ // Okay, we're about to return this as a "diagnostic to emit" one last check:
+ // if this is any sort of extension warning, and if we're in an __extension__
+ // block, silence it.
+ if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
+ return Diagnostic::Ignored;
- switch (DiagClass) {
- default: assert(0 && "Unknown diagnostic class!");
- case WARNING: return Diagnostic::Warning;
- case ERROR: return Diagnostic::Error;
- case FATAL: return Diagnostic::Fatal;
- }
+ return Result;
}
/// ProcessDiag - This is the method used to report a diagnostic that is