Mercurial > hg > CbC > CbC_llvm
comparison clang/lib/Frontend/Rewrite/InclusionRewriter.cpp @ 221:79ff65ed7e25
LLVM12 Original
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 15 Jun 2021 19:15:29 +0900 |
parents | 1d019706d866 |
children | c4bab56944e8 |
comparison
equal
deleted
inserted
replaced
220:42394fc6a535 | 221:79ff65ed7e25 |
---|---|
38 }; | 38 }; |
39 Preprocessor &PP; ///< Used to find inclusion directives. | 39 Preprocessor &PP; ///< Used to find inclusion directives. |
40 SourceManager &SM; ///< Used to read and manage source files. | 40 SourceManager &SM; ///< Used to read and manage source files. |
41 raw_ostream &OS; ///< The destination stream for rewritten contents. | 41 raw_ostream &OS; ///< The destination stream for rewritten contents. |
42 StringRef MainEOL; ///< The line ending marker to use. | 42 StringRef MainEOL; ///< The line ending marker to use. |
43 const llvm::MemoryBuffer *PredefinesBuffer; ///< The preprocessor predefines. | 43 llvm::MemoryBufferRef PredefinesBuffer; ///< The preprocessor predefines. |
44 bool ShowLineMarkers; ///< Show #line markers. | 44 bool ShowLineMarkers; ///< Show #line markers. |
45 bool UseLineDirectives; ///< Use of line directives or line markers. | 45 bool UseLineDirectives; ///< Use of line directives or line markers. |
46 /// Tracks where inclusions that change the file are found. | 46 /// Tracks where inclusions that change the file are found. |
47 std::map<unsigned, IncludedFile> FileIncludes; | 47 std::map<SourceLocation, IncludedFile> FileIncludes; |
48 /// Tracks where inclusions that import modules are found. | 48 /// Tracks where inclusions that import modules are found. |
49 std::map<unsigned, const Module *> ModuleIncludes; | 49 std::map<SourceLocation, const Module *> ModuleIncludes; |
50 /// Tracks where inclusions that enter modules (in a module build) are found. | 50 /// Tracks where inclusions that enter modules (in a module build) are found. |
51 std::map<unsigned, const Module *> ModuleEntryIncludes; | 51 std::map<SourceLocation, const Module *> ModuleEntryIncludes; |
52 /// Tracks where #if and #elif directives get evaluated and whether to true. | 52 /// Tracks where #if and #elif directives get evaluated and whether to true. |
53 std::map<unsigned, bool> IfConditions; | 53 std::map<SourceLocation, bool> IfConditions; |
54 /// Used transitively for building up the FileIncludes mapping over the | 54 /// Used transitively for building up the FileIncludes mapping over the |
55 /// various \c PPCallbacks callbacks. | 55 /// various \c PPCallbacks callbacks. |
56 SourceLocation LastInclusionLocation; | 56 SourceLocation LastInclusionLocation; |
57 public: | 57 public: |
58 InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, | 58 InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, |
59 bool UseLineDirectives); | 59 bool UseLineDirectives); |
60 void Process(FileID FileId, SrcMgr::CharacteristicKind FileType, | 60 void Process(FileID FileId, SrcMgr::CharacteristicKind FileType, |
61 const DirectoryLookup *DirLookup); | 61 const DirectoryLookup *DirLookup); |
62 void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) { | 62 void setPredefinesBuffer(const llvm::MemoryBufferRef &Buf) { |
63 PredefinesBuffer = Buf; | 63 PredefinesBuffer = Buf; |
64 } | 64 } |
65 void detectMainFileEOL(); | 65 void detectMainFileEOL(); |
66 void handleModuleBegin(Token &Tok) { | 66 void handleModuleBegin(Token &Tok) { |
67 assert(Tok.getKind() == tok::annot_module_begin); | 67 assert(Tok.getKind() == tok::annot_module_begin); |
68 ModuleEntryIncludes.insert({Tok.getLocation().getRawEncoding(), | 68 ModuleEntryIncludes.insert( |
69 (Module *)Tok.getAnnotationValue()}); | 69 {Tok.getLocation(), (Module *)Tok.getAnnotationValue()}); |
70 } | 70 } |
71 private: | 71 private: |
72 void FileChanged(SourceLocation Loc, FileChangeReason Reason, | 72 void FileChanged(SourceLocation Loc, FileChangeReason Reason, |
73 SrcMgr::CharacteristicKind FileType, | 73 SrcMgr::CharacteristicKind FileType, |
74 FileID PrevFID) override; | 74 FileID PrevFID) override; |
86 ConditionValueKind ConditionValue, SourceLocation IfLoc) override; | 86 ConditionValueKind ConditionValue, SourceLocation IfLoc) override; |
87 void WriteLineInfo(StringRef Filename, int Line, | 87 void WriteLineInfo(StringRef Filename, int Line, |
88 SrcMgr::CharacteristicKind FileType, | 88 SrcMgr::CharacteristicKind FileType, |
89 StringRef Extra = StringRef()); | 89 StringRef Extra = StringRef()); |
90 void WriteImplicitModuleImport(const Module *Mod); | 90 void WriteImplicitModuleImport(const Module *Mod); |
91 void OutputContentUpTo(const MemoryBuffer &FromFile, | 91 void OutputContentUpTo(const MemoryBufferRef &FromFile, unsigned &WriteFrom, |
92 unsigned &WriteFrom, unsigned WriteTo, | 92 unsigned WriteTo, StringRef EOL, int &lines, |
93 StringRef EOL, int &lines, | |
94 bool EnsureNewline); | 93 bool EnsureNewline); |
95 void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken, | 94 void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken, |
96 const MemoryBuffer &FromFile, StringRef EOL, | 95 const MemoryBufferRef &FromFile, StringRef EOL, |
97 unsigned &NextToWrite, int &Lines); | 96 unsigned &NextToWrite, int &Lines); |
98 const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const; | 97 const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const; |
99 const Module *FindModuleAtLocation(SourceLocation Loc) const; | 98 const Module *FindModuleAtLocation(SourceLocation Loc) const; |
100 const Module *FindEnteredModule(SourceLocation Loc) const; | 99 const Module *FindEnteredModule(SourceLocation Loc) const; |
101 bool IsIfAtLocationTrue(SourceLocation Loc) const; | 100 bool IsIfAtLocationTrue(SourceLocation Loc) const; |
107 /// Initializes an InclusionRewriter with a \p PP source and \p OS destination. | 106 /// Initializes an InclusionRewriter with a \p PP source and \p OS destination. |
108 InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS, | 107 InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS, |
109 bool ShowLineMarkers, | 108 bool ShowLineMarkers, |
110 bool UseLineDirectives) | 109 bool UseLineDirectives) |
111 : PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"), | 110 : PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"), |
112 PredefinesBuffer(nullptr), ShowLineMarkers(ShowLineMarkers), | 111 ShowLineMarkers(ShowLineMarkers), UseLineDirectives(UseLineDirectives), |
113 UseLineDirectives(UseLineDirectives), | |
114 LastInclusionLocation(SourceLocation()) {} | 112 LastInclusionLocation(SourceLocation()) {} |
115 | 113 |
116 /// Write appropriate line information as either #line directives or GNU line | 114 /// Write appropriate line information as either #line directives or GNU line |
117 /// markers depending on what mode we're in, including the \p Filename and | 115 /// markers depending on what mode we're in, including the \p Filename and |
118 /// \p Line we are located at, using the specified \p EOL line separator, and | 116 /// \p Line we are located at, using the specified \p EOL line separator, and |
162 if (LastInclusionLocation.isInvalid()) | 160 if (LastInclusionLocation.isInvalid()) |
163 // we didn't reach this file (eg: the main file) via an inclusion directive | 161 // we didn't reach this file (eg: the main file) via an inclusion directive |
164 return; | 162 return; |
165 FileID Id = FullSourceLoc(Loc, SM).getFileID(); | 163 FileID Id = FullSourceLoc(Loc, SM).getFileID(); |
166 auto P = FileIncludes.insert( | 164 auto P = FileIncludes.insert( |
167 std::make_pair(LastInclusionLocation.getRawEncoding(), | 165 std::make_pair(LastInclusionLocation, |
168 IncludedFile(Id, NewFileType, PP.GetCurDirLookup()))); | 166 IncludedFile(Id, NewFileType, PP.GetCurDirLookup()))); |
169 (void)P; | 167 (void)P; |
170 assert(P.second && "Unexpected revisitation of the same include directive"); | 168 assert(P.second && "Unexpected revisitation of the same include directive"); |
171 LastInclusionLocation = SourceLocation(); | 169 LastInclusionLocation = SourceLocation(); |
172 } | 170 } |
197 StringRef /*SearchPath*/, | 195 StringRef /*SearchPath*/, |
198 StringRef /*RelativePath*/, | 196 StringRef /*RelativePath*/, |
199 const Module *Imported, | 197 const Module *Imported, |
200 SrcMgr::CharacteristicKind FileType){ | 198 SrcMgr::CharacteristicKind FileType){ |
201 if (Imported) { | 199 if (Imported) { |
202 auto P = ModuleIncludes.insert( | 200 auto P = ModuleIncludes.insert(std::make_pair(HashLoc, Imported)); |
203 std::make_pair(HashLoc.getRawEncoding(), Imported)); | |
204 (void)P; | 201 (void)P; |
205 assert(P.second && "Unexpected revisitation of the same include directive"); | 202 assert(P.second && "Unexpected revisitation of the same include directive"); |
206 } else | 203 } else |
207 LastInclusionLocation = HashLoc; | 204 LastInclusionLocation = HashLoc; |
208 } | 205 } |
209 | 206 |
210 void InclusionRewriter::If(SourceLocation Loc, SourceRange ConditionRange, | 207 void InclusionRewriter::If(SourceLocation Loc, SourceRange ConditionRange, |
211 ConditionValueKind ConditionValue) { | 208 ConditionValueKind ConditionValue) { |
212 auto P = IfConditions.insert( | 209 auto P = IfConditions.insert(std::make_pair(Loc, ConditionValue == CVK_True)); |
213 std::make_pair(Loc.getRawEncoding(), ConditionValue == CVK_True)); | |
214 (void)P; | 210 (void)P; |
215 assert(P.second && "Unexpected revisitation of the same if directive"); | 211 assert(P.second && "Unexpected revisitation of the same if directive"); |
216 } | 212 } |
217 | 213 |
218 void InclusionRewriter::Elif(SourceLocation Loc, SourceRange ConditionRange, | 214 void InclusionRewriter::Elif(SourceLocation Loc, SourceRange ConditionRange, |
219 ConditionValueKind ConditionValue, | 215 ConditionValueKind ConditionValue, |
220 SourceLocation IfLoc) { | 216 SourceLocation IfLoc) { |
221 auto P = IfConditions.insert( | 217 auto P = IfConditions.insert(std::make_pair(Loc, ConditionValue == CVK_True)); |
222 std::make_pair(Loc.getRawEncoding(), ConditionValue == CVK_True)); | |
223 (void)P; | 218 (void)P; |
224 assert(P.second && "Unexpected revisitation of the same elif directive"); | 219 assert(P.second && "Unexpected revisitation of the same elif directive"); |
225 } | 220 } |
226 | 221 |
227 /// Simple lookup for a SourceLocation (specifically one denoting the hash in | 222 /// Simple lookup for a SourceLocation (specifically one denoting the hash in |
228 /// an inclusion directive) in the map of inclusion information, FileChanges. | 223 /// an inclusion directive) in the map of inclusion information, FileChanges. |
229 const InclusionRewriter::IncludedFile * | 224 const InclusionRewriter::IncludedFile * |
230 InclusionRewriter::FindIncludeAtLocation(SourceLocation Loc) const { | 225 InclusionRewriter::FindIncludeAtLocation(SourceLocation Loc) const { |
231 const auto I = FileIncludes.find(Loc.getRawEncoding()); | 226 const auto I = FileIncludes.find(Loc); |
232 if (I != FileIncludes.end()) | 227 if (I != FileIncludes.end()) |
233 return &I->second; | 228 return &I->second; |
234 return nullptr; | 229 return nullptr; |
235 } | 230 } |
236 | 231 |
237 /// Simple lookup for a SourceLocation (specifically one denoting the hash in | 232 /// Simple lookup for a SourceLocation (specifically one denoting the hash in |
238 /// an inclusion directive) in the map of module inclusion information. | 233 /// an inclusion directive) in the map of module inclusion information. |
239 const Module * | 234 const Module * |
240 InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const { | 235 InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const { |
241 const auto I = ModuleIncludes.find(Loc.getRawEncoding()); | 236 const auto I = ModuleIncludes.find(Loc); |
242 if (I != ModuleIncludes.end()) | 237 if (I != ModuleIncludes.end()) |
243 return I->second; | 238 return I->second; |
244 return nullptr; | 239 return nullptr; |
245 } | 240 } |
246 | 241 |
247 /// Simple lookup for a SourceLocation (specifically one denoting the hash in | 242 /// Simple lookup for a SourceLocation (specifically one denoting the hash in |
248 /// an inclusion directive) in the map of module entry information. | 243 /// an inclusion directive) in the map of module entry information. |
249 const Module * | 244 const Module * |
250 InclusionRewriter::FindEnteredModule(SourceLocation Loc) const { | 245 InclusionRewriter::FindEnteredModule(SourceLocation Loc) const { |
251 const auto I = ModuleEntryIncludes.find(Loc.getRawEncoding()); | 246 const auto I = ModuleEntryIncludes.find(Loc); |
252 if (I != ModuleEntryIncludes.end()) | 247 if (I != ModuleEntryIncludes.end()) |
253 return I->second; | 248 return I->second; |
254 return nullptr; | 249 return nullptr; |
255 } | 250 } |
256 | 251 |
257 bool InclusionRewriter::IsIfAtLocationTrue(SourceLocation Loc) const { | 252 bool InclusionRewriter::IsIfAtLocationTrue(SourceLocation Loc) const { |
258 const auto I = IfConditions.find(Loc.getRawEncoding()); | 253 const auto I = IfConditions.find(Loc); |
259 if (I != IfConditions.end()) | 254 if (I != IfConditions.end()) |
260 return I->second; | 255 return I->second; |
261 return false; | 256 return false; |
262 } | 257 } |
263 | 258 |
264 /// Detect the likely line ending style of \p FromFile by examining the first | 259 /// Detect the likely line ending style of \p FromFile by examining the first |
265 /// newline found within it. | 260 /// newline found within it. |
266 static StringRef DetectEOL(const MemoryBuffer &FromFile) { | 261 static StringRef DetectEOL(const MemoryBufferRef &FromFile) { |
267 // Detect what line endings the file uses, so that added content does not mix | 262 // Detect what line endings the file uses, so that added content does not mix |
268 // the style. We need to check for "\r\n" first because "\n\r" will match | 263 // the style. We need to check for "\r\n" first because "\n\r" will match |
269 // "\r\n\r\n". | 264 // "\r\n\r\n". |
270 const char *Pos = strchr(FromFile.getBufferStart(), '\n'); | 265 const char *Pos = strchr(FromFile.getBufferStart(), '\n'); |
271 if (!Pos) | 266 if (!Pos) |
276 return "\n\r"; | 271 return "\n\r"; |
277 return "\n"; | 272 return "\n"; |
278 } | 273 } |
279 | 274 |
280 void InclusionRewriter::detectMainFileEOL() { | 275 void InclusionRewriter::detectMainFileEOL() { |
281 bool Invalid; | 276 Optional<MemoryBufferRef> FromFile = *SM.getBufferOrNone(SM.getMainFileID()); |
282 const MemoryBuffer &FromFile = *SM.getBuffer(SM.getMainFileID(), &Invalid); | 277 assert(FromFile); |
283 assert(!Invalid); | 278 if (!FromFile) |
284 if (Invalid) | |
285 return; // Should never happen, but whatever. | 279 return; // Should never happen, but whatever. |
286 MainEOL = DetectEOL(FromFile); | 280 MainEOL = DetectEOL(*FromFile); |
287 } | 281 } |
288 | 282 |
289 /// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at | 283 /// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at |
290 /// \p WriteTo - 1. | 284 /// \p WriteTo - 1. |
291 void InclusionRewriter::OutputContentUpTo(const MemoryBuffer &FromFile, | 285 void InclusionRewriter::OutputContentUpTo(const MemoryBufferRef &FromFile, |
292 unsigned &WriteFrom, unsigned WriteTo, | 286 unsigned &WriteFrom, unsigned WriteTo, |
293 StringRef LocalEOL, int &Line, | 287 StringRef LocalEOL, int &Line, |
294 bool EnsureNewline) { | 288 bool EnsureNewline) { |
295 if (WriteTo <= WriteFrom) | 289 if (WriteTo <= WriteFrom) |
296 return; | 290 return; |
297 if (&FromFile == PredefinesBuffer) { | 291 if (FromFile == PredefinesBuffer) { |
298 // Ignore the #defines of the predefines buffer. | 292 // Ignore the #defines of the predefines buffer. |
299 WriteFrom = WriteTo; | 293 WriteFrom = WriteTo; |
300 return; | 294 return; |
301 } | 295 } |
302 | 296 |
339 /// inclusion directive disabled by a #if directive, updating \p NextToWrite | 333 /// inclusion directive disabled by a #if directive, updating \p NextToWrite |
340 /// and \p Line to track the number of source lines visited and the progress | 334 /// and \p Line to track the number of source lines visited and the progress |
341 /// through the \p FromFile buffer. | 335 /// through the \p FromFile buffer. |
342 void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex, | 336 void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex, |
343 const Token &StartToken, | 337 const Token &StartToken, |
344 const MemoryBuffer &FromFile, | 338 const MemoryBufferRef &FromFile, |
345 StringRef LocalEOL, | 339 StringRef LocalEOL, |
346 unsigned &NextToWrite, int &Line) { | 340 unsigned &NextToWrite, int &Line) { |
347 OutputContentUpTo(FromFile, NextToWrite, | 341 OutputContentUpTo(FromFile, NextToWrite, |
348 SM.getFileOffset(StartToken.getLocation()), LocalEOL, Line, | 342 SM.getFileOffset(StartToken.getLocation()), LocalEOL, Line, |
349 false); | 343 false); |
350 Token DirectiveToken; | 344 Token DirectiveToken; |
351 do { | 345 do { |
352 DirectiveLex.LexFromRawLexer(DirectiveToken); | 346 DirectiveLex.LexFromRawLexer(DirectiveToken); |
353 } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof)); | 347 } while (!DirectiveToken.is(tok::eod) && DirectiveToken.isNot(tok::eof)); |
354 if (&FromFile == PredefinesBuffer) { | 348 if (FromFile == PredefinesBuffer) { |
355 // OutputContentUpTo() would not output anything anyway. | 349 // OutputContentUpTo() would not output anything anyway. |
356 return; | 350 return; |
357 } | 351 } |
358 OS << "#if 0 /* expanded by -frewrite-includes */" << MainEOL; | 352 OS << "#if 0 /* expanded by -frewrite-includes */" << MainEOL; |
359 OutputContentUpTo(FromFile, NextToWrite, | 353 OutputContentUpTo(FromFile, NextToWrite, |
377 /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it | 371 /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it |
378 /// and including content of included files recursively. | 372 /// and including content of included files recursively. |
379 void InclusionRewriter::Process(FileID FileId, | 373 void InclusionRewriter::Process(FileID FileId, |
380 SrcMgr::CharacteristicKind FileType, | 374 SrcMgr::CharacteristicKind FileType, |
381 const DirectoryLookup *DirLookup) { | 375 const DirectoryLookup *DirLookup) { |
382 bool Invalid; | 376 MemoryBufferRef FromFile; |
383 const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid); | 377 { |
384 assert(!Invalid && "Attempting to process invalid inclusion"); | 378 auto B = SM.getBufferOrNone(FileId); |
379 assert(B && "Attempting to process invalid inclusion"); | |
380 if (B) | |
381 FromFile = *B; | |
382 } | |
385 StringRef FileName = FromFile.getBufferIdentifier(); | 383 StringRef FileName = FromFile.getBufferIdentifier(); |
386 Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts()); | 384 Lexer RawLex(FileId, FromFile, PP.getSourceManager(), PP.getLangOpts()); |
387 RawLex.SetCommentRetentionState(false); | 385 RawLex.SetCommentRetentionState(false); |
388 | 386 |
389 StringRef LocalEOL = DetectEOL(FromFile); | 387 StringRef LocalEOL = DetectEOL(FromFile); |
390 | 388 |
391 // Per the GNU docs: "1" indicates entering a new file. | 389 // Per the GNU docs: "1" indicates entering a new file. |
558 do { | 556 do { |
559 PP.Lex(Tok); | 557 PP.Lex(Tok); |
560 if (Tok.is(tok::annot_module_begin)) | 558 if (Tok.is(tok::annot_module_begin)) |
561 Rewrite->handleModuleBegin(Tok); | 559 Rewrite->handleModuleBegin(Tok); |
562 } while (Tok.isNot(tok::eof)); | 560 } while (Tok.isNot(tok::eof)); |
563 Rewrite->setPredefinesBuffer(SM.getBuffer(PP.getPredefinesFileID())); | 561 Rewrite->setPredefinesBuffer(SM.getBufferOrFake(PP.getPredefinesFileID())); |
564 Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User, nullptr); | 562 Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User, nullptr); |
565 Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User, nullptr); | 563 Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User, nullptr); |
566 OS->flush(); | 564 OS->flush(); |
567 } | 565 } |