1 //===--- ARCMT.cpp - Migration to ARC mode --------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "Internals.h"
11 #include "clang/Frontend/ASTUnit.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Frontend/TextDiagnosticPrinter.h"
14 #include "clang/Frontend/Utils.h"
15 #include "clang/AST/ASTConsumer.h"
16 #include "clang/Rewrite/Rewriter.h"
17 #include "clang/Sema/SemaDiagnostic.h"
18 #include "clang/Basic/DiagnosticCategories.h"
19 #include "clang/Lex/Preprocessor.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/ADT/Triple.h"
22 using namespace clang;
23 using namespace arcmt;
24 
25 bool CapturedDiagList::clearDiagnostic(ArrayRef<unsigned> IDs,
26                                        SourceRange range) {
27   if (range.isInvalid())
28     return false;
29 
30   bool cleared = false;
31   ListTy::iterator I = List.begin();
32   while (I != List.end()) {
33     FullSourceLoc diagLoc = I->getLocation();
34     if ((IDs.empty() || // empty means clear all diagnostics in the range.
35          std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
36         !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
37         (diagLoc == range.getEnd() ||
38            diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
39       cleared = true;
40       ListTy::iterator eraseS = I++;
41       while (I != List.end() && I->getLevel() == DiagnosticsEngine::Note)
42         ++I;
43       // Clear the diagnostic and any notes following it.
44       List.erase(eraseS, I);
45       continue;
46     }
47 
48     ++I;
49   }
50 
51   return cleared;
52 }
53 
54 bool CapturedDiagList::hasDiagnostic(ArrayRef<unsigned> IDs,
55                                      SourceRange range) const {
56   if (range.isInvalid())
57     return false;
58 
59   ListTy::const_iterator I = List.begin();
60   while (I != List.end()) {
61     FullSourceLoc diagLoc = I->getLocation();
62     if ((IDs.empty() || // empty means any diagnostic in the range.
63          std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
64         !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
65         (diagLoc == range.getEnd() ||
66            diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
67       return true;
68     }
69 
70     ++I;
71   }
72 
73   return false;
74 }
75 
76 void CapturedDiagList::reportDiagnostics(DiagnosticsEngine &Diags) const {
77   for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
78     Diags.Report(*I);
79 }
80 
81 bool CapturedDiagList::hasErrors() const {
82   for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
83     if (I->getLevel() >= DiagnosticsEngine::Error)
84       return true;
85 
86   return false;
87 }
88 
89 namespace {
90 
91 class CaptureDiagnosticConsumer : public DiagnosticConsumer {
92   DiagnosticsEngine &Diags;
93   CapturedDiagList &CapturedDiags;
94 public:
95   CaptureDiagnosticConsumer(DiagnosticsEngine &diags,
96                            CapturedDiagList &capturedDiags)
97     : Diags(diags), CapturedDiags(capturedDiags) { }
98 
99   virtual void HandleDiagnostic(DiagnosticsEngine::Level level,
100                                 const Diagnostic &Info) {
101     if (DiagnosticIDs::isARCDiagnostic(Info.getID()) ||
102         level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) {
103       CapturedDiags.push_back(StoredDiagnostic(level, Info));
104       return;
105     }
106 
107     // Non-ARC warnings are ignored.
108     Diags.setLastDiagnosticIgnored();
109   }
110 
111   DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
112     // Just drop any diagnostics that come from cloned consumers; they'll
113     // have different source managers anyway.
114     return new IgnoringDiagConsumer();
115   }
116 };
117 
118 } // end anonymous namespace
119 
120 static inline StringRef SimulatorVersionDefineName() {
121   return "__IPHONE_OS_VERSION_MIN_REQUIRED=";
122 }
123 
124 /// \brief Parse the simulator version define:
125 /// __IPHONE_OS_VERSION_MIN_REQUIRED=([0-9])([0-9][0-9])([0-9][0-9])
126 // and return the grouped values as integers, e.g:
127 //   __IPHONE_OS_VERSION_MIN_REQUIRED=40201
128 // will return Major=4, Minor=2, Micro=1.
129 static bool GetVersionFromSimulatorDefine(StringRef define,
130                                           unsigned &Major, unsigned &Minor,
131                                           unsigned &Micro) {
132   assert(define.startswith(SimulatorVersionDefineName()));
133   StringRef name, version;
134   llvm::tie(name, version) = define.split('=');
135   if (version.empty())
136     return false;
137   std::string verstr = version.str();
138   char *end;
139   unsigned num = (unsigned) strtol(verstr.c_str(), &end, 10);
140   if (*end != '\0')
141     return false;
142   Major = num / 10000;
143   num = num % 10000;
144   Minor = num / 100;
145   Micro = num % 100;
146   return true;
147 }
148 
149 static bool HasARCRuntime(CompilerInvocation &origCI) {
150   // This duplicates some functionality from Darwin::AddDeploymentTarget
151   // but this function is well defined, so keep it decoupled from the driver
152   // and avoid unrelated complications.
153 
154   for (unsigned i = 0, e = origCI.getPreprocessorOpts().Macros.size();
155          i != e; ++i) {
156     StringRef define = origCI.getPreprocessorOpts().Macros[i].first;
157     bool isUndef = origCI.getPreprocessorOpts().Macros[i].second;
158     if (isUndef)
159       continue;
160     if (!define.startswith(SimulatorVersionDefineName()))
161       continue;
162     unsigned Major = 0, Minor = 0, Micro = 0;
163     if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) &&
164         Major < 10 && Minor < 100 && Micro < 100)
165       return Major >= 5;
166   }
167 
168   llvm::Triple triple(origCI.getTargetOpts().Triple);
169 
170   if (triple.getOS() == llvm::Triple::IOS)
171     return triple.getOSMajorVersion() >= 5;
172 
173   if (triple.getOS() == llvm::Triple::Darwin)
174     return triple.getOSMajorVersion() >= 11;
175 
176   if (triple.getOS() == llvm::Triple::MacOSX) {
177     unsigned Major, Minor, Micro;
178     triple.getOSVersion(Major, Minor, Micro);
179     return Major > 10 || (Major == 10 && Minor >= 7);
180   }
181 
182   return false;
183 }
184 
185 static CompilerInvocation *
186 createInvocationForMigration(CompilerInvocation &origCI) {
187   llvm::OwningPtr<CompilerInvocation> CInvok;
188   CInvok.reset(new CompilerInvocation(origCI));
189   CInvok->getPreprocessorOpts().ImplicitPCHInclude = std::string();
190   CInvok->getPreprocessorOpts().ImplicitPTHInclude = std::string();
191   std::string define = getARCMTMacroName();
192   define += '=';
193   CInvok->getPreprocessorOpts().addMacroDef(define);
194   CInvok->getLangOpts().ObjCAutoRefCount = true;
195   CInvok->getLangOpts().setGC(LangOptions::NonGC);
196   CInvok->getDiagnosticOpts().ErrorLimit = 0;
197   CInvok->getDiagnosticOpts().Warnings.push_back(
198                                             "error=arc-unsafe-retained-assign");
199   CInvok->getLangOpts().ObjCRuntimeHasWeak = HasARCRuntime(origCI);
200 
201   return CInvok.take();
202 }
203 
204 static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
205                                    const DiagnosticOptions &diagOpts,
206                                    Preprocessor &PP) {
207   TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
208   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
209   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
210       new DiagnosticsEngine(DiagID, &printer, /*ShouldOwnClient=*/false));
211   Diags->setSourceManager(&PP.getSourceManager());
212 
213   printer.BeginSourceFile(PP.getLangOptions(), &PP);
214   arcDiags.reportDiagnostics(*Diags);
215   printer.EndSourceFile();
216 }
217 
218 //===----------------------------------------------------------------------===//
219 // checkForManualIssues.
220 //===----------------------------------------------------------------------===//
221 
222 bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
223                                  StringRef Filename, InputKind Kind,
224                                  DiagnosticConsumer *DiagClient,
225                                  bool emitPremigrationARCErrors,
226                                  StringRef plistOut) {
227   if (!origCI.getLangOpts().ObjC1)
228     return false;
229 
230   LangOptions::GCMode OrigGCMode = origCI.getLangOpts().getGC();
231 
232   std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode);
233   assert(!transforms.empty());
234 
235   llvm::OwningPtr<CompilerInvocation> CInvok;
236   CInvok.reset(createInvocationForMigration(origCI));
237   CInvok->getFrontendOpts().Inputs.clear();
238   CInvok->getFrontendOpts().Inputs.push_back(std::make_pair(Kind, Filename));
239 
240   CapturedDiagList capturedDiags;
241 
242   assert(DiagClient);
243   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
244   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
245       new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
246 
247   // Filter of all diagnostics.
248   CaptureDiagnosticConsumer errRec(*Diags, capturedDiags);
249   Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
250 
251   llvm::OwningPtr<ASTUnit> Unit(
252       ASTUnit::LoadFromCompilerInvocationAction(CInvok.take(), Diags));
253   if (!Unit)
254     return true;
255 
256   // Don't filter diagnostics anymore.
257   Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
258 
259   ASTContext &Ctx = Unit->getASTContext();
260 
261   if (Diags->hasFatalErrorOccurred()) {
262     Diags->Reset();
263     DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
264     capturedDiags.reportDiagnostics(*Diags);
265     DiagClient->EndSourceFile();
266     return true;
267   }
268 
269   if (emitPremigrationARCErrors)
270     emitPremigrationErrors(capturedDiags, origCI.getDiagnosticOpts(),
271                            Unit->getPreprocessor());
272   if (!plistOut.empty()) {
273     SmallVector<StoredDiagnostic, 8> arcDiags;
274     for (CapturedDiagList::iterator
275            I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
276       arcDiags.push_back(*I);
277     writeARCDiagsToPlist(plistOut, arcDiags,
278                          Ctx.getSourceManager(), Ctx.getLangOptions());
279   }
280 
281   // After parsing of source files ended, we want to reuse the
282   // diagnostics objects to emit further diagnostics.
283   // We call BeginSourceFile because DiagnosticConsumer requires that
284   // diagnostics with source range information are emitted only in between
285   // BeginSourceFile() and EndSourceFile().
286   DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
287 
288   // No macros will be added since we are just checking and we won't modify
289   // source code.
290   std::vector<SourceLocation> ARCMTMacroLocs;
291 
292   TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
293   MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, ARCMTMacroLocs);
294 
295   for (unsigned i=0, e = transforms.size(); i != e; ++i)
296     transforms[i](pass);
297 
298   capturedDiags.reportDiagnostics(*Diags);
299 
300   DiagClient->EndSourceFile();
301 
302   // If we are migrating code that gets the '-fobjc-arc' flag, make sure
303   // to remove it so that we don't get errors from normal compilation.
304   origCI.getLangOpts().ObjCAutoRefCount = false;
305 
306   return capturedDiags.hasErrors() || testAct.hasReportedErrors();
307 }
308 
309 //===----------------------------------------------------------------------===//
310 // applyTransformations.
311 //===----------------------------------------------------------------------===//
312 
313 static bool applyTransforms(CompilerInvocation &origCI,
314                             StringRef Filename, InputKind Kind,
315                             DiagnosticConsumer *DiagClient,
316                             StringRef outputDir,
317                             bool emitPremigrationARCErrors,
318                             StringRef plistOut) {
319   if (!origCI.getLangOpts().ObjC1)
320     return false;
321 
322   LangOptions::GCMode OrigGCMode = origCI.getLangOpts().getGC();
323 
324   // Make sure checking is successful first.
325   CompilerInvocation CInvokForCheck(origCI);
326   if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient,
327                                   emitPremigrationARCErrors, plistOut))
328     return true;
329 
330   CompilerInvocation CInvok(origCI);
331   CInvok.getFrontendOpts().Inputs.clear();
332   CInvok.getFrontendOpts().Inputs.push_back(std::make_pair(Kind, Filename));
333 
334   MigrationProcess migration(CInvok, DiagClient, outputDir);
335 
336   std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode);
337   assert(!transforms.empty());
338 
339   for (unsigned i=0, e = transforms.size(); i != e; ++i) {
340     bool err = migration.applyTransform(transforms[i]);
341     if (err) return true;
342   }
343 
344   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
345   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
346       new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
347 
348   if (outputDir.empty()) {
349     origCI.getLangOpts().ObjCAutoRefCount = true;
350     return migration.getRemapper().overwriteOriginal(*Diags);
351   } else {
352     // If we are migrating code that gets the '-fobjc-arc' flag, make sure
353     // to remove it so that we don't get errors from normal compilation.
354     origCI.getLangOpts().ObjCAutoRefCount = false;
355     return migration.getRemapper().flushToDisk(outputDir, *Diags);
356   }
357 }
358 
359 bool arcmt::applyTransformations(CompilerInvocation &origCI,
360                                  StringRef Filename, InputKind Kind,
361                                  DiagnosticConsumer *DiagClient) {
362   return applyTransforms(origCI, Filename, Kind, DiagClient,
363                          StringRef(), false, StringRef());
364 }
365 
366 bool arcmt::migrateWithTemporaryFiles(CompilerInvocation &origCI,
367                                       StringRef Filename, InputKind Kind,
368                                       DiagnosticConsumer *DiagClient,
369                                       StringRef outputDir,
370                                       bool emitPremigrationARCErrors,
371                                       StringRef plistOut) {
372   assert(!outputDir.empty() && "Expected output directory path");
373   return applyTransforms(origCI, Filename, Kind, DiagClient,
374                          outputDir, emitPremigrationARCErrors, plistOut);
375 }
376 
377 bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
378                                   remap,
379                               StringRef outputDir,
380                               DiagnosticConsumer *DiagClient) {
381   assert(!outputDir.empty());
382 
383   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
384   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
385       new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
386 
387   FileRemapper remapper;
388   bool err = remapper.initFromDisk(outputDir, *Diags,
389                                    /*ignoreIfFilesChanged=*/true);
390   if (err)
391     return true;
392 
393   CompilerInvocation CI;
394   remapper.applyMappings(CI);
395   remap = CI.getPreprocessorOpts().RemappedFiles;
396 
397   return false;
398 }
399 
400 //===----------------------------------------------------------------------===//
401 // CollectTransformActions.
402 //===----------------------------------------------------------------------===//
403 
404 namespace {
405 
406 class ARCMTMacroTrackerPPCallbacks : public PPCallbacks {
407   std::vector<SourceLocation> &ARCMTMacroLocs;
408 
409 public:
410   ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
411     : ARCMTMacroLocs(ARCMTMacroLocs) { }
412 
413   virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo *MI,
414                             SourceRange Range) {
415     if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName())
416       ARCMTMacroLocs.push_back(MacroNameTok.getLocation());
417   }
418 };
419 
420 class ARCMTMacroTrackerAction : public ASTFrontendAction {
421   std::vector<SourceLocation> &ARCMTMacroLocs;
422 
423 public:
424   ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
425     : ARCMTMacroLocs(ARCMTMacroLocs) { }
426 
427   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
428                                          StringRef InFile) {
429     CI.getPreprocessor().addPPCallbacks(
430                               new ARCMTMacroTrackerPPCallbacks(ARCMTMacroLocs));
431     return new ASTConsumer();
432   }
433 };
434 
435 class RewritesApplicator : public TransformActions::RewriteReceiver {
436   Rewriter &rewriter;
437   ASTContext &Ctx;
438   MigrationProcess::RewriteListener *Listener;
439 
440 public:
441   RewritesApplicator(Rewriter &rewriter, ASTContext &ctx,
442                      MigrationProcess::RewriteListener *listener)
443     : rewriter(rewriter), Ctx(ctx), Listener(listener) {
444     if (Listener)
445       Listener->start(ctx);
446   }
447   ~RewritesApplicator() {
448     if (Listener)
449       Listener->finish();
450   }
451 
452   virtual void insert(SourceLocation loc, StringRef text) {
453     bool err = rewriter.InsertText(loc, text, /*InsertAfter=*/true,
454                                    /*indentNewLines=*/true);
455     if (!err && Listener)
456       Listener->insert(loc, text);
457   }
458 
459   virtual void remove(CharSourceRange range) {
460     Rewriter::RewriteOptions removeOpts;
461     removeOpts.IncludeInsertsAtBeginOfRange = false;
462     removeOpts.IncludeInsertsAtEndOfRange = false;
463     removeOpts.RemoveLineIfEmpty = true;
464 
465     bool err = rewriter.RemoveText(range, removeOpts);
466     if (!err && Listener)
467       Listener->remove(range);
468   }
469 
470   virtual void increaseIndentation(CharSourceRange range,
471                                     SourceLocation parentIndent) {
472     rewriter.IncreaseIndentation(range, parentIndent);
473   }
474 };
475 
476 } // end anonymous namespace.
477 
478 /// \brief Anchor for VTable.
479 MigrationProcess::RewriteListener::~RewriteListener() { }
480 
481 MigrationProcess::MigrationProcess(const CompilerInvocation &CI,
482                                    DiagnosticConsumer *diagClient,
483                                    StringRef outputDir)
484   : OrigCI(CI), DiagClient(diagClient) {
485   if (!outputDir.empty()) {
486     llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
487     llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
488       new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
489     Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true);
490   }
491 }
492 
493 bool MigrationProcess::applyTransform(TransformFn trans,
494                                       RewriteListener *listener) {
495   llvm::OwningPtr<CompilerInvocation> CInvok;
496   CInvok.reset(createInvocationForMigration(OrigCI));
497   CInvok->getDiagnosticOpts().IgnoreWarnings = true;
498 
499   Remapper.applyMappings(*CInvok);
500 
501   CapturedDiagList capturedDiags;
502   std::vector<SourceLocation> ARCMTMacroLocs;
503 
504   assert(DiagClient);
505   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
506   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
507       new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
508 
509   // Filter of all diagnostics.
510   CaptureDiagnosticConsumer errRec(*Diags, capturedDiags);
511   Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
512 
513   llvm::OwningPtr<ARCMTMacroTrackerAction> ASTAction;
514   ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs));
515 
516   llvm::OwningPtr<ASTUnit> Unit(
517       ASTUnit::LoadFromCompilerInvocationAction(CInvok.take(), Diags,
518                                                 ASTAction.get()));
519   if (!Unit)
520     return true;
521   Unit->setOwnsRemappedFileBuffers(false); // FileRemapper manages that.
522 
523   // Don't filter diagnostics anymore.
524   Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
525 
526   ASTContext &Ctx = Unit->getASTContext();
527 
528   if (Diags->hasFatalErrorOccurred()) {
529     Diags->Reset();
530     DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
531     capturedDiags.reportDiagnostics(*Diags);
532     DiagClient->EndSourceFile();
533     return true;
534   }
535 
536   // After parsing of source files ended, we want to reuse the
537   // diagnostics objects to emit further diagnostics.
538   // We call BeginSourceFile because DiagnosticConsumer requires that
539   // diagnostics with source range information are emitted only in between
540   // BeginSourceFile() and EndSourceFile().
541   DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
542 
543   Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOptions());
544   TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
545   MigrationPass pass(Ctx, OrigCI.getLangOpts().getGC(),
546                      Unit->getSema(), TA, ARCMTMacroLocs);
547 
548   trans(pass);
549 
550   {
551     RewritesApplicator applicator(rewriter, Ctx, listener);
552     TA.applyRewrites(applicator);
553   }
554 
555   DiagClient->EndSourceFile();
556 
557   if (DiagClient->getNumErrors())
558     return true;
559 
560   for (Rewriter::buffer_iterator
561         I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
562     FileID FID = I->first;
563     RewriteBuffer &buf = I->second;
564     const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
565     assert(file);
566     std::string newFname = file->getName();
567     newFname += "-trans";
568     llvm::SmallString<512> newText;
569     llvm::raw_svector_ostream vecOS(newText);
570     buf.write(vecOS);
571     vecOS.flush();
572     llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
573                    StringRef(newText.data(), newText.size()), newFname);
574     llvm::SmallString<64> filePath(file->getName());
575     Unit->getFileManager().FixupRelativePath(filePath);
576     Remapper.remap(filePath.str(), memBuf);
577   }
578 
579   return false;
580 }
581