]> granicus.if.org Git - clang/commitdiff
Show inclusions from a preamble in clang_getInclusions.
authorErik Verbruggen <erikjv@me.com>
Wed, 6 Jan 2016 15:12:51 +0000 (15:12 +0000)
committerErik Verbruggen <erikjv@me.com>
Wed, 6 Jan 2016 15:12:51 +0000 (15:12 +0000)
When reparsing a translation unit with preamble generation turned on,
no includes are found. This is due to the fact that all SLocs from
AST/PCH files are skipped as they are 'loaded', and inclusions from a
preamble are also 'loaded'. So, in case a file has a preamble, it first
needs to process those loaded inclusions, and then check for any local
inclusions. This latter one is for any includes that are not part of the
preamble, like includes half-way through a file.

This fixes PR24748.

Differential Revision: http://reviews.llvm.org/D14329

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@256939 91177308-0d34-0410-b5e6-96231b3b80d8

test/Index/cindex-test-inclusions.c
tools/c-index-test/c-index-test.c
tools/libclang/CIndexInclusionStack.cpp

index 9c7de2e2c63d92fb5daea1383b7a0b02743cc048..b85cd24f074756a6764a30136522ff895a180fa3 100644 (file)
 // CHECK: included by:
 // CHECK: include_test.h:1:10
 // CHECK: cindex-test-inclusions.c:3:10
+
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-inclusion-stack-source %s 2>&1 | FileCheck -check-prefix=REPARSE %s
+// REPARSE: include_test_2.h
+// REPARSE: included by:
+// REPARSE: include_test.h:1:10
+// REPARSE: cindex-test-inclusions.c:3:10
+// REPARSE: include_test.h
+// REPARSE: included by:
+// REPARSE: cindex-test-inclusions.c:3:10
+// REPARSE: cindex-test-inclusions.c
+// REPARSE: included by:
index 48f22eb4bbf656fa62c244c1a5f1a8bc921c8def..8336491c0158d56d30c6ba8f58210c1169e6c8ae 100644 (file)
@@ -1593,6 +1593,8 @@ int perform_test_load_source(int argc, const char **argv,
   int num_unsaved_files = 0;
   enum CXErrorCode Err;
   int result;
+  unsigned Repeats = 0;
+  unsigned I;
 
   Idx = clang_createIndex(/* excludeDeclsFromPCH */
                           (!strcmp(filter, "local") || 
@@ -1609,6 +1611,9 @@ int perform_test_load_source(int argc, const char **argv,
     return -1;
   }
 
+  if (getenv("CINDEXTEST_EDITING"))
+    Repeats = 5;
+
   Err = clang_parseTranslationUnit2(Idx, 0,
                                     argv + num_unsaved_files,
                                     argc - num_unsaved_files,
@@ -1622,6 +1627,22 @@ int perform_test_load_source(int argc, const char **argv,
     return 1;
   }
 
+  for (I = 0; I != Repeats; ++I) {
+    if (checkForErrors(TU) != 0)
+      return -1;
+
+    if (Repeats > 1) {
+      Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
+                                         clang_defaultReparseOptions(TU));
+      if (Err != CXError_Success) {
+        describeLibclangFailure(Err);
+        free_remapped_files(unsaved_files, num_unsaved_files);
+        clang_disposeIndex(Idx);
+        return 1;
+      }
+    }
+  }
+
   result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV,
                              CommentSchemaFile);
   free_remapped_files(unsaved_files, num_unsaved_files);
index 365609b4f37b85e9743635e5ab28de06273d658a..0959374533518a51ec322ad567f37e41dc600579 100644 (file)
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
 
-extern "C" {
-void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
-                         CXClientData clientData) {
-  if (cxtu::isNotUsableTU(TU)) {
-    LOG_BAD_TU(TU);
-    return;
-  }
-
+static void getInclusions(const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const, unsigned n,
+                          CXTranslationUnit TU, CXInclusionVisitor CB,
+                          CXClientData clientData)
+{
   ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
   SourceManager &SM = CXXUnit->getSourceManager();
   ASTContext &Ctx = CXXUnit->getASTContext();
-
   SmallVector<CXSourceLocation, 10> InclusionStack;
-  unsigned n =  SM.local_sloc_entry_size();
-
-  // In the case where all the SLocEntries are in an external source, traverse
-  // those SLocEntries as well.  This is the case where we are looking
-  // at the inclusion stack of an AST/PCH file.
-  const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const;
-  if (n == 1) {
-    Getter = &SourceManager::getLoadedSLocEntry;
-    n = SM.loaded_sloc_entry_size();
-  } else
-    Getter = &SourceManager::getLocalSLocEntry;
+  const bool HasPreamble = SM.getPreambleFileID().isValid();
 
   for (unsigned i = 0 ; i < n ; ++i) {
     bool Invalid = false;
     const SrcMgr::SLocEntry &SL = (SM.*Getter)(i, &Invalid);
-    
+
     if (!SL.isFile() || Invalid)
       continue;
 
     const SrcMgr::FileInfo &FI = SL.getFile();
     if (!FI.getContentCache()->OrigEntry)
       continue;
-    
-    // Build the inclusion stack.
+
+    // If this is the main file, and there is a preamble, skip this SLoc. The
+    // inclusions of the preamble already showed it.
     SourceLocation L = FI.getIncludeLoc();
+    if (HasPreamble && CXXUnit->isInMainFileID(L))
+      continue;
+
+    // Build the inclusion stack.
     InclusionStack.clear();
     while (L.isValid()) {
       PresumedLoc PLoc = SM.getPresumedLoc(L);
       InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L));
       L = PLoc.isValid()? PLoc.getIncludeLoc() : SourceLocation();
     }
-            
+
+    // If there is a preamble, the last entry is the "inclusion" of that
+    // preamble into the main file, which has the bogus entry of main.c:1:1
+    if (HasPreamble && !InclusionStack.empty())
+      InclusionStack.pop_back();
+
     // Callback to the client.
     // FIXME: We should have a function to construct CXFiles.
     CB(static_cast<CXFile>(
-         const_cast<FileEntry *>(FI.getContentCache()->OrigEntry)), 
+         const_cast<FileEntry *>(FI.getContentCache()->OrigEntry)),
        InclusionStack.data(), InclusionStack.size(), clientData);
-  }    
+  }
+}
+
+
+extern "C" {
+void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
+                         CXClientData clientData) {
+  if (cxtu::isNotUsableTU(TU)) {
+    LOG_BAD_TU(TU);
+    return;
+  }
+
+  SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager();
+  const unsigned n =  SM.local_sloc_entry_size();
+
+  // In the case where all the SLocEntries are in an external source, traverse
+  // those SLocEntries as well.  This is the case where we are looking
+  // at the inclusion stack of an AST/PCH file. Also, if we are not looking at
+  // a AST/PCH file, but this file has a pre-compiled preamble, we also need
+  // to look in that file.
+  if (n == 1 || SM.getPreambleFileID().isValid()) {
+    getInclusions(&SourceManager::getLoadedSLocEntry,
+                  SM.loaded_sloc_entry_size(), TU, CB, clientData);
+  }
+
+  // Not a PCH/AST file. Note, if there is a preamble, it could still be that
+  // there are #includes in this file (e.g. for any include after the first
+  // declaration).
+  if (n != 1)
+    getInclusions(&SourceManager::getLocalSLocEntry, n, TU, CB, clientData);
+
 }
 } // end extern C