CIndexDiagnostic.cpp revision 7473b1c6e7ba2654d4a0d469198f0e01b485b51a
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|*                                                                            *|
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|*                     The LLVM Compiler Infrastructure                       *|
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|*                                                                            *|
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|* This file is distributed under the University of Illinois Open Source      *|
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|* License. See LICENSE.TXT for details.                                      *|
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|*                                                                            *|
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|*===----------------------------------------------------------------------===*|
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|*                                                                            *|
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|* Implements the diagnostic functions of the Clang C interface.              *|
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)|*                                                                            *|
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)\*===----------------------------------------------------------------------===*/
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CIndexDiagnostic.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CIndexer.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CXTranslationUnit.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CXSourceLocation.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CXString.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Frontend/ASTUnit.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Frontend/FrontendDiagnostic.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Frontend/DiagnosticRenderer.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Frontend/DiagnosticOptions.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/SmallString.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/Twine.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/MemoryBuffer.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/raw_ostream.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang::cxloc;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang::cxstring;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang::cxdiag;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace llvm;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<CXDiagnosticImpl *>::iterator it = Diagnostics.begin(),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       et = Diagnostics.end();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != et; ++it) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete *it;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CXDiagnosticImpl::~CXDiagnosticImpl() {}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXString Message;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXSourceLocation Loc;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : CXDiagnosticImpl(CustomNoteDiagnosticKind),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Message(createCXString(Msg)), Loc(L) {}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~CXDiagnosticCustomNoteImpl() {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clang_disposeString(Message);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXDiagnosticSeverity getSeverity() const {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CXDiagnostic_Note;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXSourceLocation getLocation() const {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Loc;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXString getSpelling() const {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Message;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXString getDiagnosticOption(CXString *Disable) const {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Disable)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *Disable = createCXString("", false);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return createCXString("", false);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned getCategory() const { return 0; }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned getNumRanges() const { return 0; }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXSourceRange getRange(unsigned Range) const { return clang_getNullRange(); }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned getNumFixIts() const { return 0; }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXString getFixIt(unsigned FixIt, CXSourceRange *ReplacementRange) const {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ReplacementRange)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *ReplacementRange = clang_getNullRange();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return createCXString("", false);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXDiagnosticRenderer(const SourceManager &SM,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const LangOptions &LangOpts,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const DiagnosticOptions &DiagOpts,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       CXDiagnosticSetImpl *mainSet)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CurrentSet(mainSet), MainSet(mainSet) {}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~CXDiagnosticRenderer() {}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void beginDiagnostic(DiagOrStoredDiag D,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               DiagnosticsEngine::Level Level) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SD)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Level != DiagnosticsEngine::Note)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CurrentSet = MainSet;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CXStoredDiagnostic *CD = new CXStoredDiagnostic(*SD, LangOpts);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CurrentSet->appendDiagnostic(CD);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Level != DiagnosticsEngine::Note)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CurrentSet = &CD->getChildDiagnostics();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     DiagnosticsEngine::Level Level,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     StringRef Message,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     ArrayRef<CharSourceRange> Ranges,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     DiagOrStoredDiag D) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!D.isNull())
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CurrentSet->appendDiagnostic(CD);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 DiagnosticsEngine::Level Level,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 ArrayRef<CharSourceRange> Ranges) {}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void emitCodeContext(SourceLocation Loc,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               DiagnosticsEngine::Level Level,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               SmallVectorImpl<CharSourceRange>& Ranges,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ArrayRef<FixItHint> Hints) {};
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void emitNote(SourceLocation Loc, StringRef Message) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                                L));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXDiagnosticSetImpl *CurrentSet;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXDiagnosticSetImpl *MainSet;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool checkIfChanged) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASTUnit *AU = static_cast<ASTUnit *>(TU->TUData);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (TU->Diagnostics && checkIfChanged) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In normal use, ASTUnit's diagnostics should not change unless we reparse.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Currently they can only change by using the internal testing flag
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // '-error-on-deserialized-decl' which will error during deserialization of
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a declaration. What will happen is:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //  -c-index-test gets a CXTranslationUnit
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //  -checks the diagnostics, the diagnostics set is lazily created,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     no errors are reported
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //  -later does an operation, like annotation of tokens, that triggers
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     -error-on-deserialized-decl, that will emit a diagnostic error,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     that ASTUnit will catch and add to its stored diagnostics vector.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //  -c-index-test wants to check whether an error occurred after performing
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     the operation but can only query the lazily created set.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We check here if a new diagnostic was appended since the last time the
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // diagnostic set was created, in which case we reset it.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CXDiagnosticSetImpl *
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (AU->stored_diag_size() != Set->getNumDiagnostics()) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Diagnostics in the ASTUnit were updated, reset the associated
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // diagnostics.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete Set;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TU->Diagnostics = 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!TU->Diagnostics) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TU->Diagnostics = Set;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DiagnosticOptions DOpts;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CXDiagnosticRenderer Renderer(AU->getSourceManager(),
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  AU->getASTContext().getLangOptions(),
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  DOpts, Set);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ei = AU->stored_diag_end(); it != ei; ++it) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Renderer.emitStoredDiagnostic(*it);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// C Interface Routines
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Unit->TUData)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!D)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (Index >= Diags->getNumDiagnostics())
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Diags->getDiagnostic(Index);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Unit->TUData)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<CXDiagnostic>(lazyCreateDiags(Unit));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No-op.  Kept as a legacy API.  CXDiagnostics are now managed
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by the enclosing CXDiagnosticSet.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Diagnostic)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return createCXString("");
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SmallString<256> Str;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  llvm::raw_svector_ostream Out(Str);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (Options & CXDiagnostic_DisplaySourceLocation) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Print source location (file:line), along with optional column
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and source ranges.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CXFile File;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned Line, Column;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &File, &Line, &Column, 0);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (File) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CXString FName = clang_getFileName(File);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Out << clang_getCString(FName) << ":" << Line << ":";
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clang_disposeString(FName);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (Options & CXDiagnostic_DisplayColumn)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Out << Column << ":";
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (Options & CXDiagnostic_DisplaySourceRanges) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool PrintedRange = false;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (unsigned I = 0; I != N; ++I) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CXFile StartFile, EndFile;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          unsigned StartLine, StartColumn, EndLine, EndColumn;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          clang_getSpellingLocation(clang_getRangeStart(Range),
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &StartFile, &StartLine, &StartColumn,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    0);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          clang_getSpellingLocation(clang_getRangeEnd(Range),
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &EndFile, &EndLine, &EndColumn, 0);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (StartFile != EndFile || StartFile != File)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            continue;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Out << "{" << StartLine << ":" << StartColumn << "-"
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << EndLine << ":" << EndColumn << "}";
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PrintedRange = true;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (PrintedRange)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Out << ":";
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Out << " ";
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Print warning/error/etc. */
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (Severity) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case CXDiagnostic_Ignored: llvm_unreachable("impossible");
285  case CXDiagnostic_Note: Out << "note: "; break;
286  case CXDiagnostic_Warning: Out << "warning: "; break;
287  case CXDiagnostic_Error: Out << "error: "; break;
288  case CXDiagnostic_Fatal: Out << "fatal error: "; break;
289  }
290
291  CXString Text = clang_getDiagnosticSpelling(Diagnostic);
292  if (clang_getCString(Text))
293    Out << clang_getCString(Text);
294  else
295    Out << "<no diagnostic text>";
296  clang_disposeString(Text);
297
298  if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
299                 CXDiagnostic_DisplayCategoryName)) {
300    bool NeedBracket = true;
301    bool NeedComma = false;
302
303    if (Options & CXDiagnostic_DisplayOption) {
304      CXString OptionName = clang_getDiagnosticOption(Diagnostic, 0);
305      if (const char *OptionText = clang_getCString(OptionName)) {
306        if (OptionText[0]) {
307          Out << " [" << OptionText;
308          NeedBracket = false;
309          NeedComma = true;
310        }
311      }
312      clang_disposeString(OptionName);
313    }
314
315    if (Options & (CXDiagnostic_DisplayCategoryId |
316                   CXDiagnostic_DisplayCategoryName)) {
317      if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
318        if (Options & CXDiagnostic_DisplayCategoryId) {
319          if (NeedBracket)
320            Out << " [";
321          if (NeedComma)
322            Out << ", ";
323          Out << CategoryID;
324          NeedBracket = false;
325          NeedComma = true;
326        }
327
328        if (Options & CXDiagnostic_DisplayCategoryName) {
329          CXString CategoryName = clang_getDiagnosticCategoryName(CategoryID);
330          if (NeedBracket)
331            Out << " [";
332          if (NeedComma)
333            Out << ", ";
334          Out << clang_getCString(CategoryName);
335          NeedBracket = false;
336          NeedComma = true;
337          clang_disposeString(CategoryName);
338        }
339      }
340    }
341
342    if (!NeedBracket)
343      Out << "]";
344  }
345
346  return createCXString(Out.str(), true);
347}
348
349unsigned clang_defaultDiagnosticDisplayOptions() {
350  return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
351         CXDiagnostic_DisplayOption;
352}
353
354enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
355  if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
356    return D->getSeverity();
357  return CXDiagnostic_Ignored;
358}
359
360CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
361  if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
362    return D->getLocation();
363  return clang_getNullLocation();
364}
365
366CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
367  if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
368    return D->getSpelling();
369  return createCXString("");
370}
371
372CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
373  if (Disable)
374    *Disable = createCXString("");
375
376  if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
377    return D->getDiagnosticOption(Disable);
378
379  return createCXString("");
380}
381
382unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
383  if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
384    return D->getCategory();
385  return 0;
386}
387
388CXString clang_getDiagnosticCategoryName(unsigned Category) {
389  return createCXString(DiagnosticIDs::getCategoryNameFromID(Category));
390}
391
392unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
393  if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
394    return D->getNumRanges();
395  return 0;
396}
397
398CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
399  CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
400  if (!D || Range >= D->getNumRanges())
401    return clang_getNullRange();
402  return D->getRange(Range);
403}
404
405unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
406  if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
407    return D->getNumFixIts();
408  return 0;
409}
410
411CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
412                                  CXSourceRange *ReplacementRange) {
413  CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
414  if (!D || FixIt >= D->getNumFixIts()) {
415    if (ReplacementRange)
416      *ReplacementRange = clang_getNullRange();
417    return createCXString("");
418  }
419  return D->getFixIt(FixIt, ReplacementRange);
420}
421
422void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) {
423  CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags);
424  if (D->isExternallyManaged())
425    delete D;
426}
427
428CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
429                                      unsigned Index) {
430  if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
431    if (Index < D->getNumDiagnostics())
432      return D->getDiagnostic(Index);
433  return 0;
434}
435
436CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) {
437  if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) {
438    CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics();
439    return ChildDiags.empty() ? 0 : (CXDiagnosticSet) &ChildDiags;
440  }
441  return 0;
442}
443
444unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
445  if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags))
446    return D->getNumDiagnostics();
447  return 0;
448}
449
450} // end extern "C"
451