Hi revane,
The IncludeDirectives class allows the users to add angled-includes in a source
file. This is necessary for some transforms that add dependency to new STL
headers.
This is a start for this class that will need to evolve later (for example to
replace uses of tr1 it will be necessary to rename/remove includes).
http://llvm-reviews.chandlerc.com/D1287
Files:
cpp11-migrate/Core/CMakeLists.txt
cpp11-migrate/Core/IncludeDirectives.cpp
cpp11-migrate/Core/IncludeDirectives.h
unittests/cpp11-migrate/CMakeLists.txt
unittests/cpp11-migrate/IncludeDirectivesTest.cpp
unittests/cpp11-migrate/VirtualFileHelper.h
Index: cpp11-migrate/Core/CMakeLists.txt
===================================================================
--- cpp11-migrate/Core/CMakeLists.txt
+++ cpp11-migrate/Core/CMakeLists.txt
@@ -8,6 +8,7 @@
IncludeExcludeInfo.cpp
PerfSupport.cpp
Reformatting.cpp
+ IncludeDirectives.cpp
)
target_link_libraries(migrateCore
clangFormat
Index: cpp11-migrate/Core/IncludeDirectives.cpp
===================================================================
--- /dev/null
+++ cpp11-migrate/Core/IncludeDirectives.cpp
@@ -0,0 +1,266 @@
+//===-- Core/IncludeDirectives.h - Include directives handling ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines the IncludeDirectives class that helps detecting
+/// and modifying \#include directives.
+///
+//===----------------------------------------------------------------------===//
+
+#include "IncludeDirectives.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+using llvm::StringRef;
+
+/// \brief PPCallbacks that fills-in the include information in the given
+/// \c IncludeDirectives.
+class IncludeDirectivesPPCallback : public clang::PPCallbacks {
+public:
+ IncludeDirectivesPPCallback(IncludeDirectives *Self) : Self(Self) {}
+
+private:
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported) LLVM_OVERRIDE {
+ SourceManager &SM = Self->Sources;
+ const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(HashLoc));
+ assert(FE && "Valid file expected.");
+
+ IncludeDirectives::Entry E(HashLoc, File, IsAngled);
+ Self->FileToEntries[FE].push_back(E);
+ Self->IncludeAsWrittenToLocationsMap[FileName].push_back(HashLoc);
+ }
+
+ IncludeDirectives *Self;
+};
+
+IncludeDirectives::IncludeDirectives(clang::CompilerInstance &CI)
+ : CI(CI), Sources(CI.getSourceManager()) {
+ CI.getPreprocessor().addPPCallbacks(new IncludeDirectivesPPCallback(this));
+}
+
+namespace {
+// Guess the end-of-line sequence used in the given FileID. If the sequence
+// can't be guessed return an Unix-style newline.
+StringRef guessEOL(SourceManager &SM, FileID ID) {
+ bool Invalid = false;
+ StringRef Content = SM.getBufferData(ID, &Invalid);
+ StringRef Buffer;
+ if (!Invalid)
+ Buffer = Content.substr(Content.find_first_of("\r\n"));
+
+ return llvm::StringSwitch<StringRef>(Buffer)
+ .StartsWith("\r\n", "\r\n")
+ .StartsWith("\n\r", "\n\r")
+ .StartsWith("\r", "\r")
+ .Default("\n");
+}
+} // end anonymous namespace
+
+/// \brief Recursively look if \p Include is included by \p File or any of the
+/// headers \p File includes.
+bool IncludeDirectives::lookForInclude(const FileEntry *File, StringRef Include,
+ const LocationVec &Locations,
+ SeenFilesSet &Seen) const {
+ // mark this file as visited
+ Seen.insert(File);
+
+ // First check if included directly in this file
+ for (LocationVec::const_iterator I = Locations.begin(), E = Locations.end();
+ I != E; ++I)
+ if (Sources.getFileEntryForID(Sources.getFileID(*I)) == File)
+ return true;
+
+ // Otherwise look recursively all the included files
+ FileToEntriesMap::const_iterator EntriesIt = FileToEntries.find(File);
+ if (EntriesIt == FileToEntries.end())
+ return false;
+ for (EntryVec::const_iterator I = EntriesIt->second.begin(),
+ E = EntriesIt->second.end();
+ I != E; ++I) {
+ // skip if this header has already been checked before
+ if (Seen.count(I->getFile()))
+ continue;
+ if (lookForInclude(I->getFile(), Include, Locations, Seen))
+ return true;
+ }
+ return false;
+}
+
+bool IncludeDirectives::hasInclude(const FileEntry *File,
+ StringRef Include) const {
+ llvm::StringMap<LocationVec>::const_iterator It =
+ IncludeAsWrittenToLocationsMap.find(Include);
+
+ // Include isn't included in any file
+ if (It == IncludeAsWrittenToLocationsMap.end())
+ return false;
+
+ SeenFilesSet Seen;
+ return lookForInclude(File, Include, It->getValue(), Seen);
+}
+
+namespace {
+// Flags that describes where to insert newlines.
+enum NewLineFlags {
+ // Add a newline at the beginning of the insertion.
+ NL_Append = 0x1,
+
+ // Prepend a newline at the beginning of the insertion.
+ NL_Prepend = 0x2,
+
+ // Prepend another newline at the end of the insertion.
+ NL_PrependAnother = 0x4,
+
+ // Convenience value to enable both \c NL_Prepend and \c NL_PrependAnother.
+ NL_PrependTwice = NL_Prepend | NL_PrependAnother
+};
+} // end anonymous namespace
+
+tooling::Replacement IncludeDirectives::addAngledInclude(StringRef File,
+ StringRef Include) {
+ const FileEntry *FE = Sources.getFileManager().getFile(File);
+ assert(FE && "Invalid file given!");
+ FileID FID = Sources.translateFile(FE);
+ assert(!FID.isInvalid() && "Invalid file entry given!");
+
+ if (hasInclude(FE, Include))
+ return tooling::Replacement();
+
+ unsigned Offset, NLFlags;
+ llvm::tie(Offset, NLFlags) = angledIncludeInsertionOffset(FID);
+
+ StringRef EOL = guessEOL(Sources, FID);
+ llvm::SmallString<32> InsertionText;
+ if (NLFlags & NL_Prepend)
+ InsertionText += EOL;
+ if (NLFlags & NL_PrependAnother)
+ InsertionText += EOL;
+ InsertionText += "#include <";
+ InsertionText += Include;
+ InsertionText += ">";
+ if (NLFlags & NL_Append)
+ InsertionText += EOL;
+ return tooling::Replacement(File, Offset, 0, InsertionText);
+}
+
+// Finds the end of a file header and returns a pair (FileOffset, NewLineFlags)
+std::pair<unsigned, unsigned>
+IncludeDirectives::findFileHeaderEndOffset(FileID FID) const {
+ unsigned NLFlags = NL_Prepend;
+ StringRef Content = Sources.getBufferData(FID);
+ Lexer Lex(Sources.getLocForStartOfFile(FID), CI.getLangOpts(),
+ Content.begin(), Content.begin(), Content.end());
+ Lex.SetCommentRetentionState(true);
+ Lex.SetKeepWhitespaceMode(true);
+
+ // find the first newline not part of a multi-line comment
+ Token Tok;
+ do {
+ Lex.LexFromRawLexer(Tok);
+ unsigned Offset = Sources.getFileOffset(Tok.getLocation());
+ // allow one newline between the comments
+ if (Tok.is(tok::unknown) && isWhitespace(Content[Offset])) {
+ StringRef Whitespaces(Content.substr(Offset, Tok.getLength()));
+ if (Whitespaces.count('\n') == 1 || Whitespaces.count('\r') == 1)
+ Lex.LexFromRawLexer(Tok);
+ else {
+ // add an empty line to separate the file header and the inclusion
+ NLFlags = NL_PrependTwice;
+ }
+ }
+ } while (Tok.is(tok::comment));
+
+ // apparently there is no header, insertion point is the beginning of the file
+ if (Tok.isNot(tok::unknown))
+ return std::make_pair(0, NL_Append);
+ return std::make_pair(Sources.getFileOffset(Tok.getLocation()), NLFlags);
+}
+
+// Get the position of the last angled include if any, or just the position of
+// the last include.
+// Returns a null SourceLocation if no entry are available.
+SourceLocation
+IncludeDirectives::angledIncludeHintLoc(const EntryVec &Entries) const {
+ if (Entries.empty())
+ return SourceLocation();
+ for (EntryVec::const_reverse_iterator I = Entries.rbegin(),
+ E = Entries.rend();
+ I != E; ++I)
+ if (I->isAngled())
+ return I->getLocation();
+ return Entries.back().getLocation();
+}
+
+// Finds the offset where an angled include should be added and returns a pair
+// (FileOffset, NewLineFlags).
+std::pair<unsigned, unsigned>
+IncludeDirectives::angledIncludeInsertionOffset(FileID FID) const {
+ const FileEntry *File = Sources.getFileEntryForID(FID);
+
+ // the location of an include directive that can be used to put our inclusion
+ // after
+ SourceLocation Hint;
+ FileToEntriesMap::const_iterator EntriesIt = FileToEntries.find(File);
+ if (EntriesIt != FileToEntries.end())
+ Hint = angledIncludeHintLoc(EntriesIt->second);
+
+ // no interesting #include lines, insertion is done after the file header
+ if (Hint.isInvalid())
+ return findFileHeaderEndOffset(FID);
+
+ unsigned Offset = Sources.getFileOffset(Hint);
+ StringRef Content = Sources.getBufferData(FID);
+
+ // find the newline after our include
+ Lexer Lex(Sources.getLocForStartOfFile(FID), CI.getLangOpts(),
+ Content.begin(), Content.begin() + Offset, Content.end());
+ Lex.SetCommentRetentionState(true);
+ Token Tok;
+ for (;;) {
+ // find beginning of end-of-line sequence
+ StringRef::size_type EOLOffset = Content.find_first_of("\r\n", Offset);
+ if (EOLOffset == StringRef::npos)
+ return std::make_pair(Content.size(), NL_Prepend); // newline missing
+ // check if the newline is directly past the end of the last token,
+ // otherwise the next Lex() call will omit this one.
+ if (Offset == EOLOffset)
+ return std::make_pair(Offset, NL_Prepend);
+
+ // look for the next end-of-line if this one is part of a multi-line comment
+ unsigned TokEnd = 0;
+ bool isInComment = false;
+ do {
+ Lex.LexFromRawLexer(Tok);
+ unsigned TokStart = Sources.getFileOffset(Tok.getLocation());
+ TokEnd = TokStart + Tok.getLength();
+
+ // the EOLOffset checks for StringRef::npos
+ assert(Tok.isNot(tok::eof) && "unexpected token!");
+
+ if (Tok.is(tok::comment)) {
+ if (EOLOffset > TokStart && EOLOffset < TokEnd) {
+ isInComment = true;
+ // skip after the comment for the new search of NL
+ Offset = TokEnd;
+ }
+ }
+ } while (TokEnd < EOLOffset);
+
+ if (!isInComment)
+ return std::make_pair(EOLOffset, NL_Prepend);
+ }
+}
Index: cpp11-migrate/Core/IncludeDirectives.h
===================================================================
--- /dev/null
+++ cpp11-migrate/Core/IncludeDirectives.h
@@ -0,0 +1,100 @@
+//===-- Core/IncludeDirectives.h - Include directives handling --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file declares the IncludeDirectives class that helps detecting
+/// and modifying \#include directives.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef CPP11_MIGRATE_INCLUDE_DIRECTIVES_H
+#define CPP11_MIGRATE_INCLUDE_DIRECTIVES_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Tooling/Refactoring.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+#include <vector>
+
+namespace clang {
+class Preprocessor;
+} // namespace clang
+
+/// \brief Support for include directives handling.
+///
+/// This class should be created with a \c clang::CompilerInstance before the
+/// file is preprocessed in order to collect the inclusion information. It can
+/// be queried as long as the compiler instance is valid.
+class IncludeDirectives {
+public:
+ IncludeDirectives(clang::CompilerInstance &CI);
+
+ /// \brief Add an angled include to a the given file.
+ ///
+ /// \param File A file accessible by a SourceManager
+ /// \param Include The include file as it should be written in the code.
+ ///
+ /// \return A replacement that is either null if the include already visible
+ /// by file (check with \c Replacement::isApplicable()) or non-null
+ /// replacement that will add the include when applied.
+ clang::tooling::Replacement addAngledInclude(llvm::StringRef File,
+ llvm::StringRef Include);
+
+private:
+ friend class IncludeDirectivesPPCallback;
+
+ /// \brief Contains some inclusion information.
+ class Entry {
+ public:
+ Entry(clang::SourceLocation Loc, const clang::FileEntry *File, bool Angled)
+ : Loc(Loc), File(File), Angled(Angled) {}
+
+ clang::SourceLocation getLocation() const { return Loc; }
+ const clang::FileEntry *getFile() const { return File; }
+ bool isAngled() const { return Angled; }
+
+ private:
+ clang::SourceLocation Loc;
+ const clang::FileEntry *File;
+ bool Angled;
+ };
+
+ // A list of entries.
+ typedef std::vector<Entry> EntryVec;
+
+ // A list of source locations.
+ typedef std::vector<clang::SourceLocation> LocationVec;
+
+ // Associates files to their includes.
+ typedef llvm::DenseMap<const clang::FileEntry *, EntryVec> FileToEntriesMap;
+
+ bool hasInclude(const clang::FileEntry *File, llvm::StringRef Include) const;
+
+ typedef llvm::SmallPtrSet<const clang::FileEntry *, 32> SeenFilesSet;
+ bool lookForInclude(const clang::FileEntry *File, llvm::StringRef Include,
+ const LocationVec &Locations, SeenFilesSet &Seen) const;
+
+ std::pair<unsigned, unsigned>
+ angledIncludeInsertionOffset(clang::FileID FID) const;
+ clang::SourceLocation angledIncludeHintLoc(const EntryVec &Entries) const;
+
+ std::pair<unsigned, unsigned>
+ findFileHeaderEndOffset(clang::FileID FID) const;
+
+ clang::CompilerInstance &CI;
+ clang::SourceManager &Sources;
+ FileToEntriesMap FileToEntries;
+ // maps include filename as written in the source code to the source locations
+ // where it appears
+ llvm::StringMap<LocationVec> IncludeAsWrittenToLocationsMap;
+};
+
+#endif // CPP11_MIGRATE_INCLUDE_DIRECTIVES_H
Index: unittests/cpp11-migrate/CMakeLists.txt
===================================================================
--- unittests/cpp11-migrate/CMakeLists.txt
+++ unittests/cpp11-migrate/CMakeLists.txt
@@ -13,6 +13,7 @@
PerfSupportTest.cpp
TransformTest.cpp
UniqueHeaderNameTest.cpp
+ IncludeDirectivesTest.cpp
)
target_link_libraries(Cpp11MigrateTests
Index: unittests/cpp11-migrate/IncludeDirectivesTest.cpp
===================================================================
--- /dev/null
+++ unittests/cpp11-migrate/IncludeDirectivesTest.cpp
@@ -0,0 +1,186 @@
+//===- cpp11-migrate/IncludeDirectivesTest.cpp ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Core/IncludeDirectives.h"
+#include "gtest/gtest.h"
+#include "VirtualFileHelper.h"
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+class TestAddIncludeAction : public PreprocessOnlyAction {
+public:
+ TestAddIncludeAction(StringRef Include, tooling::Replacements &Replaces,
+ const char *HeaderToModify = 0)
+ : Include(Include), Replaces(Replaces), HeaderToModify(HeaderToModify) {
+ // some headers that the tests can include
+ VFHelper.mapFile("/virtual/foo-inner.h", "\n");
+ VFHelper.mapFile("/virtual/foo.h", "#include </virtual/foo-inner.h>\n");
+ VFHelper.mapFile("/virtual/bar-inner.h", "\n");
+ VFHelper.mapFile("/virtual/bar.h", "#include </virtual/bar-inner.h>\n");
+ }
+
+ void addVirtualFile(StringRef FileName, StringRef Content) {
+ VFHelper.mapFile(FileName, Content);
+ }
+
+private:
+ virtual bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef FileName) LLVM_OVERRIDE {
+ if (!PreprocessOnlyAction::BeginSourceFileAction(CI, FileName))
+ return false;
+ VFHelper.mapVirtualFiles(CI.getSourceManager());
+
+ FileToModify = HeaderToModify ? HeaderToModify : FileName;
+ FileIncludes.reset(new IncludeDirectives(CI));
+ return true;
+ }
+
+ virtual void EndSourceFileAction() LLVM_OVERRIDE {
+ const tooling::Replacement &Replace = FileIncludes->addAngledInclude(FileToModify, Include);
+ if (Replace.isApplicable())
+ Replaces.insert(Replace);
+ }
+
+ StringRef Include;
+ VirtualFileHelper VFHelper;
+ tooling::Replacements &Replaces;
+ OwningPtr<IncludeDirectives> FileIncludes;
+ StringRef FileToModify;
+ // if non-null, add the include directives in this file instead of the main
+ // file.
+ const char *HeaderToModify;
+};
+
+std::string addIncludeInCode(StringRef Include, StringRef Code) {
+ tooling::Replacements Replaces;
+ EXPECT_TRUE(tooling::runToolOnCode(
+ new TestAddIncludeAction(Include, Replaces), Code));
+ return tooling::applyAllReplacements(Code, Replaces);
+}
+} // end anonymous namespace
+
+TEST(IncludeDirectivesTest, endOfLinesVariants) {
+ EXPECT_EQ("#include </virtual/foo.h>\n"
+ "#include <bar>\n",
+ addIncludeInCode("bar", "#include </virtual/foo.h>\n"));
+ EXPECT_EQ("#include </virtual/foo.h>\r\n"
+ "#include <bar>\r\n",
+ addIncludeInCode("bar", "#include </virtual/foo.h>\r\n"));
+ EXPECT_EQ("#include </virtual/foo.h>\r"
+ "#include <bar>\r",
+ addIncludeInCode("bar", "#include </virtual/foo.h>\r"));
+}
+
+TEST(IncludeDirectivesTest, ppToken) {
+ EXPECT_EQ("#define FOO </virtual/foo.h>\n"
+ "#include FOO\n"
+ "#include <bar>\n"
+ "int i;\n",
+ addIncludeInCode("bar", "#define FOO </virtual/foo.h>\n"
+ "#include FOO\n"
+ "int i;\n"));
+}
+
+TEST(IncludeDirectivesTest, noFileHeader) {
+ EXPECT_EQ("#include <bar>\n"
+ "int foo;\n",
+ addIncludeInCode("bar", "int foo;\n"));
+}
+
+TEST(IncludeDirectivesTest, commentBeforeTopMostCode) {
+ EXPECT_EQ("#include <bar>\n"
+ "// Foo\n"
+ "int foo;\n",
+ addIncludeInCode("bar", "// Foo\n"
+ "int foo;\n"));
+}
+
+TEST(IncludeDirectivesTest, multiLineComment) {
+ EXPECT_EQ("#include </virtual/foo.h> /* \n */\n"
+ "#include <bar>\n",
+ addIncludeInCode("bar", "#include </virtual/foo.h> /* \n */\n"));
+ EXPECT_EQ("#include </virtual/foo.h> /* \n */"
+ "\n#include <bar>",
+ addIncludeInCode("bar", "#include </virtual/foo.h> /* \n */"));
+}
+
+TEST(IncludeDirectivesTest, fileHeaders) {
+ EXPECT_EQ("// this is a header\n"
+ "// some license stuff here\n"
+ "\n"
+ "#include <bar>\n"
+ "\n"
+ "/// \\brief Foo\n"
+ "int foo;\n",
+ addIncludeInCode("bar", "// this is a header\n"
+ "// some license stuff here\n"
+ "\n"
+ "/// \\brief Foo\n"
+ "int foo;\n"));
+}
+
+TEST(IncludeDirectivesTest, preferablyAngledNextToAngled) {
+ EXPECT_EQ("#include </virtual/foo.h>\n"
+ "#include <bar>\n"
+ "#include \"/virtual/bar.h\"\n",
+ addIncludeInCode("bar", "#include </virtual/foo.h>\n"
+ "#include \"/virtual/bar.h\"\n"));
+ EXPECT_EQ("#include \"/virtual/foo.h\"\n"
+ "#include \"/virtual/bar.h\"\n"
+ "#include <bar>\n",
+ addIncludeInCode("bar", "#include \"/virtual/foo.h\"\n"
+ "#include \"/virtual/bar.h\"\n"));
+}
+
+TEST(IncludeDirectivesTest, avoidDuplicates) {
+ EXPECT_EQ("#include </virtual/foo.h>\n",
+ addIncludeInCode("/virtual/foo.h", "#include </virtual/foo.h>\n"));
+}
+
+namespace {
+TestAddIncludeAction *makeIndirectTestsAction(const char *HeaderToModify,
+ tooling::Replacements &Replaces) {
+ StringRef Include = "/virtual/c.h";
+ TestAddIncludeAction *TestAction =
+ new TestAddIncludeAction(Include, Replaces, HeaderToModify);
+ TestAction->addVirtualFile("/virtual/c.h", "\n");
+ TestAction->addVirtualFile("/virtual/a.h", "#include </virtual/c.h>\n");
+ TestAction->addVirtualFile("/virtual/b.h", "\n");
+ return TestAction;
+}
+} // end anonymous namespace
+
+TEST(IncludeDirectivesTest, indirectIncludes) {
+ EXPECT_EQ(
+ "#include </virtual/foo.h>\n",
+ addIncludeInCode("/virtual/foo-inner.h", "#include </virtual/foo.h>\n"));
+
+ // Test a.h that already include
+ tooling::Replacements Replaces;
+ StringRef Code = "#include </virtual/a.h>\n"
+ "#include </virtual/b.h>\n";
+
+ {
+ FrontendAction *Action = makeIndirectTestsAction("/virtual/a.h", Replaces);
+ EXPECT_TRUE(tooling::runToolOnCode(Action, Code));
+ EXPECT_EQ(unsigned(0), Replaces.size());
+ }
+
+ {
+ FrontendAction *Action = makeIndirectTestsAction("/virtual/b.h", Replaces);
+ EXPECT_TRUE(tooling::runToolOnCode(Action, Code));
+ EXPECT_EQ("#include </virtual/c.h>\n\n",
+ tooling::applyAllReplacements("\n", Replaces));
+ }
+}
Index: unittests/cpp11-migrate/VirtualFileHelper.h
===================================================================
--- unittests/cpp11-migrate/VirtualFileHelper.h
+++ unittests/cpp11-migrate/VirtualFileHelper.h
@@ -49,15 +49,21 @@
/// mapped to it.
SourceManager &getNewSourceManager() {
Sources.reset(new SourceManager(Diagnostics, Files));
- for (llvm::SmallVectorImpl<VirtualFile>::iterator I = VirtualFiles.begin(),
- E = VirtualFiles.end();
+ mapVirtualFiles(*Sources);
+ return *Sources;
+ }
+
+ /// \brief Map the virtual file contents in the given \c SourceManager.
+ void mapVirtualFiles(SourceManager &SM) const {
+ for (llvm::SmallVectorImpl<VirtualFile>::const_iterator
+ I = VirtualFiles.begin(),
+ E = VirtualFiles.end();
I != E; ++I) {
llvm::MemoryBuffer *Buf = llvm::MemoryBuffer::getMemBuffer(I->Code);
- const FileEntry *Entry = Files.getVirtualFile(
+ const FileEntry *Entry = SM.getFileManager().getVirtualFile(
I->FileName, Buf->getBufferSize(), /*ModificationTime=*/0);
- Sources->overrideFileContents(Entry, Buf);
+ SM.overrideFileContents(Entry, Buf);
}
- return *Sources;
}
private:
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits