[cfe-commits] r154472 - in /cfe/trunk: include/clang/Frontend/ASTUnit.h lib/Frontend/ASTUnit.cpp tools/libclang/CIndex.cpp tools/libclang/CIndexer.h tools/libclang/Indexing.cpp
Argyrios Kyrtzidis
akyrtzi at gmail.com
Tue Apr 10 19:11:16 PDT 2012
Author: akirtzidis
Date: Tue Apr 10 21:11:16 2012
New Revision: 154472
URL: http://llvm.org/viewvc/llvm-project?rev=154472&view=rev
Log:
[libclang] If displayDiagnostics is set (when calling clang_createIndex), make sure to
output the errors that occurred even if we did not get an AST (e.g. because the
PCH failed to load).
Also honor displayDiagnostics in clang_indexSourceFile().
rdar://11203489
Modified:
cfe/trunk/include/clang/Frontend/ASTUnit.h
cfe/trunk/lib/Frontend/ASTUnit.cpp
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/CIndexer.h
cfe/trunk/tools/libclang/Indexing.cpp
Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=154472&r1=154471&r2=154472&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Tue Apr 10 21:11:16 2012
@@ -46,6 +46,7 @@
class ASTReader;
class CodeCompleteConsumer;
class CompilerInvocation;
+class CompilerInstance;
class Decl;
class DiagnosticsEngine;
class FileEntry;
@@ -143,6 +144,10 @@
/// translation unit.
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
+ /// \brief The set of diagnostics produced when failing to parse, e.g. due
+ /// to failure to load the PCH.
+ SmallVector<StoredDiagnostic, 4> FailedParseDiagnostics;
+
/// \brief The number of stored diagnostics that come from the driver
/// itself.
///
@@ -384,7 +389,11 @@
bool AllowRebuild = true,
unsigned MaxLines = 0);
void RealizeTopLevelDeclsFromPreamble();
-
+
+ /// \brief Transfers ownership of the objects (like SourceManager) from
+ /// \param CI to this ASTUnit.
+ void transferASTDataFromCompilerInstance(CompilerInstance &CI);
+
/// \brief Allows us to assert that ASTUnit is not being used concurrently,
/// which is not supported.
///
@@ -663,6 +672,13 @@
/// \param Persistent - if true the returned ASTUnit will be complete.
/// false means the caller is only interested in getting info through the
/// provided \see Action.
+ ///
+ /// \param ErrAST - If non-null and parsing failed without any AST to return
+ /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+ /// mainly to allow the caller to see the diagnostics.
+ /// This will only receive an ASTUnit if a new one was created. If an already
+ /// created ASTUnit was passed in \param Unit then the caller can check that.
+ ///
static ASTUnit *LoadFromCompilerInvocationAction(CompilerInvocation *CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
ASTFrontendAction *Action = 0,
@@ -672,7 +688,8 @@
bool OnlyLocalDecls = false,
bool CaptureDiagnostics = false,
bool PrecompilePreamble = false,
- bool CacheCodeCompletionResults = false);
+ bool CacheCodeCompletionResults = false,
+ OwningPtr<ASTUnit> *ErrAST = 0);
/// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
/// CompilerInvocation object.
@@ -704,7 +721,11 @@
/// lifetime is expected to extend past that of the returned ASTUnit.
///
/// \param ResourceFilesPath - The path to the compiler resource files.
- //
+ ///
+ /// \param ErrAST - If non-null and parsing failed without any AST to return
+ /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+ /// mainly to allow the caller to see the diagnostics.
+ ///
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
// shouldn't need to specify them at construction time.
static ASTUnit *LoadFromCommandLine(const char **ArgBegin,
@@ -719,7 +740,8 @@
bool PrecompilePreamble = false,
TranslationUnitKind TUKind = TU_Complete,
bool CacheCodeCompletionResults = false,
- bool AllowPCHWithCompilerErrors = false);
+ bool AllowPCHWithCompilerErrors = false,
+ OwningPtr<ASTUnit> *ErrAST = 0);
/// \brief Reparse the source files using the same command-line options that
/// were originally used to produce this translation unit.
Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=154472&r1=154471&r2=154472&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Tue Apr 10 21:11:16 2012
@@ -1138,19 +1138,13 @@
}
Act->Execute();
-
- // Steal the created target, context, and preprocessor.
- TheSema.reset(Clang->takeSema());
- Consumer.reset(Clang->takeASTConsumer());
- Ctx = &Clang->getASTContext();
- PP = &Clang->getPreprocessor();
- Clang->setSourceManager(0);
- Clang->setFileManager(0);
- Target = &Clang->getTarget();
- Reader = Clang->getModuleManager();
+
+ transferASTDataFromCompilerInstance(*Clang);
Act->EndSourceFile();
+ FailedParseDiagnostics.clear();
+
return false;
error:
@@ -1159,7 +1153,11 @@
delete OverrideMainBuffer;
SavedMainFileBuffer = 0;
}
-
+
+ // Keep the ownership of the data in the ASTUnit because the client may
+ // want to see the diagnostics.
+ transferASTDataFromCompilerInstance(*Clang);
+ FailedParseDiagnostics.swap(StoredDiagnostics);
StoredDiagnostics.clear();
NumStoredDiagnosticsFromDriver = 0;
return true;
@@ -1647,6 +1645,18 @@
TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
}
+void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
+ // Steal the created target, context, and preprocessor.
+ TheSema.reset(CI.takeSema());
+ Consumer.reset(CI.takeASTConsumer());
+ Ctx = &CI.getASTContext();
+ PP = &CI.getPreprocessor();
+ CI.setSourceManager(0);
+ CI.setFileManager(0);
+ Target = &CI.getTarget();
+ Reader = CI.getModuleManager();
+}
+
StringRef ASTUnit::getMainFileName() const {
return Invocation->getFrontendOpts().Inputs[0].File;
}
@@ -1675,7 +1685,8 @@
bool OnlyLocalDecls,
bool CaptureDiagnostics,
bool PrecompilePreamble,
- bool CacheCodeCompletionResults) {
+ bool CacheCodeCompletionResults,
+ OwningPtr<ASTUnit> *ErrAST) {
assert(CI && "A CompilerInvocation is required");
OwningPtr<ASTUnit> OwnAST;
@@ -1770,8 +1781,13 @@
llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
ActCleanup(TrackerAct.get());
- if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
+ if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
+ AST->transferASTDataFromCompilerInstance(*Clang);
+ if (OwnAST && ErrAST)
+ ErrAST->swap(OwnAST);
+
return 0;
+ }
if (Persistent && !TrackerAct) {
Clang->getPreprocessor().addPPCallbacks(
@@ -1784,16 +1800,9 @@
Clang->setASTConsumer(new MultiplexConsumer(Consumers));
}
Act->Execute();
-
+
// Steal the created target, context, and preprocessor.
- AST->TheSema.reset(Clang->takeSema());
- AST->Consumer.reset(Clang->takeASTConsumer());
- AST->Ctx = &Clang->getASTContext();
- AST->PP = &Clang->getPreprocessor();
- Clang->setSourceManager(0);
- Clang->setFileManager(0);
- AST->Target = &Clang->getTarget();
- AST->Reader = Clang->getModuleManager();
+ AST->transferASTDataFromCompilerInstance(*Clang);
Act->EndSourceFile();
@@ -1872,7 +1881,8 @@
bool PrecompilePreamble,
TranslationUnitKind TUKind,
bool CacheCodeCompletionResults,
- bool AllowPCHWithCompilerErrors) {
+ bool AllowPCHWithCompilerErrors,
+ OwningPtr<ASTUnit> *ErrAST) {
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
@@ -1936,7 +1946,17 @@
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get());
- return AST->LoadFromCompilerInvocation(PrecompilePreamble) ? 0 : AST.take();
+ if (AST->LoadFromCompilerInvocation(PrecompilePreamble)) {
+ // Some error occurred, if caller wants to examine diagnostics, pass it the
+ // ASTUnit.
+ if (ErrAST) {
+ AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);
+ ErrAST->swap(AST);
+ }
+ return 0;
+ }
+
+ return AST.take();
}
bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=154472&r1=154471&r2=154472&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Apr 10 21:11:16 2012
@@ -51,6 +51,7 @@
using namespace clang::cxcursor;
using namespace clang::cxstring;
using namespace clang::cxtu;
+using namespace clang::cxindex;
CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *TU) {
if (!TU)
@@ -2482,7 +2483,28 @@
unsaved_files, num_unsaved_files,
Options);
}
-
+
+void cxindex::printDiagsToStderr(ASTUnit *Unit) {
+ if (!Unit)
+ return;
+
+ for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
+ DEnd = Unit->stored_diag_end();
+ D != DEnd; ++D) {
+ CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOpts());
+ CXString Msg = clang_formatDiagnostic(&Diag,
+ clang_defaultDiagnosticDisplayOptions());
+ fprintf(stderr, "%s\n", clang_getCString(Msg));
+ clang_disposeString(Msg);
+ }
+#ifdef LLVM_ON_WIN32
+ // On Windows, force a flush, since there may be multiple copies of
+ // stderr and stdout in the file system, all with different buffers
+ // but writing to the same device.
+ fflush(stderr);
+#endif
+}
+
struct ParseTranslationUnitInfo {
CXIndex CIdx;
const char *source_filename;
@@ -2587,6 +2609,7 @@
}
unsigned NumErrors = Diags->getClient()->getNumErrors();
+ OwningPtr<ASTUnit> ErrUnit;
OwningPtr<ASTUnit> Unit(
ASTUnit::LoadFromCommandLine(Args->size() ? &(*Args)[0] : 0
/* vector::data() not portable */,
@@ -2601,27 +2624,13 @@
PrecompilePreamble,
TUKind,
CacheCodeCompetionResults,
- /*AllowPCHWithCompilerErrors=*/true));
+ /*AllowPCHWithCompilerErrors=*/true,
+ &ErrUnit));
if (NumErrors != Diags->getClient()->getNumErrors()) {
// Make sure to check that 'Unit' is non-NULL.
- if (CXXIdx->getDisplayDiagnostics() && Unit.get()) {
- for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
- DEnd = Unit->stored_diag_end();
- D != DEnd; ++D) {
- CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOpts());
- CXString Msg = clang_formatDiagnostic(&Diag,
- clang_defaultDiagnosticDisplayOptions());
- fprintf(stderr, "%s\n", clang_getCString(Msg));
- clang_disposeString(Msg);
- }
-#ifdef LLVM_ON_WIN32
- // On Windows, force a flush, since there may be multiple copies of
- // stderr and stdout in the file system, all with different buffers
- // but writing to the same device.
- fflush(stderr);
-#endif
- }
+ if (CXXIdx->getDisplayDiagnostics())
+ printDiagsToStderr(Unit ? Unit.get() : ErrUnit.get());
}
PTUI->result = MakeCXTranslationUnit(CXXIdx, Unit.take());
Modified: cfe/trunk/tools/libclang/CIndexer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexer.h?rev=154472&r1=154471&r2=154472&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexer.h (original)
+++ cfe/trunk/tools/libclang/CIndexer.h Tue Apr 10 21:11:16 2012
@@ -25,6 +25,7 @@
}
namespace clang {
+ class ASTUnit;
class CIndexer {
bool OnlyLocalDecls;
@@ -94,6 +95,10 @@
/// \brief Print libclang's resource usage to standard error.
void PrintLibclangResourceUsage(CXTranslationUnit TU);
+
+ namespace cxindex {
+ void printDiagsToStderr(ASTUnit *Unit);
+ }
}
#endif
Modified: cfe/trunk/tools/libclang/Indexing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/Indexing.cpp?rev=154472&r1=154471&r2=154472&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/Indexing.cpp (original)
+++ cfe/trunk/tools/libclang/Indexing.cpp Tue Apr 10 21:11:16 2012
@@ -388,7 +388,8 @@
}
}
- Unit = ASTUnit::LoadFromCompilerInvocationAction(CInvok.getPtr(), Diags,
+ DiagnosticErrorTrap DiagTrap(*Diags);
+ bool Success = ASTUnit::LoadFromCompilerInvocationAction(CInvok.getPtr(), Diags,
IndexAction.get(),
Unit,
Persistent,
@@ -397,7 +398,10 @@
/*CaptureDiagnostics=*/true,
PrecompilePreamble,
CacheCodeCompletionResults);
- if (!Unit)
+ if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
+ printDiagsToStderr(Unit);
+
+ if (!Success)
return;
if (out_TU)
More information about the cfe-commits
mailing list