Home | History | Annotate | Download | only in libclang
      1 //===- CIndexInclusionStack.cpp - Clang-C Source Indexing Library ---------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines a callback mechanism for clients to get the inclusion
     11 // stack from a translation unit.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "CIndexer.h"
     16 #include "CXSourceLocation.h"
     17 #include "CXTranslationUnit.h"
     18 #include "clang/AST/DeclVisitor.h"
     19 #include "clang/Frontend/ASTUnit.h"
     20 #include "llvm/ADT/SmallString.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 using namespace clang;
     23 
     24 extern "C" {
     25 void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
     26                          CXClientData clientData) {
     27   if (cxtu::isNotUsableTU(TU)) {
     28     LOG_BAD_TU(TU);
     29     return;
     30   }
     31 
     32   ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
     33   SourceManager &SM = CXXUnit->getSourceManager();
     34   ASTContext &Ctx = CXXUnit->getASTContext();
     35 
     36   SmallVector<CXSourceLocation, 10> InclusionStack;
     37   unsigned n =  SM.local_sloc_entry_size();
     38 
     39   // In the case where all the SLocEntries are in an external source, traverse
     40   // those SLocEntries as well.  This is the case where we are looking
     41   // at the inclusion stack of an AST/PCH file.
     42   const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const;
     43   if (n == 1) {
     44     Getter = &SourceManager::getLoadedSLocEntry;
     45     n = SM.loaded_sloc_entry_size();
     46   } else
     47     Getter = &SourceManager::getLocalSLocEntry;
     48 
     49   for (unsigned i = 0 ; i < n ; ++i) {
     50     bool Invalid = false;
     51     const SrcMgr::SLocEntry &SL = (SM.*Getter)(i, &Invalid);
     52 
     53     if (!SL.isFile() || Invalid)
     54       continue;
     55 
     56     const SrcMgr::FileInfo &FI = SL.getFile();
     57     if (!FI.getContentCache()->OrigEntry)
     58       continue;
     59 
     60     // Build the inclusion stack.
     61     SourceLocation L = FI.getIncludeLoc();
     62     InclusionStack.clear();
     63     while (L.isValid()) {
     64       PresumedLoc PLoc = SM.getPresumedLoc(L);
     65       InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L));
     66       L = PLoc.isValid()? PLoc.getIncludeLoc() : SourceLocation();
     67     }
     68 
     69     // Callback to the client.
     70     // FIXME: We should have a function to construct CXFiles.
     71     CB(static_cast<CXFile>(
     72          const_cast<FileEntry *>(FI.getContentCache()->OrigEntry)),
     73        InclusionStack.data(), InclusionStack.size(), clientData);
     74   }
     75 }
     76 } // end extern C
     77