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 }