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) && SM.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...