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