Implement support for arbitrarily mapping non-error diagnostics to be either

ignored, warned about, or error'd.  Use this to implement the -Wunused_macros
command line option.

llvm-svn: 38676
This commit is contained in:
Chris Lattner 2006-07-05 00:55:08 +00:00
parent ecbf7b4bb0
commit ae41157ee5
4 changed files with 65 additions and 12 deletions

View File

@ -51,6 +51,14 @@ static const char * const DiagnosticText[] = {
0
};
Diagnostic::Diagnostic(DiagnosticClient &client) : Client(client) {
WarningsAsErrors = false;
WarnOnExtensions = false;
ErrorOnExtensions = false;
// Clear all mappings, setting them to MAP_DEFAULT.
memset(DiagMappings, 0, sizeof(DiagMappings));
}
/// isNoteWarningOrExtension - Return true if the unmapped diagnostic level of
/// the specified diagnostic ID is a Note, Warning, or Extension.
bool Diagnostic::isNoteWarningOrExtension(unsigned DiagID) {
@ -71,8 +79,16 @@ const char *Diagnostic::getDescription(unsigned DiagID) {
Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
unsigned DiagClass = getDiagClass(DiagID);
// TODO: specific diagnostics may be enabled or disabled. Filter those based
// on their DiagID.
// Specific non-error diagnostics may be mapped to various levels from ignored
// to error.
if (DiagClass < ERROR) {
switch (getDiagnosticMapping((diag::kind)DiagID)) {
case diag::MAP_DEFAULT: break;
case diag::MAP_IGNORE: return Ignored;
case diag::MAP_WARNING: DiagClass = WARNING; break;
case diag::MAP_ERROR: DiagClass = ERROR; break;
}
}
// Map diagnostic classes based on command line argument settings.
if (DiagClass == EXTENSION) {

View File

@ -78,12 +78,21 @@ static cl::opt<bool>
ErrorOnExtensions("pedantic-errors",
cl::desc("Issue an error on uses of GCC extensions"));
static cl::opt<bool>
WarnUnusedMacros("Wunused_macros",
cl::desc("Warn for unused macros in the main translation unit"));
/// InitializeDiagnostics - Initialize the diagnostic object, based on the
/// current command line option settings.
static void InitializeDiagnostics(Diagnostic &Diags) {
Diags.setWarningsAsErrors(WarningsAsErrors);
Diags.setWarnOnExtensions(WarnOnExtensions);
Diags.setErrorOnExtensions(ErrorOnExtensions);
// Silence the "macro is not used" warning unless requested.
if (!WarnUnusedMacros)
Diags.setDiagnosticMapping(diag::pp_macro_not_used, diag::MAP_IGNORE);
}
static cl::opt<bool>

View File

@ -23,11 +23,12 @@ II. Current advantages over GCC:
* All languages supported linked into same library (no cc1,cc1obj, ...).
* mmap's code in read-only, does not dirty the pages like GCC (mem footprint).
* BSD License, can be linked into non-GPL projects.
* Full diagnostic control, per diagnostic.
* Faster than GCC at lexing and preprocessing.
Future Features:
* Full diagnostic control, per diagnostic (use enums).
* Fine grained control within the source (#pragma enable/disable warning)
* Faster than GCC, preprocessing, parsing, IR generation.
* Fine grained diag control within the source (#pragma enable/disable warning).
* Faster than GCC at parsing, IR generation.
* Better token tracking within macros? (Token came from this line, which is
a macro argument instantiated here, recursively instantiated here).
* Fast #import!!
@ -118,4 +119,5 @@ Cocoa GUI Front-end:
* Tight integration with compiler components.
* Primary advantage: batch compiles, keeping digests in memory, dependency mgmt
between app frameworks, building code/digests in the background, etc.
* Interesting idea: http://nickgravgaard.com/elastictabstops/

View File

@ -24,11 +24,22 @@ namespace clang {
// Import the diagnostic enums themselves.
namespace diag {
/// diag::kind - All of the diagnostics that can be emitted by the frontend.
enum kind {
#define DIAG(ENUM,FLAGS,DESC) ENUM,
#include "DiagnosticKinds.def"
NUM_DIAGNOSTICS
};
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
/// (emit as an error), or MAP_DEFAULT (handle the default way).
enum Mapping {
MAP_DEFAULT = 0, //< Do not map this diagnostic.
MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
MAP_WARNING = 2, //< Map this diagnostic to a warning.
MAP_ERROR = 3 //< Map this diagnostic to an error.
};
}
/// Diagnostic - This concrete class is used by the front-end to report
@ -40,12 +51,12 @@ class Diagnostic {
bool WarnOnExtensions; // Enables warnings for gcc extensions: -pedantic.
bool ErrorOnExtensions; // Error on extensions: -pedantic-errors.
DiagnosticClient &Client;
/// DiagMappings - Mapping information for diagnostics. Mapping info is
/// packed into two bits per diagnostic.
unsigned char DiagMappings[(diag::NUM_DIAGNOSTICS+3)/4];
public:
Diagnostic(DiagnosticClient &client) : Client(client) {
WarningsAsErrors = false;
WarnOnExtensions = false;
ErrorOnExtensions = false;
}
Diagnostic(DiagnosticClient &client);
//===--------------------------------------------------------------------===//
// Diagnostic characterization methods, used by a client to customize how
@ -66,6 +77,22 @@ public:
void setErrorOnExtensions(bool Val) { ErrorOnExtensions = Val; }
bool getErrorOnExtensions() const { return ErrorOnExtensions; }
/// setDiagnosticMapping - This allows the client to specify that certain
/// warnings are ignored. Only NOTEs, WARNINGs, and EXTENSIONs can be mapped.
void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
assert(isNoteWarningOrExtension(Diag) && "Cannot map errors!");
unsigned char &Slot = DiagMappings[Diag/4];
unsigned Bits = (Diag & 3)*2;
Slot &= ~(3 << Bits);
Slot |= Map << Bits;
}
/// getDiagnosticMapping - Return the mapping currently set for the specified
/// diagnostic.
diag::Mapping getDiagnosticMapping(diag::kind Diag) const {
return (diag::Mapping)((DiagMappings[Diag/4] >> (Diag & 3)*2) & 3);
}
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
@ -77,7 +104,6 @@ public:
/// Level - The level of the diagnostic
enum Level {
// FIXME: Anachronism?
Ignored, Note, Warning, Error, Fatal, Sorry
};