clang: lib/ARCMigrate/FileRemapper.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

13#include "llvm/Support/FileSystem.h"

14#include "llvm/Support/MemoryBuffer.h"

15#include "llvm/Support/Path.h"

16#include "llvm/Support/raw_ostream.h"

17#include

18

19using namespace clang;

20using namespace arcmt;

21

24}

25

28}

29

31 for (MappingsTy::iterator

32 I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I)

33 resetTarget(I->second);

34 FromToMappings.clear();

35 assert(ToFromMappings.empty());

36 if (!outputDir.empty()) {

37 std::string infoFile = getRemapInfoFile(outputDir);

38 llvm::sys::fs::remove(infoFile);

39 }

40}

41

42std::string FileRemapper::getRemapInfoFile(StringRef outputDir) {

43 assert(!outputDir.empty());

45 llvm::sys::path::append(InfoFile, "remap");

46 return std::string(InfoFile);

47}

48

50 bool ignoreIfFilesChanged) {

51 std::string infoFile = getRemapInfoFile(outputDir);

53}

54

56 bool ignoreIfFilesChanged) {

57 assert(FromToMappings.empty() &&

58 "initFromDisk should be called before any remap calls");

59 std::string infoFile = std::string(filePath);

60 if (!llvm::sys::fs::exists(infoFile))

61 return false;

62

63 std::vector<std::pair<FileEntryRef, FileEntryRef>> pairs;

64

65 llvm::ErrorOr<std::unique_ptrllvm::MemoryBuffer> fileBuf =

66 llvm::MemoryBuffer::getFile(infoFile, true);

67 if (!fileBuf)

68 return report("Error opening file: " + infoFile, Diag);

69

71 fileBuf.get()->getBuffer().split(lines, "\n");

72

73 for (unsigned idx = 0; idx+3 <= lines.size(); idx += 3) {

74 StringRef fromFilename = lines[idx];

75 unsigned long long timeModified;

76 if (lines[idx+1].getAsInteger(10, timeModified))

77 return report("Invalid file data: '" + lines[idx+1] + "' not a number",

79 StringRef toFilename = lines[idx+2];

80

81 auto origFE = FileMgr->getOptionalFileRef(fromFilename);

82 if (!origFE) {

83 if (ignoreIfFilesChanged)

84 continue;

85 return report("File does not exist: " + fromFilename, Diag);

86 }

87 auto newFE = FileMgr->getOptionalFileRef(toFilename);

88 if (!newFE) {

89 if (ignoreIfFilesChanged)

90 continue;

91 return report("File does not exist: " + toFilename, Diag);

92 }

93

94 if ((uint64_t)origFE->getModificationTime() != timeModified) {

95 if (ignoreIfFilesChanged)

96 continue;

97 return report("File was modified: " + fromFilename, Diag);

98 }

99

100 pairs.push_back(std::make_pair(*origFE, *newFE));

101 }

102

103 for (unsigned i = 0, e = pairs.size(); i != e; ++i)

104 remap(pairs[i].first, pairs[i].second);

105

106 return false;

107}

108

110 using namespace llvm::sys;

111

112 if (fs::create_directory(outputDir))

113 return report("Could not create directory: " + outputDir, Diag);

114

115 std::string infoFile = getRemapInfoFile(outputDir);

117}

118

120 using namespace llvm::sys;

121

122 std::error_code EC;

123 std::string infoFile = std::string(outputPath);

124 llvm::raw_fd_ostream infoOut(infoFile, EC, llvm::sys::fs::OF_Text);

125 if (EC)

126 return report(EC.message(), Diag);

127

128 for (MappingsTy::iterator

129 I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {

130

133 fs::make_absolute(origPath);

134 infoOut << origPath << '\n';

136

137 if (const auto *FE = std::get_if(&I->second)) {

139 fs::make_absolute(newPath);

140 infoOut << newPath << '\n';

141 } else {

142

144 int fd;

145 if (fs::createTemporaryFile(

146 path::filename(origFE.getName()),

147 path::extension(origFE.getName()).drop_front(), fd, tempPath,

148 llvm::sys::fs::OF_Text))

149 return report("Could not create file: " + tempPath.str(), Diag);

150

151 llvm::raw_fd_ostream newOut(fd, true);

152 llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(I->second);

153 newOut.write(mem->getBufferStart(), mem->getBufferSize());

154 newOut.close();

155

156 auto newE = FileMgr->getOptionalFileRef(tempPath);

157 if (newE) {

158 remap(origFE, *newE);

159 infoOut << newE->getName() << '\n';

160 }

161 }

162 }

163

164 infoOut.close();

165 return false;

166}

