xref: /netbsd-src/external/apache2/llvm/dist/clang/tools/libclang/CIndexDiagnostic.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===- CIndexDiagnostic.cpp - Diagnostics C Interface ---------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // Implements the diagnostic functions of the Clang C interface.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "CIndexDiagnostic.h"
147330f729Sjoerg #include "CIndexer.h"
157330f729Sjoerg #include "CXTranslationUnit.h"
167330f729Sjoerg #include "CXSourceLocation.h"
177330f729Sjoerg #include "CXString.h"
187330f729Sjoerg 
197330f729Sjoerg #include "clang/Basic/DiagnosticOptions.h"
207330f729Sjoerg #include "clang/Frontend/ASTUnit.h"
217330f729Sjoerg #include "clang/Frontend/DiagnosticRenderer.h"
227330f729Sjoerg #include "llvm/ADT/SmallString.h"
237330f729Sjoerg #include "llvm/Support/raw_ostream.h"
247330f729Sjoerg 
257330f729Sjoerg using namespace clang;
267330f729Sjoerg using namespace clang::cxloc;
277330f729Sjoerg using namespace clang::cxdiag;
287330f729Sjoerg using namespace llvm;
297330f729Sjoerg 
~CXDiagnosticSetImpl()307330f729Sjoerg CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {}
317330f729Sjoerg 
327330f729Sjoerg void
appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D)337330f729Sjoerg CXDiagnosticSetImpl::appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D) {
347330f729Sjoerg   Diagnostics.push_back(std::move(D));
357330f729Sjoerg }
367330f729Sjoerg 
~CXDiagnosticImpl()377330f729Sjoerg CXDiagnosticImpl::~CXDiagnosticImpl() {}
387330f729Sjoerg 
397330f729Sjoerg namespace {
407330f729Sjoerg class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
417330f729Sjoerg   std::string Message;
427330f729Sjoerg   CXSourceLocation Loc;
437330f729Sjoerg public:
CXDiagnosticCustomNoteImpl(StringRef Msg,CXSourceLocation L)447330f729Sjoerg   CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
45*e038c9c4Sjoerg       : CXDiagnosticImpl(CustomNoteDiagnosticKind), Message(std::string(Msg)),
46*e038c9c4Sjoerg         Loc(L) {}
477330f729Sjoerg 
~CXDiagnosticCustomNoteImpl()487330f729Sjoerg   ~CXDiagnosticCustomNoteImpl() override {}
497330f729Sjoerg 
getSeverity() const507330f729Sjoerg   CXDiagnosticSeverity getSeverity() const override {
517330f729Sjoerg     return CXDiagnostic_Note;
527330f729Sjoerg   }
537330f729Sjoerg 
getLocation() const54*e038c9c4Sjoerg   CXSourceLocation getLocation() const override { return Loc; }
557330f729Sjoerg 
getSpelling() const567330f729Sjoerg   CXString getSpelling() const override {
577330f729Sjoerg     return cxstring::createRef(Message.c_str());
587330f729Sjoerg   }
597330f729Sjoerg 
getDiagnosticOption(CXString * Disable) const607330f729Sjoerg   CXString getDiagnosticOption(CXString *Disable) const override {
617330f729Sjoerg     if (Disable)
627330f729Sjoerg       *Disable = cxstring::createEmpty();
637330f729Sjoerg     return cxstring::createEmpty();
647330f729Sjoerg   }
657330f729Sjoerg 
getCategory() const667330f729Sjoerg   unsigned getCategory() const override { return 0; }
getCategoryText() const677330f729Sjoerg   CXString getCategoryText() const override { return cxstring::createEmpty(); }
687330f729Sjoerg 
getNumRanges() const697330f729Sjoerg   unsigned getNumRanges() const override { return 0; }
getRange(unsigned Range) const707330f729Sjoerg   CXSourceRange getRange(unsigned Range) const override {
717330f729Sjoerg     return clang_getNullRange();
727330f729Sjoerg   }
getNumFixIts() const737330f729Sjoerg   unsigned getNumFixIts() const override { return 0; }
getFixIt(unsigned FixIt,CXSourceRange * ReplacementRange) const747330f729Sjoerg   CXString getFixIt(unsigned FixIt,
757330f729Sjoerg                     CXSourceRange *ReplacementRange) const override {
767330f729Sjoerg     if (ReplacementRange)
777330f729Sjoerg       *ReplacementRange = clang_getNullRange();
787330f729Sjoerg     return cxstring::createEmpty();
797330f729Sjoerg   }
807330f729Sjoerg };
817330f729Sjoerg 
827330f729Sjoerg class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
837330f729Sjoerg public:
CXDiagnosticRenderer(const LangOptions & LangOpts,DiagnosticOptions * DiagOpts,CXDiagnosticSetImpl * mainSet)847330f729Sjoerg   CXDiagnosticRenderer(const LangOptions &LangOpts,
857330f729Sjoerg                        DiagnosticOptions *DiagOpts,
867330f729Sjoerg                        CXDiagnosticSetImpl *mainSet)
877330f729Sjoerg   : DiagnosticNoteRenderer(LangOpts, DiagOpts),
887330f729Sjoerg     CurrentSet(mainSet), MainSet(mainSet) {}
897330f729Sjoerg 
~CXDiagnosticRenderer()907330f729Sjoerg   ~CXDiagnosticRenderer() override {}
917330f729Sjoerg 
beginDiagnostic(DiagOrStoredDiag D,DiagnosticsEngine::Level Level)927330f729Sjoerg   void beginDiagnostic(DiagOrStoredDiag D,
937330f729Sjoerg                        DiagnosticsEngine::Level Level) override {
947330f729Sjoerg 
957330f729Sjoerg     const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
967330f729Sjoerg     if (!SD)
977330f729Sjoerg       return;
987330f729Sjoerg 
997330f729Sjoerg     if (Level != DiagnosticsEngine::Note)
1007330f729Sjoerg       CurrentSet = MainSet;
1017330f729Sjoerg 
1027330f729Sjoerg     auto Owner = std::make_unique<CXStoredDiagnostic>(*SD, LangOpts);
1037330f729Sjoerg     CXStoredDiagnostic &CD = *Owner;
1047330f729Sjoerg     CurrentSet->appendDiagnostic(std::move(Owner));
1057330f729Sjoerg 
1067330f729Sjoerg     if (Level != DiagnosticsEngine::Note)
1077330f729Sjoerg       CurrentSet = &CD.getChildDiagnostics();
1087330f729Sjoerg   }
1097330f729Sjoerg 
emitDiagnosticMessage(FullSourceLoc Loc,PresumedLoc PLoc,DiagnosticsEngine::Level Level,StringRef Message,ArrayRef<CharSourceRange> Ranges,DiagOrStoredDiag D)1107330f729Sjoerg   void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
1117330f729Sjoerg                              DiagnosticsEngine::Level Level, StringRef Message,
1127330f729Sjoerg                              ArrayRef<CharSourceRange> Ranges,
1137330f729Sjoerg                              DiagOrStoredDiag D) override {
1147330f729Sjoerg     if (!D.isNull())
1157330f729Sjoerg       return;
1167330f729Sjoerg 
1177330f729Sjoerg     CXSourceLocation L;
1187330f729Sjoerg     if (Loc.hasManager())
1197330f729Sjoerg       L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
1207330f729Sjoerg     else
1217330f729Sjoerg       L = clang_getNullLocation();
1227330f729Sjoerg     CurrentSet->appendDiagnostic(
1237330f729Sjoerg         std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
1247330f729Sjoerg   }
1257330f729Sjoerg 
emitDiagnosticLoc(FullSourceLoc Loc,PresumedLoc PLoc,DiagnosticsEngine::Level Level,ArrayRef<CharSourceRange> Ranges)1267330f729Sjoerg   void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
1277330f729Sjoerg                          DiagnosticsEngine::Level Level,
1287330f729Sjoerg                          ArrayRef<CharSourceRange> Ranges) override {}
1297330f729Sjoerg 
emitCodeContext(FullSourceLoc Loc,DiagnosticsEngine::Level Level,SmallVectorImpl<CharSourceRange> & Ranges,ArrayRef<FixItHint> Hints)1307330f729Sjoerg   void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
1317330f729Sjoerg                        SmallVectorImpl<CharSourceRange> &Ranges,
1327330f729Sjoerg                        ArrayRef<FixItHint> Hints) override {}
1337330f729Sjoerg 
emitNote(FullSourceLoc Loc,StringRef Message)1347330f729Sjoerg   void emitNote(FullSourceLoc Loc, StringRef Message) override {
1357330f729Sjoerg     CXSourceLocation L;
1367330f729Sjoerg     if (Loc.hasManager())
1377330f729Sjoerg       L = translateSourceLocation(Loc.getManager(), LangOpts, Loc);
1387330f729Sjoerg     else
1397330f729Sjoerg       L = clang_getNullLocation();
1407330f729Sjoerg     CurrentSet->appendDiagnostic(
1417330f729Sjoerg         std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L));
1427330f729Sjoerg   }
1437330f729Sjoerg 
1447330f729Sjoerg   CXDiagnosticSetImpl *CurrentSet;
1457330f729Sjoerg   CXDiagnosticSetImpl *MainSet;
1467330f729Sjoerg };
1477330f729Sjoerg }
1487330f729Sjoerg 
lazyCreateDiags(CXTranslationUnit TU,bool checkIfChanged)1497330f729Sjoerg CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
1507330f729Sjoerg                                              bool checkIfChanged) {
1517330f729Sjoerg   ASTUnit *AU = cxtu::getASTUnit(TU);
1527330f729Sjoerg 
1537330f729Sjoerg   if (TU->Diagnostics && checkIfChanged) {
1547330f729Sjoerg     // In normal use, ASTUnit's diagnostics should not change unless we reparse.
1557330f729Sjoerg     // Currently they can only change by using the internal testing flag
1567330f729Sjoerg     // '-error-on-deserialized-decl' which will error during deserialization of
1577330f729Sjoerg     // a declaration. What will happen is:
1587330f729Sjoerg     //
1597330f729Sjoerg     //  -c-index-test gets a CXTranslationUnit
1607330f729Sjoerg     //  -checks the diagnostics, the diagnostics set is lazily created,
1617330f729Sjoerg     //     no errors are reported
1627330f729Sjoerg     //  -later does an operation, like annotation of tokens, that triggers
1637330f729Sjoerg     //     -error-on-deserialized-decl, that will emit a diagnostic error,
1647330f729Sjoerg     //     that ASTUnit will catch and add to its stored diagnostics vector.
1657330f729Sjoerg     //  -c-index-test wants to check whether an error occurred after performing
1667330f729Sjoerg     //     the operation but can only query the lazily created set.
1677330f729Sjoerg     //
1687330f729Sjoerg     // We check here if a new diagnostic was appended since the last time the
1697330f729Sjoerg     // diagnostic set was created, in which case we reset it.
1707330f729Sjoerg 
1717330f729Sjoerg     CXDiagnosticSetImpl *
1727330f729Sjoerg       Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
1737330f729Sjoerg     if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
1747330f729Sjoerg       // Diagnostics in the ASTUnit were updated, reset the associated
1757330f729Sjoerg       // diagnostics.
1767330f729Sjoerg       delete Set;
1777330f729Sjoerg       TU->Diagnostics = nullptr;
1787330f729Sjoerg     }
1797330f729Sjoerg   }
1807330f729Sjoerg 
1817330f729Sjoerg   if (!TU->Diagnostics) {
1827330f729Sjoerg     CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
1837330f729Sjoerg     TU->Diagnostics = Set;
1847330f729Sjoerg     IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions;
1857330f729Sjoerg     CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
1867330f729Sjoerg                                   &*DOpts, Set);
1877330f729Sjoerg 
1887330f729Sjoerg     for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
1897330f729Sjoerg          ei = AU->stored_diag_end(); it != ei; ++it) {
1907330f729Sjoerg       Renderer.emitStoredDiagnostic(*it);
1917330f729Sjoerg     }
1927330f729Sjoerg   }
1937330f729Sjoerg   return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
1947330f729Sjoerg }
1957330f729Sjoerg 
1967330f729Sjoerg //-----------------------------------------------------------------------------
1977330f729Sjoerg // C Interface Routines
1987330f729Sjoerg //-----------------------------------------------------------------------------
clang_getNumDiagnostics(CXTranslationUnit Unit)1997330f729Sjoerg unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
2007330f729Sjoerg   if (cxtu::isNotUsableTU(Unit)) {
2017330f729Sjoerg     LOG_BAD_TU(Unit);
2027330f729Sjoerg     return 0;
2037330f729Sjoerg   }
2047330f729Sjoerg   if (!cxtu::getASTUnit(Unit))
2057330f729Sjoerg     return 0;
2067330f729Sjoerg   return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
2077330f729Sjoerg }
2087330f729Sjoerg 
clang_getDiagnostic(CXTranslationUnit Unit,unsigned Index)2097330f729Sjoerg CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
2107330f729Sjoerg   if (cxtu::isNotUsableTU(Unit)) {
2117330f729Sjoerg     LOG_BAD_TU(Unit);
2127330f729Sjoerg     return nullptr;
2137330f729Sjoerg   }
2147330f729Sjoerg 
2157330f729Sjoerg   CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
2167330f729Sjoerg   if (!D)
2177330f729Sjoerg     return nullptr;
2187330f729Sjoerg 
2197330f729Sjoerg   CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
2207330f729Sjoerg   if (Index >= Diags->getNumDiagnostics())
2217330f729Sjoerg     return nullptr;
2227330f729Sjoerg 
2237330f729Sjoerg   return Diags->getDiagnostic(Index);
2247330f729Sjoerg }
2257330f729Sjoerg 
clang_getDiagnosticSetFromTU(CXTranslationUnit Unit)2267330f729Sjoerg CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
2277330f729Sjoerg   if (cxtu::isNotUsableTU(Unit)) {
2287330f729Sjoerg     LOG_BAD_TU(Unit);
2297330f729Sjoerg     return nullptr;
2307330f729Sjoerg   }
2317330f729Sjoerg   if (!cxtu::getASTUnit(Unit))
2327330f729Sjoerg     return nullptr;
2337330f729Sjoerg   return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
2347330f729Sjoerg }
2357330f729Sjoerg 
clang_disposeDiagnostic(CXDiagnostic Diagnostic)2367330f729Sjoerg void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
2377330f729Sjoerg   // No-op.  Kept as a legacy API.  CXDiagnostics are now managed
2387330f729Sjoerg   // by the enclosing CXDiagnosticSet.
2397330f729Sjoerg }
2407330f729Sjoerg 
clang_formatDiagnostic(CXDiagnostic Diagnostic,unsigned Options)2417330f729Sjoerg CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
2427330f729Sjoerg   if (!Diagnostic)
2437330f729Sjoerg     return cxstring::createEmpty();
2447330f729Sjoerg 
2457330f729Sjoerg   CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
2467330f729Sjoerg 
2477330f729Sjoerg   SmallString<256> Str;
2487330f729Sjoerg   llvm::raw_svector_ostream Out(Str);
2497330f729Sjoerg 
2507330f729Sjoerg   if (Options & CXDiagnostic_DisplaySourceLocation) {
2517330f729Sjoerg     // Print source location (file:line), along with optional column
2527330f729Sjoerg     // and source ranges.
2537330f729Sjoerg     CXFile File;
2547330f729Sjoerg     unsigned Line, Column;
2557330f729Sjoerg     clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
2567330f729Sjoerg                               &File, &Line, &Column, nullptr);
2577330f729Sjoerg     if (File) {
2587330f729Sjoerg       CXString FName = clang_getFileName(File);
2597330f729Sjoerg       Out << clang_getCString(FName) << ":" << Line << ":";
2607330f729Sjoerg       clang_disposeString(FName);
2617330f729Sjoerg       if (Options & CXDiagnostic_DisplayColumn)
2627330f729Sjoerg         Out << Column << ":";
2637330f729Sjoerg 
2647330f729Sjoerg       if (Options & CXDiagnostic_DisplaySourceRanges) {
2657330f729Sjoerg         unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
2667330f729Sjoerg         bool PrintedRange = false;
2677330f729Sjoerg         for (unsigned I = 0; I != N; ++I) {
2687330f729Sjoerg           CXFile StartFile, EndFile;
2697330f729Sjoerg           CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
2707330f729Sjoerg 
2717330f729Sjoerg           unsigned StartLine, StartColumn, EndLine, EndColumn;
2727330f729Sjoerg           clang_getSpellingLocation(clang_getRangeStart(Range),
2737330f729Sjoerg                                     &StartFile, &StartLine, &StartColumn,
2747330f729Sjoerg                                     nullptr);
2757330f729Sjoerg           clang_getSpellingLocation(clang_getRangeEnd(Range),
2767330f729Sjoerg                                     &EndFile, &EndLine, &EndColumn, nullptr);
2777330f729Sjoerg 
2787330f729Sjoerg           if (StartFile != EndFile || StartFile != File)
2797330f729Sjoerg             continue;
2807330f729Sjoerg 
2817330f729Sjoerg           Out << "{" << StartLine << ":" << StartColumn << "-"
2827330f729Sjoerg               << EndLine << ":" << EndColumn << "}";
2837330f729Sjoerg           PrintedRange = true;
2847330f729Sjoerg         }
2857330f729Sjoerg         if (PrintedRange)
2867330f729Sjoerg           Out << ":";
2877330f729Sjoerg       }
2887330f729Sjoerg 
2897330f729Sjoerg       Out << " ";
2907330f729Sjoerg     }
2917330f729Sjoerg   }
2927330f729Sjoerg 
2937330f729Sjoerg   /* Print warning/error/etc. */
2947330f729Sjoerg   switch (Severity) {
2957330f729Sjoerg   case CXDiagnostic_Ignored: llvm_unreachable("impossible");
2967330f729Sjoerg   case CXDiagnostic_Note: Out << "note: "; break;
2977330f729Sjoerg   case CXDiagnostic_Warning: Out << "warning: "; break;
2987330f729Sjoerg   case CXDiagnostic_Error: Out << "error: "; break;
2997330f729Sjoerg   case CXDiagnostic_Fatal: Out << "fatal error: "; break;
3007330f729Sjoerg   }
3017330f729Sjoerg 
3027330f729Sjoerg   CXString Text = clang_getDiagnosticSpelling(Diagnostic);
3037330f729Sjoerg   if (clang_getCString(Text))
3047330f729Sjoerg     Out << clang_getCString(Text);
3057330f729Sjoerg   else
3067330f729Sjoerg     Out << "<no diagnostic text>";
3077330f729Sjoerg   clang_disposeString(Text);
3087330f729Sjoerg 
3097330f729Sjoerg   if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
3107330f729Sjoerg                  CXDiagnostic_DisplayCategoryName)) {
3117330f729Sjoerg     bool NeedBracket = true;
3127330f729Sjoerg     bool NeedComma = false;
3137330f729Sjoerg 
3147330f729Sjoerg     if (Options & CXDiagnostic_DisplayOption) {
3157330f729Sjoerg       CXString OptionName = clang_getDiagnosticOption(Diagnostic, nullptr);
3167330f729Sjoerg       if (const char *OptionText = clang_getCString(OptionName)) {
3177330f729Sjoerg         if (OptionText[0]) {
3187330f729Sjoerg           Out << " [" << OptionText;
3197330f729Sjoerg           NeedBracket = false;
3207330f729Sjoerg           NeedComma = true;
3217330f729Sjoerg         }
3227330f729Sjoerg       }
3237330f729Sjoerg       clang_disposeString(OptionName);
3247330f729Sjoerg     }
3257330f729Sjoerg 
3267330f729Sjoerg     if (Options & (CXDiagnostic_DisplayCategoryId |
3277330f729Sjoerg                    CXDiagnostic_DisplayCategoryName)) {
3287330f729Sjoerg       if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
3297330f729Sjoerg         if (Options & CXDiagnostic_DisplayCategoryId) {
3307330f729Sjoerg           if (NeedBracket)
3317330f729Sjoerg             Out << " [";
3327330f729Sjoerg           if (NeedComma)
3337330f729Sjoerg             Out << ", ";
3347330f729Sjoerg           Out << CategoryID;
3357330f729Sjoerg           NeedBracket = false;
3367330f729Sjoerg           NeedComma = true;
3377330f729Sjoerg         }
3387330f729Sjoerg 
3397330f729Sjoerg         if (Options & CXDiagnostic_DisplayCategoryName) {
3407330f729Sjoerg           CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic);
3417330f729Sjoerg           if (NeedBracket)
3427330f729Sjoerg             Out << " [";
3437330f729Sjoerg           if (NeedComma)
3447330f729Sjoerg             Out << ", ";
3457330f729Sjoerg           Out << clang_getCString(CategoryName);
3467330f729Sjoerg           NeedBracket = false;
3477330f729Sjoerg           NeedComma = true;
3487330f729Sjoerg           clang_disposeString(CategoryName);
3497330f729Sjoerg         }
3507330f729Sjoerg       }
3517330f729Sjoerg     }
3527330f729Sjoerg 
3537330f729Sjoerg     (void) NeedComma; // Silence dead store warning.
3547330f729Sjoerg     if (!NeedBracket)
3557330f729Sjoerg       Out << "]";
3567330f729Sjoerg   }
3577330f729Sjoerg 
3587330f729Sjoerg   return cxstring::createDup(Out.str());
3597330f729Sjoerg }
3607330f729Sjoerg 
clang_defaultDiagnosticDisplayOptions()3617330f729Sjoerg unsigned clang_defaultDiagnosticDisplayOptions() {
3627330f729Sjoerg   return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
3637330f729Sjoerg          CXDiagnostic_DisplayOption;
3647330f729Sjoerg }
3657330f729Sjoerg 
clang_getDiagnosticSeverity(CXDiagnostic Diag)3667330f729Sjoerg enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
3677330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
3687330f729Sjoerg     return D->getSeverity();
3697330f729Sjoerg   return CXDiagnostic_Ignored;
3707330f729Sjoerg }
3717330f729Sjoerg 
clang_getDiagnosticLocation(CXDiagnostic Diag)3727330f729Sjoerg CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
3737330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
3747330f729Sjoerg     return D->getLocation();
3757330f729Sjoerg   return clang_getNullLocation();
3767330f729Sjoerg }
3777330f729Sjoerg 
clang_getDiagnosticSpelling(CXDiagnostic Diag)3787330f729Sjoerg CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
3797330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
3807330f729Sjoerg     return D->getSpelling();
3817330f729Sjoerg   return cxstring::createEmpty();
3827330f729Sjoerg }
3837330f729Sjoerg 
clang_getDiagnosticOption(CXDiagnostic Diag,CXString * Disable)3847330f729Sjoerg CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
3857330f729Sjoerg   if (Disable)
3867330f729Sjoerg     *Disable = cxstring::createEmpty();
3877330f729Sjoerg 
3887330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
3897330f729Sjoerg     return D->getDiagnosticOption(Disable);
3907330f729Sjoerg 
3917330f729Sjoerg   return cxstring::createEmpty();
3927330f729Sjoerg }
3937330f729Sjoerg 
clang_getDiagnosticCategory(CXDiagnostic Diag)3947330f729Sjoerg unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
3957330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
3967330f729Sjoerg     return D->getCategory();
3977330f729Sjoerg   return 0;
3987330f729Sjoerg }
3997330f729Sjoerg 
clang_getDiagnosticCategoryName(unsigned Category)4007330f729Sjoerg CXString clang_getDiagnosticCategoryName(unsigned Category) {
4017330f729Sjoerg   // Kept for backward compatibility.
4027330f729Sjoerg   return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
4037330f729Sjoerg }
4047330f729Sjoerg 
clang_getDiagnosticCategoryText(CXDiagnostic Diag)4057330f729Sjoerg CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
4067330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
4077330f729Sjoerg     return D->getCategoryText();
4087330f729Sjoerg   return cxstring::createEmpty();
4097330f729Sjoerg }
4107330f729Sjoerg 
clang_getDiagnosticNumRanges(CXDiagnostic Diag)4117330f729Sjoerg unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
4127330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
4137330f729Sjoerg     return D->getNumRanges();
4147330f729Sjoerg   return 0;
4157330f729Sjoerg }
4167330f729Sjoerg 
clang_getDiagnosticRange(CXDiagnostic Diag,unsigned Range)4177330f729Sjoerg CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
4187330f729Sjoerg   CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
4197330f729Sjoerg   if (!D || Range >= D->getNumRanges())
4207330f729Sjoerg     return clang_getNullRange();
4217330f729Sjoerg   return D->getRange(Range);
4227330f729Sjoerg }
4237330f729Sjoerg 
clang_getDiagnosticNumFixIts(CXDiagnostic Diag)4247330f729Sjoerg unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
4257330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
4267330f729Sjoerg     return D->getNumFixIts();
4277330f729Sjoerg   return 0;
4287330f729Sjoerg }
4297330f729Sjoerg 
clang_getDiagnosticFixIt(CXDiagnostic Diag,unsigned FixIt,CXSourceRange * ReplacementRange)4307330f729Sjoerg CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
4317330f729Sjoerg                                   CXSourceRange *ReplacementRange) {
4327330f729Sjoerg   CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
4337330f729Sjoerg   if (!D || FixIt >= D->getNumFixIts()) {
4347330f729Sjoerg     if (ReplacementRange)
4357330f729Sjoerg       *ReplacementRange = clang_getNullRange();
4367330f729Sjoerg     return cxstring::createEmpty();
4377330f729Sjoerg   }
4387330f729Sjoerg   return D->getFixIt(FixIt, ReplacementRange);
4397330f729Sjoerg }
4407330f729Sjoerg 
clang_disposeDiagnosticSet(CXDiagnosticSet Diags)4417330f729Sjoerg void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
4427330f729Sjoerg   if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) {
4437330f729Sjoerg     if (D->isExternallyManaged())
4447330f729Sjoerg       delete D;
4457330f729Sjoerg   }
4467330f729Sjoerg }
4477330f729Sjoerg 
clang_getDiagnosticInSet(CXDiagnosticSet Diags,unsigned Index)4487330f729Sjoerg CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
4497330f729Sjoerg                                       unsigned Index) {
4507330f729Sjoerg   if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
4517330f729Sjoerg     if (Index < D->getNumDiagnostics())
4527330f729Sjoerg       return D->getDiagnostic(Index);
4537330f729Sjoerg   return nullptr;
4547330f729Sjoerg }
4557330f729Sjoerg 
clang_getChildDiagnostics(CXDiagnostic Diag)4567330f729Sjoerg CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
4577330f729Sjoerg   if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
4587330f729Sjoerg     CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
4597330f729Sjoerg     return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags;
4607330f729Sjoerg   }
4617330f729Sjoerg   return nullptr;
4627330f729Sjoerg }
4637330f729Sjoerg 
clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags)4647330f729Sjoerg unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
4657330f729Sjoerg   if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
4667330f729Sjoerg     return D->getNumDiagnostics();
4677330f729Sjoerg   return 0;
4687330f729Sjoerg }
469