blob: 4e47b25a4bf0127735e17e7ce77d260b4a3b114e [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
Douglas Gregor811db4e2012-10-23 22:26:28 +000019#include "clang/Basic/DiagnosticOptions.h"
Mehdi Amini9670f842016-07-18 19:02:11 +000020#include "clang/Frontend/ASTUnit.h"
21#include "clang/Frontend/DiagnosticRenderer.h"
22#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregord770f732010-02-22 23:17:23 +000023#include "llvm/ADT/SmallString.h"
Douglas Gregord770f732010-02-22 23:17:23 +000024#include "llvm/Support/raw_ostream.h"
Douglas Gregorac0605e2010-01-28 06:00:51 +000025
Douglas Gregor4f9c3762010-01-28 00:27:43 +000026using namespace clang;
27using namespace clang::cxloc;
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +000028using namespace clang::cxdiag;
Douglas Gregor33cdd812010-02-18 18:08:43 +000029using namespace llvm;
Douglas Gregor4f9c3762010-01-28 00:27:43 +000030
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000031CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {}
Ted Kremenekd010ba42011-11-10 08:43:12 +000032
David Blaikie759548b2014-08-29 18:43:24 +000033void
34CXDiagnosticSetImpl::appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D) {
35 Diagnostics.push_back(std::move(D));
Ted Kremenekd010ba42011-11-10 08:43:12 +000036}
37
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000038CXDiagnosticImpl::~CXDiagnosticImpl() {}
Ted Kremenekd010ba42011-11-10 08:43:12 +000039
Ted Kremenek914c7e62012-02-14 02:46:03 +000040namespace {
41class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
Ted Kremenekb05119c2012-02-14 06:54:46 +000042 std::string Message;
Ted Kremenek914c7e62012-02-14 02:46:03 +000043 CXSourceLocation Loc;
44public:
45 CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
46 : CXDiagnosticImpl(CustomNoteDiagnosticKind),
Ted Kremenekb05119c2012-02-14 06:54:46 +000047 Message(Msg), Loc(L) {}
Ted Kremenek914c7e62012-02-14 02:46:03 +000048
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000049 ~CXDiagnosticCustomNoteImpl() override {}
Craig Topper36835562014-03-15 07:47:46 +000050
51 CXDiagnosticSeverity getSeverity() const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000052 return CXDiagnostic_Note;
53 }
Craig Topper36835562014-03-15 07:47:46 +000054
55 CXSourceLocation getLocation() const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000056 return Loc;
57 }
Craig Topper36835562014-03-15 07:47:46 +000058
59 CXString getSpelling() const override {
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000060 return cxstring::createRef(Message.c_str());
Ted Kremenek914c7e62012-02-14 02:46:03 +000061 }
Craig Topper36835562014-03-15 07:47:46 +000062
63 CXString getDiagnosticOption(CXString *Disable) const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000064 if (Disable)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000065 *Disable = cxstring::createEmpty();
66 return cxstring::createEmpty();
Ted Kremenek914c7e62012-02-14 02:46:03 +000067 }
Ted Kremenek26a6d492012-04-12 00:03:31 +000068
Craig Topper36835562014-03-15 07:47:46 +000069 unsigned getCategory() const override { return 0; }
70 CXString getCategoryText() const override { return cxstring::createEmpty(); }
71
72 unsigned getNumRanges() const override { return 0; }
73 CXSourceRange getRange(unsigned Range) const override {
74 return clang_getNullRange();
75 }
76 unsigned getNumFixIts() const override { return 0; }
77 CXString getFixIt(unsigned FixIt,
78 CXSourceRange *ReplacementRange) const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000079 if (ReplacementRange)
80 *ReplacementRange = clang_getNullRange();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000081 return cxstring::createEmpty();
Ted Kremenek914c7e62012-02-14 02:46:03 +000082 }
83};
84
85class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
86public:
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +000087 CXDiagnosticRenderer(const LangOptions &LangOpts,
Douglas Gregor811db4e2012-10-23 22:26:28 +000088 DiagnosticOptions *DiagOpts,
Ted Kremenek914c7e62012-02-14 02:46:03 +000089 CXDiagnosticSetImpl *mainSet)
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +000090 : DiagnosticNoteRenderer(LangOpts, DiagOpts),
Ted Kremenek914c7e62012-02-14 02:46:03 +000091 CurrentSet(mainSet), MainSet(mainSet) {}
Alexander Kornienko34eb2072015-04-11 02:00:23 +000092
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000093 ~CXDiagnosticRenderer() override {}
Ted Kremenek914c7e62012-02-14 02:46:03 +000094
Craig Topper36835562014-03-15 07:47:46 +000095 void beginDiagnostic(DiagOrStoredDiag D,
96 DiagnosticsEngine::Level Level) override {
97
Ted Kremenek914c7e62012-02-14 02:46:03 +000098 const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
99 if (!SD)
100 return;
101
102 if (Level != DiagnosticsEngine::Note)
103 CurrentSet = MainSet;
David Blaikie759548b2014-08-29 18:43:24 +0000104
105 auto Owner = llvm::make_unique<CXStoredDiagnostic>(*SD, LangOpts);
106 CXStoredDiagnostic &CD = *Owner;
107 CurrentSet->appendDiagnostic(std::move(Owner));
108
Ted Kremenek914c7e62012-02-14 02:46:03 +0000109 if (Level != DiagnosticsEngine::Note)
David Blaikie759548b2014-08-29 18:43:24 +0000110 CurrentSet = &CD.getChildDiagnostics();
Ted Kremenek914c7e62012-02-14 02:46:03 +0000111 }
Craig Topper36835562014-03-15 07:47:46 +0000112
Christof Doumafb4a0452017-06-27 09:50:38 +0000113 void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
114 DiagnosticsEngine::Level Level, StringRef Message,
Craig Topper36835562014-03-15 07:47:46 +0000115 ArrayRef<CharSourceRange> Ranges,
Craig Topper36835562014-03-15 07:47:46 +0000116 DiagOrStoredDiag D) override {
Ted Kremenek914c7e62012-02-14 02:46:03 +0000117 if (!D.isNull())
118 return;
119
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000120 CXSourceLocation L;
Christof Doumafb4a0452017-06-27 09:50:38 +0000121 if (Loc.hasManager())
122 L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000123 else
124 L = clang_getNullLocation();
David Blaikie759548b2014-08-29 18:43:24 +0000125 CurrentSet->appendDiagnostic(
126 llvm::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
Ted Kremenek914c7e62012-02-14 02:46:03 +0000127 }
Ted Kremenek914c7e62012-02-14 02:46:03 +0000128
Christof Doumafb4a0452017-06-27 09:50:38 +0000129 void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
Craig Topper36835562014-03-15 07:47:46 +0000130 DiagnosticsEngine::Level Level,
Christof Doumafb4a0452017-06-27 09:50:38 +0000131 ArrayRef<CharSourceRange> Ranges) override {}
Craig Topper36835562014-03-15 07:47:46 +0000132
Christof Doumafb4a0452017-06-27 09:50:38 +0000133 void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
134 SmallVectorImpl<CharSourceRange> &Ranges,
135 ArrayRef<FixItHint> Hints) override {}
Craig Topper36835562014-03-15 07:47:46 +0000136
Christof Doumafb4a0452017-06-27 09:50:38 +0000137 void emitNote(FullSourceLoc Loc, StringRef Message) override {
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000138 CXSourceLocation L;
Christof Doumafb4a0452017-06-27 09:50:38 +0000139 if (Loc.hasManager())
140 L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000141 else
142 L = clang_getNullLocation();
David Blaikie759548b2014-08-29 18:43:24 +0000143 CurrentSet->appendDiagnostic(
144 llvm::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
Ted Kremenek914c7e62012-02-14 02:46:03 +0000145 }
146
147 CXDiagnosticSetImpl *CurrentSet;
148 CXDiagnosticSetImpl *MainSet;
149};
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000150}
Ted Kremenek914c7e62012-02-14 02:46:03 +0000151
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +0000152CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
153 bool checkIfChanged) {
Dmitri Gribenkoc22ea1c2013-01-26 18:53:38 +0000154 ASTUnit *AU = cxtu::getASTUnit(TU);
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000155
156 if (TU->Diagnostics && checkIfChanged) {
Argyrios Kyrtzidis7ae5d9c2011-11-16 08:59:00 +0000157 // In normal use, ASTUnit's diagnostics should not change unless we reparse.
158 // Currently they can only change by using the internal testing flag
159 // '-error-on-deserialized-decl' which will error during deserialization of
160 // a declaration. What will happen is:
161 //
162 // -c-index-test gets a CXTranslationUnit
163 // -checks the diagnostics, the diagnostics set is lazily created,
164 // no errors are reported
165 // -later does an operation, like annotation of tokens, that triggers
166 // -error-on-deserialized-decl, that will emit a diagnostic error,
167 // that ASTUnit will catch and add to its stored diagnostics vector.
168 // -c-index-test wants to check whether an error occurred after performing
169 // the operation but can only query the lazily created set.
170 //
171 // We check here if a new diagnostic was appended since the last time the
172 // diagnostic set was created, in which case we reset it.
173
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000174 CXDiagnosticSetImpl *
175 Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
176 if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
177 // Diagnostics in the ASTUnit were updated, reset the associated
178 // diagnostics.
179 delete Set;
Craig Topper69186e72014-06-08 08:38:04 +0000180 TU->Diagnostics = nullptr;
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000181 }
182 }
183
Ted Kremenekd010ba42011-11-10 08:43:12 +0000184 if (!TU->Diagnostics) {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000185 CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
186 TU->Diagnostics = Set;
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000187 IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions;
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000188 CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
Douglas Gregor811db4e2012-10-23 22:26:28 +0000189 &*DOpts, Set);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000190
191 for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
192 ei = AU->stored_diag_end(); it != ei; ++it) {
Ted Kremenek914c7e62012-02-14 02:46:03 +0000193 Renderer.emitStoredDiagnostic(*it);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000194 }
195 }
196 return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
197}
198
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000199//-----------------------------------------------------------------------------
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000200// C Interface Routines
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000201//-----------------------------------------------------------------------------
Douglas Gregor33cdd812010-02-18 18:08:43 +0000202unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000203 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000204 LOG_BAD_TU(Unit);
205 return 0;
206 }
Dmitri Gribenkod36209e2013-01-26 21:32:42 +0000207 if (!cxtu::getASTUnit(Unit))
Ted Kremenekd010ba42011-11-10 08:43:12 +0000208 return 0;
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000209 return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
Douglas Gregor33cdd812010-02-18 18:08:43 +0000210}
211
212CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000213 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000214 LOG_BAD_TU(Unit);
Craig Topper69186e72014-06-08 08:38:04 +0000215 return nullptr;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000216 }
217
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000218 CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
219 if (!D)
Craig Topper69186e72014-06-08 08:38:04 +0000220 return nullptr;
Douglas Gregor33cdd812010-02-18 18:08:43 +0000221
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000222 CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000223 if (Index >= Diags->getNumDiagnostics())
Craig Topper69186e72014-06-08 08:38:04 +0000224 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000225
226 return Diags->getDiagnostic(Index);
Douglas Gregor33cdd812010-02-18 18:08:43 +0000227}
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000228
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000229CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000230 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000231 LOG_BAD_TU(Unit);
Craig Topper69186e72014-06-08 08:38:04 +0000232 return nullptr;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000233 }
Dmitri Gribenkod36209e2013-01-26 21:32:42 +0000234 if (!cxtu::getASTUnit(Unit))
Craig Topper69186e72014-06-08 08:38:04 +0000235 return nullptr;
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000236 return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
237}
Douglas Gregor33cdd812010-02-18 18:08:43 +0000238
239void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000240 // No-op. Kept as a legacy API. CXDiagnostics are now managed
241 // by the enclosing CXDiagnosticSet.
Douglas Gregor33cdd812010-02-18 18:08:43 +0000242}
243
Douglas Gregord770f732010-02-22 23:17:23 +0000244CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
245 if (!Diagnostic)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000246 return cxstring::createEmpty();
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000247
248 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
249
Dylan Noblesmithf1a13f22012-02-13 12:32:26 +0000250 SmallString<256> Str;
Douglas Gregord770f732010-02-22 23:17:23 +0000251 llvm::raw_svector_ostream Out(Str);
252
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000253 if (Options & CXDiagnostic_DisplaySourceLocation) {
254 // Print source location (file:line), along with optional column
255 // and source ranges.
256 CXFile File;
257 unsigned Line, Column;
Douglas Gregor229bebd2010-11-09 06:24:54 +0000258 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
Craig Topper69186e72014-06-08 08:38:04 +0000259 &File, &Line, &Column, nullptr);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000260 if (File) {
261 CXString FName = clang_getFileName(File);
Douglas Gregord770f732010-02-22 23:17:23 +0000262 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000263 clang_disposeString(FName);
264 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregord770f732010-02-22 23:17:23 +0000265 Out << Column << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000266
267 if (Options & CXDiagnostic_DisplaySourceRanges) {
268 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
269 bool PrintedRange = false;
270 for (unsigned I = 0; I != N; ++I) {
271 CXFile StartFile, EndFile;
272 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
273
274 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregor229bebd2010-11-09 06:24:54 +0000275 clang_getSpellingLocation(clang_getRangeStart(Range),
276 &StartFile, &StartLine, &StartColumn,
Craig Topper69186e72014-06-08 08:38:04 +0000277 nullptr);
Douglas Gregor229bebd2010-11-09 06:24:54 +0000278 clang_getSpellingLocation(clang_getRangeEnd(Range),
Craig Topper69186e72014-06-08 08:38:04 +0000279 &EndFile, &EndLine, &EndColumn, nullptr);
280
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000281 if (StartFile != EndFile || StartFile != File)
282 continue;
283
Douglas Gregord770f732010-02-22 23:17:23 +0000284 Out << "{" << StartLine << ":" << StartColumn << "-"
285 << EndLine << ":" << EndColumn << "}";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000286 PrintedRange = true;
287 }
288 if (PrintedRange)
Douglas Gregord770f732010-02-22 23:17:23 +0000289 Out << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000290 }
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000291
292 Out << " ";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000293 }
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000294 }
295
296 /* Print warning/error/etc. */
297 switch (Severity) {
David Blaikieaa347f92011-09-23 20:26:49 +0000298 case CXDiagnostic_Ignored: llvm_unreachable("impossible");
Douglas Gregord770f732010-02-22 23:17:23 +0000299 case CXDiagnostic_Note: Out << "note: "; break;
300 case CXDiagnostic_Warning: Out << "warning: "; break;
301 case CXDiagnostic_Error: Out << "error: "; break;
302 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000303 }
304
305 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
306 if (clang_getCString(Text))
Douglas Gregord770f732010-02-22 23:17:23 +0000307 Out << clang_getCString(Text);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000308 else
Douglas Gregord770f732010-02-22 23:17:23 +0000309 Out << "<no diagnostic text>";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000310 clang_disposeString(Text);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000311
312 if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
313 CXDiagnostic_DisplayCategoryName)) {
314 bool NeedBracket = true;
315 bool NeedComma = false;
316
317 if (Options & CXDiagnostic_DisplayOption) {
Craig Topper69186e72014-06-08 08:38:04 +0000318 CXString OptionName = clang_getDiagnosticOption(Diagnostic, nullptr);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000319 if (const char *OptionText = clang_getCString(OptionName)) {
320 if (OptionText[0]) {
321 Out << " [" << OptionText;
322 NeedBracket = false;
323 NeedComma = true;
324 }
325 }
326 clang_disposeString(OptionName);
327 }
328
329 if (Options & (CXDiagnostic_DisplayCategoryId |
330 CXDiagnostic_DisplayCategoryName)) {
331 if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
332 if (Options & CXDiagnostic_DisplayCategoryId) {
333 if (NeedBracket)
334 Out << " [";
335 if (NeedComma)
336 Out << ", ";
337 Out << CategoryID;
338 NeedBracket = false;
339 NeedComma = true;
340 }
341
342 if (Options & CXDiagnostic_DisplayCategoryName) {
Ted Kremenek26a6d492012-04-12 00:03:31 +0000343 CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000344 if (NeedBracket)
345 Out << " [";
346 if (NeedComma)
347 Out << ", ";
348 Out << clang_getCString(CategoryName);
349 NeedBracket = false;
350 NeedComma = true;
351 clang_disposeString(CategoryName);
352 }
353 }
354 }
Ted Kremenek34b45462012-04-04 00:55:33 +0000355
356 (void) NeedComma; // Silence dead store warning.
Douglas Gregora750e8e2010-11-19 16:18:16 +0000357 if (!NeedBracket)
358 Out << "]";
359 }
360
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000361 return cxstring::createDup(Out.str());
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000362}
363
364unsigned clang_defaultDiagnosticDisplayOptions() {
Douglas Gregora750e8e2010-11-19 16:18:16 +0000365 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
366 CXDiagnostic_DisplayOption;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000367}
368
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000369enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000370 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
371 return D->getSeverity();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000372 return CXDiagnostic_Ignored;
373}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000374
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000375CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000376 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
377 return D->getLocation();
378 return clang_getNullLocation();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000379}
380
381CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000382 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
383 return D->getSpelling();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000384 return cxstring::createEmpty();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000385}
386
Douglas Gregora750e8e2010-11-19 16:18:16 +0000387CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
388 if (Disable)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000389 *Disable = cxstring::createEmpty();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000390
391 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
392 return D->getDiagnosticOption(Disable);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000393
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000394 return cxstring::createEmpty();
Douglas Gregora750e8e2010-11-19 16:18:16 +0000395}
396
397unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000398 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
399 return D->getCategory();
400 return 0;
Douglas Gregora750e8e2010-11-19 16:18:16 +0000401}
402
403CXString clang_getDiagnosticCategoryName(unsigned Category) {
Alp Toker958027b2014-07-14 19:42:55 +0000404 // Kept for backward compatibility.
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000405 return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
Douglas Gregora750e8e2010-11-19 16:18:16 +0000406}
407
Ted Kremenek26a6d492012-04-12 00:03:31 +0000408CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
409 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
410 return D->getCategoryText();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000411 return cxstring::createEmpty();
Ted Kremenek26a6d492012-04-12 00:03:31 +0000412}
413
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000414unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000415 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
416 return D->getNumRanges();
417 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000418}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000419
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000420CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000421 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
422 if (!D || Range >= D->getNumRanges())
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000423 return clang_getNullRange();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000424 return D->getRange(Range);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000425}
426
427unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000428 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
429 return D->getNumFixIts();
430 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000431}
432
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000433CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
Douglas Gregor836ec942010-02-19 18:16:06 +0000434 CXSourceRange *ReplacementRange) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000435 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
436 if (!D || FixIt >= D->getNumFixIts()) {
Douglas Gregor836ec942010-02-19 18:16:06 +0000437 if (ReplacementRange)
438 *ReplacementRange = clang_getNullRange();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000439 return cxstring::createEmpty();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000440 }
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000441 return D->getFixIt(FixIt, ReplacementRange);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000442}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000443
Ted Kremenekd010ba42011-11-10 08:43:12 +0000444void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
Dmitri Gribenko371c2172014-02-12 14:17:58 +0000445 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) {
446 if (D->isExternallyManaged())
447 delete D;
448 }
Ted Kremenekd010ba42011-11-10 08:43:12 +0000449}
450
451CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
452 unsigned Index) {
453 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
454 if (Index < D->getNumDiagnostics())
455 return D->getDiagnostic(Index);
Craig Topper69186e72014-06-08 08:38:04 +0000456 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000457}
458
459CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
460 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
461 CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
Craig Topper69186e72014-06-08 08:38:04 +0000462 return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000463 }
Craig Topper69186e72014-06-08 08:38:04 +0000464 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000465}
466
467unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
468 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
469 return D->getNumDiagnostics();
470 return 0;
471}