File: Record.h

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (154 lines) | stat: -rw-r--r-- 5,899 bytes parent folder | download | duplicates (2)
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