clang: lib/Frontend/HeaderIncludeGen.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
14#include "llvm/ADT/SmallString.h"
15#include "llvm/Support/JSON.h"
16#include "llvm/Support/raw_ostream.h"
17using namespace clang;
18
19namespace {
20class HeaderIncludesCallback : public PPCallbacks {
22 raw_ostream *OutputFile;
24 unsigned CurrentIncludeDepth;
25 bool HasProcessedPredefines;
26 bool OwnsOutputFile;
27 bool ShowAllHeaders;
28 bool ShowDepth;
29 bool MSStyle;
30
31public:
32 HeaderIncludesCallback(const Preprocessor *PP, bool ShowAllHeaders_,
33 raw_ostream *OutputFile_,
35 bool OwnsOutputFile_, bool ShowDepth_, bool MSStyle_)
36 : SM(PP->getSourceManager()), OutputFile(OutputFile_), DepOpts(DepOpts),
37 CurrentIncludeDepth(0), HasProcessedPredefines(false),
38 OwnsOutputFile(OwnsOutputFile_), ShowAllHeaders(ShowAllHeaders_),
39 ShowDepth(ShowDepth_), MSStyle(MSStyle_) {}
40
41 ~HeaderIncludesCallback() override {
42 if (OwnsOutputFile)
43 delete OutputFile;
44 }
45
46 HeaderIncludesCallback(const HeaderIncludesCallback &) = delete;
47 HeaderIncludesCallback &operator=(const HeaderIncludesCallback &) = delete;
48
51 FileID PrevFID) override;
52
55
56private:
59 return false;
60
61
62
63
64 return (HasProcessedPredefines ||
65 (ShowAllHeaders && CurrentIncludeDepth > 2));
66 }
67};
68
69
70
71
72
73
74
75
76
77
78
79class HeaderIncludesJSONCallback : public PPCallbacks {
81 raw_ostream *OutputFile;
82 bool OwnsOutputFile;
84
85public:
86 HeaderIncludesJSONCallback(const Preprocessor *PP, raw_ostream *OutputFile_,
87 bool OwnsOutputFile_)
88 : SM(PP->getSourceManager()), OutputFile(OutputFile_),
89 OwnsOutputFile(OwnsOutputFile_) {}
90
91 ~HeaderIncludesJSONCallback() override {
92 if (OwnsOutputFile)
93 delete OutputFile;
94 }
95
96 HeaderIncludesJSONCallback(const HeaderIncludesJSONCallback &) = delete;
97 HeaderIncludesJSONCallback &
98 operator=(const HeaderIncludesJSONCallback &) = delete;
99
101
104 FileID PrevFID) override;
105
108};
109}
110
112 bool ShowDepth, unsigned CurrentIncludeDepth,
113 bool MSStyle) {
114
116 if (!MSStyle)
118
120 if (MSStyle)
121 Msg += "Note: including file:";
122
123 if (ShowDepth) {
124
125 for (unsigned i = 1; i != CurrentIncludeDepth; ++i)
126 Msg += MSStyle ? ' ' : '.';
127
128 if (!MSStyle)
129 Msg += ' ';
130 }
131 Msg += Pathname;
132 Msg += '\n';
133
134 *OutputFile << Msg;
135 OutputFile->flush();
136}
137
140 bool ShowAllHeaders, StringRef OutputPath,
141 bool ShowDepth, bool MSStyle) {
142 raw_ostream *OutputFile = &llvm::errs();
143 bool OwnsOutputFile = false;
144
145
146 if (MSStyle) {
148 default:
149 llvm_unreachable("Invalid destination for /showIncludes output!");
150 case ShowIncludesDestination::Stderr:
151 OutputFile = &llvm::errs();
152 break;
153 case ShowIncludesDestination::Stdout:
154 OutputFile = &llvm::outs();
155 break;
156 }
157 }
158
159
160 if (!OutputPath.empty()) {
161 std::error_code EC;
162 llvm::raw_fd_ostream *OS = new llvm::raw_fd_ostream(
163 OutputPath.str(), EC,
164 llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF);
165 if (EC) {
167 << EC.message();
168 delete OS;
169 } else {
170 OS->SetUnbuffered();
171 OutputFile = OS;
172 OwnsOutputFile = true;
173 }
174 }
175
178 llvm_unreachable("unexpected header format kind");
181 "header filtering is currently always disabled when output format is"
182 "textual");
183
184
185
186
187
188 for (const auto &Header : DepOpts.ExtraDeps)
189 PrintHeaderInfo(OutputFile, Header.first, ShowDepth, 2, MSStyle);
190 PP.addPPCallbacks(std::make_unique(
191 &PP, ShowAllHeaders, OutputFile, DepOpts, OwnsOutputFile, ShowDepth,
192 MSStyle));
193 break;
194 }
197 "only-direct-system is the only option for filtering");
198 PP.addPPCallbacks(std::make_unique(
199 &PP, OutputFile, OwnsOutputFile));
200 break;
201 }
202 }
203}
204
206 FileChangeReason Reason,
209
210
213 return;
214
215
217 ++CurrentIncludeDepth;
219 if (CurrentIncludeDepth)
220 --CurrentIncludeDepth;
221
222
223
224 if (CurrentIncludeDepth == 1 && !HasProcessedPredefines)
225 HasProcessedPredefines = true;
226
227 return;
228 } else {
229 return;
230 }
231
232 if (!ShouldShowHeader(NewFileType))
233 return;
234
235 unsigned IncludeDepth = CurrentIncludeDepth;
236 if (!HasProcessedPredefines)
237 --IncludeDepth;
238
239
240
242 UserLoc.getFilename() != StringRef("")) {
244 MSStyle);
245 }
246}
247
248void HeaderIncludesCallback::FileSkipped(const FileEntryRef &SkippedFile, const
249 Token &FilenameTok,
252 return;
253
254 if (!ShouldShowHeader(FileType))
255 return;
256
258 CurrentIncludeDepth + 1, MSStyle);
259}
260
261void HeaderIncludesJSONCallback::EndOfMainFile() {
264 SM.getFileManager().makeAbsolutePath(MainFile);
265
266 std::string Str;
267 llvm::raw_string_ostream OS(Str);
268 llvm::json::OStream JOS(OS);
269 JOS.object([&] {
270 JOS.attribute("source", MainFile.c_str());
271 JOS.attributeArray("includes", [&] {
272 llvm::StringSet<> SeenHeaders;
273 for (const std::string &H : IncludedHeaders)
274 if (SeenHeaders.insert(H).second)
275 JOS.value(H);
276 });
277 });
278 OS << "\n";
279
280 if (OutputFile->get_kind() == raw_ostream::OStreamKind::OK_FDStream) {
281 llvm::raw_fd_ostream *FDS = static_cast<llvm::raw_fd_ostream *>(OutputFile);
282 if (auto L = FDS->lock())
283 *OutputFile << Str;
284 } else
285 *OutputFile << Str;
286}
287
288
289
290
293 return SrcMgr::isSystem(NewFileType) && .isInSystemHeader(PrevLoc);
294}
295
296void HeaderIncludesJSONCallback::FileChanged(
301 return;
302
303
304
307 return;
308
310 UserLoc.getFilename() != StringRef(""))
311 IncludedHeaders.push_back(UserLoc.getFilename());
312}
313
314void HeaderIncludesJSONCallback::FileSkipped(
318 return;
319
320 IncludedHeaders.push_back(SkippedFile.getName().str());
321}
llvm::json::OStream & JOS
llvm::MachO::FileType FileType
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
DependencyOutputOptions - Options for controlling the compiler dependency file generation.
ShowIncludesDestination ShowIncludesDest
Destination of cl.exe style /showIncludes info.
HeaderIncludeFormatKind HeaderIncludeFormat
The format of header information.
HeaderIncludeFilteringKind HeaderIncludeFiltering
Determine whether header information should be filtered.
unsigned ShowSkippedHeaderIncludes
With ShowHeaderIncludes, show also includes that were skipped due to the "include guard optimizatio...
std::vector< std::pair< std::string, ExtraDepKind > > ExtraDeps
A list of extra dependencies (filename and kind) to be used for every target.
unsigned IncludeSystemHeaders
Include system header dependencies.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
static std::string Stringify(StringRef Str, bool Charify=false)
Stringify - Convert the specified string into a C string by i) escaping '\' and " characters and ii) ...
This interface provides a way to observe the actions of the preprocessor as it does its thing.
virtual void EndOfMainFile()
Callback invoked when the end of the main file is reached.
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID=FileID())
Callback invoked whenever a source file is entered or exited.
virtual void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok, SrcMgr::CharacteristicKind FileType)
Callback invoked whenever a source file is skipped as the result of header guard optimization.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
DiagnosticsEngine & getDiagnostics() const
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
Token - This structure provides full information about a lexed token.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
The JSON file list parser is used to communicate input to InstallAPI.
@ HIFIL_Only_Direct_System
void AttachHeaderIncludeGen(Preprocessor &PP, const DependencyOutputOptions &DepOpts, bool ShowAllHeaders=false, StringRef OutputPath={}, bool ShowDepth=true, bool MSStyle=false)
AttachHeaderIncludeGen - Create a header include list generator, and attach it to the given preproces...