blob: aa732e300a9a8db2cc8b1ad1988ce949ed458cc9 [file] [log] [blame]
Chris Lattner22eb9722006-06-18 05:43:12 +00001//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Diagnostic-related interfaces.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/Diagnostic.h"
15#include "clang/Basic/SourceLocation.h"
16#include <cassert>
17using namespace llvm;
18using namespace clang;
19
20/// Flag values for diagnostics.
21enum {
22 // Diagnostic classes.
23 NOTE = 0x01,
24 WARNING = 0x02,
25 EXTENSION = 0x03,
26 ERROR = 0x04,
27 FATAL = 0x05,
28 class_mask = 0x07
29};
30
31/// DiagnosticFlags - A set of flags, or'd together, that describe the
32/// diagnostic.
33static unsigned char DiagnosticFlags[] = {
34#define DIAG(ENUM,FLAGS,DESC) FLAGS,
35#include "clang/Basic/DiagnosticKinds.def"
36 0
37};
38
39/// getDiagClass - Return the class field of the diagnostic.
40///
41static unsigned getDiagClass(unsigned DiagID) {
42 assert(DiagID < diag::NUM_DIAGNOSTICS && "Diagnostic ID out of range!");
43 return DiagnosticFlags[DiagID] & class_mask;
44}
45
46/// DiagnosticText - An english message to print for the diagnostic. These
47/// should be localized.
48static const char * const DiagnosticText[] = {
49#define DIAG(ENUM,FLAGS,DESC) DESC,
50#include "clang/Basic/DiagnosticKinds.def"
51 0
52};
53
Chris Lattnerae411572006-07-05 00:55:08 +000054Diagnostic::Diagnostic(DiagnosticClient &client) : Client(client) {
55 WarningsAsErrors = false;
56 WarnOnExtensions = false;
57 ErrorOnExtensions = false;
58 // Clear all mappings, setting them to MAP_DEFAULT.
59 memset(DiagMappings, 0, sizeof(DiagMappings));
60}
61
Chris Lattner22eb9722006-06-18 05:43:12 +000062/// isNoteWarningOrExtension - Return true if the unmapped diagnostic level of
63/// the specified diagnostic ID is a Note, Warning, or Extension.
64bool Diagnostic::isNoteWarningOrExtension(unsigned DiagID) {
65 return getDiagClass(DiagID) < ERROR;
66}
67
68
69/// getDescription - Given a diagnostic ID, return a description of the
70/// issue.
71const char *Diagnostic::getDescription(unsigned DiagID) {
72 assert(DiagID < diag::NUM_DIAGNOSTICS && "Diagnostic ID out of range!");
73 return DiagnosticText[DiagID];
74}
75
76/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
77/// object, classify the specified diagnostic ID into a Level, consumable by
78/// the DiagnosticClient.
79Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
80 unsigned DiagClass = getDiagClass(DiagID);
81
Chris Lattnerae411572006-07-05 00:55:08 +000082 // Specific non-error diagnostics may be mapped to various levels from ignored
83 // to error.
84 if (DiagClass < ERROR) {
85 switch (getDiagnosticMapping((diag::kind)DiagID)) {
86 case diag::MAP_DEFAULT: break;
87 case diag::MAP_IGNORE: return Ignored;
88 case diag::MAP_WARNING: DiagClass = WARNING; break;
89 case diag::MAP_ERROR: DiagClass = ERROR; break;
90 }
91 }
Chris Lattner22eb9722006-06-18 05:43:12 +000092
93 // Map diagnostic classes based on command line argument settings.
94 if (DiagClass == EXTENSION) {
95 if (ErrorOnExtensions)
96 DiagClass = ERROR;
97 else if (WarnOnExtensions)
98 DiagClass = WARNING;
99 else
100 return Ignored;
101 }
102
103 // If warnings are to be treated as errors, indicate this as such.
104 if (DiagClass == WARNING && WarningsAsErrors)
105 DiagClass = ERROR;
106
107 switch (DiagClass) {
108 default: assert(0 && "Unknown diagnostic class!");
109 case NOTE: return Diagnostic::Note;
110 case WARNING: return Diagnostic::Warning;
111 case ERROR: return Diagnostic::Error;
112 case FATAL: return Diagnostic::Fatal;
113 }
114}
115
116/// Report - Issue the message to the client. If the client wants us to stop
117/// compilation, return true, otherwise return false. DiagID is a member of
118/// the diag::kind enum.
Chris Lattnercb283342006-06-18 06:48:37 +0000119void Diagnostic::Report(SourceLocation Pos, unsigned DiagID,
Steve Naroff71ce2e02007-05-18 22:53:50 +0000120 const std::string *Strs, unsigned NumStrs,
Chris Lattnerbeeb9bc2007-05-19 08:07:42 +0000121 const SourceRange *Ranges, unsigned NumRanges) {
Chris Lattner22eb9722006-06-18 05:43:12 +0000122 // Figure out the diagnostic level of this message.
123 Diagnostic::Level DiagLevel = getDiagnosticLevel(DiagID);
124
Chris Lattnercb283342006-06-18 06:48:37 +0000125 // If the client doesn't care about this message, don't issue it.
Chris Lattner22eb9722006-06-18 05:43:12 +0000126 if (DiagLevel == Diagnostic::Ignored)
Chris Lattnercb283342006-06-18 06:48:37 +0000127 return;
Chris Lattner22eb9722006-06-18 05:43:12 +0000128
129 // Finally, report it.
Steve Naroff71ce2e02007-05-18 22:53:50 +0000130 Client.HandleDiagnostic(DiagLevel, Pos, (diag::kind)DiagID, Strs, NumStrs,
131 Ranges, NumRanges);
Chris Lattner22eb9722006-06-18 05:43:12 +0000132}
133
134DiagnosticClient::~DiagnosticClient() {}