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