Re-apply my diagnostics-capture patch for CIndex, with some tweaks to
try to address the msvc failures.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96624 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 61e9210..5eddee4 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/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 @@
}
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 @@
// 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 @@
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 @@
*endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
}
+void clang_enableStackTraces(void) {
+ llvm::sys::PrintStackTraceOnErrorSignal();
+}
+
} // end: extern "C"
//===----------------------------------------------------------------------===//
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index 1c445b7..449bb95 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -5,12 +5,15 @@
_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/tools/CIndex/CIndexCodeCompletion.cpp b/tools/CIndex/CIndexCodeCompletion.cpp
index 9e89463..08510f2 100644
--- a/tools/CIndex/CIndexCodeCompletion.cpp
+++ b/tools/CIndex/CIndexCodeCompletion.cpp
@@ -177,6 +177,9 @@
/// \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 @@
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 @@
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/tools/CIndex/CIndexDiagnostic.cpp b/tools/CIndex/CIndexDiagnostic.cpp
index 70676f0..07c1983 100644
--- a/tools/CIndex/CIndexDiagnostic.cpp
+++ b/tools/CIndex/CIndexDiagnostic.cpp
@@ -47,6 +47,81 @@
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 @@
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 @@
StoredDiagnostic Stored = StoredDiagnostic::Deserialize(FileMgr, SourceMgr,
Memory, MemoryEnd);
if (!Stored)
- return;
+ break;
Diags.push_back(Stored);
}
+ delete F;
}
diff --git a/tools/CIndex/CIndexer.h b/tools/CIndex/CIndexer.h
index d559f13..1fa3ca9 100644
--- a/tools/CIndex/CIndexer.h
+++ b/tools/CIndex/CIndexer.h
@@ -34,11 +34,14 @@
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 @@
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;