handle labeldecls.
[clang.git] / tools / libclang / CIndexDiagnostic.cpp
blobfa3b1cec7fb3998d4c69dd4db9d874430c0070bf
1 /*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\
2 |* *|
3 |* The LLVM Compiler Infrastructure *|
4 |* *|
5 |* This file is distributed under the University of Illinois Open Source *|
6 |* License. See LICENSE.TXT for details. *|
7 |* *|
8 |*===----------------------------------------------------------------------===*|
9 |* *|
10 |* Implements the diagnostic functions of the Clang C interface. *|
11 |* *|
12 \*===----------------------------------------------------------------------===*/
13 #include "CIndexDiagnostic.h"
14 #include "CIndexer.h"
15 #include "CXTranslationUnit.h"
16 #include "CXSourceLocation.h"
17 #include "CXString.h"
19 #include "clang/Frontend/ASTUnit.h"
20 #include "clang/Frontend/FrontendDiagnostic.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/raw_ostream.h"
26 using namespace clang;
27 using namespace clang::cxloc;
28 using namespace clang::cxstring;
29 using namespace llvm;
31 //-----------------------------------------------------------------------------
32 // C Interface Routines
33 //-----------------------------------------------------------------------------
34 extern "C" {
36 unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
37 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
38 return CXXUnit? CXXUnit->stored_diag_size() : 0;
41 CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
42 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
43 if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
44 return 0;
46 return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
47 CXXUnit->getASTContext().getLangOptions());
50 void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
51 CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
52 delete Stored;
55 CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
56 if (!Diagnostic)
57 return createCXString("");
59 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
61 llvm::SmallString<256> Str;
62 llvm::raw_svector_ostream Out(Str);
64 if (Options & CXDiagnostic_DisplaySourceLocation) {
65 // Print source location (file:line), along with optional column
66 // and source ranges.
67 CXFile File;
68 unsigned Line, Column;
69 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
70 &File, &Line, &Column, 0);
71 if (File) {
72 CXString FName = clang_getFileName(File);
73 Out << clang_getCString(FName) << ":" << Line << ":";
74 clang_disposeString(FName);
75 if (Options & CXDiagnostic_DisplayColumn)
76 Out << Column << ":";
78 if (Options & CXDiagnostic_DisplaySourceRanges) {
79 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
80 bool PrintedRange = false;
81 for (unsigned I = 0; I != N; ++I) {
82 CXFile StartFile, EndFile;
83 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
85 unsigned StartLine, StartColumn, EndLine, EndColumn;
86 clang_getSpellingLocation(clang_getRangeStart(Range),
87 &StartFile, &StartLine, &StartColumn,
88 0);
89 clang_getSpellingLocation(clang_getRangeEnd(Range),
90 &EndFile, &EndLine, &EndColumn, 0);
92 if (StartFile != EndFile || StartFile != File)
93 continue;
95 Out << "{" << StartLine << ":" << StartColumn << "-"
96 << EndLine << ":" << EndColumn << "}";
97 PrintedRange = true;
99 if (PrintedRange)
100 Out << ":";
103 Out << " ";
107 /* Print warning/error/etc. */
108 switch (Severity) {
109 case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
110 case CXDiagnostic_Note: Out << "note: "; break;
111 case CXDiagnostic_Warning: Out << "warning: "; break;
112 case CXDiagnostic_Error: Out << "error: "; break;
113 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
116 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
117 if (clang_getCString(Text))
118 Out << clang_getCString(Text);
119 else
120 Out << "<no diagnostic text>";
121 clang_disposeString(Text);
123 if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
124 CXDiagnostic_DisplayCategoryName)) {
125 bool NeedBracket = true;
126 bool NeedComma = false;
128 if (Options & CXDiagnostic_DisplayOption) {
129 CXString OptionName = clang_getDiagnosticOption(Diagnostic, 0);
130 if (const char *OptionText = clang_getCString(OptionName)) {
131 if (OptionText[0]) {
132 Out << " [" << OptionText;
133 NeedBracket = false;
134 NeedComma = true;
137 clang_disposeString(OptionName);
140 if (Options & (CXDiagnostic_DisplayCategoryId |
141 CXDiagnostic_DisplayCategoryName)) {
142 if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
143 if (Options & CXDiagnostic_DisplayCategoryId) {
144 if (NeedBracket)
145 Out << " [";
146 if (NeedComma)
147 Out << ", ";
148 Out << CategoryID;
149 NeedBracket = false;
150 NeedComma = true;
153 if (Options & CXDiagnostic_DisplayCategoryName) {
154 CXString CategoryName = clang_getDiagnosticCategoryName(CategoryID);
155 if (NeedBracket)
156 Out << " [";
157 if (NeedComma)
158 Out << ", ";
159 Out << clang_getCString(CategoryName);
160 NeedBracket = false;
161 NeedComma = true;
162 clang_disposeString(CategoryName);
167 if (!NeedBracket)
168 Out << "]";
171 return createCXString(Out.str(), true);
174 unsigned clang_defaultDiagnosticDisplayOptions() {
175 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
176 CXDiagnostic_DisplayOption;
179 enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
180 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
181 if (!StoredDiag)
182 return CXDiagnostic_Ignored;
184 switch (StoredDiag->Diag.getLevel()) {
185 case Diagnostic::Ignored: return CXDiagnostic_Ignored;
186 case Diagnostic::Note: return CXDiagnostic_Note;
187 case Diagnostic::Warning: return CXDiagnostic_Warning;
188 case Diagnostic::Error: return CXDiagnostic_Error;
189 case Diagnostic::Fatal: return CXDiagnostic_Fatal;
192 llvm_unreachable("Invalid diagnostic level");
193 return CXDiagnostic_Ignored;
196 CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
197 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
198 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
199 return clang_getNullLocation();
201 return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
202 StoredDiag->LangOpts,
203 StoredDiag->Diag.getLocation());
206 CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
207 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
208 if (!StoredDiag)
209 return createCXString("");
211 return createCXString(StoredDiag->Diag.getMessage(), false);
214 CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
215 if (Disable)
216 *Disable = createCXString("");
218 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
219 if (!StoredDiag)
220 return createCXString("");
222 unsigned ID = StoredDiag->Diag.getID();
223 if (const char *Option = DiagnosticIDs::getWarningOptionForDiag(ID)) {
224 if (Disable)
225 *Disable = createCXString((llvm::Twine("-Wno-") + Option).str());
226 return createCXString((llvm::Twine("-W") + Option).str());
229 if (ID == diag::fatal_too_many_errors) {
230 if (Disable)
231 *Disable = createCXString("-ferror-limit=0");
232 return createCXString("-ferror-limit=");
235 bool EnabledByDefault;
236 if (DiagnosticIDs::isBuiltinExtensionDiag(ID, EnabledByDefault) &&
237 !EnabledByDefault)
238 return createCXString("-pedantic");
240 return createCXString("");
243 unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
244 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
245 if (!StoredDiag)
246 return 0;
248 return DiagnosticIDs::getCategoryNumberForDiag(StoredDiag->Diag.getID());
251 CXString clang_getDiagnosticCategoryName(unsigned Category) {
252 return createCXString(DiagnosticIDs::getCategoryNameFromID(Category));
255 unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
256 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
257 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
258 return 0;
260 return StoredDiag->Diag.range_size();
263 CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
264 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
265 if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
266 StoredDiag->Diag.getLocation().isInvalid())
267 return clang_getNullRange();
269 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
270 StoredDiag->LangOpts,
271 StoredDiag->Diag.range_begin()[Range]);
274 unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
275 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
276 if (!StoredDiag)
277 return 0;
279 return StoredDiag->Diag.fixit_size();
282 CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
283 CXSourceRange *ReplacementRange) {
284 CXStoredDiagnostic *StoredDiag
285 = static_cast<CXStoredDiagnostic *>(Diagnostic);
286 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
287 StoredDiag->Diag.getLocation().isInvalid()) {
288 if (ReplacementRange)
289 *ReplacementRange = clang_getNullRange();
291 return createCXString("");
294 const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
295 if (ReplacementRange) {
296 // Create a range that covers the entire replacement (or
297 // removal) range, adjusting the end of the range to point to
298 // the end of the token.
299 *ReplacementRange
300 = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
301 StoredDiag->LangOpts,
302 Hint.RemoveRange);
305 return createCXString(Hint.CodeToInsert);
308 } // end extern "C"