//===--- 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 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() {}