blob: 34792d5bdfaaff0de5aad64f220717b70d7e0ede [file] [log] [blame]
Fangrui Song524b3c12019-03-01 06:49:51 +00001//===- CIndexDiagnostic.cpp - Diagnostics C Interface ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implements the diagnostic functions of the Clang C interface.
10//
11//===----------------------------------------------------------------------===//
12
Douglas Gregor4f9c3762010-01-28 00:27:43 +000013#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"
Douglas Gregord770f732010-02-22 23:17:23 +000022#include "llvm/ADT/SmallString.h"
Douglas Gregord770f732010-02-22 23:17:23 +000023#include "llvm/Support/raw_ostream.h"
Douglas Gregorac0605e2010-01-28 06:00:51 +000024
Douglas Gregor4f9c3762010-01-28 00:27:43 +000025using namespace clang;
26using namespace clang::cxloc;
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +000027using namespace clang::cxdiag;
Douglas Gregor33cdd812010-02-18 18:08:43 +000028using namespace llvm;
Douglas Gregor4f9c3762010-01-28 00:27:43 +000029
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000030CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {}
Ted Kremenekd010ba42011-11-10 08:43:12 +000031
David Blaikie759548b2014-08-29 18:43:24 +000032void
33CXDiagnosticSetImpl::appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D) {
34 Diagnostics.push_back(std::move(D));
Ted Kremenekd010ba42011-11-10 08:43:12 +000035}
36
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000037CXDiagnosticImpl::~CXDiagnosticImpl() {}
Ted Kremenekd010ba42011-11-10 08:43:12 +000038
Ted Kremenek914c7e62012-02-14 02:46:03 +000039namespace {
40class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
Ted Kremenekb05119c2012-02-14 06:54:46 +000041 std::string Message;
Ted Kremenek914c7e62012-02-14 02:46:03 +000042 CXSourceLocation Loc;
43public:
44 CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
Benjamin Krameradcd0262020-01-28 20:23:46 +010045 : CXDiagnosticImpl(CustomNoteDiagnosticKind), Message(std::string(Msg)),
46 Loc(L) {}
Ted Kremenek914c7e62012-02-14 02:46:03 +000047
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000048 ~CXDiagnosticCustomNoteImpl() override {}
Craig Topper36835562014-03-15 07:47:46 +000049
50 CXDiagnosticSeverity getSeverity() const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000051 return CXDiagnostic_Note;
52 }
Craig Topper36835562014-03-15 07:47:46 +000053
Benjamin Krameradcd0262020-01-28 20:23:46 +010054 CXSourceLocation getLocation() const override { return Loc; }
Craig Topper36835562014-03-15 07:47:46 +000055
56 CXString getSpelling() const override {
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000057 return cxstring::createRef(Message.c_str());
Ted Kremenek914c7e62012-02-14 02:46:03 +000058 }
Craig Topper36835562014-03-15 07:47:46 +000059
60 CXString getDiagnosticOption(CXString *Disable) const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000061 if (Disable)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000062 *Disable = cxstring::createEmpty();
63 return cxstring::createEmpty();
Ted Kremenek914c7e62012-02-14 02:46:03 +000064 }
Ted Kremenek26a6d492012-04-12 00:03:31 +000065
Craig Topper36835562014-03-15 07:47:46 +000066 unsigned getCategory() const override { return 0; }
67 CXString getCategoryText() const override { return cxstring::createEmpty(); }
68
69 unsigned getNumRanges() const override { return 0; }
70 CXSourceRange getRange(unsigned Range) const override {
71 return clang_getNullRange();
72 }
73 unsigned getNumFixIts() const override { return 0; }
74 CXString getFixIt(unsigned FixIt,
75 CXSourceRange *ReplacementRange) const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000076 if (ReplacementRange)
77 *ReplacementRange = clang_getNullRange();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000078 return cxstring::createEmpty();
Ted Kremenek914c7e62012-02-14 02:46:03 +000079 }
80};
81
82class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
83public:
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +000084 CXDiagnosticRenderer(const LangOptions &LangOpts,
Douglas Gregor811db4e2012-10-23 22:26:28 +000085 DiagnosticOptions *DiagOpts,
Ted Kremenek914c7e62012-02-14 02:46:03 +000086 CXDiagnosticSetImpl *mainSet)
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +000087 : DiagnosticNoteRenderer(LangOpts, DiagOpts),
Ted Kremenek914c7e62012-02-14 02:46:03 +000088 CurrentSet(mainSet), MainSet(mainSet) {}
Alexander Kornienko34eb2072015-04-11 02:00:23 +000089
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000090 ~CXDiagnosticRenderer() override {}
Ted Kremenek914c7e62012-02-14 02:46:03 +000091
Craig Topper36835562014-03-15 07:47:46 +000092 void beginDiagnostic(DiagOrStoredDiag D,
93 DiagnosticsEngine::Level Level) override {
94
Ted Kremenek914c7e62012-02-14 02:46:03 +000095 const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
96 if (!SD)
97 return;
98
99 if (Level != DiagnosticsEngine::Note)
100 CurrentSet = MainSet;
David Blaikie759548b2014-08-29 18:43:24 +0000101
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000102 auto Owner = std::make_unique<CXStoredDiagnostic>(*SD, LangOpts);
David Blaikie759548b2014-08-29 18:43:24 +0000103 CXStoredDiagnostic &CD = *Owner;
104 CurrentSet->appendDiagnostic(std::move(Owner));
105
Ted Kremenek914c7e62012-02-14 02:46:03 +0000106 if (Level != DiagnosticsEngine::Note)
David Blaikie759548b2014-08-29 18:43:24 +0000107 CurrentSet = &CD.getChildDiagnostics();
Ted Kremenek914c7e62012-02-14 02:46:03 +0000108 }
Craig Topper36835562014-03-15 07:47:46 +0000109
Christof Doumafb4a0452017-06-27 09:50:38 +0000110 void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
111 DiagnosticsEngine::Level Level, StringRef Message,
Craig Topper36835562014-03-15 07:47:46 +0000112 ArrayRef<CharSourceRange> Ranges,
Craig Topper36835562014-03-15 07:47:46 +0000113 DiagOrStoredDiag D) override {
Ted Kremenek914c7e62012-02-14 02:46:03 +0000114 if (!D.isNull())
115 return;
116
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000117 CXSourceLocation L;
Christof Doumafb4a0452017-06-27 09:50:38 +0000118 if (Loc.hasManager())
119 L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000120 else
121 L = clang_getNullLocation();
David Blaikie759548b2014-08-29 18:43:24 +0000122 CurrentSet->appendDiagnostic(
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000123 std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
Ted Kremenek914c7e62012-02-14 02:46:03 +0000124 }
Ted Kremenek914c7e62012-02-14 02:46:03 +0000125
Christof Doumafb4a0452017-06-27 09:50:38 +0000126 void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
Craig Topper36835562014-03-15 07:47:46 +0000127 DiagnosticsEngine::Level Level,
Christof Doumafb4a0452017-06-27 09:50:38 +0000128 ArrayRef<CharSourceRange> Ranges) override {}
Craig Topper36835562014-03-15 07:47:46 +0000129
Christof Doumafb4a0452017-06-27 09:50:38 +0000130 void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
131 SmallVectorImpl<CharSourceRange> &Ranges,
132 ArrayRef<FixItHint> Hints) override {}
Craig Topper36835562014-03-15 07:47:46 +0000133
Christof Doumafb4a0452017-06-27 09:50:38 +0000134 void emitNote(FullSourceLoc Loc, StringRef Message) override {
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000135 CXSourceLocation L;
Christof Doumafb4a0452017-06-27 09:50:38 +0000136 if (Loc.hasManager())
137 L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000138 else
139 L = clang_getNullLocation();
David Blaikie759548b2014-08-29 18:43:24 +0000140 CurrentSet->appendDiagnostic(
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000141 std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
Ted Kremenek914c7e62012-02-14 02:46:03 +0000142 }
143
144 CXDiagnosticSetImpl *CurrentSet;
145 CXDiagnosticSetImpl *MainSet;
146};
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000147}
Ted Kremenek914c7e62012-02-14 02:46:03 +0000148
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +0000149CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
150 bool checkIfChanged) {
Dmitri Gribenkoc22ea1c2013-01-26 18:53:38 +0000151 ASTUnit *AU = cxtu::getASTUnit(TU);
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000152
153 if (TU->Diagnostics && checkIfChanged) {
Argyrios Kyrtzidis7ae5d9c2011-11-16 08:59:00 +0000154 // In normal use, ASTUnit's diagnostics should not change unless we reparse.
155 // Currently they can only change by using the internal testing flag
156 // '-error-on-deserialized-decl' which will error during deserialization of
157 // a declaration. What will happen is:
158 //
159 // -c-index-test gets a CXTranslationUnit
160 // -checks the diagnostics, the diagnostics set is lazily created,
161 // no errors are reported
162 // -later does an operation, like annotation of tokens, that triggers
163 // -error-on-deserialized-decl, that will emit a diagnostic error,
164 // that ASTUnit will catch and add to its stored diagnostics vector.
165 // -c-index-test wants to check whether an error occurred after performing
166 // the operation but can only query the lazily created set.
167 //
168 // We check here if a new diagnostic was appended since the last time the
169 // diagnostic set was created, in which case we reset it.
170
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000171 CXDiagnosticSetImpl *
172 Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
173 if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
174 // Diagnostics in the ASTUnit were updated, reset the associated
175 // diagnostics.
176 delete Set;
Craig Topper69186e72014-06-08 08:38:04 +0000177 TU->Diagnostics = nullptr;
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000178 }
179 }
180
Ted Kremenekd010ba42011-11-10 08:43:12 +0000181 if (!TU->Diagnostics) {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000182 CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
183 TU->Diagnostics = Set;
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000184 IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions;
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000185 CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
Douglas Gregor811db4e2012-10-23 22:26:28 +0000186 &*DOpts, Set);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000187
188 for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
189 ei = AU->stored_diag_end(); it != ei; ++it) {
Ted Kremenek914c7e62012-02-14 02:46:03 +0000190 Renderer.emitStoredDiagnostic(*it);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000191 }
192 }
193 return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
194}
195
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000196//-----------------------------------------------------------------------------
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000197// C Interface Routines
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000198//-----------------------------------------------------------------------------
Douglas Gregor33cdd812010-02-18 18:08:43 +0000199unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000200 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000201 LOG_BAD_TU(Unit);
202 return 0;
203 }
Dmitri Gribenkod36209e2013-01-26 21:32:42 +0000204 if (!cxtu::getASTUnit(Unit))
Ted Kremenekd010ba42011-11-10 08:43:12 +0000205 return 0;
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000206 return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
Douglas Gregor33cdd812010-02-18 18:08:43 +0000207}
208
209CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000210 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000211 LOG_BAD_TU(Unit);
Craig Topper69186e72014-06-08 08:38:04 +0000212 return nullptr;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000213 }
214
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000215 CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
216 if (!D)
Craig Topper69186e72014-06-08 08:38:04 +0000217 return nullptr;
Douglas Gregor33cdd812010-02-18 18:08:43 +0000218
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000219 CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000220 if (Index >= Diags->getNumDiagnostics())
Craig Topper69186e72014-06-08 08:38:04 +0000221 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000222
223 return Diags->getDiagnostic(Index);
Douglas Gregor33cdd812010-02-18 18:08:43 +0000224}
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000225
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000226CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000227 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000228 LOG_BAD_TU(Unit);
Craig Topper69186e72014-06-08 08:38:04 +0000229 return nullptr;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000230 }
Dmitri Gribenkod36209e2013-01-26 21:32:42 +0000231 if (!cxtu::getASTUnit(Unit))
Craig Topper69186e72014-06-08 08:38:04 +0000232 return nullptr;
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000233 return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
234}
Douglas Gregor33cdd812010-02-18 18:08:43 +0000235
236void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000237 // No-op. Kept as a legacy API. CXDiagnostics are now managed
238 // by the enclosing CXDiagnosticSet.
Douglas Gregor33cdd812010-02-18 18:08:43 +0000239}
240
Douglas Gregord770f732010-02-22 23:17:23 +0000241CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
242 if (!Diagnostic)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000243 return cxstring::createEmpty();
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000244
245 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
246
Dylan Noblesmithf1a13f22012-02-13 12:32:26 +0000247 SmallString<256> Str;
Douglas Gregord770f732010-02-22 23:17:23 +0000248 llvm::raw_svector_ostream Out(Str);
249
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000250 if (Options & CXDiagnostic_DisplaySourceLocation) {
251 // Print source location (file:line), along with optional column
252 // and source ranges.
253 CXFile File;
254 unsigned Line, Column;
Douglas Gregor229bebd2010-11-09 06:24:54 +0000255 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
Craig Topper69186e72014-06-08 08:38:04 +0000256 &File, &Line, &Column, nullptr);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000257 if (File) {
258 CXString FName = clang_getFileName(File);
Douglas Gregord770f732010-02-22 23:17:23 +0000259 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000260 clang_disposeString(FName);
261 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregord770f732010-02-22 23:17:23 +0000262 Out << Column << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000263
264 if (Options & CXDiagnostic_DisplaySourceRanges) {
265 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
266 bool PrintedRange = false;
267 for (unsigned I = 0; I != N; ++I) {
268 CXFile StartFile, EndFile;
269 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
270
271 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregor229bebd2010-11-09 06:24:54 +0000272 clang_getSpellingLocation(clang_getRangeStart(Range),
273 &StartFile, &StartLine, &StartColumn,
Craig Topper69186e72014-06-08 08:38:04 +0000274 nullptr);
Douglas Gregor229bebd2010-11-09 06:24:54 +0000275 clang_getSpellingLocation(clang_getRangeEnd(Range),
Craig Topper69186e72014-06-08 08:38:04 +0000276 &EndFile, &EndLine, &EndColumn, nullptr);
277
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000278 if (StartFile != EndFile || StartFile != File)
279 continue;
280
Douglas Gregord770f732010-02-22 23:17:23 +0000281 Out << "{" << StartLine << ":" << StartColumn << "-"
282 << EndLine << ":" << EndColumn << "}";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000283 PrintedRange = true;
284 }
285 if (PrintedRange)
Douglas Gregord770f732010-02-22 23:17:23 +0000286 Out << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000287 }
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000288
289 Out << " ";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000290 }
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000291 }
292
293 /* Print warning/error/etc. */
294 switch (Severity) {
David Blaikieaa347f92011-09-23 20:26:49 +0000295 case CXDiagnostic_Ignored: llvm_unreachable("impossible");
Douglas Gregord770f732010-02-22 23:17:23 +0000296 case CXDiagnostic_Note: Out << "note: "; break;
297 case CXDiagnostic_Warning: Out << "warning: "; break;
298 case CXDiagnostic_Error: Out << "error: "; break;
299 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000300 }
301
302 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
303 if (clang_getCString(Text))
Douglas Gregord770f732010-02-22 23:17:23 +0000304 Out << clang_getCString(Text);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000305 else
Douglas Gregord770f732010-02-22 23:17:23 +0000306 Out << "<no diagnostic text>";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000307 clang_disposeString(Text);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000308
309 if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
310 CXDiagnostic_DisplayCategoryName)) {
311 bool NeedBracket = true;
312 bool NeedComma = false;
313
314 if (Options & CXDiagnostic_DisplayOption) {
Craig Topper69186e72014-06-08 08:38:04 +0000315 CXString OptionName = clang_getDiagnosticOption(Diagnostic, nullptr);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000316 if (const char *OptionText = clang_getCString(OptionName)) {
317 if (OptionText[0]) {
318 Out << " [" << OptionText;
319 NeedBracket = false;
320 NeedComma = true;
321 }
322 }
323 clang_disposeString(OptionName);
324 }
325
326 if (Options & (CXDiagnostic_DisplayCategoryId |
327 CXDiagnostic_DisplayCategoryName)) {
328 if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
329 if (Options & CXDiagnostic_DisplayCategoryId) {
330 if (NeedBracket)
331 Out << " [";
332 if (NeedComma)
333 Out << ", ";
334 Out << CategoryID;
335 NeedBracket = false;
336 NeedComma = true;
337 }
338
339 if (Options & CXDiagnostic_DisplayCategoryName) {
Ted Kremenek26a6d492012-04-12 00:03:31 +0000340 CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000341 if (NeedBracket)
342 Out << " [";
343 if (NeedComma)
344 Out << ", ";
345 Out << clang_getCString(CategoryName);
346 NeedBracket = false;
347 NeedComma = true;
348 clang_disposeString(CategoryName);
349 }
350 }
351 }
Ted Kremenek34b45462012-04-04 00:55:33 +0000352
353 (void) NeedComma; // Silence dead store warning.
Douglas Gregora750e8e2010-11-19 16:18:16 +0000354 if (!NeedBracket)
355 Out << "]";
356 }
357
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000358 return cxstring::createDup(Out.str());
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000359}
360
361unsigned clang_defaultDiagnosticDisplayOptions() {
Douglas Gregora750e8e2010-11-19 16:18:16 +0000362 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
363 CXDiagnostic_DisplayOption;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000364}
365
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000366enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000367 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
368 return D->getSeverity();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000369 return CXDiagnostic_Ignored;
370}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000371
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000372CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000373 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
374 return D->getLocation();
375 return clang_getNullLocation();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000376}
377
378CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000379 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
380 return D->getSpelling();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000381 return cxstring::createEmpty();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000382}
383
Douglas Gregora750e8e2010-11-19 16:18:16 +0000384CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
385 if (Disable)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000386 *Disable = cxstring::createEmpty();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000387
388 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
389 return D->getDiagnosticOption(Disable);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000390
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000391 return cxstring::createEmpty();
Douglas Gregora750e8e2010-11-19 16:18:16 +0000392}
393
394unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000395 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
396 return D->getCategory();
397 return 0;
Douglas Gregora750e8e2010-11-19 16:18:16 +0000398}
399
400CXString clang_getDiagnosticCategoryName(unsigned Category) {
Alp Toker958027b2014-07-14 19:42:55 +0000401 // Kept for backward compatibility.
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000402 return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
Douglas Gregora750e8e2010-11-19 16:18:16 +0000403}
404
Ted Kremenek26a6d492012-04-12 00:03:31 +0000405CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
406 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
407 return D->getCategoryText();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000408 return cxstring::createEmpty();
Ted Kremenek26a6d492012-04-12 00:03:31 +0000409}
410
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000411unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000412 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
413 return D->getNumRanges();
414 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000415}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000416
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000417CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000418 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
419 if (!D || Range >= D->getNumRanges())
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000420 return clang_getNullRange();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000421 return D->getRange(Range);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000422}
423
424unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000425 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
426 return D->getNumFixIts();
427 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000428}
429
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000430CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
Douglas Gregor836ec942010-02-19 18:16:06 +0000431 CXSourceRange *ReplacementRange) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000432 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
433 if (!D || FixIt >= D->getNumFixIts()) {
Douglas Gregor836ec942010-02-19 18:16:06 +0000434 if (ReplacementRange)
435 *ReplacementRange = clang_getNullRange();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000436 return cxstring::createEmpty();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000437 }
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000438 return D->getFixIt(FixIt, ReplacementRange);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000439}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000440
Ted Kremenekd010ba42011-11-10 08:43:12 +0000441void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
Dmitri Gribenko371c2172014-02-12 14:17:58 +0000442 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) {
443 if (D->isExternallyManaged())
444 delete D;
445 }
Ted Kremenekd010ba42011-11-10 08:43:12 +0000446}
447
448CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
449 unsigned Index) {
450 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
451 if (Index < D->getNumDiagnostics())
452 return D->getDiagnostic(Index);
Craig Topper69186e72014-06-08 08:38:04 +0000453 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000454}
455
456CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
457 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
458 CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
Craig Topper69186e72014-06-08 08:38:04 +0000459 return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000460 }
Craig Topper69186e72014-06-08 08:38:04 +0000461 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000462}
463
464unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
465 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
466 return D->getNumDiagnostics();
467 return 0;
468}