154 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Where Analysis.h analyzes AST nodes and recorded preprocessor events, this10// 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_H18#define CLANG_INCLUDE_CLEANER_RECORD_H19 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 31namespace clang {32class ASTConsumer;33class ASTContext;34class CompilerInstance;35class Decl;36class FileEntry;37class Preprocessor;38class PPCallbacks;39class FileManager;40 41namespace include_cleaner {42 43/// Captures #include mapping information. It analyses IWYU Pragma comments and44/// other use-instead-like mechanisms (#pragma include_instead) on included45/// files.46///47/// This is a low-level piece being used in the "Location => Header" analysis48/// step to determine the final public header rather than the header directly49/// defines the symbol.50class PragmaIncludes {51public:52 /// Installs an analysing PPCallback and CommentHandler and populates results53 /// to the structure.54 void record(const CompilerInstance &CI);55 56 /// Installs an analysing PPCallback and CommentHandler and populates results57 /// to the structure.58 void record(Preprocessor &P);59 60 /// Returns true if the given #include of the main-file should never be61 /// 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 81private:82 class RecordPragma;83 84 /// The public header mapping by the IWYU private pragma. For private pragmas85 // without public mapping an empty StringRef is stored.86 //87 // !!NOTE: instead of using a FileEntry* to identify the physical file, we88 // deliberately use the UniqueID to ensure the result is stable across89 // 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 it96 /// hasn't been opened before. So store the path and convert it to a97 /// FileEntry by opening the file again through a FileManager.98 ///99 /// We don't use RealPathName, as opening the file through a different name100 /// 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 an111 // always_keep pragma or because user marked particular includes with112 // 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 pragma120};121 122/// Recorded main-file parser events relevant to include-cleaner.123struct 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, even138/// when they occur in the main file (e.g. IWYU pragmas).139struct 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_cleaner151} // namespace clang152 153#endif154