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