зеркало из https://github.com/microsoft/clang-1.git
146 строки
4.5 KiB
C++
146 строки
4.5 KiB
C++
//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by Chris Lattner and is distributed under
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the Diagnostic-related interfaces.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Basic/Diagnostic.h"
|
|
#include "clang/Basic/SourceLocation.h"
|
|
#include <cassert>
|
|
using namespace clang;
|
|
|
|
/// Flag values for diagnostics.
|
|
enum {
|
|
// Diagnostic classes.
|
|
NOTE = 0x01,
|
|
WARNING = 0x02,
|
|
EXTENSION = 0x03,
|
|
ERROR = 0x04,
|
|
class_mask = 0x07
|
|
};
|
|
|
|
/// DiagnosticFlags - A set of flags, or'd together, that describe the
|
|
/// diagnostic.
|
|
static unsigned char DiagnosticFlags[] = {
|
|
#define DIAG(ENUM,FLAGS,DESC) FLAGS,
|
|
#include "clang/Basic/DiagnosticKinds.def"
|
|
0
|
|
};
|
|
|
|
/// getDiagClass - Return the class field of the diagnostic.
|
|
///
|
|
static unsigned getDiagClass(unsigned DiagID) {
|
|
assert(DiagID < diag::NUM_DIAGNOSTICS && "Diagnostic ID out of range!");
|
|
return DiagnosticFlags[DiagID] & class_mask;
|
|
}
|
|
|
|
/// DiagnosticText - An english message to print for the diagnostic. These
|
|
/// should be localized.
|
|
static const char * const DiagnosticText[] = {
|
|
#define DIAG(ENUM,FLAGS,DESC) DESC,
|
|
#include "clang/Basic/DiagnosticKinds.def"
|
|
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));
|
|
|
|
ErrorOccurred = false;
|
|
NumDiagnostics = 0;
|
|
NumErrors = 0;
|
|
}
|
|
|
|
/// isNoteWarningOrExtension - Return true if the unmapped diagnostic level of
|
|
/// the specified diagnostic ID is a Note, Warning, or Extension.
|
|
bool Diagnostic::isNoteWarningOrExtension(unsigned DiagID) {
|
|
return getDiagClass(DiagID) < ERROR;
|
|
}
|
|
|
|
|
|
/// getDescription - Given a diagnostic ID, return a description of the
|
|
/// issue.
|
|
const char *Diagnostic::getDescription(unsigned DiagID) {
|
|
assert(DiagID < diag::NUM_DIAGNOSTICS && "Diagnostic ID out of range!");
|
|
return DiagnosticText[DiagID];
|
|
}
|
|
|
|
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
|
|
/// object, classify the specified diagnostic ID into a Level, consumable by
|
|
/// the DiagnosticClient.
|
|
Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
|
|
unsigned DiagClass = getDiagClass(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) {
|
|
if (ErrorOnExtensions)
|
|
DiagClass = ERROR;
|
|
else if (WarnOnExtensions)
|
|
DiagClass = WARNING;
|
|
else
|
|
return Ignored;
|
|
}
|
|
|
|
// If warnings are to be treated as errors, indicate this as such.
|
|
if (DiagClass == WARNING && WarningsAsErrors)
|
|
DiagClass = ERROR;
|
|
|
|
switch (DiagClass) {
|
|
default: assert(0 && "Unknown diagnostic class!");
|
|
case NOTE: return Diagnostic::Note;
|
|
case WARNING: return Diagnostic::Warning;
|
|
case ERROR: return Diagnostic::Error;
|
|
}
|
|
}
|
|
|
|
/// Report - Issue the message to the client. If the client wants us to stop
|
|
/// compilation, return true, otherwise return false. DiagID is a member of
|
|
/// the diag::kind enum.
|
|
void Diagnostic::Report(SourceLocation Pos, unsigned DiagID,
|
|
const std::string *Strs, unsigned NumStrs,
|
|
const SourceRange *Ranges, unsigned NumRanges) {
|
|
// Figure out the diagnostic level of this message.
|
|
Diagnostic::Level DiagLevel = getDiagnosticLevel(DiagID);
|
|
|
|
// If the client doesn't care about this message, don't issue it.
|
|
if (DiagLevel == Diagnostic::Ignored)
|
|
return;
|
|
|
|
if (DiagLevel >= Diagnostic::Error) {
|
|
ErrorOccurred = true;
|
|
++NumErrors;
|
|
}
|
|
|
|
// Are we going to ignore this diagnosic?
|
|
if (Client.IgnoreDiagnostic(DiagLevel, Pos))
|
|
return;
|
|
|
|
// Finally, report it.
|
|
Client.HandleDiagnostic(DiagLevel, Pos, (diag::kind)DiagID, Strs, NumStrs,
|
|
Ranges, NumRanges);
|
|
++NumDiagnostics;
|
|
}
|
|
|
|
DiagnosticClient::~DiagnosticClient() {}
|