diff options
Diffstat (limited to 'clang/tools/CIndex')
-rw-r--r-- | clang/tools/CIndex/CIndex.cpp | 47 | ||||
-rw-r--r-- | clang/tools/CIndex/CIndex.exports | 3 | ||||
-rw-r--r-- | clang/tools/CIndex/CIndexCodeCompletion.cpp | 22 | ||||
-rw-r--r-- | clang/tools/CIndex/CIndexDiagnostic.cpp | 85 | ||||
-rw-r--r-- | clang/tools/CIndex/CIndexer.h | 12 |
5 files changed, 149 insertions, 20 deletions
diff --git a/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index 61e9210aa50..5eddee45b2c 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/tools/CIndex/CIndex.cpp @@ -27,6 +27,7 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/System/Program.h" +#include "llvm/System/Signals.h" // Needed to define L_TMPNAM on some systems. #include <cstdio> @@ -907,10 +908,13 @@ bool CursorVisitor::VisitAttributes(Decl *D) { } extern "C" { -CXIndex clang_createIndex(int excludeDeclarationsFromPCH) { +CXIndex clang_createIndex(int excludeDeclarationsFromPCH, + int displayDiagnostics) { CIndexer *CIdxr = new CIndexer(); if (excludeDeclarationsFromPCH) CIdxr->setOnlyLocalDecls(); + if (displayDiagnostics) + CIdxr->setDisplayDiagnostics(); return CIdxr; } @@ -997,8 +1001,18 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, // FIXME: Until we have broader testing, just drop the entire AST if we // encountered an error. - if (NumErrors != Diags->getNumErrors()) + if (NumErrors != Diags->getNumErrors()) { + if (CXXIdx->getDisplayDiagnostics()) { + for (ASTUnit::diag_iterator D = Unit->diag_begin(), + DEnd = Unit->diag_end(); + D != DEnd; ++D) { + CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOptions()); + clang_displayDiagnostic(&Diag, stderr, + clang_defaultDiagnosticDisplayOptions()); + } + } return 0; + } return Unit.take(); } @@ -1089,18 +1103,35 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, RemappedFiles.data(), RemappedFiles.size(), /*CaptureDiagnostics=*/true); - if (ATU) - ATU->unlinkTemporaryFile(); - - // FIXME: Currently we don't report diagnostics on invalid ASTs. if (ATU) { LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files, ATU->getFileManager(), ATU->getSourceManager(), ATU->getDiagnostics()); + } else if (CXXIdx->getDisplayDiagnostics()) { + // We failed to load the ASTUnit, but we can still deserialize the + // diagnostics and emit them. + FileManager FileMgr; + SourceManager SourceMgr; + // FIXME: Faked LangOpts! + LangOptions LangOpts; + llvm::SmallVector<StoredDiagnostic, 4> Diags; + LoadSerializedDiagnostics(DiagnosticsFile, + num_unsaved_files, unsaved_files, + FileMgr, SourceMgr, Diags); + for (llvm::SmallVector<StoredDiagnostic, 4>::iterator D = Diags.begin(), + DEnd = Diags.end(); + D != DEnd; ++D) { + CXStoredDiagnostic Diag(*D, LangOpts); + clang_displayDiagnostic(&Diag, stderr, + clang_defaultDiagnosticDisplayOptions()); + } } + if (ATU) + ATU->unlinkTemporaryFile(); + for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i) TemporaryFiles[i].eraseFromDisk(); @@ -1909,6 +1940,10 @@ void clang_getDefinitionSpellingAndExtent(CXCursor C, *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc()); } +void clang_enableStackTraces(void) { + llvm::sys::PrintStackTraceOnErrorSignal(); +} + } // end: extern "C" //===----------------------------------------------------------------------===// diff --git a/clang/tools/CIndex/CIndex.exports b/clang/tools/CIndex/CIndex.exports index 1c445b74aaa..449bb95a947 100644 --- a/clang/tools/CIndex/CIndex.exports +++ b/clang/tools/CIndex/CIndex.exports @@ -5,12 +5,15 @@ _clang_codeCompleteGetNumDiagnostics _clang_createIndex _clang_createTranslationUnit _clang_createTranslationUnitFromSourceFile +_clang_defaultDiagnosticDisplayOptions +_clang_displayDiagnostic _clang_disposeCodeCompleteResults _clang_disposeDiagnostic _clang_disposeIndex _clang_disposeString _clang_disposeTokens _clang_disposeTranslationUnit +_clang_enableStackTraces _clang_equalCursors _clang_equalLocations _clang_getClangVersion diff --git a/clang/tools/CIndex/CIndexCodeCompletion.cpp b/clang/tools/CIndex/CIndexCodeCompletion.cpp index 9e8946381ae..08510f2e557 100644 --- a/clang/tools/CIndex/CIndexCodeCompletion.cpp +++ b/clang/tools/CIndex/CIndexCodeCompletion.cpp @@ -177,6 +177,9 @@ static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd, /// \brief The CXCodeCompleteResults structure we allocate internally; /// the client only sees the initial CXCodeCompleteResults structure. struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { + AllocatedCXCodeCompleteResults(); + ~AllocatedCXCodeCompleteResults(); + /// \brief The memory buffer from which we parsed the results. We /// retain this buffer because the completion strings point into it. llvm::MemoryBuffer *Buffer; @@ -194,6 +197,16 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { FileManager FileMgr; }; +AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults() + : CXCodeCompleteResults(), Buffer(0) { } + +AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() { + for (unsigned I = 0, N = NumResults; I != N; ++I) + delete (CodeCompletionString *)Results[I].CompletionString; + delete [] Results; + delete Buffer; +} + CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, const char *source_filename, int num_command_line_args, @@ -368,15 +381,6 @@ void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) { AllocatedCXCodeCompleteResults *Results = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn); - - for (unsigned I = 0, N = Results->NumResults; I != N; ++I) - delete (CXCompletionString *)Results->Results[I].CompletionString; - delete [] Results->Results; - - Results->Results = 0; - Results->NumResults = 0; - delete Results->Buffer; - Results->Buffer = 0; delete Results; } diff --git a/clang/tools/CIndex/CIndexDiagnostic.cpp b/clang/tools/CIndex/CIndexDiagnostic.cpp index 70676f0e141..07c1983672d 100644 --- a/clang/tools/CIndex/CIndexDiagnostic.cpp +++ b/clang/tools/CIndex/CIndexDiagnostic.cpp @@ -47,6 +47,81 @@ void clang_disposeDiagnostic(CXDiagnostic Diagnostic) { delete Stored; } +void clang_displayDiagnostic(CXDiagnostic Diagnostic, FILE *Out, + unsigned Options) { + if (!Diagnostic || !Out) + return; + + CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic); + + // Ignore diagnostics that should be ignored. + if (Severity == CXDiagnostic_Ignored) + return; + + if (Options & CXDiagnostic_DisplaySourceLocation) { + // Print source location (file:line), along with optional column + // and source ranges. + CXFile File; + unsigned Line, Column; + clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic), + &File, &Line, &Column, 0); + if (File) { + CXString FName = clang_getFileName(File); + fprintf(Out, "%s:%d:", clang_getCString(FName), Line); + clang_disposeString(FName); + if (Options & CXDiagnostic_DisplayColumn) + fprintf(Out, "%d:", Column); + + if (Options & CXDiagnostic_DisplaySourceRanges) { + unsigned N = clang_getDiagnosticNumRanges(Diagnostic); + bool PrintedRange = false; + for (unsigned I = 0; I != N; ++I) { + CXFile StartFile, EndFile; + CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I); + + unsigned StartLine, StartColumn, EndLine, EndColumn; + clang_getInstantiationLocation(clang_getRangeStart(Range), + &StartFile, &StartLine, &StartColumn, + 0); + clang_getInstantiationLocation(clang_getRangeEnd(Range), + &EndFile, &EndLine, &EndColumn, 0); + + if (StartFile != EndFile || StartFile != File) + continue; + + fprintf(Out, "{%d:%d-%d:%d}", StartLine, StartColumn, + EndLine, EndColumn); + PrintedRange = true; + } + if (PrintedRange) + fprintf(Out, ":"); + } + } + + fprintf(Out, " "); + } + + /* Print warning/error/etc. */ + switch (Severity) { + case CXDiagnostic_Ignored: assert(0 && "impossible"); break; + case CXDiagnostic_Note: fprintf(Out, "note: "); break; + case CXDiagnostic_Warning: fprintf(Out, "warning: "); break; + case CXDiagnostic_Error: fprintf(Out, "error: "); break; + case CXDiagnostic_Fatal: fprintf(Out, "fatal error: "); break; + } + + CXString Text = clang_getDiagnosticSpelling(Diagnostic); + if (clang_getCString(Text)) + fprintf(Out, "%s\n", clang_getCString(Text)); + else + fprintf(Out, "<no diagnostic text>\n"); + clang_disposeString(Text); +} + +unsigned clang_defaultDiagnosticDisplayOptions() { + return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn; +} + enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) { CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag); if (!StoredDiag) @@ -204,15 +279,18 @@ void clang::LoadSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath, Diags.push_back(StoredDiagnostic(Diagnostic::Fatal, (Twine("could not remap from missing file ") + unsaved_files[I].Filename).str())); + delete F; return; } MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(unsaved_files[I].Contents, unsaved_files[I].Contents + unsaved_files[I].Length); - if (!Buffer) + if (!Buffer) { + delete F; return; - + } + SourceMgr.overrideFileContents(File, Buffer); } @@ -224,8 +302,9 @@ void clang::LoadSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath, StoredDiagnostic Stored = StoredDiagnostic::Deserialize(FileMgr, SourceMgr, Memory, MemoryEnd); if (!Stored) - return; + break; Diags.push_back(Stored); } + delete F; } diff --git a/clang/tools/CIndex/CIndexer.h b/clang/tools/CIndex/CIndexer.h index d559f138647..1fa3ca93876 100644 --- a/clang/tools/CIndex/CIndexer.h +++ b/clang/tools/CIndex/CIndexer.h @@ -34,11 +34,14 @@ namespace cxstring { class CIndexer { bool UseExternalASTGeneration; bool OnlyLocalDecls; - + bool DisplayDiagnostics; + llvm::sys::Path ClangPath; public: - CIndexer() : UseExternalASTGeneration(false), OnlyLocalDecls(false) { } + CIndexer() + : UseExternalASTGeneration(false), OnlyLocalDecls(false), + DisplayDiagnostics(false) { } /// \brief Whether we only want to see "local" declarations (that did not /// come from a previous precompiled header). If false, we want to see all @@ -46,6 +49,11 @@ public: bool getOnlyLocalDecls() const { return OnlyLocalDecls; } void setOnlyLocalDecls(bool Local = true) { OnlyLocalDecls = Local; } + bool getDisplayDiagnostics() const { return DisplayDiagnostics; } + void setDisplayDiagnostics(bool Display = true) { + DisplayDiagnostics = Display; + } + bool getUseExternalASTGeneration() const { return UseExternalASTGeneration; } void setUseExternalASTGeneration(bool Value) { UseExternalASTGeneration = Value; |