/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/libclang/CIndexInclusionStack.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- CIndexInclusionStack.cpp - Clang-C Source Indexing Library ---------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file defines a callback mechanism for clients to get the inclusion |
10 | | // stack from a translation unit. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "CIndexer.h" |
15 | | #include "CXSourceLocation.h" |
16 | | #include "CXTranslationUnit.h" |
17 | | #include "clang/AST/DeclVisitor.h" |
18 | | #include "clang/Frontend/ASTUnit.h" |
19 | | using namespace clang; |
20 | | |
21 | | namespace { |
22 | | void getInclusions(bool IsLocal, unsigned n, CXTranslationUnit TU, |
23 | 3 | CXInclusionVisitor CB, CXClientData clientData) { |
24 | 3 | ASTUnit *CXXUnit = cxtu::getASTUnit(TU); |
25 | 3 | SourceManager &SM = CXXUnit->getSourceManager(); |
26 | 3 | ASTContext &Ctx = CXXUnit->getASTContext(); |
27 | 3 | SmallVector<CXSourceLocation, 10> InclusionStack; |
28 | 3 | const bool HasPreamble = SM.getPreambleFileID().isValid(); |
29 | | |
30 | 15 | for (unsigned i = 0 ; i < n ; ++i12 ) { |
31 | 12 | bool Invalid = false; |
32 | 12 | const SrcMgr::SLocEntry &SL = |
33 | 12 | IsLocal ? SM.getLocalSLocEntry(i)8 : SM.getLoadedSLocEntry(i, &Invalid)4 ; |
34 | 12 | if (!SL.isFile() || Invalid10 ) |
35 | 2 | continue; |
36 | | |
37 | 10 | const SrcMgr::FileInfo &FI = SL.getFile(); |
38 | 10 | if (!FI.getContentCache().OrigEntry) |
39 | 3 | continue; |
40 | | |
41 | | // If this is the main file, and there is a preamble, skip this SLoc. The |
42 | | // inclusions of the preamble already showed it. |
43 | 7 | SourceLocation L = FI.getIncludeLoc(); |
44 | 7 | if (HasPreamble && CXXUnit->isInMainFileID(L)4 ) |
45 | 1 | continue; |
46 | | |
47 | | // Build the inclusion stack. |
48 | 6 | InclusionStack.clear(); |
49 | 14 | while (L.isValid()) { |
50 | 8 | PresumedLoc PLoc = SM.getPresumedLoc(L); |
51 | 8 | InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L)); |
52 | 8 | L = PLoc.isValid()? PLoc.getIncludeLoc() : SourceLocation()0 ; |
53 | 8 | } |
54 | | |
55 | | // If there is a preamble, the last entry is the "inclusion" of that |
56 | | // preamble into the main file, which has the bogus entry of main.c:1:1 |
57 | 6 | if (HasPreamble && !InclusionStack.empty()3 ) |
58 | 2 | InclusionStack.pop_back(); |
59 | | |
60 | | // Callback to the client. |
61 | | // FIXME: We should have a function to construct CXFiles. |
62 | 6 | CB(static_cast<CXFile>( |
63 | 6 | const_cast<FileEntry *>(FI.getContentCache().OrigEntry)), |
64 | 6 | InclusionStack.data(), InclusionStack.size(), clientData); |
65 | 6 | } |
66 | 3 | } |
67 | | } // namespace |
68 | | |
69 | | void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB, |
70 | 2 | CXClientData clientData) { |
71 | 2 | if (cxtu::isNotUsableTU(TU)) { |
72 | 0 | LOG_BAD_TU(TU); |
73 | 0 | return; |
74 | 0 | } |
75 | | |
76 | 2 | SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager(); |
77 | 2 | const unsigned n = SM.local_sloc_entry_size(); |
78 | | |
79 | | // In the case where all the SLocEntries are in an external source, traverse |
80 | | // those SLocEntries as well. This is the case where we are looking |
81 | | // at the inclusion stack of an AST/PCH file. Also, if we are not looking at |
82 | | // a AST/PCH file, but this file has a pre-compiled preamble, we also need |
83 | | // to look in that file. |
84 | 2 | if (n == 1 || SM.getPreambleFileID().isValid()) { |
85 | 1 | getInclusions(/*IsLocal=*/false, SM.loaded_sloc_entry_size(), TU, CB, |
86 | 1 | clientData); |
87 | 1 | } |
88 | | |
89 | | // Not a PCH/AST file. Note, if there is a preamble, it could still be that |
90 | | // there are #includes in this file (e.g. for any include after the first |
91 | | // declaration). |
92 | 2 | if (n != 1) |
93 | 2 | getInclusions(/*IsLocal=*/true, n, TU, CB, clientData); |
94 | 2 | } |