167

169 StringRef outputDir) {

170 using namespace llvm::sys;

171

172 for (MappingsTy::iterator

173 I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {

175 assert(std::holds_alternative<llvm::MemoryBuffer *>(I->second));

176 if (!fs::exists(origFE.getName()))

177 return report(StringRef("File does not exist: ") + origFE.getName(),

179

180 std::error_code EC;

181 llvm::raw_fd_ostream Out(origFE.getName(), EC, llvm::sys::fs::OF_None);

182 if (EC)

183 return report(EC.message(), Diag);

184

185 llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(I->second);

186 Out.write(mem->getBufferStart(), mem->getBufferSize());

187 Out.close();

188 }

189

190 clear(outputDir);

191 return false;

192}

193

195 llvm::function_ref<void(StringRef, StringRef)> CaptureFile,

196 llvm::function_ref<void(StringRef, const llvm::MemoryBufferRef &)>

197 CaptureBuffer) const {

198 for (auto &Mapping : FromToMappings) {

199 if (const auto *FE = std::get_if(&Mapping.second)) {

200 CaptureFile(Mapping.first.getName(), FE->getName());

201 continue;

202 }

203 CaptureBuffer(

204 Mapping.first.getName(),

205 std::get<llvm::MemoryBuffer *>(Mapping.second)->getMemBufferRef());

206 }

207}

208

210 for (MappingsTy::const_iterator

211 I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {

212 if (const auto *FE = std::get_if(&I->second)) {

213 PPOpts.addRemappedFile(I->first.getName(), FE->getName());

214 } else {

215 llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(I->second);

217 }

218 }

219

221}

222

224 std::unique_ptrllvm::MemoryBuffer memBuf) {

226 assert(File);

228}

229

231 std::unique_ptrllvm::MemoryBuffer MemBuf) {

232 auto [It, New] = FromToMappings.insert({File, nullptr});

233 if (!New)

234 resetTarget(It->second);

235 It->second = MemBuf.release();

236}

237

239 auto [It, New] = FromToMappings.insert({File, nullptr});

240 if (!New)

241 resetTarget(It->second);

242 It->second = NewFile;

243 ToFromMappings.insert({NewFile, File});

244}

245

249 return std::nullopt;

250

251

252 auto I = ToFromMappings.find(*File);

253 if (I != ToFromMappings.end()) {

254 *File = I->second;

255 assert(FromToMappings.contains(*File) && "Original file not in mappings!");

256 }

258}

259

260void FileRemapper::resetTarget(Target &targ) {

261 if (std::holds_alternative<llvm::MemoryBuffer *>(targ)) {

262 llvm::MemoryBuffer *oldmem = std::get<llvm::MemoryBuffer *>(targ);

263 delete oldmem;

264 } else {

265 FileEntryRef toFE = std::get(targ);

266 ToFromMappings.erase(toFE);

267 }

268}

269

272 << err.str();

273 return true;

274}

Defines the Diagnostic-related interfaces.

Defines the clang::FileManager interface and associated types.

static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)

Produce a diagnostic highlighting some portion of a literal.

llvm::MachO::Target Target

Concrete class used by the front-end to report problems and issues.

A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...

time_t getModificationTime() const

StringRef getName() const

The name of this FileEntry.

Implements support for file system lookup, file system caching, and directory search management.

Keeps track of options that affect how file operations are performed.

PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...

bool RetainRemappedFileBuffers

Whether the compiler instance should retain (i.e., not free) the buffers associated with remapped fil...

void addRemappedFile(StringRef From, StringRef To)

bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)

void forEachMapping(llvm::function_ref< void(StringRef, StringRef)> CaptureFile, llvm::function_ref< void(StringRef, const llvm::MemoryBufferRef &)> CaptureBuffer) const

Iterate through all the mappings.

bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)

bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag)

void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)

void clear(StringRef outputDir=StringRef())

void applyMappings(PreprocessorOptions &PPOpts) const

bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)

bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir=StringRef())

The JSON file list parser is used to communicate input to InstallAPI.