1e5dd7070Spatrick //===- CIndexDiagnostic.cpp - Diagnostics C Interface ---------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // Implements the diagnostic functions of the Clang C interface.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "CIndexDiagnostic.h"
14e5dd7070Spatrick #include "CIndexer.h"
15e5dd7070Spatrick #include "CXTranslationUnit.h"
16e5dd7070Spatrick #include "CXSourceLocation.h"
17e5dd7070Spatrick #include "CXString.h"
18e5dd7070Spatrick
19e5dd7070Spatrick #include "clang/Basic/DiagnosticOptions.h"
20e5dd7070Spatrick #include "clang/Frontend/ASTUnit.h"
21e5dd7070Spatrick #include "clang/Frontend/DiagnosticRenderer.h"
22e5dd7070Spatrick #include "llvm/ADT/SmallString.h"
23e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
24e5dd7070Spatrick
25e5dd7070Spatrick using namespace clang;
26e5dd7070Spatrick using namespace clang::cxloc;
27e5dd7070Spatrick using namespace clang::cxdiag;
28e5dd7070Spatrick using namespace llvm;
29e5dd7070Spatrick
~CXDiagnosticSetImpl()30e5dd7070Spatrick CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {}
31e5dd7070Spatrick
32e5dd7070Spatrick void
appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D)33e5dd7070Spatrick CXDiagnosticSetImpl::appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D) {
34e5dd7070Spatrick Diagnostics.push_back(std::move(D));
35e5dd7070Spatrick }
36e5dd7070Spatrick
~CXDiagnosticImpl()37e5dd7070Spatrick CXDiagnosticImpl::~CXDiagnosticImpl() {}
38e5dd7070Spatrick
39e5dd7070Spatrick namespace {
40e5dd7070Spatrick class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
41e5dd7070Spatrick std::string Message;
42e5dd7070Spatrick CXSourceLocation Loc;
43e5dd7070Spatrick public:
CXDiagnosticCustomNoteImpl(StringRef Msg,CXSourceLocation L)44e5dd7070Spatrick CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
45*ec727ea7Spatrick : CXDiagnosticImpl(CustomNoteDiagnosticKind), Message(std::string(Msg)),
46*ec727ea7Spatrick Loc(L) {}
47e5dd7070Spatrick
~CXDiagnosticCustomNoteImpl()48e5dd7070Spatrick ~CXDiagnosticCustomNoteImpl() override {}
49e5dd7070Spatrick
getSeverity() const50e5dd7070Spatrick CXDiagnosticSeverity getSeverity() const override {
51e5dd7070Spatrick return CXDiagnostic_Note;
52e5dd7070Spatrick }
53e5dd7070Spatrick
getLocation() const54*ec727ea7Spatrick CXSourceLocation getLocation() const override { return Loc; }
55e5dd7070Spatrick
getSpelling() const56e5dd7070Spatrick CXString getSpelling() const override {
57e5dd7070Spatrick return cxstring::createRef(Message.c_str());
58e5dd7070Spatrick }
59e5dd7070Spatrick
getDiagnosticOption(CXString * Disable) const60e5dd7070Spatrick CXString getDiagnosticOption(CXString *Disable) const override {
61e5dd7070Spatrick if (Disable)
62e5dd7070Spatrick *Disable = cxstring::createEmpty();
63e5dd7070Spatrick return cxstring::createEmpty();
64e5dd7070Spatrick }
65e5dd7070Spatrick
getCategory() const66e5dd7070Spatrick unsigned getCategory() const override { return 0; }
getCategoryText() const67e5dd7070Spatrick CXString getCategoryText() const override { return cxstring::createEmpty(); }
68e5dd7070Spatrick
getNumRanges() const69e5dd7070Spatrick unsigned getNumRanges() const override { return 0; }
getRange(unsigned Range) const70e5dd7070Spatrick CXSourceRange getRange(unsigned Range) const override {
71e5dd7070Spatrick return clang_getNullRange();
72e5dd7070Spatrick }
getNumFixIts() const73e5dd7070Spatrick unsigned getNumFixIts() const override { return 0; }
getFixIt(unsigned FixIt,CXSourceRange * ReplacementRange) const74e5dd7070Spatrick CXString getFixIt(unsigned FixIt,
75e5dd7070Spatrick CXSourceRange *ReplacementRange) const override {
76e5dd7070Spatrick if (ReplacementRange)
77e5dd7070Spatrick *ReplacementRange = clang_getNullRange();
78e5dd7070Spatrick return cxstring::createEmpty();
79e5dd7070Spatrick }
80e5dd7070Spatrick };
81e5dd7070Spatrick
82e5dd7070Spatrick class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
83e5dd7070Spatrick public:
CXDiagnosticRenderer(const LangOptions & LangOpts,DiagnosticOptions * DiagOpts,CXDiagnosticSetImpl * mainSet)84e5dd7070Spatrick CXDiagnosticRenderer(const LangOptions &LangOpts,
85e5dd7070Spatrick DiagnosticOptions *DiagOpts,
86e5dd7070Spatrick CXDiagnosticSetImpl *mainSet)
87e5dd7070Spatrick : DiagnosticNoteRenderer(LangOpts, DiagOpts),
88e5dd7070Spatrick CurrentSet(mainSet), MainSet(mainSet) {}
89e5dd7070Spatrick
~CXDiagnosticRenderer()90e5dd7070Spatrick ~CXDiagnosticRenderer() override {}
91e5dd7070Spatrick
beginDiagnostic(DiagOrStoredDiag D,DiagnosticsEngine::Level Level)92e5dd7070Spatrick void beginDiagnostic(DiagOrStoredDiag D,
93e5dd7070Spatrick DiagnosticsEngine::Level Level) override {
94e5dd7070Spatrick
95e5dd7070Spatrick const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
96e5dd7070Spatrick if (!SD)
97e5dd7070Spatrick return;
98e5dd7070Spatrick
99e5dd7070Spatrick if (Level != DiagnosticsEngine::Note)
100e5dd7070Spatrick CurrentSet = MainSet;
101e5dd7070Spatrick
102e5dd7070Spatrick auto Owner = std::make_unique<CXStoredDiagnostic>(*SD, LangOpts);
103e5dd7070Spatrick CXStoredDiagnostic &CD = *Owner;
104e5dd7070Spatrick CurrentSet->appendDiagnostic(std::move(Owner));
105e5dd7070Spatrick
106e5dd7070Spatrick if (Level != DiagnosticsEngine::Note)
107e5dd7070Spatrick CurrentSet = &CD.getChildDiagnostics();
108e5dd7070Spatrick }
109e5dd7070Spatrick
emitDiagnosticMessage(FullSourceLoc Loc,PresumedLoc PLoc,DiagnosticsEngine::Level Level,StringRef Message,ArrayRef<CharSourceRange> Ranges,DiagOrStoredDiag D)110e5dd7070Spatrick void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
111e5dd7070Spatrick DiagnosticsEngine::Level Level, StringRef Message,
112e5dd7070Spatrick ArrayRef<CharSourceRange> Ranges,
113e5dd7070Spatrick DiagOrStoredDiag D) override {
114e5dd7070Spatrick if (!D.isNull())
115e5dd7070Spatrick return;
116e5dd7070Spatrick
117e5dd7070Spatrick CXSourceLocation L;
118e5dd7070Spatrick if (Loc.hasManager())
119e5dd7070Spatrick L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
120e5dd7070Spatrick else
121e5dd7070Spatrick L = clang_getNullLocation();
122e5dd7070Spatrick CurrentSet->appendDiagnostic(
123e5dd7070Spatrick std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
124e5dd7070Spatrick }
125e5dd7070Spatrick
emitDiagnosticLoc(FullSourceLoc Loc,PresumedLoc PLoc,DiagnosticsEngine::Level Level,ArrayRef<CharSourceRange> Ranges)126e5dd7070Spatrick void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
127e5dd7070Spatrick DiagnosticsEngine::Level Level,
128e5dd7070Spatrick ArrayRef<CharSourceRange> Ranges) override {}
129e5dd7070Spatrick
emitCodeContext(FullSourceLoc Loc,DiagnosticsEngine::Level Level,SmallVectorImpl<CharSourceRange> & Ranges,ArrayRef<FixItHint> Hints)130e5dd7070Spatrick void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
131e5dd7070Spatrick SmallVectorImpl<CharSourceRange> &Ranges,
132e5dd7070Spatrick ArrayRef<FixItHint> Hints) override {}
133e5dd7070Spatrick
emitNote(FullSourceLoc Loc,StringRef Message)134e5dd7070Spatrick void emitNote(FullSourceLoc Loc, StringRef Message) override {
135e5dd7070Spatrick CXSourceLocation L;
136e5dd7070Spatrick if (Loc.hasManager())
137e5dd7070Spatrick L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
138e5dd7070Spatrick else
139e5dd7070Spatrick L = clang_getNullLocation();
140e5dd7070Spatrick CurrentSet->appendDiagnostic(
141e5dd7070Spatrick std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
142e5dd7070Spatrick }
143e5dd7070Spatrick
144e5dd7070Spatrick CXDiagnosticSetImpl *CurrentSet;
145e5dd7070Spatrick CXDiagnosticSetImpl *MainSet;
146e5dd7070Spatrick };
147e5dd7070Spatrick }
148e5dd7070Spatrick
lazyCreateDiags(CXTranslationUnit TU,bool checkIfChanged)149e5dd7070Spatrick CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
150e5dd7070Spatrick bool checkIfChanged) {
151e5dd7070Spatrick ASTUnit *AU = cxtu::getASTUnit(TU);
152e5dd7070Spatrick
153e5dd7070Spatrick if (TU->Diagnostics && checkIfChanged) {
154e5dd7070Spatrick // In normal use, ASTUnit's diagnostics should not change unless we reparse.
155e5dd7070Spatrick // Currently they can only change by using the internal testing flag
156e5dd7070Spatrick // '-error-on-deserialized-decl' which will error during deserialization of
157e5dd7070Spatrick // a declaration. What will happen is:
158e5dd7070Spatrick //
159e5dd7070Spatrick // -c-index-test gets a CXTranslationUnit
160e5dd7070Spatrick // -checks the diagnostics, the diagnostics set is lazily created,
161e5dd7070Spatrick // no errors are reported
162e5dd7070Spatrick // -later does an operation, like annotation of tokens, that triggers
163e5dd7070Spatrick // -error-on-deserialized-decl, that will emit a diagnostic error,
164e5dd7070Spatrick // that ASTUnit will catch and add to its stored diagnostics vector.
165e5dd7070Spatrick // -c-index-test wants to check whether an error occurred after performing
166e5dd7070Spatrick // the operation but can only query the lazily created set.
167e5dd7070Spatrick //
168e5dd7070Spatrick // We check here if a new diagnostic was appended since the last time the
169e5dd7070Spatrick // diagnostic set was created, in which case we reset it.
170e5dd7070Spatrick
171e5dd7070Spatrick CXDiagnosticSetImpl *
172e5dd7070Spatrick Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
173e5dd7070Spatrick if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
174e5dd7070Spatrick // Diagnostics in the ASTUnit were updated, reset the associated
175e5dd7070Spatrick // diagnostics.
176e5dd7070Spatrick delete Set;
177e5dd7070Spatrick TU->Diagnostics = nullptr;
178e5dd7070Spatrick }
179e5dd7070Spatrick }
180e5dd7070Spatrick
181e5dd7070Spatrick if (!TU->Diagnostics) {
182e5dd7070Spatrick CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
183e5dd7070Spatrick TU->Diagnostics = Set;
184e5dd7070Spatrick IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions;
185e5dd7070Spatrick CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
186e5dd7070Spatrick &*DOpts, Set);
187e5dd7070Spatrick
188e5dd7070Spatrick for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
189e5dd7070Spatrick ei = AU->stored_diag_end(); it != ei; ++it) {
190e5dd7070Spatrick Renderer.emitStoredDiagnostic(*it);
191e5dd7070Spatrick }
192e5dd7070Spatrick }
193e5dd7070Spatrick return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
194e5dd7070Spatrick }
195e5dd7070Spatrick
196e5dd7070Spatrick //-----------------------------------------------------------------------------
197e5dd7070Spatrick // C Interface Routines
198e5dd7070Spatrick //-----------------------------------------------------------------------------
clang_getNumDiagnostics(CXTranslationUnit Unit)199e5dd7070Spatrick unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
200e5dd7070Spatrick if (cxtu::isNotUsableTU(Unit)) {
201e5dd7070Spatrick LOG_BAD_TU(Unit);
202e5dd7070Spatrick return 0;
203e5dd7070Spatrick }
204e5dd7070Spatrick if (!cxtu::getASTUnit(Unit))
205e5dd7070Spatrick return 0;
206e5dd7070Spatrick return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
207e5dd7070Spatrick }
208e5dd7070Spatrick
clang_getDiagnostic(CXTranslationUnit Unit,unsigned Index)209e5dd7070Spatrick CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
210e5dd7070Spatrick if (cxtu::isNotUsableTU(Unit)) {
211e5dd7070Spatrick LOG_BAD_TU(Unit);
212e5dd7070Spatrick return nullptr;
213e5dd7070Spatrick }
214e5dd7070Spatrick
215e5dd7070Spatrick CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
216e5dd7070Spatrick if (!D)
217e5dd7070Spatrick return nullptr;
218e5dd7070Spatrick
219e5dd7070Spatrick CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
220e5dd7070Spatrick if (Index >= Diags->getNumDiagnostics())
221e5dd7070Spatrick return nullptr;
222e5dd7070Spatrick
223e5dd7070Spatrick return Diags->getDiagnostic(Index);
224e5dd7070Spatrick }
225e5dd7070Spatrick
clang_getDiagnosticSetFromTU(CXTranslationUnit Unit)226e5dd7070Spatrick CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
227e5dd7070Spatrick if (cxtu::isNotUsableTU(Unit)) {
228e5dd7070Spatrick LOG_BAD_TU(Unit);
229e5dd7070Spatrick return nullptr;
230e5dd7070Spatrick }
231e5dd7070Spatrick if (!cxtu::getASTUnit(Unit))
232e5dd7070Spatrick return nullptr;
233e5dd7070Spatrick return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
234e5dd7070Spatrick }
235e5dd7070Spatrick
clang_disposeDiagnostic(CXDiagnostic Diagnostic)236e5dd7070Spatrick void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
237e5dd7070Spatrick // No-op. Kept as a legacy API. CXDiagnostics are now managed
238e5dd7070Spatrick // by the enclosing CXDiagnosticSet.
239e5dd7070Spatrick }
240e5dd7070Spatrick
clang_formatDiagnostic(CXDiagnostic Diagnostic,unsigned Options)241e5dd7070Spatrick CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
242e5dd7070Spatrick if (!Diagnostic)
243e5dd7070Spatrick return cxstring::createEmpty();
244e5dd7070Spatrick
245e5dd7070Spatrick CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
246e5dd7070Spatrick
247e5dd7070Spatrick SmallString<256> Str;
248e5dd7070Spatrick llvm::raw_svector_ostream Out(Str);
249e5dd7070Spatrick
250e5dd7070Spatrick if (Options & CXDiagnostic_DisplaySourceLocation) {
251e5dd7070Spatrick // Print source location (file:line), along with optional column
252e5dd7070Spatrick // and source ranges.
253e5dd7070Spatrick CXFile File;
254e5dd7070Spatrick unsigned Line, Column;
255e5dd7070Spatrick clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
256e5dd7070Spatrick &File, &Line, &Column, nullptr);
257e5dd7070Spatrick if (File) {
258e5dd7070Spatrick CXString FName = clang_getFileName(File);
259e5dd7070Spatrick Out << clang_getCString(FName) << ":" << Line << ":";
260e5dd7070Spatrick clang_disposeString(FName);
261e5dd7070Spatrick if (Options & CXDiagnostic_DisplayColumn)
262e5dd7070Spatrick Out << Column << ":";
263e5dd7070Spatrick
264e5dd7070Spatrick if (Options & CXDiagnostic_DisplaySourceRanges) {
265e5dd7070Spatrick unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
266e5dd7070Spatrick bool PrintedRange = false;
267e5dd7070Spatrick for (unsigned I = 0; I != N; ++I) {
268e5dd7070Spatrick CXFile StartFile, EndFile;
269e5dd7070Spatrick CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
270e5dd7070Spatrick
271e5dd7070Spatrick unsigned StartLine, StartColumn, EndLine, EndColumn;
272e5dd7070Spatrick clang_getSpellingLocation(clang_getRangeStart(Range),
273e5dd7070Spatrick &StartFile, &StartLine, &StartColumn,
274e5dd7070Spatrick nullptr);
275e5dd7070Spatrick clang_getSpellingLocation(clang_getRangeEnd(Range),
276e5dd7070Spatrick &EndFile, &EndLine, &EndColumn, nullptr);
277e5dd7070Spatrick
278e5dd7070Spatrick if (StartFile != EndFile || StartFile != File)
279e5dd7070Spatrick continue;
280e5dd7070Spatrick
281e5dd7070Spatrick Out << "{" << StartLine << ":" << StartColumn << "-"
282e5dd7070Spatrick << EndLine << ":" << EndColumn << "}";
283e5dd7070Spatrick PrintedRange = true;
284e5dd7070Spatrick }
285e5dd7070Spatrick if (PrintedRange)
286e5dd7070Spatrick Out << ":";
287e5dd7070Spatrick }
288e5dd7070Spatrick
289e5dd7070Spatrick Out << " ";
290e5dd7070Spatrick }
291e5dd7070Spatrick }
292e5dd7070Spatrick
293e5dd7070Spatrick /* Print warning/error/etc. */
294e5dd7070Spatrick switch (Severity) {
295e5dd7070Spatrick case CXDiagnostic_Ignored: llvm_unreachable("impossible");
296e5dd7070Spatrick case CXDiagnostic_Note: Out << "note: "; break;
297e5dd7070Spatrick case CXDiagnostic_Warning: Out << "warning: "; break;
298e5dd7070Spatrick case CXDiagnostic_Error: Out << "error: "; break;
299e5dd7070Spatrick case CXDiagnostic_Fatal: Out << "fatal error: "; break;
300e5dd7070Spatrick }
301e5dd7070Spatrick
302e5dd7070Spatrick CXString Text = clang_getDiagnosticSpelling(Diagnostic);
303e5dd7070Spatrick if (clang_getCString(Text))
304e5dd7070Spatrick Out << clang_getCString(Text);
305e5dd7070Spatrick else
306e5dd7070Spatrick Out << "<no diagnostic text>";
307e5dd7070Spatrick clang_disposeString(Text);
308e5dd7070Spatrick
309e5dd7070Spatrick if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
310e5dd7070Spatrick CXDiagnostic_DisplayCategoryName)) {
311e5dd7070Spatrick bool NeedBracket = true;
312e5dd7070Spatrick bool NeedComma = false;
313e5dd7070Spatrick
314e5dd7070Spatrick if (Options & CXDiagnostic_DisplayOption) {
315e5dd7070Spatrick CXString OptionName = clang_getDiagnosticOption(Diagnostic, nullptr);
316e5dd7070Spatrick if (const char *OptionText = clang_getCString(OptionName)) {
317e5dd7070Spatrick if (OptionText[0]) {
318e5dd7070Spatrick Out << " [" << OptionText;
319e5dd7070Spatrick NeedBracket = false;
320e5dd7070Spatrick NeedComma = true;
321e5dd7070Spatrick }
322e5dd7070Spatrick }
323e5dd7070Spatrick clang_disposeString(OptionName);
324e5dd7070Spatrick }
325e5dd7070Spatrick
326e5dd7070Spatrick if (Options & (CXDiagnostic_DisplayCategoryId |
327e5dd7070Spatrick CXDiagnostic_DisplayCategoryName)) {
328e5dd7070Spatrick if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
329e5dd7070Spatrick if (Options & CXDiagnostic_DisplayCategoryId) {
330e5dd7070Spatrick if (NeedBracket)
331e5dd7070Spatrick Out << " [";
332e5dd7070Spatrick if (NeedComma)
333e5dd7070Spatrick Out << ", ";
334e5dd7070Spatrick Out << CategoryID;
335e5dd7070Spatrick NeedBracket = false;
336e5dd7070Spatrick NeedComma = true;
337e5dd7070Spatrick }
338e5dd7070Spatrick
339e5dd7070Spatrick if (Options & CXDiagnostic_DisplayCategoryName) {
340e5dd7070Spatrick CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic);
341e5dd7070Spatrick if (NeedBracket)
342e5dd7070Spatrick Out << " [";
343e5dd7070Spatrick if (NeedComma)
344e5dd7070Spatrick Out << ", ";
345e5dd7070Spatrick Out << clang_getCString(CategoryName);
346e5dd7070Spatrick NeedBracket = false;
347e5dd7070Spatrick NeedComma = true;
348e5dd7070Spatrick clang_disposeString(CategoryName);
349e5dd7070Spatrick }
350e5dd7070Spatrick }
351e5dd7070Spatrick }
352e5dd7070Spatrick
353e5dd7070Spatrick (void) NeedComma; // Silence dead store warning.
354e5dd7070Spatrick if (!NeedBracket)
355e5dd7070Spatrick Out << "]";
356e5dd7070Spatrick }
357e5dd7070Spatrick
358e5dd7070Spatrick return cxstring::createDup(Out.str());
359e5dd7070Spatrick }
360e5dd7070Spatrick
clang_defaultDiagnosticDisplayOptions()361e5dd7070Spatrick unsigned clang_defaultDiagnosticDisplayOptions() {
362e5dd7070Spatrick return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
363e5dd7070Spatrick CXDiagnostic_DisplayOption;
364e5dd7070Spatrick }
365e5dd7070Spatrick
clang_getDiagnosticSeverity(CXDiagnostic Diag)366e5dd7070Spatrick enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
367e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
368e5dd7070Spatrick return D->getSeverity();
369e5dd7070Spatrick return CXDiagnostic_Ignored;
370e5dd7070Spatrick }
371e5dd7070Spatrick
clang_getDiagnosticLocation(CXDiagnostic Diag)372e5dd7070Spatrick CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
373e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
374e5dd7070Spatrick return D->getLocation();
375e5dd7070Spatrick return clang_getNullLocation();
376e5dd7070Spatrick }
377e5dd7070Spatrick
clang_getDiagnosticSpelling(CXDiagnostic Diag)378e5dd7070Spatrick CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
379e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
380e5dd7070Spatrick return D->getSpelling();
381e5dd7070Spatrick return cxstring::createEmpty();
382e5dd7070Spatrick }
383e5dd7070Spatrick
clang_getDiagnosticOption(CXDiagnostic Diag,CXString * Disable)384e5dd7070Spatrick CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
385e5dd7070Spatrick if (Disable)
386e5dd7070Spatrick *Disable = cxstring::createEmpty();
387e5dd7070Spatrick
388e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
389e5dd7070Spatrick return D->getDiagnosticOption(Disable);
390e5dd7070Spatrick
391e5dd7070Spatrick return cxstring::createEmpty();
392e5dd7070Spatrick }
393e5dd7070Spatrick
clang_getDiagnosticCategory(CXDiagnostic Diag)394e5dd7070Spatrick unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
395e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
396e5dd7070Spatrick return D->getCategory();
397e5dd7070Spatrick return 0;
398e5dd7070Spatrick }
399e5dd7070Spatrick
clang_getDiagnosticCategoryName(unsigned Category)400e5dd7070Spatrick CXString clang_getDiagnosticCategoryName(unsigned Category) {
401e5dd7070Spatrick // Kept for backward compatibility.
402e5dd7070Spatrick return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
403e5dd7070Spatrick }
404e5dd7070Spatrick
clang_getDiagnosticCategoryText(CXDiagnostic Diag)405e5dd7070Spatrick CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
406e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
407e5dd7070Spatrick return D->getCategoryText();
408e5dd7070Spatrick return cxstring::createEmpty();
409e5dd7070Spatrick }
410e5dd7070Spatrick
clang_getDiagnosticNumRanges(CXDiagnostic Diag)411e5dd7070Spatrick unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
412e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
413e5dd7070Spatrick return D->getNumRanges();
414e5dd7070Spatrick return 0;
415e5dd7070Spatrick }
416e5dd7070Spatrick
clang_getDiagnosticRange(CXDiagnostic Diag,unsigned Range)417e5dd7070Spatrick CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
418e5dd7070Spatrick CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
419e5dd7070Spatrick if (!D || Range >= D->getNumRanges())
420e5dd7070Spatrick return clang_getNullRange();
421e5dd7070Spatrick return D->getRange(Range);
422e5dd7070Spatrick }
423e5dd7070Spatrick
clang_getDiagnosticNumFixIts(CXDiagnostic Diag)424e5dd7070Spatrick unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
425e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
426e5dd7070Spatrick return D->getNumFixIts();
427e5dd7070Spatrick return 0;
428e5dd7070Spatrick }
429e5dd7070Spatrick
clang_getDiagnosticFixIt(CXDiagnostic Diag,unsigned FixIt,CXSourceRange * ReplacementRange)430e5dd7070Spatrick CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
431e5dd7070Spatrick CXSourceRange *ReplacementRange) {
432e5dd7070Spatrick CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
433e5dd7070Spatrick if (!D || FixIt >= D->getNumFixIts()) {
434e5dd7070Spatrick if (ReplacementRange)
435e5dd7070Spatrick *ReplacementRange = clang_getNullRange();
436e5dd7070Spatrick return cxstring::createEmpty();
437e5dd7070Spatrick }
438e5dd7070Spatrick return D->getFixIt(FixIt, ReplacementRange);
439e5dd7070Spatrick }
440e5dd7070Spatrick
clang_disposeDiagnosticSet(CXDiagnosticSet Diags)441e5dd7070Spatrick void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
442e5dd7070Spatrick if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) {
443e5dd7070Spatrick if (D->isExternallyManaged())
444e5dd7070Spatrick delete D;
445e5dd7070Spatrick }
446e5dd7070Spatrick }
447e5dd7070Spatrick
clang_getDiagnosticInSet(CXDiagnosticSet Diags,unsigned Index)448e5dd7070Spatrick CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
449e5dd7070Spatrick unsigned Index) {
450e5dd7070Spatrick if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
451e5dd7070Spatrick if (Index < D->getNumDiagnostics())
452e5dd7070Spatrick return D->getDiagnostic(Index);
453e5dd7070Spatrick return nullptr;
454e5dd7070Spatrick }
455e5dd7070Spatrick
clang_getChildDiagnostics(CXDiagnostic Diag)456e5dd7070Spatrick CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
457e5dd7070Spatrick if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
458e5dd7070Spatrick CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
459e5dd7070Spatrick return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags;
460e5dd7070Spatrick }
461e5dd7070Spatrick return nullptr;
462e5dd7070Spatrick }
463e5dd7070Spatrick
clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags)464e5dd7070Spatrick unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
465e5dd7070Spatrick if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
466e5dd7070Spatrick return D->getNumDiagnostics();
467e5dd7070Spatrick return 0;
468e5dd7070Spatrick }
469