[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