aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp139
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();
}