class InclusionRewriter : public PPCallbacks {
/// Information about which #includes were actually performed,
/// created by preprocessor callbacks.
- struct FileChange {
- const Module *Mod;
- SourceLocation From;
+ struct IncludedFile {
FileID Id;
SrcMgr::CharacteristicKind FileType;
- FileChange(SourceLocation From, const Module *Mod) : Mod(Mod), From(From) {
- }
+ 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.
const llvm::MemoryBuffer *PredefinesBuffer; ///< The preprocessor predefines.
bool ShowLineMarkers; ///< Show #line markers.
bool UseLineDirectives; ///< Use of line directives or line markers.
- typedef std::map<unsigned, FileChange> FileChangeMap;
- FileChangeMap FileChanges; ///< Tracks which files were included where.
- /// Used transitively for building up the FileChanges mapping over the
+ /// Tracks where inclusions that change the file are found.
+ std::map<unsigned, IncludedFile> FileIncludes;
+ /// Tracks where inclusions that import modules are found.
+ std::map<unsigned, const Module *> ModuleIncludes;
+ /// Used transitively for building up the FileIncludes mapping over the
/// various \c PPCallbacks callbacks.
- FileChangeMap::iterator LastInsertedFileChange;
+ SourceLocation LastInclusionLocation;
public:
InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers,
bool UseLineDirectives);
bool HandleHasInclude(FileID FileId, Lexer &RawLex,
const DirectoryLookup *Lookup, Token &Tok,
bool &FileExists);
- const FileChange *FindFileChangeLocation(SourceLocation Loc) const;
+ const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const;
+ const Module *FindModuleAtLocation(SourceLocation Loc) const;
StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken);
};
: PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"),
PredefinesBuffer(nullptr), ShowLineMarkers(ShowLineMarkers),
UseLineDirectives(UseLineDirectives),
- LastInsertedFileChange(FileChanges.end()) {}
+ LastInclusionLocation(SourceLocation()) {}
/// Write appropriate line information as either #line directives or GNU line
/// markers depending on what mode we're in, including the \p Filename and
FileID) {
if (Reason != EnterFile)
return;
- if (LastInsertedFileChange == FileChanges.end())
+ if (LastInclusionLocation.isInvalid())
// we didn't reach this file (eg: the main file) via an inclusion directive
return;
- LastInsertedFileChange->second.Id = FullSourceLoc(Loc, SM).getFileID();
- LastInsertedFileChange->second.FileType = NewFileType;
- LastInsertedFileChange = FileChanges.end();
+ FileID Id = FullSourceLoc(Loc, SM).getFileID();
+ auto P = FileIncludes.emplace(LastInclusionLocation.getRawEncoding(),
+ IncludedFile(Id, NewFileType));
+ assert(P.second && "Unexpected revisitation of the same include directive");
+ LastInclusionLocation = SourceLocation();
}
/// Called whenever an inclusion is skipped due to canonical header protection
void InclusionRewriter::FileSkipped(const FileEntry &/*SkippedFile*/,
const Token &/*FilenameTok*/,
SrcMgr::CharacteristicKind /*FileType*/) {
- assert(LastInsertedFileChange != FileChanges.end() && "A file, that wasn't "
- "found via an inclusion directive, was skipped");
- FileChanges.erase(LastInsertedFileChange);
- LastInsertedFileChange = FileChanges.end();
+ assert(!LastInclusionLocation.isInvalid() &&
+ "A file, that wasn't found via an inclusion directive, was skipped");
+ LastInclusionLocation = SourceLocation();
}
/// This should be called whenever the preprocessor encounters include
StringRef /*SearchPath*/,
StringRef /*RelativePath*/,
const Module *Imported) {
- assert(LastInsertedFileChange == FileChanges.end() && "Another inclusion "
- "directive was found before the previous one was processed");
- std::pair<FileChangeMap::iterator, bool> p = FileChanges.insert(
- std::make_pair(HashLoc.getRawEncoding(), FileChange(HashLoc, Imported)));
- assert(p.second && "Unexpected revisitation of the same include directive");
- if (!Imported)
- LastInsertedFileChange = p.first;
+ assert(LastInclusionLocation.isInvalid() &&
+ "Another inclusion directive was found before the previous one "
+ "was processed");
+ if (Imported) {
+ auto P = ModuleIncludes.emplace(HashLoc.getRawEncoding(), Imported);
+ assert(P.second && "Unexpected revisitation of the same include directive");
+ } else
+ LastInclusionLocation = HashLoc;
}
/// Simple lookup for a SourceLocation (specifically one denoting the hash in
/// an inclusion directive) in the map of inclusion information, FileChanges.
-const InclusionRewriter::FileChange *
-InclusionRewriter::FindFileChangeLocation(SourceLocation Loc) const {
- FileChangeMap::const_iterator I = FileChanges.find(Loc.getRawEncoding());
- if (I != FileChanges.end())
+const InclusionRewriter::IncludedFile *
+InclusionRewriter::FindIncludeAtLocation(SourceLocation Loc) const {
+ const auto I = FileIncludes.find(Loc.getRawEncoding());
+ if (I != FileIncludes.end())
return &I->second;
return nullptr;
}
+/// Simple lookup for a SourceLocation (specifically one denoting the hash in
+/// an inclusion directive) in the map of module inclusion information.
+const Module *
+InclusionRewriter::FindModuleAtLocation(SourceLocation Loc) const {
+ const auto I = ModuleIncludes.find(Loc.getRawEncoding());
+ if (I != ModuleIncludes.end())
+ return I->second;
+ return nullptr;
+}
+
/// Detect the likely line ending style of \p FromFile by examining the first
/// newline found within it.
static StringRef DetectEOL(const MemoryBuffer &FromFile) {
{
bool Invalid;
const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid);
- if (Invalid) // invalid inclusion
- return false;
+ assert(!Invalid && "Attempting to process invalid inclusion");
const char *FileName = FromFile.getBufferIdentifier();
Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts());
RawLex.SetCommentRetentionState(false);
if (FileId != PP.getPredefinesFileID())
WriteLineInfo(FileName, Line - 1, FileType, "");
StringRef LineInfoExtra;
- if (const FileChange *Change = FindFileChangeLocation(
- HashToken.getLocation())) {
- if (Change->Mod) {
- WriteImplicitModuleImport(Change->Mod);
-
- // else now include and recursively process the file
- } else if (Process(Change->Id, Change->FileType)) {
+ SourceLocation Loc = HashToken.getLocation();
+ if (const Module *Mod = FindModuleAtLocation(Loc))
+ WriteImplicitModuleImport(Mod);
+ else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) {
+ // include and recursively process the file
+ if (Process(Inc->Id, Inc->FileType)) {
// and set lineinfo back to this file, if the nested one was
// actually included
// `2' indicates returning to a file (after having included