18f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===--- FileRemapper.cpp - File Remapping Helper -------------------------===//
28f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//
38f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//                     The LLVM Compiler Infrastructure
48f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//
58f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// This file is distributed under the University of Illinois Open Source
68f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// License. See LICENSE.TXT for details.
78f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//
88f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
98f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
108f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/ARCMigrate/FileRemapper.h"
1130660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Basic/Diagnostic.h"
1255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/FileManager.h"
1355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/PreprocessorOptions.h"
1455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/FileSystem.h"
158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/Support/MemoryBuffer.h"
168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/Support/Path.h"
178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/Support/raw_ostream.h"
188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include <fstream>
198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace clang;
218f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace arcmt;
228f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
238f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallFileRemapper::FileRemapper() {
248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  FileMgr.reset(new FileManager(FileSystemOptions()));
258f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
278f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallFileRemapper::~FileRemapper() {
288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  clear();
298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
308f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
315f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid FileRemapper::clear(StringRef outputDir) {
328f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  for (MappingsTy::iterator
338f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall         I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I)
348f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    resetTarget(I->second);
358f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  FromToMappings.clear();
368f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  assert(ToFromMappings.empty());
378f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!outputDir.empty()) {
388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    std::string infoFile = getRemapInfoFile(outputDir);
39651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    llvm::sys::fs::remove(infoFile);
408f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
418f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
428f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
435f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstd::string FileRemapper::getRemapInfoFile(StringRef outputDir) {
448f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  assert(!outputDir.empty());
450b214905f7fff7fa21ecc54a17b97372ba0c9a07Benjamin Kramer  SmallString<128> InfoFile = outputDir;
460b214905f7fff7fa21ecc54a17b97372ba0c9a07Benjamin Kramer  llvm::sys::path::append(InfoFile, "remap");
470b214905f7fff7fa21ecc54a17b97372ba0c9a07Benjamin Kramer  return InfoFile.str();
488f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
498f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
50d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikiebool FileRemapper::initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
518f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall                                bool ignoreIfFilesChanged) {
5230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  std::string infoFile = getRemapInfoFile(outputDir);
5330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return initFromFile(infoFile, Diag, ignoreIfFilesChanged);
5430660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
5530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
5630660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
5730660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                bool ignoreIfFilesChanged) {
588f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  assert(FromToMappings.empty() &&
598f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall         "initFromDisk should be called before any remap calls");
6030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  std::string infoFile = filePath;
618f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  bool fileExists = false;
628f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  llvm::sys::fs::exists(infoFile, fileExists);
638f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!fileExists)
648f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return false;
658f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
668f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
68ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
69ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      llvm::MemoryBuffer::getFile(infoFile.c_str());
70ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  if (!fileBuf)
716748ae15b3eed61b3b61f9b77470a802a1643fbbBenjamin Kramer    return report("Error opening file: " + infoFile, Diag);
7256773de654224ef1504ae67a3aa87ffed189e6feArgyrios Kyrtzidis
7356773de654224ef1504ae67a3aa87ffed189e6feArgyrios Kyrtzidis  SmallVector<StringRef, 64> lines;
74ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  fileBuf.get()->getBuffer().split(lines, "\n");
758f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
76d37c67b8f26ffe31e7f7292f26ab39cee78151d8Argyrios Kyrtzidis  for (unsigned idx = 0; idx+3 <= lines.size(); idx += 3) {
776748ae15b3eed61b3b61f9b77470a802a1643fbbBenjamin Kramer    StringRef fromFilename = lines[idx];
78484e2b195605cfe92b79b3baf9ea070666f8b332Douglas Gregor    unsigned long long timeModified;
7995109d2eb6f3670e8558868429f2a622b05e7d4fDavid Blaikie    if (lines[idx+1].getAsInteger(10, timeModified))
8095109d2eb6f3670e8558868429f2a622b05e7d4fDavid Blaikie      return report("Invalid file data: '" + lines[idx+1] + "' not a number",
8195109d2eb6f3670e8558868429f2a622b05e7d4fDavid Blaikie                    Diag);
826748ae15b3eed61b3b61f9b77470a802a1643fbbBenjamin Kramer    StringRef toFilename = lines[idx+2];
8356773de654224ef1504ae67a3aa87ffed189e6feArgyrios Kyrtzidis
848f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    const FileEntry *origFE = FileMgr->getFile(fromFilename);
858f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (!origFE) {
868f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      if (ignoreIfFilesChanged)
878f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall        continue;
886748ae15b3eed61b3b61f9b77470a802a1643fbbBenjamin Kramer      return report("File does not exist: " + fromFilename, Diag);
898f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    const FileEntry *newFE = FileMgr->getFile(toFilename);
918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (!newFE) {
928f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      if (ignoreIfFilesChanged)
938f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall        continue;
946748ae15b3eed61b3b61f9b77470a802a1643fbbBenjamin Kramer      return report("File does not exist: " + toFilename, Diag);
958f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
968f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
978f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if ((uint64_t)origFE->getModificationTime() != timeModified) {
988f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      if (ignoreIfFilesChanged)
998f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall        continue;
1006748ae15b3eed61b3b61f9b77470a802a1643fbbBenjamin Kramer      return report("File was modified: " + fromFilename, Diag);
1018f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
1028f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    pairs.push_back(std::make_pair(origFE, newFE));
1048f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1058f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1068f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  for (unsigned i = 0, e = pairs.size(); i != e; ++i)
1078f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    remap(pairs[i].first, pairs[i].second);
1088f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1098f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return false;
1108f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
1118f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
112d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikiebool FileRemapper::flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag) {
1138f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  using namespace llvm::sys;
1148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
115ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  if (fs::create_directory(outputDir))
1166748ae15b3eed61b3b61f9b77470a802a1643fbbBenjamin Kramer    return report("Could not create directory: " + outputDir, Diag);
1178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  std::string infoFile = getRemapInfoFile(outputDir);
11930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return flushToFile(infoFile, Diag);
12030660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
12130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
12230660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
12330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  using namespace llvm::sys;
12430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  std::string errMsg;
12630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  std::string infoFile = outputPath;
127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  llvm::raw_fd_ostream infoOut(infoFile.c_str(), errMsg, llvm::sys::fs::F_None);
12855a8a8db2d6a75343008fe8fde50865530d90cecArgyrios Kyrtzidis  if (!errMsg.empty())
1298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return report(errMsg, Diag);
1308f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1318f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  for (MappingsTy::iterator
1328f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall         I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
1338f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1348f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    const FileEntry *origFE = I->first;
135f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    SmallString<200> origPath = StringRef(origFE->getName());
13669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    fs::make_absolute(origPath);
13769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    infoOut << origPath << '\n';
1388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    infoOut << (uint64_t)origFE->getModificationTime() << '\n';
1398f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1408f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
141f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith      SmallString<200> newPath = StringRef(FE->getName());
14269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      fs::make_absolute(newPath);
14369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      infoOut << newPath << '\n';
1448f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    } else {
1458f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
146f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith      SmallString<64> tempPath;
1478f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      int fd;
1481ec4a86a867fc04f35d13bc9e33b04cf2171fe41Rafael Espindola      if (fs::createTemporaryFile(path::filename(origFE->getName()),
1491ec4a86a867fc04f35d13bc9e33b04cf2171fe41Rafael Espindola                                  path::extension(origFE->getName()), fd,
1501ec4a86a867fc04f35d13bc9e33b04cf2171fe41Rafael Espindola                                  tempPath))
1516748ae15b3eed61b3b61f9b77470a802a1643fbbBenjamin Kramer        return report("Could not create file: " + tempPath.str(), Diag);
1528f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1538f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      llvm::raw_fd_ostream newOut(fd, /*shouldClose=*/true);
1548f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
1558f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      newOut.write(mem->getBufferStart(), mem->getBufferSize());
1568f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      newOut.close();
1578f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1588f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      const FileEntry *newE = FileMgr->getFile(tempPath);
1598f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      remap(origFE, newE);
1608f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      infoOut << newE->getName() << '\n';
1618f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
1628f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1638f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1648f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  infoOut.close();
1658f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return false;
1668f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
1678f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
168d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikiebool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag,
1695f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                     StringRef outputDir) {
1708f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  using namespace llvm::sys;
1718f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1728f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  for (MappingsTy::iterator
1738f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall         I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
1748f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    const FileEntry *origFE = I->first;
175ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    assert(I->second.is<llvm::MemoryBuffer *>());
176ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    bool fileExists = false;
177ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    fs::exists(origFE->getName(), fileExists);
178ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    if (!fileExists)
179ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis      return report(StringRef("File does not exist: ") + origFE->getName(),
180ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis                    Diag);
1818f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
182ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    std::string errMsg;
183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    llvm::raw_fd_ostream Out(origFE->getName(), errMsg, llvm::sys::fs::F_None);
184ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    if (!errMsg.empty())
185ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis      return report(errMsg, Diag);
1868f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
187ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
188ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    Out.write(mem->getBufferStart(), mem->getBufferSize());
189ad3c2b5faa3f28b0425eb3a0d6c994ec8ca65019Argyrios Kyrtzidis    Out.close();
1908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1928f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  clear(outputDir);
1938f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return false;
1948f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
1958f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
19630660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const {
1978f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  for (MappingsTy::const_iterator
1988f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall         I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
1998f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
2008f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      PPOpts.addRemappedFile(I->first->getName(), FE->getName());
2018f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    } else {
2028f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
2038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      PPOpts.addRemappedFile(I->first->getName(), mem);
2048f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
2058f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2068f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2078f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  PPOpts.RetainRemappedFileBuffers = true;
2088f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2098f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2105f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid FileRemapper::remap(StringRef filePath, llvm::MemoryBuffer *memBuf) {
2118f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  remap(getOriginalFile(filePath), memBuf);
2128f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2138f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallvoid FileRemapper::remap(const FileEntry *file, llvm::MemoryBuffer *memBuf) {
2158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  assert(file);
2168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  Target &targ = FromToMappings[file];
2178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  resetTarget(targ);
2188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  targ = memBuf;
2198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2218f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallvoid FileRemapper::remap(const FileEntry *file, const FileEntry *newfile) {
2228f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  assert(file && newfile);
2238f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  Target &targ = FromToMappings[file];
2248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  resetTarget(targ);
2258f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  targ = newfile;
2268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  ToFromMappings[newfile] = file;
2278f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2295f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerconst FileEntry *FileRemapper::getOriginalFile(StringRef filePath) {
2308f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  const FileEntry *file = FileMgr->getFile(filePath);
2318f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  // If we are updating a file that overriden an original file,
2328f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  // actually update the original file.
2338f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
2348f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    I = ToFromMappings.find(file);
2358f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (I != ToFromMappings.end()) {
2368f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    file = I->second;
2378f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    assert(FromToMappings.find(file) != FromToMappings.end() &&
2388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall           "Original file not in mappings!");
2398f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2408f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return file;
2418f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2428f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2438f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallvoid FileRemapper::resetTarget(Target &targ) {
2448f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!targ)
2458f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return;
2468f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2478f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (llvm::MemoryBuffer *oldmem = targ.dyn_cast<llvm::MemoryBuffer *>()) {
2488f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    delete oldmem;
2498f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  } else {
2508f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    const FileEntry *toFE = targ.get<const FileEntry *>();
2517e42392eb2ea29ddeb6d125417fb4c17d847b5e0Benjamin Kramer    ToFromMappings.erase(toFE);
2528f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
2538f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2548f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
255d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikiebool FileRemapper::report(const Twine &err, DiagnosticsEngine &Diag) {
256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      << err.str();
2588f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return true;
2598f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
260