blob: 624e9262150d97dd15ba8ad69f032c8cbc2800a8 [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)
45 : CXDiagnosticImpl(CustomNoteDiagnosticKind),
Ted Kremenekb05119c2012-02-14 06:54:46 +000046 Message(Msg), 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
54 CXSourceLocation getLocation() const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000055 return Loc;
56 }
Craig Topper36835562014-03-15 07:47:46 +000057
58 CXString getSpelling() const override {
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +000059 return cxstring::createRef(Message.c_str());
Ted Kremenek914c7e62012-02-14 02:46:03 +000060 }
Craig Topper36835562014-03-15 07:47:46 +000061
62 CXString getDiagnosticOption(CXString *Disable) const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000063 if (Disable)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000064 *Disable = cxstring::createEmpty();
65 return cxstring::createEmpty();
Ted Kremenek914c7e62012-02-14 02:46:03 +000066 }
Ted Kremenek26a6d492012-04-12 00:03:31 +000067
Craig Topper36835562014-03-15 07:47:46 +000068 unsigned getCategory() const override { return 0; }
69 CXString getCategoryText() const override { return cxstring::createEmpty(); }
70
71 unsigned getNumRanges() const override { return 0; }
72 CXSourceRange getRange(unsigned Range) const override {
73 return clang_getNullRange();
74 }
75 unsigned getNumFixIts() const override { return 0; }
76 CXString getFixIt(unsigned FixIt,
77 CXSourceRange *ReplacementRange) const override {
Ted Kremenek914c7e62012-02-14 02:46:03 +000078 if (ReplacementRange)
79 *ReplacementRange = clang_getNullRange();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +000080 return cxstring::createEmpty();
Ted Kremenek914c7e62012-02-14 02:46:03 +000081 }
82};
83
84class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
85public:
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +000086 CXDiagnosticRenderer(const LangOptions &LangOpts,
Douglas Gregor811db4e2012-10-23 22:26:28 +000087 DiagnosticOptions *DiagOpts,
Ted Kremenek914c7e62012-02-14 02:46:03 +000088 CXDiagnosticSetImpl *mainSet)
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +000089 : DiagnosticNoteRenderer(LangOpts, DiagOpts),
Ted Kremenek914c7e62012-02-14 02:46:03 +000090 CurrentSet(mainSet), MainSet(mainSet) {}
Alexander Kornienko34eb2072015-04-11 02:00:23 +000091
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000092 ~CXDiagnosticRenderer() override {}
Ted Kremenek914c7e62012-02-14 02:46:03 +000093
Craig Topper36835562014-03-15 07:47:46 +000094 void beginDiagnostic(DiagOrStoredDiag D,
95 DiagnosticsEngine::Level Level) override {
96
Ted Kremenek914c7e62012-02-14 02:46:03 +000097 const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
98 if (!SD)
99 return;
100
101 if (Level != DiagnosticsEngine::Note)
102 CurrentSet = MainSet;
David Blaikie759548b2014-08-29 18:43:24 +0000103
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000104 auto Owner = std::make_unique<CXStoredDiagnostic>(*SD, LangOpts);
David Blaikie759548b2014-08-29 18:43:24 +0000105 CXStoredDiagnostic &CD = *Owner;
106 CurrentSet->appendDiagnostic(std::move(Owner));
107
Ted Kremenek914c7e62012-02-14 02:46:03 +0000108 if (Level != DiagnosticsEngine::Note)
David Blaikie759548b2014-08-29 18:43:24 +0000109 CurrentSet = &CD.getChildDiagnostics();
Ted Kremenek914c7e62012-02-14 02:46:03 +0000110 }
Craig Topper36835562014-03-15 07:47:46 +0000111
Christof Doumafb4a0452017-06-27 09:50:38 +0000112 void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
113 DiagnosticsEngine::Level Level, StringRef Message,
Craig Topper36835562014-03-15 07:47:46 +0000114 ArrayRef<CharSourceRange> Ranges,
Craig Topper36835562014-03-15 07:47:46 +0000115 DiagOrStoredDiag D) override {
Ted Kremenek914c7e62012-02-14 02:46:03 +0000116 if (!D.isNull())
117 return;
118
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000119 CXSourceLocation L;
Christof Doumafb4a0452017-06-27 09:50:38 +0000120 if (Loc.hasManager())
121 L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000122 else
123 L = clang_getNullLocation();
David Blaikie759548b2014-08-29 18:43:24 +0000124 CurrentSet->appendDiagnostic(
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000125 std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
Ted Kremenek914c7e62012-02-14 02:46:03 +0000126 }
Ted Kremenek914c7e62012-02-14 02:46:03 +0000127
Christof Doumafb4a0452017-06-27 09:50:38 +0000128 void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
Craig Topper36835562014-03-15 07:47:46 +0000129 DiagnosticsEngine::Level Level,
Christof Doumafb4a0452017-06-27 09:50:38 +0000130 ArrayRef<CharSourceRange> Ranges) override {}
Craig Topper36835562014-03-15 07:47:46 +0000131
Christof Doumafb4a0452017-06-27 09:50:38 +0000132 void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
133 SmallVectorImpl<CharSourceRange> &Ranges,
134 ArrayRef<FixItHint> Hints) override {}
Craig Topper36835562014-03-15 07:47:46 +0000135
Christof Doumafb4a0452017-06-27 09:50:38 +0000136 void emitNote(FullSourceLoc Loc, StringRef Message) override {
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000137 CXSourceLocation L;
Christof Doumafb4a0452017-06-27 09:50:38 +0000138 if (Loc.hasManager())
139 L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000140 else
141 L = clang_getNullLocation();
David Blaikie759548b2014-08-29 18:43:24 +0000142 CurrentSet->appendDiagnostic(
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000143 std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
Ted Kremenek914c7e62012-02-14 02:46:03 +0000144 }
145
146 CXDiagnosticSetImpl *CurrentSet;
147 CXDiagnosticSetImpl *MainSet;
148};
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000149}
Ted Kremenek914c7e62012-02-14 02:46:03 +0000150
Argyrios Kyrtzidisf2d99b02011-12-01 02:42:50 +0000151CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
152 bool checkIfChanged) {
Dmitri Gribenkoc22ea1c2013-01-26 18:53:38 +0000153 ASTUnit *AU = cxtu::getASTUnit(TU);
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000154
155 if (TU->Diagnostics && checkIfChanged) {
Argyrios Kyrtzidis7ae5d9c2011-11-16 08:59:00 +0000156 // In normal use, ASTUnit's diagnostics should not change unless we reparse.
157 // Currently they can only change by using the internal testing flag
158 // '-error-on-deserialized-decl' which will error during deserialization of
159 // a declaration. What will happen is:
160 //
161 // -c-index-test gets a CXTranslationUnit
162 // -checks the diagnostics, the diagnostics set is lazily created,
163 // no errors are reported
164 // -later does an operation, like annotation of tokens, that triggers
165 // -error-on-deserialized-decl, that will emit a diagnostic error,
166 // that ASTUnit will catch and add to its stored diagnostics vector.
167 // -c-index-test wants to check whether an error occurred after performing
168 // the operation but can only query the lazily created set.
169 //
170 // We check here if a new diagnostic was appended since the last time the
171 // diagnostic set was created, in which case we reset it.
172
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000173 CXDiagnosticSetImpl *
174 Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
175 if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
176 // Diagnostics in the ASTUnit were updated, reset the associated
177 // diagnostics.
178 delete Set;
Craig Topper69186e72014-06-08 08:38:04 +0000179 TU->Diagnostics = nullptr;
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000180 }
181 }
182
Ted Kremenekd010ba42011-11-10 08:43:12 +0000183 if (!TU->Diagnostics) {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000184 CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
185 TU->Diagnostics = Set;
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000186 IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions;
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000187 CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
Douglas Gregor811db4e2012-10-23 22:26:28 +0000188 &*DOpts, Set);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000189
190 for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
191 ei = AU->stored_diag_end(); it != ei; ++it) {
Ted Kremenek914c7e62012-02-14 02:46:03 +0000192 Renderer.emitStoredDiagnostic(*it);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000193 }
194 }
195 return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
196}
197
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000198//-----------------------------------------------------------------------------
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000199// C Interface Routines
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000200//-----------------------------------------------------------------------------
Douglas Gregor33cdd812010-02-18 18:08:43 +0000201unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000202 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000203 LOG_BAD_TU(Unit);
204 return 0;
205 }
Dmitri Gribenkod36209e2013-01-26 21:32:42 +0000206 if (!cxtu::getASTUnit(Unit))
Ted Kremenekd010ba42011-11-10 08:43:12 +0000207 return 0;
Argyrios Kyrtzidisf03e7342011-11-16 02:34:55 +0000208 return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
Douglas Gregor33cdd812010-02-18 18:08:43 +0000209}
210
211CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000212 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000213 LOG_BAD_TU(Unit);
Craig Topper69186e72014-06-08 08:38:04 +0000214 return nullptr;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000215 }
216
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000217 CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
218 if (!D)
Craig Topper69186e72014-06-08 08:38:04 +0000219 return nullptr;
Douglas Gregor33cdd812010-02-18 18:08:43 +0000220
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000221 CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000222 if (Index >= Diags->getNumDiagnostics())
Craig Topper69186e72014-06-08 08:38:04 +0000223 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000224
225 return Diags->getDiagnostic(Index);
Douglas Gregor33cdd812010-02-18 18:08:43 +0000226}
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000227
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000228CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
Dmitri Gribenko852d6222014-02-11 15:02:48 +0000229 if (cxtu::isNotUsableTU(Unit)) {
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000230 LOG_BAD_TU(Unit);
Craig Topper69186e72014-06-08 08:38:04 +0000231 return nullptr;
Dmitri Gribenko256454f2014-02-11 14:34:14 +0000232 }
Dmitri Gribenkod36209e2013-01-26 21:32:42 +0000233 if (!cxtu::getASTUnit(Unit))
Craig Topper69186e72014-06-08 08:38:04 +0000234 return nullptr;
Ted Kremenekb4a8b052011-12-09 22:28:32 +0000235 return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
236}
Douglas Gregor33cdd812010-02-18 18:08:43 +0000237
238void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000239 // No-op. Kept as a legacy API. CXDiagnostics are now managed
240 // by the enclosing CXDiagnosticSet.
Douglas Gregor33cdd812010-02-18 18:08:43 +0000241}
242
Douglas Gregord770f732010-02-22 23:17:23 +0000243CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
244 if (!Diagnostic)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000245 return cxstring::createEmpty();
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000246
247 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
248
Dylan Noblesmithf1a13f22012-02-13 12:32:26 +0000249 SmallString<256> Str;
Douglas Gregord770f732010-02-22 23:17:23 +0000250 llvm::raw_svector_ostream Out(Str);
251
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000252 if (Options & CXDiagnostic_DisplaySourceLocation) {
253 // Print source location (file:line), along with optional column
254 // and source ranges.
255 CXFile File;
256 unsigned Line, Column;
Douglas Gregor229bebd2010-11-09 06:24:54 +0000257 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
Craig Topper69186e72014-06-08 08:38:04 +0000258 &File, &Line, &Column, nullptr);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000259 if (File) {
260 CXString FName = clang_getFileName(File);
Douglas Gregord770f732010-02-22 23:17:23 +0000261 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000262 clang_disposeString(FName);
263 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregord770f732010-02-22 23:17:23 +0000264 Out << Column << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000265
266 if (Options & CXDiagnostic_DisplaySourceRanges) {
267 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
268 bool PrintedRange = false;
269 for (unsigned I = 0; I != N; ++I) {
270 CXFile StartFile, EndFile;
271 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
272
273 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregor229bebd2010-11-09 06:24:54 +0000274 clang_getSpellingLocation(clang_getRangeStart(Range),
275 &StartFile, &StartLine, &StartColumn,
Craig Topper69186e72014-06-08 08:38:04 +0000276 nullptr);
Douglas Gregor229bebd2010-11-09 06:24:54 +0000277 clang_getSpellingLocation(clang_getRangeEnd(Range),
Craig Topper69186e72014-06-08 08:38:04 +0000278 &EndFile, &EndLine, &EndColumn, nullptr);
279
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000280 if (StartFile != EndFile || StartFile != File)
281 continue;
282
Douglas Gregord770f732010-02-22 23:17:23 +0000283 Out << "{" << StartLine << ":" << StartColumn << "-"
284 << EndLine << ":" << EndColumn << "}";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000285 PrintedRange = true;
286 }
287 if (PrintedRange)
Douglas Gregord770f732010-02-22 23:17:23 +0000288 Out << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000289 }
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000290
291 Out << " ";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000292 }
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000293 }
294
295 /* Print warning/error/etc. */
296 switch (Severity) {
David Blaikieaa347f92011-09-23 20:26:49 +0000297 case CXDiagnostic_Ignored: llvm_unreachable("impossible");
Douglas Gregord770f732010-02-22 23:17:23 +0000298 case CXDiagnostic_Note: Out << "note: "; break;
299 case CXDiagnostic_Warning: Out << "warning: "; break;
300 case CXDiagnostic_Error: Out << "error: "; break;
301 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000302 }
303
304 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
305 if (clang_getCString(Text))
Douglas Gregord770f732010-02-22 23:17:23 +0000306 Out << clang_getCString(Text);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000307 else
Douglas Gregord770f732010-02-22 23:17:23 +0000308 Out << "<no diagnostic text>";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000309 clang_disposeString(Text);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000310
311 if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
312 CXDiagnostic_DisplayCategoryName)) {
313 bool NeedBracket = true;
314 bool NeedComma = false;
315
316 if (Options & CXDiagnostic_DisplayOption) {
Craig Topper69186e72014-06-08 08:38:04 +0000317 CXString OptionName = clang_getDiagnosticOption(Diagnostic, nullptr);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000318 if (const char *OptionText = clang_getCString(OptionName)) {
319 if (OptionText[0]) {
320 Out << " [" << OptionText;
321 NeedBracket = false;
322 NeedComma = true;
323 }
324 }
325 clang_disposeString(OptionName);
326 }
327
328 if (Options & (CXDiagnostic_DisplayCategoryId |
329 CXDiagnostic_DisplayCategoryName)) {
330 if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
331 if (Options & CXDiagnostic_DisplayCategoryId) {
332 if (NeedBracket)
333 Out << " [";
334 if (NeedComma)
335 Out << ", ";
336 Out << CategoryID;
337 NeedBracket = false;
338 NeedComma = true;
339 }
340
341 if (Options & CXDiagnostic_DisplayCategoryName) {
Ted Kremenek26a6d492012-04-12 00:03:31 +0000342 CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000343 if (NeedBracket)
344 Out << " [";
345 if (NeedComma)
346 Out << ", ";
347 Out << clang_getCString(CategoryName);
348 NeedBracket = false;
349 NeedComma = true;
350 clang_disposeString(CategoryName);
351 }
352 }
353 }
Ted Kremenek34b45462012-04-04 00:55:33 +0000354
355 (void) NeedComma; // Silence dead store warning.
Douglas Gregora750e8e2010-11-19 16:18:16 +0000356 if (!NeedBracket)
357 Out << "]";
358 }
359
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000360 return cxstring::createDup(Out.str());
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000361}
362
363unsigned clang_defaultDiagnosticDisplayOptions() {
Douglas Gregora750e8e2010-11-19 16:18:16 +0000364 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
365 CXDiagnostic_DisplayOption;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000366}
367
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000368enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000369 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
370 return D->getSeverity();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000371 return CXDiagnostic_Ignored;
372}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000373
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000374CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000375 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
376 return D->getLocation();
377 return clang_getNullLocation();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000378}
379
380CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000381 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
382 return D->getSpelling();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000383 return cxstring::createEmpty();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000384}
385
Douglas Gregora750e8e2010-11-19 16:18:16 +0000386CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
387 if (Disable)
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000388 *Disable = cxstring::createEmpty();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000389
390 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
391 return D->getDiagnosticOption(Disable);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000392
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000393 return cxstring::createEmpty();
Douglas Gregora750e8e2010-11-19 16:18:16 +0000394}
395
396unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000397 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
398 return D->getCategory();
399 return 0;
Douglas Gregora750e8e2010-11-19 16:18:16 +0000400}
401
402CXString clang_getDiagnosticCategoryName(unsigned Category) {
Alp Toker958027b2014-07-14 19:42:55 +0000403 // Kept for backward compatibility.
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000404 return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
Douglas Gregora750e8e2010-11-19 16:18:16 +0000405}
406
Ted Kremenek26a6d492012-04-12 00:03:31 +0000407CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
408 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
409 return D->getCategoryText();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000410 return cxstring::createEmpty();
Ted Kremenek26a6d492012-04-12 00:03:31 +0000411}
412
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000413unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000414 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
415 return D->getNumRanges();
416 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000417}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000418
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000419CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000420 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
421 if (!D || Range >= D->getNumRanges())
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000422 return clang_getNullRange();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000423 return D->getRange(Range);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000424}
425
426unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000427 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
428 return D->getNumFixIts();
429 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000430}
431
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000432CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
Douglas Gregor836ec942010-02-19 18:16:06 +0000433 CXSourceRange *ReplacementRange) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000434 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
435 if (!D || FixIt >= D->getNumFixIts()) {
Douglas Gregor836ec942010-02-19 18:16:06 +0000436 if (ReplacementRange)
437 *ReplacementRange = clang_getNullRange();
Dmitri Gribenko36a6dd02013-02-01 14:21:22 +0000438 return cxstring::createEmpty();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000439 }
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000440 return D->getFixIt(FixIt, ReplacementRange);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000441}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000442
Ted Kremenekd010ba42011-11-10 08:43:12 +0000443void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
Dmitri Gribenko371c2172014-02-12 14:17:58 +0000444 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) {
445 if (D->isExternallyManaged())
446 delete D;
447 }
Ted Kremenekd010ba42011-11-10 08:43:12 +0000448}
449
450CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
451 unsigned Index) {
452 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
453 if (Index < D->getNumDiagnostics())
454 return D->getDiagnostic(Index);
Craig Topper69186e72014-06-08 08:38:04 +0000455 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000456}
457
458CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
459 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
460 CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
Craig Topper69186e72014-06-08 08:38:04 +0000461 return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000462 }
Craig Topper69186e72014-06-08 08:38:04 +0000463 return nullptr;
Ted Kremenekd010ba42011-11-10 08:43:12 +0000464}
465
466unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
467 if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
468 return D->getNumDiagnostics();
469 return 0;
470}