14#include "llvm/ADT/SmallString.h"
15#include "llvm/Support/JSON.h"
16#include "llvm/Support/raw_ostream.h"
22 raw_ostream *OutputFile;
24 unsigned CurrentIncludeDepth;
25 bool HasProcessedPredefines;
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_) {}
41 ~HeaderIncludesCallback()
override {
46 HeaderIncludesCallback(
const HeaderIncludesCallback &) =
delete;
47 HeaderIncludesCallback &operator=(
const HeaderIncludesCallback &) =
delete;
64 return (HasProcessedPredefines ||
65 (ShowAllHeaders && CurrentIncludeDepth > 2));
79class HeaderIncludesJSONCallback :
public PPCallbacks {
81 raw_ostream *OutputFile;
86 HeaderIncludesJSONCallback(
const Preprocessor *PP, raw_ostream *OutputFile_,
88 :
SM(PP->getSourceManager()), OutputFile(OutputFile_),
89 OwnsOutputFile(OwnsOutputFile_) {}
91 ~HeaderIncludesJSONCallback()
override {
96 HeaderIncludesJSONCallback(
const HeaderIncludesJSONCallback &) =
delete;
97 HeaderIncludesJSONCallback &
98 operator=(
const HeaderIncludesJSONCallback &) =
delete;
114class HeaderIncludesDirectPerFileCallback :
public PPCallbacks {
117 raw_ostream *OutputFile;
119 using DependencyMap = llvm::DenseMap<FileEntryRef, SmallVector<FileEntryRef>>;
120 DependencyMap Dependencies;
123 HeaderIncludesDirectPerFileCallback(
const Preprocessor *PP,
124 raw_ostream *OutputFile_,
125 bool OwnsOutputFile_)
126 :
SM(PP->getSourceManager()), HSI(PP->getHeaderSearchInfo()),
127 OutputFile(OutputFile_), OwnsOutputFile(OwnsOutputFile_) {}
129 ~HeaderIncludesDirectPerFileCallback()
override {
134 HeaderIncludesDirectPerFileCallback(
135 const HeaderIncludesDirectPerFileCallback &) =
delete;
136 HeaderIncludesDirectPerFileCallback &
137 operator=(
const HeaderIncludesDirectPerFileCallback &) =
delete;
145 StringRef RelativePath,
const Module *SuggestedModule,
150 const Module *Imported)
override;
155 bool ShowDepth,
unsigned CurrentIncludeDepth,
164 Msg +=
"Note: including file:";
168 for (
unsigned i = 1; i != CurrentIncludeDepth; ++i)
169 Msg += MSStyle ?
' ' :
'.';
183 bool ShowAllHeaders, StringRef OutputPath,
184 bool ShowDepth,
bool MSStyle) {
185 raw_ostream *OutputFile = &llvm::errs();
186 bool OwnsOutputFile =
false;
192 llvm_unreachable(
"Invalid destination for /showIncludes output!");
193 case ShowIncludesDestination::Stderr:
194 OutputFile = &llvm::errs();
196 case ShowIncludesDestination::Stdout:
197 OutputFile = &llvm::outs();
203 if (!OutputPath.empty()) {
205 llvm::raw_fd_ostream *OS =
new llvm::raw_fd_ostream(
206 OutputPath.str(), EC,
207 llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF);
215 OwnsOutputFile =
true;
221 llvm_unreachable(
"unexpected header format kind");
224 "header filtering is currently always disabled when output format is"
231 for (
const auto &Header : DepOpts.
ExtraDeps)
234 &PP, ShowAllHeaders, OutputFile, DepOpts, OwnsOutputFile, ShowDepth,
241 llvm_unreachable(
"Unknown HeaderIncludeFilteringKind enum");
244 &PP, OutputFile, OwnsOutputFile));
247 PP.
addPPCallbacks(std::make_unique<HeaderIncludesDirectPerFileCallback>(
248 &PP, OutputFile, OwnsOutputFile));
256 FileChangeReason Reason,
267 ++CurrentIncludeDepth;
269 if (CurrentIncludeDepth)
270 --CurrentIncludeDepth;
274 if (CurrentIncludeDepth == 1 && !HasProcessedPredefines)
275 HasProcessedPredefines =
true;
282 if (!ShouldShowHeader(NewFileType))
285 unsigned IncludeDepth = CurrentIncludeDepth;
286 if (!HasProcessedPredefines)
292 UserLoc.
getFilename() != StringRef(
"<command line>")) {
298void HeaderIncludesCallback::FileSkipped(
const FileEntryRef &SkippedFile,
const
308 CurrentIncludeDepth + 1, MSStyle);
311void HeaderIncludesJSONCallback::EndOfMainFile() {
316 SM.getFileManager().makeAbsolutePath(MainFile);
320 llvm::raw_string_ostream OS(Str);
321 llvm::json::OStream
JOS(OS);
323 JOS.attribute(
"source", MainFile.c_str());
324 JOS.attributeArray(
"includes", [&] {
325 llvm::StringSet<> SeenHeaders;
326 for (const std::string &H : IncludedHeaders)
327 if (SeenHeaders.insert(H).second)
333 if (OutputFile->get_kind() == raw_ostream::OStreamKind::OK_FDStream) {
334 llvm::raw_fd_ostream *FDS =
static_cast<llvm::raw_fd_ostream *
>(OutputFile);
335 if (
auto L = FDS->lock())
349void HeaderIncludesJSONCallback::FileChanged(
363 UserLoc.
getFilename() != StringRef(
"<command line>"))
367void HeaderIncludesJSONCallback::FileSkipped(
373 IncludedHeaders.push_back(SkippedFile.
getName().str());
376void HeaderIncludesDirectPerFileCallback::EndOfMainFile() {
377 if (Dependencies.empty())
382 for (
auto F = Dependencies.begin(), FEnd = Dependencies.end(); F != FEnd;
384 SourceFiles.push_back(F->first);
391 llvm::raw_string_ostream OS(Str);
392 llvm::json::OStream
JOS(OS);
394 for (
auto S = SourceFiles.begin(), SE = SourceFiles.end(); S != SE; ++S) {
396 SmallVector<FileEntryRef> &Deps = Dependencies[*S];
397 JOS.attribute(
"source", S->getName().str());
398 JOS.attributeArray(
"includes", [&] {
399 for (unsigned I = 0, N = Deps.size(); I != N; ++I)
400 JOS.value(Deps[I].getName().str());
407 if (OutputFile->get_kind() == raw_ostream::OStreamKind::OK_FDStream) {
408 llvm::raw_fd_ostream *FDS =
static_cast<llvm::raw_fd_ostream *
>(OutputFile);
409 if (
auto L = FDS->lock())
415void HeaderIncludesDirectPerFileCallback::InclusionDirective(
418 StringRef SearchPath, StringRef RelativePath,
const Module *SuggestedModule,
424 if (
SM.isInSystemHeader(
Loc))
430 Dependencies[*FromFile].push_back(*
File);
433void HeaderIncludesDirectPerFileCallback::moduleImport(
SourceLocation ImportLoc,
440 if (
SM.isInSystemHeader(
Loc))
447 HSI.getModuleMap().getModuleMapFileForUniquing(Imported);
451 Dependencies[*FromFile].push_back(*ModuleMapFile);
llvm::json::OStream & JOS
llvm::MachO::FileType FileType
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
Represents a character-granular source range.
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...
Record the location of an inclusion directive, such as an #include or #import statement.
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) ...
Describes a module or submodule.
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.
virtual void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, const Module *Imported)
Callback invoked whenever there was an explicit module-import syntax.
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...