1 | //===--- Record.h - Record compiler events ------------------------- C++-*-===// |
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 | // Where Analysis.h analyzes AST nodes and recorded preprocessor events, this |
10 | // file defines ways to capture AST and preprocessor information from a parse. |
11 | // |
12 | // These are the simplest way to connect include-cleaner logic to the parser, |
13 | // but other ways are possible (for example clangd records includes separately). |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #ifndef CLANG_INCLUDE_CLEANER_RECORD_H |
18 | #define CLANG_INCLUDE_CLEANER_RECORD_H |
19 | |
20 | #include "clang-include-cleaner/Types.h" |
21 | #include "clang/Basic/SourceLocation.h" |
22 | #include "llvm/ADT/DenseMap.h" |
23 | #include "llvm/ADT/DenseSet.h" |
24 | #include "llvm/ADT/SmallVector.h" |
25 | #include "llvm/ADT/StringRef.h" |
26 | #include "llvm/Support/Allocator.h" |
27 | #include "llvm/Support/FileSystem/UniqueID.h" |
28 | #include <memory> |
29 | #include <vector> |
30 | |
31 | namespace clang { |
32 | class ASTConsumer; |
33 | class ASTContext; |
34 | class CompilerInstance; |
35 | class Decl; |
36 | class FileEntry; |
37 | class Preprocessor; |
38 | class PPCallbacks; |
39 | class FileManager; |
40 | |
41 | namespace include_cleaner { |
42 | |
43 | /// Captures #include mapping information. It analyses IWYU Pragma comments and |
44 | /// other use-instead-like mechanisms (#pragma include_instead) on included |
45 | /// files. |
46 | /// |
47 | /// This is a low-level piece being used in the "Location => Header" analysis |
48 | /// step to determine the final public header rather than the header directly |
49 | /// defines the symbol. |
50 | class PragmaIncludes { |
51 | public: |
52 | /// Installs an analysing PPCallback and CommentHandler and populates results |
53 | /// to the structure. |
54 | void record(const CompilerInstance &CI); |
55 | |
56 | /// Installs an analysing PPCallback and CommentHandler and populates results |
57 | /// to the structure. |
58 | void record(Preprocessor &P); |
59 | |
60 | /// Returns true if the given #include of the main-file should never be |
61 | /// removed. |
62 | bool shouldKeep(const FileEntry *FE) const; |
63 | |
64 | /// Returns the public mapping include for the given physical header file. |
65 | /// Returns "" if there is none. |
66 | llvm::StringRef getPublic(const FileEntry *File) const; |
67 | |
68 | /// Returns all direct exporter headers for the given header file. |
69 | /// Returns empty if there is none. |
70 | llvm::SmallVector<FileEntryRef> getExporters(const FileEntry *File, |
71 | FileManager &FM) const; |
72 | llvm::SmallVector<FileEntryRef> getExporters(tooling::stdlib::Header, |
73 | FileManager &FM) const; |
74 | |
75 | /// Returns true if the given file is a self-contained file. |
76 | bool isSelfContained(const FileEntry *File) const; |
77 | |
78 | /// Returns true if the given file is marked with the IWYU private pragma. |
79 | bool isPrivate(const FileEntry *File) const; |
80 | |
81 | private: |
82 | class RecordPragma; |
83 | |
84 | /// The public header mapping by the IWYU private pragma. For private pragmas |
85 | // without public mapping an empty StringRef is stored. |
86 | // |
87 | // !!NOTE: instead of using a FileEntry* to identify the physical file, we |
88 | // deliberately use the UniqueID to ensure the result is stable across |
89 | // FileManagers (for clangd's preamble and main-file builds). |
90 | llvm::DenseMap<llvm::sys::fs::UniqueID, llvm::StringRef /*VerbatimSpelling*/> |
91 | IWYUPublic; |
92 | |
93 | /// A reverse map from the underlying header to its exporter headers. |
94 | /// |
95 | /// There's no way to get a FileEntry from a UniqueID, especially when it |
96 | /// hasn't been opened before. So store the path and convert it to a |
97 | /// FileEntry by opening the file again through a FileManager. |
98 | /// |
99 | /// We don't use RealPathName, as opening the file through a different name |
100 | /// changes its preferred name. Clearly this is fragile! |
101 | llvm::DenseMap<llvm::sys::fs::UniqueID, |
102 | llvm::SmallVector</*FileEntry::getName()*/ llvm::StringRef>> |
103 | IWYUExportBy; |
104 | llvm::DenseMap<tooling::stdlib::Header, |
105 | llvm::SmallVector</*FileEntry::getName()*/ llvm::StringRef>> |
106 | StdIWYUExportBy; |
107 | |
108 | /// Contains all non self-contained files detected during the parsing. |
109 | llvm::DenseSet<llvm::sys::fs::UniqueID> NonSelfContainedFiles; |
110 | // Files whose inclusions shouldn't be dropped. E.g. because they have an |
111 | // always_keep pragma or because user marked particular includes with |
112 | // keep/export pragmas in the main file. |
113 | llvm::DenseSet<llvm::sys::fs::UniqueID> ShouldKeep; |
114 | |
115 | /// Owns the strings. |
116 | /// Each record() pushes a new one, while keeping all the old strings alive. |
117 | std::vector<std::shared_ptr<const llvm::BumpPtrAllocator>> Arena; |
118 | |
119 | // FIXME: add support for clang use_instead pragma |
120 | }; |
121 | |
122 | /// Recorded main-file parser events relevant to include-cleaner. |
123 | struct RecordedAST { |
124 | /// The consumer (when installed into clang) tracks declarations in `*this`. |
125 | std::unique_ptr<ASTConsumer> record(); |
126 | |
127 | ASTContext *Ctx = nullptr; |
128 | /// The set of declarations written at file scope inside the main file. |
129 | /// |
130 | /// These are the roots of the subtrees that should be traversed to find uses. |
131 | /// (Traversing the TranslationUnitDecl would find uses inside headers!) |
132 | std::vector<Decl *> Roots; |
133 | }; |
134 | |
135 | /// Recorded main-file preprocessor events relevant to include-cleaner. |
136 | /// |
137 | /// This doesn't include facts that we record globally for the whole TU, even |
138 | /// when they occur in the main file (e.g. IWYU pragmas). |
139 | struct RecordedPP { |
140 | /// The callback (when installed into clang) tracks macros/includes in this. |
141 | std::unique_ptr<PPCallbacks> record(const Preprocessor &PP); |
142 | |
143 | /// Describes where macros were used in the main file. |
144 | std::vector<SymbolReference> MacroReferences; |
145 | |
146 | /// The include directives seen in the main file. |
147 | include_cleaner::Includes Includes; |
148 | }; |
149 | |
150 | } // namespace include_cleaner |
151 | } // namespace clang |
152 | |
153 | #endif |
154 | |