blob: 0e9dde8d1ede0cc7b7bb5b5ed9baa4afc4f3d20f [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"
Ted Kremenek7473b1c2012-02-14 02:46:03 +000021#include "clang/Frontend/DiagnosticRenderer.h"
Douglas Gregor02c23eb2012-10-23 22:26:28 +000022#include "clang/Basic/DiagnosticOptions.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000023#include "llvm/ADT/SmallString.h"
Douglas Gregora88084b2010-02-18 18:08:43 +000024#include "llvm/ADT/Twine.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000025#include "llvm/Support/MemoryBuffer.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000026#include "llvm/Support/raw_ostream.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000027
Douglas Gregor5352ac02010-01-28 00:27:43 +000028using namespace clang;
29using namespace clang::cxloc;
Argyrios Kyrtzidis996e6e52011-12-01 02:42:50 +000030using namespace clang::cxdiag;
Douglas Gregora88084b2010-02-18 18:08:43 +000031using namespace llvm;
Douglas Gregor5352ac02010-01-28 00:27:43 +000032
Ted Kremenek15322172011-11-10 08:43:12 +000033
34CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {
35 for (std::vector<CXDiagnosticImpl *>::iterator it = Diagnostics.begin(),
36 et = Diagnostics.end();
37 it != et; ++it) {
38 delete *it;
39 }
40}
41
42CXDiagnosticImpl::~CXDiagnosticImpl() {}
43
Ted Kremenek7473b1c2012-02-14 02:46:03 +000044namespace {
45class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
Ted Kremenek7b8290f2012-02-14 06:54:46 +000046 std::string Message;
Ted Kremenek7473b1c2012-02-14 02:46:03 +000047 CXSourceLocation Loc;
48public:
49 CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
50 : CXDiagnosticImpl(CustomNoteDiagnosticKind),
Ted Kremenek7b8290f2012-02-14 06:54:46 +000051 Message(Msg), Loc(L) {}
Ted Kremenek7473b1c2012-02-14 02:46:03 +000052
Ted Kremenek7b8290f2012-02-14 06:54:46 +000053 virtual ~CXDiagnosticCustomNoteImpl() {}
Ted Kremenek7473b1c2012-02-14 02:46:03 +000054
55 CXDiagnosticSeverity getSeverity() const {
56 return CXDiagnostic_Note;
57 }
58
59 CXSourceLocation getLocation() const {
60 return Loc;
61 }
62
63 CXString getSpelling() const {
Dmitri Gribenko5595ded2013-02-02 02:19:29 +000064 return cxstring::createRef(Message.c_str());
Ted Kremenek7473b1c2012-02-14 02:46:03 +000065 }
66
67 CXString getDiagnosticOption(CXString *Disable) const {
68 if (Disable)
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +000069 *Disable = cxstring::createEmpty();
70 return cxstring::createEmpty();
Ted Kremenek7473b1c2012-02-14 02:46:03 +000071 }
72
73 unsigned getCategory() const { return 0; }
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +000074 CXString getCategoryText() const { return cxstring::createEmpty(); }
Ted Kremenek78d5d3b2012-04-12 00:03:31 +000075
Ted Kremenek7473b1c2012-02-14 02:46:03 +000076 unsigned getNumRanges() const { return 0; }
77 CXSourceRange getRange(unsigned Range) const { return clang_getNullRange(); }
78 unsigned getNumFixIts() const { return 0; }
79 CXString getFixIt(unsigned FixIt, CXSourceRange *ReplacementRange) const {
80 if (ReplacementRange)
81 *ReplacementRange = clang_getNullRange();
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +000082 return cxstring::createEmpty();
Ted Kremenek7473b1c2012-02-14 02:46:03 +000083 }
84};
85
86class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
87public:
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +000088 CXDiagnosticRenderer(const LangOptions &LangOpts,
Douglas Gregor02c23eb2012-10-23 22:26:28 +000089 DiagnosticOptions *DiagOpts,
Ted Kremenek7473b1c2012-02-14 02:46:03 +000090 CXDiagnosticSetImpl *mainSet)
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +000091 : DiagnosticNoteRenderer(LangOpts, DiagOpts),
Ted Kremenek7473b1c2012-02-14 02:46:03 +000092 CurrentSet(mainSet), MainSet(mainSet) {}
93
94 virtual ~CXDiagnosticRenderer() {}
95
96 virtual void beginDiagnostic(DiagOrStoredDiag D,
97 DiagnosticsEngine::Level Level) {
98
99 const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
100 if (!SD)
101 return;
102
103 if (Level != DiagnosticsEngine::Note)
104 CurrentSet = MainSet;
105
106 CXStoredDiagnostic *CD = new CXStoredDiagnostic(*SD, LangOpts);
107 CurrentSet->appendDiagnostic(CD);
108
109 if (Level != DiagnosticsEngine::Note)
110 CurrentSet = &CD->getChildDiagnostics();
111 }
112
113 virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
114 DiagnosticsEngine::Level Level,
115 StringRef Message,
116 ArrayRef<CharSourceRange> Ranges,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000117 const SourceManager *SM,
Ted Kremenek7473b1c2012-02-14 02:46:03 +0000118 DiagOrStoredDiag D) {
119 if (!D.isNull())
120 return;
121
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000122 CXSourceLocation L;
123 if (SM)
124 L = translateSourceLocation(*SM, LangOpts, Loc);
125 else
126 L = clang_getNullLocation();
Ted Kremenek7473b1c2012-02-14 02:46:03 +0000127 CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L);
128 CurrentSet->appendDiagnostic(CD);
129 }
130
131 virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
132 DiagnosticsEngine::Level Level,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000133 ArrayRef<CharSourceRange> Ranges,
134 const SourceManager &SM) {}
Ted Kremenek7473b1c2012-02-14 02:46:03 +0000135
136 virtual void emitCodeContext(SourceLocation Loc,
137 DiagnosticsEngine::Level Level,
138 SmallVectorImpl<CharSourceRange>& Ranges,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000139 ArrayRef<FixItHint> Hints,
140 const SourceManager &SM) {}
Ted Kremenek7473b1c2012-02-14 02:46:03 +0000141
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000142 virtual void emitNote(SourceLocation Loc, StringRef Message,
143 const SourceManager *SM) {
144 CXSourceLocation L;
145 if (SM)
146 L = translateSourceLocation(*SM, LangOpts, Loc);
147 else
148 L = clang_getNullLocation();
Ted Kremenek7473b1c2012-02-14 02:46:03 +0000149 CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message,
150 L));
151 }
152
153 CXDiagnosticSetImpl *CurrentSet;
154 CXDiagnosticSetImpl *MainSet;
155};
156}
157
Argyrios Kyrtzidis996e6e52011-12-01 02:42:50 +0000158CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
159 bool checkIfChanged) {
Dmitri Gribenko5694feb2013-01-26 18:53:38 +0000160 ASTUnit *AU = cxtu::getASTUnit(TU);
Argyrios Kyrtzidis220b45c2011-11-16 02:34:55 +0000161
162 if (TU->Diagnostics && checkIfChanged) {
Argyrios Kyrtzidisc88e58c2011-11-16 08:59:00 +0000163 // In normal use, ASTUnit's diagnostics should not change unless we reparse.
164 // Currently they can only change by using the internal testing flag
165 // '-error-on-deserialized-decl' which will error during deserialization of
166 // a declaration. What will happen is:
167 //
168 // -c-index-test gets a CXTranslationUnit
169 // -checks the diagnostics, the diagnostics set is lazily created,
170 // no errors are reported
171 // -later does an operation, like annotation of tokens, that triggers
172 // -error-on-deserialized-decl, that will emit a diagnostic error,
173 // that ASTUnit will catch and add to its stored diagnostics vector.
174 // -c-index-test wants to check whether an error occurred after performing
175 // the operation but can only query the lazily created set.
176 //
177 // We check here if a new diagnostic was appended since the last time the
178 // diagnostic set was created, in which case we reset it.
179
Argyrios Kyrtzidis220b45c2011-11-16 02:34:55 +0000180 CXDiagnosticSetImpl *
181 Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
182 if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
183 // Diagnostics in the ASTUnit were updated, reset the associated
184 // diagnostics.
185 delete Set;
186 TU->Diagnostics = 0;
187 }
188 }
189
Ted Kremenek15322172011-11-10 08:43:12 +0000190 if (!TU->Diagnostics) {
Ted Kremenek15322172011-11-10 08:43:12 +0000191 CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
192 TU->Diagnostics = Set;
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000193 IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions;
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000194 CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
Douglas Gregor02c23eb2012-10-23 22:26:28 +0000195 &*DOpts, Set);
Ted Kremenek15322172011-11-10 08:43:12 +0000196
197 for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
198 ei = AU->stored_diag_end(); it != ei; ++it) {
Ted Kremenek7473b1c2012-02-14 02:46:03 +0000199 Renderer.emitStoredDiagnostic(*it);
Ted Kremenek15322172011-11-10 08:43:12 +0000200 }
201 }
202 return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
203}
204
Douglas Gregor5352ac02010-01-28 00:27:43 +0000205//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000206// C Interface Routines
Douglas Gregor5352ac02010-01-28 00:27:43 +0000207//-----------------------------------------------------------------------------
208extern "C" {
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000209
Douglas Gregora88084b2010-02-18 18:08:43 +0000210unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Dmitri Gribenkoe42e5782013-01-26 21:32:42 +0000211 if (!cxtu::getASTUnit(Unit))
Ted Kremenek15322172011-11-10 08:43:12 +0000212 return 0;
Argyrios Kyrtzidis220b45c2011-11-16 02:34:55 +0000213 return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
Douglas Gregora88084b2010-02-18 18:08:43 +0000214}
215
216CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Ted Kremenek0373fcc2011-12-09 22:28:32 +0000217 CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
218 if (!D)
Douglas Gregora88084b2010-02-18 18:08:43 +0000219 return 0;
220
Ted Kremenek0373fcc2011-12-09 22:28:32 +0000221 CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
Ted Kremenek15322172011-11-10 08:43:12 +0000222 if (Index >= Diags->getNumDiagnostics())
223 return 0;
224
225 return Diags->getDiagnostic(Index);
Douglas Gregora88084b2010-02-18 18:08:43 +0000226}
Ted Kremenek0373fcc2011-12-09 22:28:32 +0000227
228CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
Dmitri Gribenkoe42e5782013-01-26 21:32:42 +0000229 if (!cxtu::getASTUnit(Unit))
Ted Kremenek0373fcc2011-12-09 22:28:32 +0000230 return 0;
231 return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
232}
Douglas Gregora88084b2010-02-18 18:08:43 +0000233
234void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
Ted Kremenek15322172011-11-10 08:43:12 +0000235 // No-op. Kept as a legacy API. CXDiagnostics are now managed
236 // by the enclosing CXDiagnosticSet.
Douglas Gregora88084b2010-02-18 18:08:43 +0000237}
238
Douglas Gregor274f1902010-02-22 23:17:23 +0000239CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
240 if (!Diagnostic)
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +0000241 return cxstring::createEmpty();
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000242
243 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
244
Dylan Noblesmith36d59272012-02-13 12:32:26 +0000245 SmallString<256> Str;
Douglas Gregor274f1902010-02-22 23:17:23 +0000246 llvm::raw_svector_ostream Out(Str);
247
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000248 if (Options & CXDiagnostic_DisplaySourceLocation) {
249 // Print source location (file:line), along with optional column
250 // and source ranges.
251 CXFile File;
252 unsigned Line, Column;
Douglas Gregora9b06d42010-11-09 06:24:54 +0000253 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
254 &File, &Line, &Column, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000255 if (File) {
256 CXString FName = clang_getFileName(File);
Douglas Gregor274f1902010-02-22 23:17:23 +0000257 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000258 clang_disposeString(FName);
259 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregor274f1902010-02-22 23:17:23 +0000260 Out << Column << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000261
262 if (Options & CXDiagnostic_DisplaySourceRanges) {
263 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
264 bool PrintedRange = false;
265 for (unsigned I = 0; I != N; ++I) {
266 CXFile StartFile, EndFile;
267 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
268
269 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregora9b06d42010-11-09 06:24:54 +0000270 clang_getSpellingLocation(clang_getRangeStart(Range),
271 &StartFile, &StartLine, &StartColumn,
272 0);
273 clang_getSpellingLocation(clang_getRangeEnd(Range),
274 &EndFile, &EndLine, &EndColumn, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000275
276 if (StartFile != EndFile || StartFile != File)
277 continue;
278
Douglas Gregor274f1902010-02-22 23:17:23 +0000279 Out << "{" << StartLine << ":" << StartColumn << "-"
280 << EndLine << ":" << EndColumn << "}";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000281 PrintedRange = true;
282 }
283 if (PrintedRange)
Douglas Gregor274f1902010-02-22 23:17:23 +0000284 Out << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000285 }
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000286
287 Out << " ";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000288 }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000289 }
290
291 /* Print warning/error/etc. */
292 switch (Severity) {
David Blaikieeb2d1f12011-09-23 20:26:49 +0000293 case CXDiagnostic_Ignored: llvm_unreachable("impossible");
Douglas Gregor274f1902010-02-22 23:17:23 +0000294 case CXDiagnostic_Note: Out << "note: "; break;
295 case CXDiagnostic_Warning: Out << "warning: "; break;
296 case CXDiagnostic_Error: Out << "error: "; break;
297 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000298 }
299
300 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
301 if (clang_getCString(Text))
Douglas Gregor274f1902010-02-22 23:17:23 +0000302 Out << clang_getCString(Text);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000303 else
Douglas Gregor274f1902010-02-22 23:17:23 +0000304 Out << "<no diagnostic text>";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000305 clang_disposeString(Text);
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000306
307 if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
308 CXDiagnostic_DisplayCategoryName)) {
309 bool NeedBracket = true;
310 bool NeedComma = false;
311
312 if (Options & CXDiagnostic_DisplayOption) {
313 CXString OptionName = clang_getDiagnosticOption(Diagnostic, 0);
314 if (const char *OptionText = clang_getCString(OptionName)) {
315 if (OptionText[0]) {
316 Out << " [" << OptionText;
317 NeedBracket = false;
318 NeedComma = true;
319 }
320 }
321 clang_disposeString(OptionName);
322 }
323
324 if (Options & (CXDiagnostic_DisplayCategoryId |
325 CXDiagnostic_DisplayCategoryName)) {
326 if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
327 if (Options & CXDiagnostic_DisplayCategoryId) {
328 if (NeedBracket)
329 Out << " [";
330 if (NeedComma)
331 Out << ", ";
332 Out << CategoryID;
333 NeedBracket = false;
334 NeedComma = true;
335 }
336
337 if (Options & CXDiagnostic_DisplayCategoryName) {
Ted Kremenek78d5d3b2012-04-12 00:03:31 +0000338 CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic);
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000339 if (NeedBracket)
340 Out << " [";
341 if (NeedComma)
342 Out << ", ";
343 Out << clang_getCString(CategoryName);
344 NeedBracket = false;
345 NeedComma = true;
346 clang_disposeString(CategoryName);
347 }
348 }
349 }
Ted Kremenek8e598382012-04-04 00:55:33 +0000350
351 (void) NeedComma; // Silence dead store warning.
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000352 if (!NeedBracket)
353 Out << "]";
354 }
355
Dmitri Gribenko5595ded2013-02-02 02:19:29 +0000356 return cxstring::createDup(Out.str());
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000357}
358
359unsigned clang_defaultDiagnosticDisplayOptions() {
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000360 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
361 CXDiagnostic_DisplayOption;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000362}
363
Douglas Gregor5352ac02010-01-28 00:27:43 +0000364enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000365 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
366 return D->getSeverity();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000367 return CXDiagnostic_Ignored;
368}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000369
Douglas Gregor5352ac02010-01-28 00:27:43 +0000370CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000371 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
372 return D->getLocation();
373 return clang_getNullLocation();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000374}
375
376CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000377 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
378 return D->getSpelling();
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +0000379 return cxstring::createEmpty();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000380}
381
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000382CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
383 if (Disable)
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +0000384 *Disable = cxstring::createEmpty();
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000385
386 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
387 return D->getDiagnosticOption(Disable);
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000388
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +0000389 return cxstring::createEmpty();
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000390}
391
392unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000393 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
394 return D->getCategory();
395 return 0;
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000396}
397
398CXString clang_getDiagnosticCategoryName(unsigned Category) {
Ted Kremenek78d5d3b2012-04-12 00:03:31 +0000399 // Kept for backwards compatibility.
Dmitri Gribenko5595ded2013-02-02 02:19:29 +0000400 return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000401}
402
Ted Kremenek78d5d3b2012-04-12 00:03:31 +0000403CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
404 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
405 return D->getCategoryText();
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +0000406 return cxstring::createEmpty();
Ted Kremenek78d5d3b2012-04-12 00:03:31 +0000407}
408
Douglas Gregora3890ba2010-02-08 23:11:56 +0000409unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000410 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
411 return D->getNumRanges();
412 return 0;
Douglas Gregor5352ac02010-01-28 00:27:43 +0000413}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000414
Douglas Gregora3890ba2010-02-08 23:11:56 +0000415CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000416 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
417 if (!D || Range >= D->getNumRanges())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000418 return clang_getNullRange();
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000419 return D->getRange(Range);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000420}
421
422unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000423 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
424 return D->getNumFixIts();
425 return 0;
Douglas Gregor5352ac02010-01-28 00:27:43 +0000426}
427
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000428CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
Douglas Gregor473d7012010-02-19 18:16:06 +0000429 CXSourceRange *ReplacementRange) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000430 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
431 if (!D || FixIt >= D->getNumFixIts()) {
Douglas Gregor473d7012010-02-19 18:16:06 +0000432 if (ReplacementRange)
433 *ReplacementRange = clang_getNullRange();
Dmitri Gribenkodc66adb2013-02-01 14:21:22 +0000434 return cxstring::createEmpty();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000435 }
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000436 return D->getFixIt(FixIt, ReplacementRange);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000437}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000438
Ted Kremenek15322172011-11-10 08:43:12 +0000439void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
440 CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags);
441 if (D->isExternallyManaged())
442 delete D;
443}
444
445CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
446 unsigned Index) {
447 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
448 if (Index < D->getNumDiagnostics())
449 return D->getDiagnostic(Index);
450 return 0;
451}
452
453CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
454 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
455 CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
456 return ChildDiags.empty() ? 0 : (CXDiagnosticSet) &ChildDiags;
457 }
458 return 0;
459}
460
461unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
462 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
463 return D->getNumDiagnostics();
464 return 0;
465}
466
Douglas Gregor5352ac02010-01-28 00:27:43 +0000467} // end extern "C"