1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "Internals.h" |
10 | #include "clang/AST/ASTConsumer.h" |
11 | #include "clang/Basic/DiagnosticCategories.h" |
12 | #include "clang/Frontend/ASTUnit.h" |
13 | #include "clang/Frontend/CompilerInstance.h" |
14 | #include "clang/Frontend/FrontendAction.h" |
15 | #include "clang/Frontend/TextDiagnosticPrinter.h" |
16 | #include "clang/Frontend/Utils.h" |
17 | #include "clang/Lex/Preprocessor.h" |
18 | #include "clang/Lex/PreprocessorOptions.h" |
19 | #include "clang/Rewrite/Core/Rewriter.h" |
20 | #include "clang/Sema/SemaDiagnostic.h" |
21 | #include "clang/Serialization/ASTReader.h" |
22 | #include "llvm/ADT/Triple.h" |
23 | #include "llvm/Support/MemoryBuffer.h" |
24 | #include <utility> |
25 | using namespace clang; |
26 | using namespace arcmt; |
27 | |
28 | bool CapturedDiagList::clearDiagnostic(ArrayRef<unsigned> IDs, |
29 | SourceRange range) { |
30 | if (range.isInvalid()) |
31 | return false; |
32 | |
33 | bool cleared = false; |
34 | ListTy::iterator I = List.begin(); |
35 | while (I != List.end()) { |
36 | FullSourceLoc diagLoc = I->getLocation(); |
37 | if ((IDs.empty() || |
38 | llvm::is_contained(IDs, I->getID())) && |
39 | !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) && |
40 | (diagLoc == range.getEnd() || |
41 | diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) { |
42 | cleared = true; |
43 | ListTy::iterator eraseS = I++; |
44 | if (eraseS->getLevel() != DiagnosticsEngine::Note) |
45 | while (I != List.end() && I->getLevel() == DiagnosticsEngine::Note) |
46 | ++I; |
47 | |
48 | I = List.erase(eraseS, I); |
49 | continue; |
50 | } |
51 | |
52 | ++I; |
53 | } |
54 | |
55 | return cleared; |
56 | } |
57 | |
58 | bool CapturedDiagList::hasDiagnostic(ArrayRef<unsigned> IDs, |
59 | SourceRange range) const { |
60 | if (range.isInvalid()) |
61 | return false; |
62 | |
63 | ListTy::const_iterator I = List.begin(); |
64 | while (I != List.end()) { |
65 | FullSourceLoc diagLoc = I->getLocation(); |
66 | if ((IDs.empty() || |
67 | std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) && |
68 | !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) && |
69 | (diagLoc == range.getEnd() || |
70 | diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) { |
71 | return true; |
72 | } |
73 | |
74 | ++I; |
75 | } |
76 | |
77 | return false; |
78 | } |
79 | |
80 | void CapturedDiagList::reportDiagnostics(DiagnosticsEngine &Diags) const { |
81 | for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I) |
82 | Diags.Report(*I); |
83 | } |
84 | |
85 | bool CapturedDiagList::hasErrors() const { |
86 | for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I) |
87 | if (I->getLevel() >= DiagnosticsEngine::Error) |
88 | return true; |
89 | |
90 | return false; |
91 | } |
92 | |
93 | namespace { |
94 | |
95 | class CaptureDiagnosticConsumer : public DiagnosticConsumer { |
96 | DiagnosticsEngine &Diags; |
97 | DiagnosticConsumer &DiagClient; |
98 | CapturedDiagList &CapturedDiags; |
99 | bool HasBegunSourceFile; |
100 | public: |
101 | CaptureDiagnosticConsumer(DiagnosticsEngine &diags, |
102 | DiagnosticConsumer &client, |
103 | CapturedDiagList &capturedDiags) |
104 | : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags), |
105 | HasBegunSourceFile(false) { } |
106 | |
107 | void BeginSourceFile(const LangOptions &Opts, |
108 | const Preprocessor *PP) override { |
109 | |
110 | |
111 | |
112 | if (!HasBegunSourceFile) { |
113 | DiagClient.BeginSourceFile(Opts, PP); |
114 | HasBegunSourceFile = true; |
115 | } |
116 | } |
117 | |
118 | void FinishCapture() { |
119 | |
120 | |
121 | |
122 | if (HasBegunSourceFile) { |
123 | DiagClient.EndSourceFile(); |
124 | HasBegunSourceFile = false; |
125 | } |
126 | } |
127 | |
128 | ~CaptureDiagnosticConsumer() override { |
129 | (0) . __assert_fail ("!HasBegunSourceFile && \"FinishCapture not called!\"", "/home/seafit/code_projects/clang_source/clang/lib/ARCMigrate/ARCMT.cpp", 129, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!HasBegunSourceFile && "FinishCapture not called!"); |
130 | } |
131 | |
132 | void HandleDiagnostic(DiagnosticsEngine::Level level, |
133 | const Diagnostic &Info) override { |
134 | if (DiagnosticIDs::isARCDiagnostic(Info.getID()) || |
135 | level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) { |
136 | if (Info.getLocation().isValid()) |
137 | CapturedDiags.push_back(StoredDiagnostic(level, Info)); |
138 | return; |
139 | } |
140 | |
141 | |
142 | Diags.setLastDiagnosticIgnored(); |
143 | } |
144 | }; |
145 | |
146 | } |
147 | |
148 | static bool HasARCRuntime(CompilerInvocation &origCI) { |
149 | |
150 | |
151 | |
152 | llvm::Triple triple(origCI.getTargetOpts().Triple); |
153 | |
154 | if (triple.isiOS()) |
155 | return triple.getOSMajorVersion() >= 5; |
156 | |
157 | if (triple.isWatchOS()) |
158 | return true; |
159 | |
160 | if (triple.getOS() == llvm::Triple::Darwin) |
161 | return triple.getOSMajorVersion() >= 11; |
162 | |
163 | if (triple.getOS() == llvm::Triple::MacOSX) { |
164 | unsigned Major, Minor, Micro; |
165 | triple.getOSVersion(Major, Minor, Micro); |
166 | return Major > 10 || (Major == 10 && Minor >= 7); |
167 | } |
168 | |
169 | return false; |
170 | } |
171 | |
172 | static CompilerInvocation * |
173 | createInvocationForMigration(CompilerInvocation &origCI, |
174 | const PCHContainerReader &PCHContainerRdr) { |
175 | std::unique_ptr<CompilerInvocation> CInvok; |
176 | CInvok.reset(new CompilerInvocation(origCI)); |
177 | PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); |
178 | if (!PPOpts.ImplicitPCHInclude.empty()) { |
179 | |
180 | |
181 | FileManager FileMgr(origCI.getFileSystemOpts()); |
182 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
183 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( |
184 | new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(), |
185 | new IgnoringDiagConsumer())); |
186 | std::string OriginalFile = ASTReader::getOriginalSourceFile( |
187 | PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerRdr, *Diags); |
188 | if (!OriginalFile.empty()) |
189 | PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile); |
190 | PPOpts.ImplicitPCHInclude.clear(); |
191 | } |
192 | std::string define = getARCMTMacroName(); |
193 | define += '='; |
194 | CInvok->getPreprocessorOpts().addMacroDef(define); |
195 | CInvok->getLangOpts()->ObjCAutoRefCount = true; |
196 | CInvok->getLangOpts()->setGC(LangOptions::NonGC); |
197 | CInvok->getDiagnosticOpts().ErrorLimit = 0; |
198 | CInvok->getDiagnosticOpts().PedanticErrors = 0; |
199 | |
200 | |
201 | std::vector<std::string> WarnOpts; |
202 | for (std::vector<std::string>::iterator |
203 | I = CInvok->getDiagnosticOpts().Warnings.begin(), |
204 | E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) { |
205 | if (!StringRef(*I).startswith("error")) |
206 | WarnOpts.push_back(*I); |
207 | } |
208 | WarnOpts.push_back("error=arc-unsafe-retained-assign"); |
209 | CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts); |
210 | |
211 | CInvok->getLangOpts()->ObjCWeakRuntime = HasARCRuntime(origCI); |
212 | CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime; |
213 | |
214 | return CInvok.release(); |
215 | } |
216 | |
217 | static void emitPremigrationErrors(const CapturedDiagList &arcDiags, |
218 | DiagnosticOptions *diagOpts, |
219 | Preprocessor &PP) { |
220 | TextDiagnosticPrinter printer(llvm::errs(), diagOpts); |
221 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
222 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( |
223 | new DiagnosticsEngine(DiagID, diagOpts, &printer, |
224 | )); |
225 | Diags->setSourceManager(&PP.getSourceManager()); |
226 | |
227 | printer.BeginSourceFile(PP.getLangOpts(), &PP); |
228 | arcDiags.reportDiagnostics(*Diags); |
229 | printer.EndSourceFile(); |
230 | } |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | bool arcmt::checkForManualIssues( |
237 | CompilerInvocation &origCI, const FrontendInputFile &Input, |
238 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, |
239 | DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors, |
240 | StringRef plistOut) { |
241 | if (!origCI.getLangOpts()->ObjC) |
242 | return false; |
243 | |
244 | LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC(); |
245 | bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError; |
246 | bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval; |
247 | |
248 | std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode, |
249 | NoFinalizeRemoval); |
250 | assert(!transforms.empty()); |
251 | |
252 | std::unique_ptr<CompilerInvocation> CInvok; |
253 | CInvok.reset( |
254 | createInvocationForMigration(origCI, PCHContainerOps->getRawReader())); |
255 | CInvok->getFrontendOpts().Inputs.clear(); |
256 | CInvok->getFrontendOpts().Inputs.push_back(Input); |
257 | |
258 | CapturedDiagList capturedDiags; |
259 | |
260 | assert(DiagClient); |
261 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
262 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( |
263 | new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(), |
264 | DiagClient, )); |
265 | |
266 | |
267 | CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags); |
268 | Diags->setClient(&errRec, ); |
269 | |
270 | std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction( |
271 | std::move(CInvok), PCHContainerOps, Diags)); |
272 | if (!Unit) { |
273 | errRec.FinishCapture(); |
274 | return true; |
275 | } |
276 | |
277 | |
278 | Diags->setClient(DiagClient, ); |
279 | |
280 | ASTContext &Ctx = Unit->getASTContext(); |
281 | |
282 | if (Diags->hasFatalErrorOccurred()) { |
283 | Diags->Reset(); |
284 | DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor()); |
285 | capturedDiags.reportDiagnostics(*Diags); |
286 | DiagClient->EndSourceFile(); |
287 | errRec.FinishCapture(); |
288 | return true; |
289 | } |
290 | |
291 | if (emitPremigrationARCErrors) |
292 | emitPremigrationErrors(capturedDiags, &origCI.getDiagnosticOpts(), |
293 | Unit->getPreprocessor()); |
294 | if (!plistOut.empty()) { |
295 | SmallVector<StoredDiagnostic, 8> arcDiags; |
296 | for (CapturedDiagList::iterator |
297 | I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I) |
298 | arcDiags.push_back(*I); |
299 | writeARCDiagsToPlist(plistOut, arcDiags, |
300 | Ctx.getSourceManager(), Ctx.getLangOpts()); |
301 | } |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor()); |
309 | |
310 | |
311 | |
312 | std::vector<SourceLocation> ARCMTMacroLocs; |
313 | |
314 | TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor()); |
315 | MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags, |
316 | ARCMTMacroLocs); |
317 | pass.setNoFinalizeRemoval(NoFinalizeRemoval); |
318 | if (!NoNSAllocReallocError) |
319 | Diags->setSeverity(diag::warn_arcmt_nsalloc_realloc, diag::Severity::Error, |
320 | SourceLocation()); |
321 | |
322 | for (unsigned i=0, e = transforms.size(); i != e; ++i) |
323 | transforms[i](pass); |
324 | |
325 | capturedDiags.reportDiagnostics(*Diags); |
326 | |
327 | DiagClient->EndSourceFile(); |
328 | errRec.FinishCapture(); |
329 | |
330 | return capturedDiags.hasErrors() || testAct.hasReportedErrors(); |
331 | } |
332 | |
333 | |
334 | |
335 | |
336 | |
337 | static bool |
338 | applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input, |
339 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, |
340 | DiagnosticConsumer *DiagClient, StringRef outputDir, |
341 | bool emitPremigrationARCErrors, StringRef plistOut) { |
342 | if (!origCI.getLangOpts()->ObjC) |
343 | return false; |
344 | |
345 | LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC(); |
346 | |
347 | |
348 | CompilerInvocation CInvokForCheck(origCI); |
349 | if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps, |
350 | DiagClient, emitPremigrationARCErrors, |
351 | plistOut)) |
352 | return true; |
353 | |
354 | CompilerInvocation CInvok(origCI); |
355 | CInvok.getFrontendOpts().Inputs.clear(); |
356 | CInvok.getFrontendOpts().Inputs.push_back(Input); |
357 | |
358 | MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir); |
359 | bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval; |
360 | |
361 | std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode, |
362 | NoFinalizeRemoval); |
363 | assert(!transforms.empty()); |
364 | |
365 | for (unsigned i=0, e = transforms.size(); i != e; ++i) { |
366 | bool err = migration.applyTransform(transforms[i]); |
367 | if (err) return true; |
368 | } |
369 | |
370 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
371 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( |
372 | new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(), |
373 | DiagClient, )); |
374 | |
375 | if (outputDir.empty()) { |
376 | origCI.getLangOpts()->ObjCAutoRefCount = true; |
377 | return migration.getRemapper().overwriteOriginal(*Diags); |
378 | } else { |
379 | return migration.getRemapper().flushToDisk(outputDir, *Diags); |
380 | } |
381 | } |
382 | |
383 | bool arcmt::applyTransformations( |
384 | CompilerInvocation &origCI, const FrontendInputFile &Input, |
385 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, |
386 | DiagnosticConsumer *DiagClient) { |
387 | return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, |
388 | StringRef(), false, StringRef()); |
389 | } |
390 | |
391 | bool arcmt::migrateWithTemporaryFiles( |
392 | CompilerInvocation &origCI, const FrontendInputFile &Input, |
393 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, |
394 | DiagnosticConsumer *DiagClient, StringRef outputDir, |
395 | bool emitPremigrationARCErrors, StringRef plistOut) { |
396 | (0) . __assert_fail ("!outputDir.empty() && \"Expected output directory path\"", "/home/seafit/code_projects/clang_source/clang/lib/ARCMigrate/ARCMT.cpp", 396, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!outputDir.empty() && "Expected output directory path"); |
397 | return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir, |
398 | emitPremigrationARCErrors, plistOut); |
399 | } |
400 | |
401 | bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > & |
402 | remap, |
403 | StringRef outputDir, |
404 | DiagnosticConsumer *DiagClient) { |
405 | assert(!outputDir.empty()); |
406 | |
407 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
408 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( |
409 | new DiagnosticsEngine(DiagID, new DiagnosticOptions, |
410 | DiagClient, )); |
411 | |
412 | FileRemapper remapper; |
413 | bool err = remapper.initFromDisk(outputDir, *Diags, |
414 | ); |
415 | if (err) |
416 | return true; |
417 | |
418 | PreprocessorOptions PPOpts; |
419 | remapper.applyMappings(PPOpts); |
420 | remap = PPOpts.RemappedFiles; |
421 | |
422 | return false; |
423 | } |
424 | |
425 | |
426 | |
427 | |
428 | |
429 | |
430 | namespace { |
431 | |
432 | class ARCMTMacroTrackerPPCallbacks : public PPCallbacks { |
433 | std::vector<SourceLocation> &ARCMTMacroLocs; |
434 | |
435 | public: |
436 | ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs) |
437 | : ARCMTMacroLocs(ARCMTMacroLocs) { } |
438 | |
439 | void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, |
440 | SourceRange Range, const MacroArgs *Args) override { |
441 | if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName()) |
442 | ARCMTMacroLocs.push_back(MacroNameTok.getLocation()); |
443 | } |
444 | }; |
445 | |
446 | class ARCMTMacroTrackerAction : public ASTFrontendAction { |
447 | std::vector<SourceLocation> &ARCMTMacroLocs; |
448 | |
449 | public: |
450 | ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs) |
451 | : ARCMTMacroLocs(ARCMTMacroLocs) { } |
452 | |
453 | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, |
454 | StringRef InFile) override { |
455 | CI.getPreprocessor().addPPCallbacks( |
456 | llvm::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs)); |
457 | return llvm::make_unique<ASTConsumer>(); |
458 | } |
459 | }; |
460 | |
461 | class RewritesApplicator : public TransformActions::RewriteReceiver { |
462 | Rewriter &rewriter; |
463 | MigrationProcess::RewriteListener *Listener; |
464 | |
465 | public: |
466 | RewritesApplicator(Rewriter &rewriter, ASTContext &ctx, |
467 | MigrationProcess::RewriteListener *listener) |
468 | : rewriter(rewriter), Listener(listener) { |
469 | if (Listener) |
470 | Listener->start(ctx); |
471 | } |
472 | ~RewritesApplicator() override { |
473 | if (Listener) |
474 | Listener->finish(); |
475 | } |
476 | |
477 | void insert(SourceLocation loc, StringRef text) override { |
478 | bool err = rewriter.InsertText(loc, text, , |
479 | ); |
480 | if (!err && Listener) |
481 | Listener->insert(loc, text); |
482 | } |
483 | |
484 | void remove(CharSourceRange range) override { |
485 | Rewriter::RewriteOptions removeOpts; |
486 | removeOpts.IncludeInsertsAtBeginOfRange = false; |
487 | removeOpts.IncludeInsertsAtEndOfRange = false; |
488 | removeOpts.RemoveLineIfEmpty = true; |
489 | |
490 | bool err = rewriter.RemoveText(range, removeOpts); |
491 | if (!err && Listener) |
492 | Listener->remove(range); |
493 | } |
494 | |
495 | void increaseIndentation(CharSourceRange range, |
496 | SourceLocation parentIndent) override { |
497 | rewriter.IncreaseIndentation(range, parentIndent); |
498 | } |
499 | }; |
500 | |
501 | } |
502 | |
503 | |
504 | MigrationProcess::RewriteListener::~RewriteListener() { } |
505 | |
506 | MigrationProcess::MigrationProcess( |
507 | const CompilerInvocation &CI, |
508 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, |
509 | DiagnosticConsumer *diagClient, StringRef outputDir) |
510 | : OrigCI(CI), PCHContainerOps(std::move(PCHContainerOps)), |
511 | DiagClient(diagClient), HadARCErrors(false) { |
512 | if (!outputDir.empty()) { |
513 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
514 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( |
515 | new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), |
516 | DiagClient, )); |
517 | Remapper.initFromDisk(outputDir, *Diags, ); |
518 | } |
519 | } |
520 | |
521 | bool MigrationProcess::applyTransform(TransformFn trans, |
522 | RewriteListener *listener) { |
523 | std::unique_ptr<CompilerInvocation> CInvok; |
524 | CInvok.reset( |
525 | createInvocationForMigration(OrigCI, PCHContainerOps->getRawReader())); |
526 | CInvok->getDiagnosticOpts().IgnoreWarnings = true; |
527 | |
528 | Remapper.applyMappings(CInvok->getPreprocessorOpts()); |
529 | |
530 | CapturedDiagList capturedDiags; |
531 | std::vector<SourceLocation> ARCMTMacroLocs; |
532 | |
533 | assert(DiagClient); |
534 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); |
535 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( |
536 | new DiagnosticsEngine(DiagID, new DiagnosticOptions, |
537 | DiagClient, )); |
538 | |
539 | |
540 | CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags); |
541 | Diags->setClient(&errRec, ); |
542 | |
543 | std::unique_ptr<ARCMTMacroTrackerAction> ASTAction; |
544 | ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs)); |
545 | |
546 | std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction( |
547 | std::move(CInvok), PCHContainerOps, Diags, ASTAction.get())); |
548 | if (!Unit) { |
549 | errRec.FinishCapture(); |
550 | return true; |
551 | } |
552 | Unit->setOwnsRemappedFileBuffers(false); |
553 | |
554 | HadARCErrors = HadARCErrors || capturedDiags.hasErrors(); |
555 | |
556 | |
557 | Diags->setClient(DiagClient, ); |
558 | |
559 | ASTContext &Ctx = Unit->getASTContext(); |
560 | |
561 | if (Diags->hasFatalErrorOccurred()) { |
562 | Diags->Reset(); |
563 | DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor()); |
564 | capturedDiags.reportDiagnostics(*Diags); |
565 | DiagClient->EndSourceFile(); |
566 | errRec.FinishCapture(); |
567 | return true; |
568 | } |
569 | |
570 | |
571 | |
572 | |
573 | |
574 | |
575 | DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor()); |
576 | |
577 | Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); |
578 | TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor()); |
579 | MigrationPass pass(Ctx, OrigCI.getLangOpts()->getGC(), |
580 | Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs); |
581 | |
582 | trans(pass); |
583 | |
584 | { |
585 | RewritesApplicator applicator(rewriter, Ctx, listener); |
586 | TA.applyRewrites(applicator); |
587 | } |
588 | |
589 | DiagClient->EndSourceFile(); |
590 | errRec.FinishCapture(); |
591 | |
592 | if (DiagClient->getNumErrors()) |
593 | return true; |
594 | |
595 | for (Rewriter::buffer_iterator |
596 | I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { |
597 | FileID FID = I->first; |
598 | RewriteBuffer &buf = I->second; |
599 | const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); |
600 | assert(file); |
601 | std::string newFname = file->getName(); |
602 | newFname += "-trans"; |
603 | SmallString<512> newText; |
604 | llvm::raw_svector_ostream vecOS(newText); |
605 | buf.write(vecOS); |
606 | std::unique_ptr<llvm::MemoryBuffer> memBuf( |
607 | llvm::MemoryBuffer::getMemBufferCopy( |
608 | StringRef(newText.data(), newText.size()), newFname)); |
609 | SmallString<64> filePath(file->getName()); |
610 | Unit->getFileManager().FixupRelativePath(filePath); |
611 | Remapper.remap(filePath.str(), std::move(memBuf)); |
612 | } |
613 | |
614 | return false; |
615 | } |
616 | |