diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp | 139 |
1 files changed, 75 insertions, 64 deletions
diff --git a/contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp b/contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp index 3f2a78127477..b6b37461089e 100644 --- a/contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -14,11 +14,11 @@ #include "clang/Rewrite/Frontend/Rewriters.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/PreprocessorOutputOptions.h" -#include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Pragma.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" +#include <optional> using namespace clang; using namespace llvm; @@ -31,10 +31,8 @@ class InclusionRewriter : public PPCallbacks { struct IncludedFile { FileID Id; SrcMgr::CharacteristicKind FileType; - const DirectoryLookup *DirLookup; - IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType, - const DirectoryLookup *DirLookup) - : Id(Id), FileType(FileType), DirLookup(DirLookup) {} + IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType) + : Id(Id), FileType(FileType) {} }; Preprocessor &PP; ///< Used to find inclusion directives. SourceManager &SM; ///< Used to read and manage source files. @@ -57,8 +55,7 @@ class InclusionRewriter : public PPCallbacks { public: InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, bool UseLineDirectives); - void Process(FileID FileId, SrcMgr::CharacteristicKind FileType, - const DirectoryLookup *DirLookup); + void Process(FileID FileId, SrcMgr::CharacteristicKind FileType); void setPredefinesBuffer(const llvm::MemoryBufferRef &Buf) { PredefinesBuffer = Buf; } @@ -76,9 +73,9 @@ private: SrcMgr::CharacteristicKind FileType) override; void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, - CharSourceRange FilenameRange, const FileEntry *File, - StringRef SearchPath, StringRef RelativePath, - const Module *Imported, + CharSourceRange FilenameRange, + OptionalFileEntryRef File, StringRef SearchPath, + StringRef RelativePath, const Module *Imported, SrcMgr::CharacteristicKind FileType) override; void If(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind ConditionValue) override; @@ -93,8 +90,10 @@ private: bool EnsureNewline); void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken, const MemoryBufferRef &FromFile, StringRef EOL, - unsigned &NextToWrite, int &Lines); + unsigned &NextToWrite, int &Lines, + const IncludedFile *Inc = nullptr); const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const; + StringRef getIncludedFileName(const IncludedFile *Inc) const; const Module *FindModuleAtLocation(SourceLocation Loc) const; const Module *FindEnteredModule(SourceLocation Loc) const; bool IsIfAtLocationTrue(SourceLocation Loc) const; @@ -162,8 +161,7 @@ void InclusionRewriter::FileChanged(SourceLocation Loc, return; FileID Id = FullSourceLoc(Loc, SM).getFileID(); auto P = FileIncludes.insert( - std::make_pair(LastInclusionLocation, - IncludedFile(Id, NewFileType, PP.GetCurDirLookup()))); + std::make_pair(LastInclusionLocation, IncludedFile(Id, NewFileType))); (void)P; assert(P.second && "Unexpected revisitation of the same include directive"); LastInclusionLocation = SourceLocation(); @@ -186,16 +184,12 @@ void InclusionRewriter::FileSkipped(const FileEntryRef & /*SkippedFile*/, /// FileChanged() or FileSkipped() is called after this (or neither is /// called if this #include results in an error or does not textually include /// anything). -void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, - const Token &/*IncludeTok*/, - StringRef /*FileName*/, - bool /*IsAngled*/, - CharSourceRange /*FilenameRange*/, - const FileEntry * /*File*/, - StringRef /*SearchPath*/, - StringRef /*RelativePath*/, - const Module *Imported, - SrcMgr::CharacteristicKind FileType){ +void InclusionRewriter::InclusionDirective( + SourceLocation HashLoc, const Token & /*IncludeTok*/, + StringRef /*FileName*/, bool /*IsAngled*/, + CharSourceRange /*FilenameRange*/, OptionalFileEntryRef /*File*/, + StringRef /*SearchPath*/, StringRef /*RelativePath*/, + const Module *Imported, SrcMgr::CharacteristicKind FileType) { if (Imported) { auto P = ModuleIncludes.insert(std::make_pair(HashLoc, Imported)); (void)P; @@ -256,28 +250,13 @@ bool InclusionRewriter::IsIfAtLocationTrue(SourceLocation Loc) const { return false; } -/// Detect the likely line ending style of \p FromFile by examining the first -/// newline found within it. -static StringRef DetectEOL(const MemoryBufferRef &FromFile) { - // Detect what line endings the file uses, so that added content does not mix - // the style. We need to check for "\r\n" first because "\n\r" will match - // "\r\n\r\n". - const char *Pos = strchr(FromFile.getBufferStart(), '\n'); - if (!Pos) - return "\n"; - if (Pos - 1 >= FromFile.getBufferStart() && Pos[-1] == '\r') - return "\r\n"; - if (Pos + 1 < FromFile.getBufferEnd() && Pos[1] == '\r') - return "\n\r"; - return "\n"; -} - void InclusionRewriter::detectMainFileEOL() { - Optional<MemoryBufferRef> FromFile = *SM.getBufferOrNone(SM.getMainFileID()); + std::optional<MemoryBufferRef> FromFile = + *SM.getBufferOrNone(SM.getMainFileID()); assert(FromFile); if (!FromFile) return; // Should never happen, but whatever. - MainEOL = DetectEOL(*FromFile); + MainEOL = FromFile->getBuffer().detectEOL(); } /// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at @@ -304,30 +283,47 @@ void InclusionRewriter::OutputContentUpTo(const MemoryBufferRef &FromFile, StringRef TextToWrite(FromFile.getBufferStart() + WriteFrom, WriteTo - WriteFrom); + // count lines manually, it's faster than getPresumedLoc() + Line += TextToWrite.count(LocalEOL); if (MainEOL == LocalEOL) { OS << TextToWrite; - // count lines manually, it's faster than getPresumedLoc() - Line += TextToWrite.count(LocalEOL); - if (EnsureNewline && !TextToWrite.endswith(LocalEOL)) - OS << MainEOL; } else { // Output the file one line at a time, rewriting the line endings as we go. StringRef Rest = TextToWrite; while (!Rest.empty()) { - StringRef LineText; - std::tie(LineText, Rest) = Rest.split(LocalEOL); + // Identify and output the next line excluding an EOL sequence if present. + size_t Idx = Rest.find(LocalEOL); + StringRef LineText = Rest.substr(0, Idx); OS << LineText; - Line++; - if (!Rest.empty()) + if (Idx != StringRef::npos) { + // An EOL sequence was present, output the EOL sequence for the + // main source file and skip past the local EOL sequence. OS << MainEOL; + Idx += LocalEOL.size(); + } + // Strip the line just handled. If Idx is npos or matches the end of the + // text, Rest will be set to an empty string and the loop will terminate. + Rest = Rest.substr(Idx); } - if (TextToWrite.endswith(LocalEOL) || EnsureNewline) - OS << MainEOL; } + if (EnsureNewline && !TextToWrite.ends_with(LocalEOL)) + OS << MainEOL; + WriteFrom = WriteTo; } +StringRef +InclusionRewriter::getIncludedFileName(const IncludedFile *Inc) const { + if (Inc) { + auto B = SM.getBufferOrNone(Inc->Id); + assert(B && "Attempting to process invalid inclusion"); + if (B) + return llvm::sys::path::filename(B->getBufferIdentifier()); + } + return StringRef(); +} + /// Print characters from \p FromFile starting at \p NextToWrite up until the /// inclusion directive at \p StartToken, then print out the inclusion /// inclusion directive disabled by a #if directive, updating \p NextToWrite @@ -337,7 +333,8 @@ void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex, const Token &StartToken, const MemoryBufferRef &FromFile, StringRef LocalEOL, - unsigned &NextToWrite, int &Line) { + unsigned &NextToWrite, int &Line, + const IncludedFile *Inc) { OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(StartToken.getLocation()), LocalEOL, Line, false); @@ -349,12 +346,21 @@ void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex, // OutputContentUpTo() would not output anything anyway. return; } - OS << "#if 0 /* expanded by -frewrite-includes */" << MainEOL; + if (Inc) { + OS << "#if defined(__CLANG_REWRITTEN_INCLUDES) "; + if (isSystem(Inc->FileType)) + OS << "|| defined(__CLANG_REWRITTEN_SYSTEM_INCLUDES) "; + OS << "/* " << getIncludedFileName(Inc); + } else { + OS << "#if 0 /*"; + } + OS << " expanded by -frewrite-includes */" << MainEOL; OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(DirectiveToken.getLocation()) + DirectiveToken.getLength(), LocalEOL, Line, true); - OS << "#endif /* expanded by -frewrite-includes */" << MainEOL; + OS << (Inc ? "#else /* " : "#endif /*") << getIncludedFileName(Inc) + << " expanded by -frewrite-includes */" << MainEOL; } /// Find the next identifier in the pragma directive specified by \p RawToken. @@ -371,8 +377,7 @@ StringRef InclusionRewriter::NextIdentifierName(Lexer &RawLex, /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it /// and including content of included files recursively. void InclusionRewriter::Process(FileID FileId, - SrcMgr::CharacteristicKind FileType, - const DirectoryLookup *DirLookup) { + SrcMgr::CharacteristicKind FileType) { MemoryBufferRef FromFile; { auto B = SM.getBufferOrNone(FileId); @@ -384,7 +389,7 @@ void InclusionRewriter::Process(FileID FileId, Lexer RawLex(FileId, FromFile, PP.getSourceManager(), PP.getLangOpts()); RawLex.SetCommentRetentionState(false); - StringRef LocalEOL = DetectEOL(FromFile); + StringRef LocalEOL = FromFile.getBuffer().detectEOL(); // Per the GNU docs: "1" indicates entering a new file. if (FileId == SM.getMainFileID() || FileId == PP.getPredefinesFileID()) @@ -418,26 +423,32 @@ void InclusionRewriter::Process(FileID FileId, case tok::pp_include: case tok::pp_include_next: case tok::pp_import: { - CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL, NextToWrite, - Line); + SourceLocation Loc = HashToken.getLocation(); + const IncludedFile *Inc = FindIncludeAtLocation(Loc); + CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL, + NextToWrite, Line, Inc); if (FileId != PP.getPredefinesFileID()) WriteLineInfo(FileName, Line - 1, FileType, ""); StringRef LineInfoExtra; - SourceLocation Loc = HashToken.getLocation(); if (const Module *Mod = FindModuleAtLocation(Loc)) WriteImplicitModuleImport(Mod); - else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) { + else if (Inc) { const Module *Mod = FindEnteredModule(Loc); if (Mod) OS << "#pragma clang module begin " << Mod->getFullModuleName(true) << "\n"; // Include and recursively process the file. - Process(Inc->Id, Inc->FileType, Inc->DirLookup); + Process(Inc->Id, Inc->FileType); if (Mod) OS << "#pragma clang module end /*" << Mod->getFullModuleName(true) << "*/\n"; + // There's no #include, therefore no #if, for -include files. + if (FromFile != PredefinesBuffer) { + OS << "#endif /* " << getIncludedFileName(Inc) + << " expanded by -frewrite-includes */" << LocalEOL; + } // Add line marker to indicate we're returning from an included // file. @@ -559,7 +570,7 @@ void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, Rewrite->handleModuleBegin(Tok); } while (Tok.isNot(tok::eof)); Rewrite->setPredefinesBuffer(SM.getBufferOrFake(PP.getPredefinesFileID())); - Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User, nullptr); - Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User, nullptr); + Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User); + Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User); OS->flush(); } |