Mercurial > hg > CbC > CbC_llvm
comparison clang/lib/Frontend/Rewrite/InclusionRewriter.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 79ff65ed7e25 |
children | 1f2b6ac9f198 |
comparison
equal
deleted
inserted
replaced
232:70dce7da266c | 236:c4bab56944e8 |
---|---|
12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
13 | 13 |
14 #include "clang/Rewrite/Frontend/Rewriters.h" | 14 #include "clang/Rewrite/Frontend/Rewriters.h" |
15 #include "clang/Basic/SourceManager.h" | 15 #include "clang/Basic/SourceManager.h" |
16 #include "clang/Frontend/PreprocessorOutputOptions.h" | 16 #include "clang/Frontend/PreprocessorOutputOptions.h" |
17 #include "clang/Lex/HeaderSearch.h" | |
18 #include "clang/Lex/Pragma.h" | 17 #include "clang/Lex/Pragma.h" |
19 #include "clang/Lex/Preprocessor.h" | 18 #include "clang/Lex/Preprocessor.h" |
20 #include "llvm/ADT/SmallString.h" | 19 #include "llvm/ADT/SmallString.h" |
21 #include "llvm/Support/raw_ostream.h" | 20 #include "llvm/Support/raw_ostream.h" |
22 | 21 |
29 /// Information about which #includes were actually performed, | 28 /// Information about which #includes were actually performed, |
30 /// created by preprocessor callbacks. | 29 /// created by preprocessor callbacks. |
31 struct IncludedFile { | 30 struct IncludedFile { |
32 FileID Id; | 31 FileID Id; |
33 SrcMgr::CharacteristicKind FileType; | 32 SrcMgr::CharacteristicKind FileType; |
34 const DirectoryLookup *DirLookup; | 33 IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType) |
35 IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType, | 34 : Id(Id), FileType(FileType) {} |
36 const DirectoryLookup *DirLookup) | |
37 : Id(Id), FileType(FileType), DirLookup(DirLookup) {} | |
38 }; | 35 }; |
39 Preprocessor &PP; ///< Used to find inclusion directives. | 36 Preprocessor &PP; ///< Used to find inclusion directives. |
40 SourceManager &SM; ///< Used to read and manage source files. | 37 SourceManager &SM; ///< Used to read and manage source files. |
41 raw_ostream &OS; ///< The destination stream for rewritten contents. | 38 raw_ostream &OS; ///< The destination stream for rewritten contents. |
42 StringRef MainEOL; ///< The line ending marker to use. | 39 StringRef MainEOL; ///< The line ending marker to use. |
55 /// various \c PPCallbacks callbacks. | 52 /// various \c PPCallbacks callbacks. |
56 SourceLocation LastInclusionLocation; | 53 SourceLocation LastInclusionLocation; |
57 public: | 54 public: |
58 InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, | 55 InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, |
59 bool UseLineDirectives); | 56 bool UseLineDirectives); |
60 void Process(FileID FileId, SrcMgr::CharacteristicKind FileType, | 57 void Process(FileID FileId, SrcMgr::CharacteristicKind FileType); |
61 const DirectoryLookup *DirLookup); | |
62 void setPredefinesBuffer(const llvm::MemoryBufferRef &Buf) { | 58 void setPredefinesBuffer(const llvm::MemoryBufferRef &Buf) { |
63 PredefinesBuffer = Buf; | 59 PredefinesBuffer = Buf; |
64 } | 60 } |
65 void detectMainFileEOL(); | 61 void detectMainFileEOL(); |
66 void handleModuleBegin(Token &Tok) { | 62 void handleModuleBegin(Token &Tok) { |
74 FileID PrevFID) override; | 70 FileID PrevFID) override; |
75 void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok, | 71 void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok, |
76 SrcMgr::CharacteristicKind FileType) override; | 72 SrcMgr::CharacteristicKind FileType) override; |
77 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, | 73 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, |
78 StringRef FileName, bool IsAngled, | 74 StringRef FileName, bool IsAngled, |
79 CharSourceRange FilenameRange, const FileEntry *File, | 75 CharSourceRange FilenameRange, |
80 StringRef SearchPath, StringRef RelativePath, | 76 Optional<FileEntryRef> File, StringRef SearchPath, |
81 const Module *Imported, | 77 StringRef RelativePath, const Module *Imported, |
82 SrcMgr::CharacteristicKind FileType) override; | 78 SrcMgr::CharacteristicKind FileType) override; |
83 void If(SourceLocation Loc, SourceRange ConditionRange, | 79 void If(SourceLocation Loc, SourceRange ConditionRange, |
84 ConditionValueKind ConditionValue) override; | 80 ConditionValueKind ConditionValue) override; |
85 void Elif(SourceLocation Loc, SourceRange ConditionRange, | 81 void Elif(SourceLocation Loc, SourceRange ConditionRange, |
86 ConditionValueKind ConditionValue, SourceLocation IfLoc) override; | 82 ConditionValueKind ConditionValue, SourceLocation IfLoc) override; |
160 if (LastInclusionLocation.isInvalid()) | 156 if (LastInclusionLocation.isInvalid()) |
161 // we didn't reach this file (eg: the main file) via an inclusion directive | 157 // we didn't reach this file (eg: the main file) via an inclusion directive |
162 return; | 158 return; |
163 FileID Id = FullSourceLoc(Loc, SM).getFileID(); | 159 FileID Id = FullSourceLoc(Loc, SM).getFileID(); |
164 auto P = FileIncludes.insert( | 160 auto P = FileIncludes.insert( |
165 std::make_pair(LastInclusionLocation, | 161 std::make_pair(LastInclusionLocation, IncludedFile(Id, NewFileType))); |
166 IncludedFile(Id, NewFileType, PP.GetCurDirLookup()))); | |
167 (void)P; | 162 (void)P; |
168 assert(P.second && "Unexpected revisitation of the same include directive"); | 163 assert(P.second && "Unexpected revisitation of the same include directive"); |
169 LastInclusionLocation = SourceLocation(); | 164 LastInclusionLocation = SourceLocation(); |
170 } | 165 } |
171 | 166 |
189 void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, | 184 void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, |
190 const Token &/*IncludeTok*/, | 185 const Token &/*IncludeTok*/, |
191 StringRef /*FileName*/, | 186 StringRef /*FileName*/, |
192 bool /*IsAngled*/, | 187 bool /*IsAngled*/, |
193 CharSourceRange /*FilenameRange*/, | 188 CharSourceRange /*FilenameRange*/, |
194 const FileEntry * /*File*/, | 189 Optional<FileEntryRef> /*File*/, |
195 StringRef /*SearchPath*/, | 190 StringRef /*SearchPath*/, |
196 StringRef /*RelativePath*/, | 191 StringRef /*RelativePath*/, |
197 const Module *Imported, | 192 const Module *Imported, |
198 SrcMgr::CharacteristicKind FileType){ | 193 SrcMgr::CharacteristicKind FileType){ |
199 if (Imported) { | 194 if (Imported) { |
254 if (I != IfConditions.end()) | 249 if (I != IfConditions.end()) |
255 return I->second; | 250 return I->second; |
256 return false; | 251 return false; |
257 } | 252 } |
258 | 253 |
259 /// Detect the likely line ending style of \p FromFile by examining the first | |
260 /// newline found within it. | |
261 static StringRef DetectEOL(const MemoryBufferRef &FromFile) { | |
262 // Detect what line endings the file uses, so that added content does not mix | |
263 // the style. We need to check for "\r\n" first because "\n\r" will match | |
264 // "\r\n\r\n". | |
265 const char *Pos = strchr(FromFile.getBufferStart(), '\n'); | |
266 if (!Pos) | |
267 return "\n"; | |
268 if (Pos - 1 >= FromFile.getBufferStart() && Pos[-1] == '\r') | |
269 return "\r\n"; | |
270 if (Pos + 1 < FromFile.getBufferEnd() && Pos[1] == '\r') | |
271 return "\n\r"; | |
272 return "\n"; | |
273 } | |
274 | |
275 void InclusionRewriter::detectMainFileEOL() { | 254 void InclusionRewriter::detectMainFileEOL() { |
276 Optional<MemoryBufferRef> FromFile = *SM.getBufferOrNone(SM.getMainFileID()); | 255 Optional<MemoryBufferRef> FromFile = *SM.getBufferOrNone(SM.getMainFileID()); |
277 assert(FromFile); | 256 assert(FromFile); |
278 if (!FromFile) | 257 if (!FromFile) |
279 return; // Should never happen, but whatever. | 258 return; // Should never happen, but whatever. |
280 MainEOL = DetectEOL(*FromFile); | 259 MainEOL = FromFile->getBuffer().detectEOL(); |
281 } | 260 } |
282 | 261 |
283 /// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at | 262 /// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at |
284 /// \p WriteTo - 1. | 263 /// \p WriteTo - 1. |
285 void InclusionRewriter::OutputContentUpTo(const MemoryBufferRef &FromFile, | 264 void InclusionRewriter::OutputContentUpTo(const MemoryBufferRef &FromFile, |
369 } | 348 } |
370 | 349 |
371 /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it | 350 /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it |
372 /// and including content of included files recursively. | 351 /// and including content of included files recursively. |
373 void InclusionRewriter::Process(FileID FileId, | 352 void InclusionRewriter::Process(FileID FileId, |
374 SrcMgr::CharacteristicKind FileType, | 353 SrcMgr::CharacteristicKind FileType) { |
375 const DirectoryLookup *DirLookup) { | |
376 MemoryBufferRef FromFile; | 354 MemoryBufferRef FromFile; |
377 { | 355 { |
378 auto B = SM.getBufferOrNone(FileId); | 356 auto B = SM.getBufferOrNone(FileId); |
379 assert(B && "Attempting to process invalid inclusion"); | 357 assert(B && "Attempting to process invalid inclusion"); |
380 if (B) | 358 if (B) |
382 } | 360 } |
383 StringRef FileName = FromFile.getBufferIdentifier(); | 361 StringRef FileName = FromFile.getBufferIdentifier(); |
384 Lexer RawLex(FileId, FromFile, PP.getSourceManager(), PP.getLangOpts()); | 362 Lexer RawLex(FileId, FromFile, PP.getSourceManager(), PP.getLangOpts()); |
385 RawLex.SetCommentRetentionState(false); | 363 RawLex.SetCommentRetentionState(false); |
386 | 364 |
387 StringRef LocalEOL = DetectEOL(FromFile); | 365 StringRef LocalEOL = FromFile.getBuffer().detectEOL(); |
388 | 366 |
389 // Per the GNU docs: "1" indicates entering a new file. | 367 // Per the GNU docs: "1" indicates entering a new file. |
390 if (FileId == SM.getMainFileID() || FileId == PP.getPredefinesFileID()) | 368 if (FileId == SM.getMainFileID() || FileId == PP.getPredefinesFileID()) |
391 WriteLineInfo(FileName, 1, FileType, ""); | 369 WriteLineInfo(FileName, 1, FileType, ""); |
392 else | 370 else |
431 if (Mod) | 409 if (Mod) |
432 OS << "#pragma clang module begin " | 410 OS << "#pragma clang module begin " |
433 << Mod->getFullModuleName(true) << "\n"; | 411 << Mod->getFullModuleName(true) << "\n"; |
434 | 412 |
435 // Include and recursively process the file. | 413 // Include and recursively process the file. |
436 Process(Inc->Id, Inc->FileType, Inc->DirLookup); | 414 Process(Inc->Id, Inc->FileType); |
437 | 415 |
438 if (Mod) | 416 if (Mod) |
439 OS << "#pragma clang module end /*" | 417 OS << "#pragma clang module end /*" |
440 << Mod->getFullModuleName(true) << "*/\n"; | 418 << Mod->getFullModuleName(true) << "*/\n"; |
441 | 419 |
557 PP.Lex(Tok); | 535 PP.Lex(Tok); |
558 if (Tok.is(tok::annot_module_begin)) | 536 if (Tok.is(tok::annot_module_begin)) |
559 Rewrite->handleModuleBegin(Tok); | 537 Rewrite->handleModuleBegin(Tok); |
560 } while (Tok.isNot(tok::eof)); | 538 } while (Tok.isNot(tok::eof)); |
561 Rewrite->setPredefinesBuffer(SM.getBufferOrFake(PP.getPredefinesFileID())); | 539 Rewrite->setPredefinesBuffer(SM.getBufferOrFake(PP.getPredefinesFileID())); |
562 Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User, nullptr); | 540 Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User); |
563 Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User, nullptr); | 541 Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User); |
564 OS->flush(); | 542 OS->flush(); |
565 } | 543 } |