blob: 0d97ebd9335bef5be4271de81ecba388d4cf4446 [file] [log] [blame]
Douglas Gregor33cdd812010-02-18 18:08:43 +00001/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\
Douglas Gregor4f9c3762010-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 Kremenek7df92ae2010-11-17 23:24:11 +000015#include "CXTranslationUnit.h"
Douglas Gregor4f9c3762010-01-28 00:27:43 +000016#include "CXSourceLocation.h"
Ted Kremenek4b4f3692010-11-16 01:56:27 +000017#include "CXString.h"
Douglas Gregor4f9c3762010-01-28 00:27:43 +000018
Benjamin Kramer064414532010-04-12 19:45:50 +000019#include "clang/Frontend/ASTUnit.h"
Douglas Gregorac0605e2010-01-28 06:00:51 +000020#include "clang/Frontend/FrontendDiagnostic.h"
Ted Kremenek914c7e62012-02-14 02:46:03 +000021#include "clang/Frontend/DiagnosticRenderer.h"
Douglas Gregor811db4e2012-10-23 22:26:28 +000022#include "clang/Basic/DiagnosticOptions.h"
Douglas Gregord770f732010-02-22 23:17:23 +000023#include "llvm/ADT/SmallString.h"
Douglas Gregor33cdd812010-02-18 18:08:43 +000024#include "llvm/ADT/Twine.h"
Douglas Gregorac0605e2010-01-28 06:00:51 +000025#include "llvm/Support/MemoryBuffer.h"
Douglas Gregord770f732010-02-22 23:17:23 +000026#include "llvm/Support/raw_ostream.h"
Douglas Gregorac0605e2010-01-28 06:00:51 +000027
Douglas Gregor4f9c3762010-01-28 00:27:43 +000028using namespace clang;
29using namespace clang::cxloc;
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +000030using namespace clang::cxdiag;
Douglas Gregor33cdd812010-02-18 18:08:43 +000031using namespace llvm;
Douglas Gregor4f9c3762010-01-28 00:27:43 +000032
Ted Kremenekd010ba42011-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 Kremenek914c7e62012-02-14 02:46:03 +000044namespace {
45class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
Ted Kremenekb05119c2012-02-14 06:54:46 +000046 std::string Message;
Ted Kremenek914c7e62012-02-14 02:46:03 +000047 CXSourceLocation Loc;
48public:
49 CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
50 : CXDiagnosticImpl(CustomNoteDiagnosticKind),
Ted Kremenekb05119c2012-02-14 06:54:46 +000051 Message(Msg), Loc(L) {}
Ted Kremenek914c7e62012-02-14 02:46:03 +000052
Ted Kremenekb05119c2012-02-14 06:54:46 +000053 virtual ~CXDiagnosticCustomNoteImpl() {}
Craig Topper36835562014-03-15 07:47:46 +000054
55 CXDiagnosticSeverity getSeverity() const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000056 return CXDiagnostic_Note;
57 }
Craig Topper36835562014-03-15 07:47:46 +000058
59 CXSourceLocation getLocation() const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000060 return Loc;
61 }
Craig Topper36835562014-03-15 07:47:46 +000062
63 CXString getSpelling() const override {
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000064 return cxstring::createRef(Message.c_str());
Ted Kremenek914c7e62012-02-14 02:46:03 +000065 }
Craig Topper36835562014-03-15 07:47:46 +000066
67 CXString getDiagnosticOption(CXString *Disable) const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000068 if (Disable)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000069 *Disable = cxstring::createEmpty();
70 return cxstring::createEmpty();
Ted Kremenek914c7e62012-02-14 02:46:03 +000071 }
Ted Kremenek26a6d492012-04-12 00:03:31 +000072
Craig Topper36835562014-03-15 07:47:46 +000073 unsigned getCategory() const override { return 0; }
74 CXString getCategoryText() const override { return cxstring::createEmpty(); }
75
76 unsigned getNumRanges() const override { return 0; }
77 CXSourceRange getRange(unsigned Range) const override {
78 return clang_getNullRange();
79 }
80 unsigned getNumFixIts() const override { return 0; }
81 CXString getFixIt(unsigned FixIt,
82 CXSourceRange *ReplacementRange) const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000083 if (ReplacementRange)
84 *ReplacementRange = clang_getNullRange();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000085 return cxstring::createEmpty();
Ted Kremenek914c7e62012-02-14 02:46:03 +000086 }
87};
88
89class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
90public:
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +000091 CXDiagnosticRenderer(const LangOptions &LangOpts,
Douglas Gregor811db4e2012-10-23 22:26:28 +000092 DiagnosticOptions *DiagOpts,
Ted Kremenek914c7e62012-02-14 02:46:03 +000093 CXDiagnosticSetImpl *mainSet)
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +000094 : DiagnosticNoteRenderer(LangOpts, DiagOpts),
Ted Kremenek914c7e62012-02-14 02:46:03 +000095 CurrentSet(mainSet), MainSet(mainSet) {}
96
97 virtual ~CXDiagnosticRenderer() {}
98
Craig Topper36835562014-03-15 07:47:46 +000099 void beginDiagnostic(DiagOrStoredDiag D,
100 DiagnosticsEngine::Level Level) override {
101
Ted Kremenek914c7e62012-02-14 02:46:03 +0000102 const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
103 if (!SD)
104 return;
105
106 if (Level != DiagnosticsEngine::Note)
107 CurrentSet = MainSet;
108
109 CXStoredDiagnostic *CD = new CXStoredDiagnostic(*SD, LangOpts);
110 CurrentSet->appendDiagnostic(CD);
111
112 if (Level != DiagnosticsEngine::Note)
113 CurrentSet = &CD->getChildDiagnostics();
114 }
Craig Topper36835562014-03-15 07:47:46 +0000115
116 void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
117 DiagnosticsEngine::Level Level,
118 StringRef Message,
119 ArrayRef<CharSourceRange> Ranges,
120 const SourceManager *SM,
121 DiagOrStoredDiag D) override {
Ted Kremenek914c7e62012-02-14 02:46:03 +0000122 if (!D.isNull())
123 return;
124
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000125 CXSourceLocation L;
126 if (SM)
127 L = translateSourceLocation(*SM, LangOpts, Loc);
128 else
129 L = clang_getNullLocation();
Ted Kremenek914c7e62012-02-14 02:46:03 +0000130 CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L);
131 CurrentSet->appendDiagnostic(CD);
132 }
Ted Kremenek914c7e62012-02-14 02:46:03 +0000133
Craig Topper36835562014-03-15 07:47:46 +0000134 void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
135 DiagnosticsEngine::Level Level,
136 ArrayRef<CharSourceRange> Ranges,
137 const SourceManager &SM) override {}
138
139 void emitCodeContext(SourceLocation Loc,
140 DiagnosticsEngine::Level Level,
141 SmallVectorImpl<CharSourceRange>& Ranges,
142 ArrayRef<FixItHint> Hints,
143 const SourceManager &SM) override {}
144
145 void emitNote(SourceLocation Loc, StringRef Message,
146 const SourceManager *SM) override {
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000147 CXSourceLocation L;
148 if (SM)
149 L = translateSourceLocation(*SM, LangOpts, Loc);
150 else
151 L = clang_getNullLocation();
Ted Kremenek914c7e62012-02-14 02:46:03 +0000152 CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message,
153 L));
154 }
155
156 CXDiagnosticSetImpl *CurrentSet;
157 CXDiagnosticSetImpl *MainSet;
158};
159}
160
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +0000161CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
162 bool checkIfChanged) {
Dmitri Gribenkoc22ea1c2013-01-26 18:53:38 +0000163 ASTUnit *AU = cxtu::getASTUnit(TU);
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000164
165 if (TU->Diagnostics && checkIfChanged) {
Argyrios Kyrtzidis7ae5d9c2011-11-16 08:59:00 +0000166 // In normal use, ASTUnit's diagnostics should not change unless we reparse.
167 // Currently they can only change by using the internal testing flag
168 // '-error-on-deserialized-decl' which will error during deserialization of
169 // a declaration. What will happen is:
170 //
171 // -c-index-test gets a CXTranslationUnit
172 // -checks the diagnostics, the diagnostics set is lazily created,
173 // no errors are reported
174 // -later does an operation, like annotation of tokens, that triggers
175 // -error-on-deserialized-decl, that will emit a diagnostic error,
176 // that ASTUnit will catch and add to its stored diagnostics vector.
177 // -c-index-test wants to check whether an error occurred after performing
178 // the operation but can only query the lazily created set.
179 //
180 // We check here if a new diagnostic was appended since the last time the
181 // diagnostic set was created, in which case we reset it.
182
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000183 CXDiagnosticSetImpl *
184 Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
185 if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
186 // Diagnostics in the ASTUnit were updated, reset the associated
187 // diagnostics.
188 delete Set;
Craig Topper69186e72014-06-08 08:38:04 +0000189 TU->Diagnostics = nullptr;
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000190 }
191 }
192
Ted Kremenekd010ba42011-11-10 08:43:12 +0000193 if (!TU->Diagnostics) {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000194 CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
195 TU->Diagnostics = Set;
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000196 IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions;
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000197 CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
Douglas Gregor811db4e2012-10-23 22:26:28 +0000198 &*DOpts, Set);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000199
200 for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
201 ei = AU->stored_diag_end(); it != ei; ++it) {
Ted Kremenek914c7e62012-02-14 02:46:03 +0000202 Renderer.emitStoredDiagnostic(*it);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000203 }
204 }
205 return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
206}
207
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000208//-----------------------------------------------------------------------------
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000209// C Interface Routines
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000210//-----------------------------------------------------------------------------
211extern "C" {
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000212
Douglas Gregor33cdd812010-02-18 18:08:43 +0000213unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000214 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000215 LOG_BAD_TU(Unit);
216 return 0;
217 }
Dmitri Gribenkod36209e2013-01-26 21:32:42 +0000218 if (!cxtu::getASTUnit(Unit))
Ted Kremenekd010ba42011-11-10 08:43:12 +0000219 return 0;
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000220 return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
Douglas Gregor33cdd812010-02-18 18:08:43 +0000221}
222
223CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000224 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000225 LOG_BAD_TU(Unit);
Craig Topper69186e72014-06-08 08:38:04 +0000226 return nullptr;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000227 }
228
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000229 CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
230 if (!D)
Craig Topper69186e72014-06-08 08:38:04 +0000231 return nullptr;
Douglas Gregor33cdd812010-02-18 18:08:43 +0000232
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000233 CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000234 if (Index >= Diags->getNumDiagnostics())
Craig Topper69186e72014-06-08 08:38:04 +0000235 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000236
237 return Diags->getDiagnostic(Index);
Douglas Gregor33cdd812010-02-18 18:08:43 +0000238}
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000239
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000240CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000241 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000242 LOG_BAD_TU(Unit);
Craig Topper69186e72014-06-08 08:38:04 +0000243 return nullptr;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000244 }
Dmitri Gribenkod36209e2013-01-26 21:32:42 +0000245 if (!cxtu::getASTUnit(Unit))
Craig Topper69186e72014-06-08 08:38:04 +0000246 return nullptr;
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000247 return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
248}
Douglas Gregor33cdd812010-02-18 18:08:43 +0000249
250void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000251 // No-op. Kept as a legacy API. CXDiagnostics are now managed
252 // by the enclosing CXDiagnosticSet.
Douglas Gregor33cdd812010-02-18 18:08:43 +0000253}
254
Douglas Gregord770f732010-02-22 23:17:23 +0000255CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
256 if (!Diagnostic)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000257 return cxstring::createEmpty();
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000258
259 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
260
Dylan Noblesmithf1a13f22012-02-13 12:32:26 +0000261 SmallString<256> Str;
Douglas Gregord770f732010-02-22 23:17:23 +0000262 llvm::raw_svector_ostream Out(Str);
263
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000264 if (Options & CXDiagnostic_DisplaySourceLocation) {
265 // Print source location (file:line), along with optional column
266 // and source ranges.
267 CXFile File;
268 unsigned Line, Column;
Douglas Gregor229bebd2010-11-09 06:24:54 +0000269 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
Craig Topper69186e72014-06-08 08:38:04 +0000270 &File, &Line, &Column, nullptr);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000271 if (File) {
272 CXString FName = clang_getFileName(File);
Douglas Gregord770f732010-02-22 23:17:23 +0000273 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000274 clang_disposeString(FName);
275 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregord770f732010-02-22 23:17:23 +0000276 Out << Column << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000277
278 if (Options & CXDiagnostic_DisplaySourceRanges) {
279 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
280 bool PrintedRange = false;
281 for (unsigned I = 0; I != N; ++I) {
282 CXFile StartFile, EndFile;
283 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
284
285 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregor229bebd2010-11-09 06:24:54 +0000286 clang_getSpellingLocation(clang_getRangeStart(Range),
287 &StartFile, &StartLine, &StartColumn,
Craig Topper69186e72014-06-08 08:38:04 +0000288 nullptr);
Douglas Gregor229bebd2010-11-09 06:24:54 +0000289 clang_getSpellingLocation(clang_getRangeEnd(Range),
Craig Topper69186e72014-06-08 08:38:04 +0000290 &EndFile, &EndLine, &EndColumn, nullptr);
291
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000292 if (StartFile != EndFile || StartFile != File)
293 continue;
294
Douglas Gregord770f732010-02-22 23:17:23 +0000295 Out << "{" << StartLine << ":" << StartColumn << "-"
296 << EndLine << ":" << EndColumn << "}";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000297 PrintedRange = true;
298 }
299 if (PrintedRange)
Douglas Gregord770f732010-02-22 23:17:23 +0000300 Out << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000301 }
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000302
303 Out << " ";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000304 }
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000305 }
306
307 /* Print warning/error/etc. */
308 switch (Severity) {
David Blaikieaa347f92011-09-23 20:26:49 +0000309 case CXDiagnostic_Ignored: llvm_unreachable("impossible");
Douglas Gregord770f732010-02-22 23:17:23 +0000310 case CXDiagnostic_Note: Out << "note: "; break;
311 case CXDiagnostic_Warning: Out << "warning: "; break;
312 case CXDiagnostic_Error: Out << "error: "; break;
313 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000314 }
315
316 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
317 if (clang_getCString(Text))
Douglas Gregord770f732010-02-22 23:17:23 +0000318 Out << clang_getCString(Text);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000319 else
Douglas Gregord770f732010-02-22 23:17:23 +0000320 Out << "<no diagnostic text>";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000321 clang_disposeString(Text);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000322
323 if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
324 CXDiagnostic_DisplayCategoryName)) {
325 bool NeedBracket = true;
326 bool NeedComma = false;
327
328 if (Options & CXDiagnostic_DisplayOption) {
Craig Topper69186e72014-06-08 08:38:04 +0000329 CXString OptionName = clang_getDiagnosticOption(Diagnostic, nullptr);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000330 if (const char *OptionText = clang_getCString(OptionName)) {
331 if (OptionText[0]) {
332 Out << " [" << OptionText;
333 NeedBracket = false;
334 NeedComma = true;
335 }
336 }
337 clang_disposeString(OptionName);
338 }
339
340 if (Options & (CXDiagnostic_DisplayCategoryId |
341 CXDiagnostic_DisplayCategoryName)) {
342 if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
343 if (Options & CXDiagnostic_DisplayCategoryId) {
344 if (NeedBracket)
345 Out << " [";
346 if (NeedComma)
347 Out << ", ";
348 Out << CategoryID;
349 NeedBracket = false;
350 NeedComma = true;
351 }
352
353 if (Options & CXDiagnostic_DisplayCategoryName) {
Ted Kremenek26a6d492012-04-12 00:03:31 +0000354 CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000355 if (NeedBracket)
356 Out << " [";
357 if (NeedComma)
358 Out << ", ";
359 Out << clang_getCString(CategoryName);
360 NeedBracket = false;
361 NeedComma = true;
362 clang_disposeString(CategoryName);
363 }
364 }
365 }
Ted Kremenek34b45462012-04-04 00:55:33 +0000366
367 (void) NeedComma; // Silence dead store warning.
Douglas Gregora750e8e2010-11-19 16:18:16 +0000368 if (!NeedBracket)
369 Out << "]";
370 }
371
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000372 return cxstring::createDup(Out.str());
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000373}
374
375unsigned clang_defaultDiagnosticDisplayOptions() {
Douglas Gregora750e8e2010-11-19 16:18:16 +0000376 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
377 CXDiagnostic_DisplayOption;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000378}
379
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000380enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000381 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
382 return D->getSeverity();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000383 return CXDiagnostic_Ignored;
384}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000385
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000386CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000387 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
388 return D->getLocation();
389 return clang_getNullLocation();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000390}
391
392CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000393 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
394 return D->getSpelling();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000395 return cxstring::createEmpty();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000396}
397
Douglas Gregora750e8e2010-11-19 16:18:16 +0000398CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
399 if (Disable)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000400 *Disable = cxstring::createEmpty();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000401
402 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
403 return D->getDiagnosticOption(Disable);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000404
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000405 return cxstring::createEmpty();
Douglas Gregora750e8e2010-11-19 16:18:16 +0000406}
407
408unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000409 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
410 return D->getCategory();
411 return 0;
Douglas Gregora750e8e2010-11-19 16:18:16 +0000412}
413
414CXString clang_getDiagnosticCategoryName(unsigned Category) {
Alp Toker958027b2014-07-14 19:42:55 +0000415 // Kept for backward compatibility.
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000416 return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
Douglas Gregora750e8e2010-11-19 16:18:16 +0000417}
418
Ted Kremenek26a6d492012-04-12 00:03:31 +0000419CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
420 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
421 return D->getCategoryText();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000422 return cxstring::createEmpty();
Ted Kremenek26a6d492012-04-12 00:03:31 +0000423}
424
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000425unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000426 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
427 return D->getNumRanges();
428 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000429}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000430
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000431CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000432 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
433 if (!D || Range >= D->getNumRanges())
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000434 return clang_getNullRange();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000435 return D->getRange(Range);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000436}
437
438unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000439 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
440 return D->getNumFixIts();
441 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000442}
443
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000444CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
Douglas Gregor836ec942010-02-19 18:16:06 +0000445 CXSourceRange *ReplacementRange) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000446 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
447 if (!D || FixIt >= D->getNumFixIts()) {
Douglas Gregor836ec942010-02-19 18:16:06 +0000448 if (ReplacementRange)
449 *ReplacementRange = clang_getNullRange();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000450 return cxstring::createEmpty();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000451 }
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000452 return D->getFixIt(FixIt, ReplacementRange);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000453}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000454
Ted Kremenekd010ba42011-11-10 08:43:12 +0000455void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
Dmitri Gribenko371c2172014-02-12 14:17:58 +0000456 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) {
457 if (D->isExternallyManaged())
458 delete D;
459 }
Ted Kremenekd010ba42011-11-10 08:43:12 +0000460}
461
462CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
463 unsigned Index) {
464 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
465 if (Index < D->getNumDiagnostics())
466 return D->getDiagnostic(Index);
Craig Topper69186e72014-06-08 08:38:04 +0000467 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000468}
469
470CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
471 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
472 CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
Craig Topper69186e72014-06-08 08:38:04 +0000473 return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000474 }
Craig Topper69186e72014-06-08 08:38:04 +0000475 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000476}
477
478unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
479 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
480 return D->getNumDiagnostics();
481 return 0;
482}
483
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000484} // end extern "C"