mirror of
https://github.com/intel/llvm.git
synced 2026-02-05 04:46:27 +08:00
out of the llvm namespace. This makes the clang namespace be a sibling of llvm instead of being a child. The good thing about this is that it makes many things unambiguous. The bad things is that many things in the llvm namespace (notably data structures like smallvector) now require an llvm:: qualifier. IMO, libsystem and libsupport should be split out of llvm into their own namespace in the future, which will fix this issue. llvm-svn: 39659
148 lines
4.6 KiB
C++
148 lines
4.6 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,
|
|
FATAL = 0x05,
|
|
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;
|
|
case FATAL: return Diagnostic::Fatal;
|
|
}
|
|
}
|
|
|
|
/// 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() {}
|