blob: db71a767c91686be2f597ea1e9773d43ac36efa3 [file] [log] [blame]
Douglas Gregora88084b2010-02-18 18:08:43 +00001/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\
Douglas Gregor5352ac02010-01-28 00:27:43 +00002|* *|
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"
Ted Kremenek0a90d322010-11-17 23:24:11 +000015#include "CXTranslationUnit.h"
Douglas Gregor5352ac02010-01-28 00:27:43 +000016#include "CXSourceLocation.h"
Ted Kremeneked122732010-11-16 01:56:27 +000017#include "CXString.h"
Douglas Gregor5352ac02010-01-28 00:27:43 +000018
Benjamin Kramerb846deb2010-04-12 19:45:50 +000019#include "clang/Frontend/ASTUnit.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000020#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000021#include "llvm/ADT/SmallString.h"
Douglas Gregora88084b2010-02-18 18:08:43 +000022#include "llvm/ADT/Twine.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000023#include "llvm/Support/MemoryBuffer.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000024#include "llvm/Support/raw_ostream.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000025
Douglas Gregor5352ac02010-01-28 00:27:43 +000026using namespace clang;
27using namespace clang::cxloc;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000028using namespace clang::cxstring;
Douglas Gregora88084b2010-02-18 18:08:43 +000029using namespace llvm;
Douglas Gregor5352ac02010-01-28 00:27:43 +000030
31//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000032// C Interface Routines
Douglas Gregor5352ac02010-01-28 00:27:43 +000033//-----------------------------------------------------------------------------
34extern "C" {
Ted Kremenekee4db4f2010-02-17 00:41:08 +000035
Douglas Gregora88084b2010-02-18 18:08:43 +000036unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Ted Kremeneka60ed472010-11-16 08:15:36 +000037 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
Douglas Gregor405634b2010-04-05 18:10:21 +000038 return CXXUnit? CXXUnit->stored_diag_size() : 0;
Douglas Gregora88084b2010-02-18 18:08:43 +000039}
40
41CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Ted Kremeneka60ed472010-11-16 08:15:36 +000042 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
Douglas Gregor405634b2010-04-05 18:10:21 +000043 if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
Douglas Gregora88084b2010-02-18 18:08:43 +000044 return 0;
45
Douglas Gregor405634b2010-04-05 18:10:21 +000046 return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
Douglas Gregora88084b2010-02-18 18:08:43 +000047 CXXUnit->getASTContext().getLangOptions());
48}
49
50void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
51 CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
52 delete Stored;
53}
54
Douglas Gregor274f1902010-02-22 23:17:23 +000055CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
56 if (!Diagnostic)
57 return createCXString("");
Douglas Gregor0a812cf2010-02-18 23:07:20 +000058
59 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
60
Douglas Gregor274f1902010-02-22 23:17:23 +000061 llvm::SmallString<256> Str;
62 llvm::raw_svector_ostream Out(Str);
63
Douglas Gregor0a812cf2010-02-18 23:07:20 +000064 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;
Douglas Gregora9b06d42010-11-09 06:24:54 +000069 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
70 &File, &Line, &Column, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +000071 if (File) {
72 CXString FName = clang_getFileName(File);
Douglas Gregor274f1902010-02-22 23:17:23 +000073 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000074 clang_disposeString(FName);
75 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregor274f1902010-02-22 23:17:23 +000076 Out << Column << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000077
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);
84
85 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregora9b06d42010-11-09 06:24:54 +000086 clang_getSpellingLocation(clang_getRangeStart(Range),
87 &StartFile, &StartLine, &StartColumn,
88 0);
89 clang_getSpellingLocation(clang_getRangeEnd(Range),
90 &EndFile, &EndLine, &EndColumn, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +000091
92 if (StartFile != EndFile || StartFile != File)
93 continue;
94
Douglas Gregor274f1902010-02-22 23:17:23 +000095 Out << "{" << StartLine << ":" << StartColumn << "-"
96 << EndLine << ":" << EndColumn << "}";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000097 PrintedRange = true;
98 }
99 if (PrintedRange)
Douglas Gregor274f1902010-02-22 23:17:23 +0000100 Out << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000101 }
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000102
103 Out << " ";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000104 }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000105 }
106
107 /* Print warning/error/etc. */
108 switch (Severity) {
David Blaikieeb2d1f12011-09-23 20:26:49 +0000109 case CXDiagnostic_Ignored: llvm_unreachable("impossible");
Douglas Gregor274f1902010-02-22 23:17:23 +0000110 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;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000114 }
115
116 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
117 if (clang_getCString(Text))
Douglas Gregor274f1902010-02-22 23:17:23 +0000118 Out << clang_getCString(Text);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000119 else
Douglas Gregor274f1902010-02-22 23:17:23 +0000120 Out << "<no diagnostic text>";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000121 clang_disposeString(Text);
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000122
123 if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
124 CXDiagnostic_DisplayCategoryName)) {
125 bool NeedBracket = true;
126 bool NeedComma = false;
127
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;
135 }
136 }
137 clang_disposeString(OptionName);
138 }
139
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;
151 }
152
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);
163 }
164 }
165 }
166
167 if (!NeedBracket)
168 Out << "]";
169 }
170
Douglas Gregor274f1902010-02-22 23:17:23 +0000171 return createCXString(Out.str(), true);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000172}
173
174unsigned clang_defaultDiagnosticDisplayOptions() {
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000175 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
176 CXDiagnostic_DisplayOption;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000177}
178
Douglas Gregor5352ac02010-01-28 00:27:43 +0000179enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
180 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
181 if (!StoredDiag)
182 return CXDiagnostic_Ignored;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000183
Douglas Gregora88084b2010-02-18 18:08:43 +0000184 switch (StoredDiag->Diag.getLevel()) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000185 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;
190 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000191
Douglas Gregor5352ac02010-01-28 00:27:43 +0000192 llvm_unreachable("Invalid diagnostic level");
193 return CXDiagnostic_Ignored;
194}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000195
Douglas Gregor5352ac02010-01-28 00:27:43 +0000196CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
197 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000198 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +0000199 return clang_getNullLocation();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000200
Douglas Gregora88084b2010-02-18 18:08:43 +0000201 return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
202 StoredDiag->LangOpts,
203 StoredDiag->Diag.getLocation());
Douglas Gregor5352ac02010-01-28 00:27:43 +0000204}
205
206CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
207 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
208 if (!StoredDiag)
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000209 return createCXString("");
210
Douglas Gregora88084b2010-02-18 18:08:43 +0000211 return createCXString(StoredDiag->Diag.getMessage(), false);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000212}
213
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000214CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
215 if (Disable)
216 *Disable = createCXString("");
217
218 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
219 if (!StoredDiag)
220 return createCXString("");
221
222 unsigned ID = StoredDiag->Diag.getID();
Chris Lattner5f9e2722011-07-23 10:55:15 +0000223 StringRef Option = DiagnosticIDs::getWarningOptionForDiag(ID);
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000224 if (!Option.empty()) {
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000225 if (Disable)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000226 *Disable = createCXString((Twine("-Wno-") + Option).str());
227 return createCXString((Twine("-W") + Option).str());
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000228 }
229
230 if (ID == diag::fatal_too_many_errors) {
231 if (Disable)
232 *Disable = createCXString("-ferror-limit=0");
233 return createCXString("-ferror-limit=");
234 }
235
236 bool EnabledByDefault;
237 if (DiagnosticIDs::isBuiltinExtensionDiag(ID, EnabledByDefault) &&
238 !EnabledByDefault)
239 return createCXString("-pedantic");
240
241 return createCXString("");
242}
243
244unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
245 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
246 if (!StoredDiag)
247 return 0;
248
249 return DiagnosticIDs::getCategoryNumberForDiag(StoredDiag->Diag.getID());
250}
251
252CXString clang_getDiagnosticCategoryName(unsigned Category) {
253 return createCXString(DiagnosticIDs::getCategoryNameFromID(Category));
254}
255
Douglas Gregora3890ba2010-02-08 23:11:56 +0000256unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000257 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000258 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000259 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000260
Douglas Gregora88084b2010-02-18 18:08:43 +0000261 return StoredDiag->Diag.range_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000262}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000263
Douglas Gregora3890ba2010-02-08 23:11:56 +0000264CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
265 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000266 if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
267 StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000268 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000269
Douglas Gregora88084b2010-02-18 18:08:43 +0000270 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
271 StoredDiag->LangOpts,
272 StoredDiag->Diag.range_begin()[Range]);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000273}
274
275unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
276 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
277 if (!StoredDiag)
278 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000279
Douglas Gregora88084b2010-02-18 18:08:43 +0000280 return StoredDiag->Diag.fixit_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000281}
282
Douglas Gregor473d7012010-02-19 18:16:06 +0000283CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
284 CXSourceRange *ReplacementRange) {
285 CXStoredDiagnostic *StoredDiag
286 = static_cast<CXStoredDiagnostic *>(Diagnostic);
Douglas Gregora88084b2010-02-18 18:08:43 +0000287 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
288 StoredDiag->Diag.getLocation().isInvalid()) {
Douglas Gregor473d7012010-02-19 18:16:06 +0000289 if (ReplacementRange)
290 *ReplacementRange = clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000291
292 return createCXString("");
Douglas Gregor5352ac02010-01-28 00:27:43 +0000293 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000294
Douglas Gregor849b2432010-03-31 17:46:05 +0000295 const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
Douglas Gregor473d7012010-02-19 18:16:06 +0000296 if (ReplacementRange) {
Douglas Gregor783c56f2010-08-18 14:24:02 +0000297 // Create a range that covers the entire replacement (or
298 // removal) range, adjusting the end of the range to point to
299 // the end of the token.
300 *ReplacementRange
301 = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
302 StoredDiag->LangOpts,
303 Hint.RemoveRange);
Douglas Gregor473d7012010-02-19 18:16:06 +0000304 }
305
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000306 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000307}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000308
Douglas Gregor5352ac02010-01-28 00:27:43 +0000309} // end extern "C"