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