aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/ARCMigrate/ARCMT.cpp616
-rw-r--r--clang/lib/ARCMigrate/ARCMTActions.cpp59
-rw-r--r--clang/lib/ARCMigrate/CMakeLists.txt48
-rw-r--r--clang/lib/ARCMigrate/FileRemapper.cpp274
-rw-r--r--clang/lib/ARCMigrate/Internals.h180
-rw-r--r--clang/lib/ARCMigrate/ObjCMT.cpp2262
-rw-r--r--clang/lib/ARCMigrate/PlistReporter.cpp124
-rw-r--r--clang/lib/ARCMigrate/TransAPIUses.cpp107
-rw-r--r--clang/lib/ARCMigrate/TransARCAssign.cpp77
-rw-r--r--clang/lib/ARCMigrate/TransAutoreleasePool.cpp435
-rw-r--r--clang/lib/ARCMigrate/TransBlockObjCVariable.cpp146
-rw-r--r--clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp249
-rw-r--r--clang/lib/ARCMigrate/TransGCAttrs.cpp350
-rw-r--r--clang/lib/ARCMigrate/TransGCCalls.cpp76
-rw-r--r--clang/lib/ARCMigrate/TransProperties.cpp379
-rw-r--r--clang/lib/ARCMigrate/TransProtectedScope.cpp203
-rw-r--r--clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp459
-rw-r--r--clang/lib/ARCMigrate/TransUnbridgedCasts.cpp466
-rw-r--r--clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp77
-rw-r--r--clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp224
-rw-r--r--clang/lib/ARCMigrate/TransformActions.cpp700
-rw-r--r--clang/lib/ARCMigrate/Transforms.cpp594
-rw-r--r--clang/lib/ARCMigrate/Transforms.h224
-rw-r--r--clang/lib/CMakeLists.txt3
-rw-r--r--clang/lib/Driver/Action.cpp9
-rw-r--r--clang/lib/Driver/Driver.cpp6
-rw-r--r--clang/lib/Driver/ToolChain.cpp1
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp76
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.cpp14
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp8
-rw-r--r--clang/lib/FrontendTool/CMakeLists.txt6
-rw-r--r--clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp39
-rw-r--r--clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp3
33 files changed, 5 insertions, 8489 deletions
diff --git a/clang/lib/ARCMigrate/ARCMT.cpp b/clang/lib/ARCMigrate/ARCMT.cpp
deleted file mode 100644
index 1a8a200..0000000
--- a/clang/lib/ARCMigrate/ARCMT.cpp
+++ /dev/null
@@ -1,616 +0,0 @@
-//===--- ARCMT.cpp - Migration to ARC mode --------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ARCMigrate/ARCMT.h"
-#include "Internals.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/DiagnosticCategories.h"
-#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendAction.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Frontend/Utils.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "clang/Serialization/ASTReader.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/TargetParser/Triple.h"
-#include <utility>
-using namespace clang;
-using namespace arcmt;
-
-bool CapturedDiagList::clearDiagnostic(ArrayRef<unsigned> IDs,
- SourceRange range) {
- if (range.isInvalid())
- return false;
-
- bool cleared = false;
- ListTy::iterator I = List.begin();
- while (I != List.end()) {
- FullSourceLoc diagLoc = I->getLocation();
- if ((IDs.empty() || // empty means clear all diagnostics in the range.
- llvm::is_contained(IDs, I->getID())) &&
- !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
- (diagLoc == range.getEnd() ||
- diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
- cleared = true;
- ListTy::iterator eraseS = I++;
- if (eraseS->getLevel() != DiagnosticsEngine::Note)
- while (I != List.end() && I->getLevel() == DiagnosticsEngine::Note)
- ++I;
- // Clear the diagnostic and any notes following it.
- I = List.erase(eraseS, I);
- continue;
- }
-
- ++I;
- }
-
- return cleared;
-}
-
-bool CapturedDiagList::hasDiagnostic(ArrayRef<unsigned> IDs,
- SourceRange range) const {
- if (range.isInvalid())
- return false;
-
- ListTy::const_iterator I = List.begin();
- while (I != List.end()) {
- FullSourceLoc diagLoc = I->getLocation();
- if ((IDs.empty() || // empty means any diagnostic in the range.
- llvm::is_contained(IDs, I->getID())) &&
- !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
- (diagLoc == range.getEnd() ||
- diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
- return true;
- }
-
- ++I;
- }
-
- return false;
-}
-
-void CapturedDiagList::reportDiagnostics(DiagnosticsEngine &Diags) const {
- for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
- Diags.Report(*I);
-}
-
-bool CapturedDiagList::hasErrors() const {
- for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
- if (I->getLevel() >= DiagnosticsEngine::Error)
- return true;
-
- return false;
-}
-
-namespace {
-
-class CaptureDiagnosticConsumer : public DiagnosticConsumer {
- DiagnosticsEngine &Diags;
- DiagnosticConsumer &DiagClient;
- CapturedDiagList &CapturedDiags;
- bool HasBegunSourceFile;
-public:
- CaptureDiagnosticConsumer(DiagnosticsEngine &diags,
- DiagnosticConsumer &client,
- CapturedDiagList &capturedDiags)
- : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags),
- HasBegunSourceFile(false) { }
-
- void BeginSourceFile(const LangOptions &Opts,
- const Preprocessor *PP) override {
- // Pass BeginSourceFile message onto DiagClient on first call.
- // The corresponding EndSourceFile call will be made from an
- // explicit call to FinishCapture.
- if (!HasBegunSourceFile) {
- DiagClient.BeginSourceFile(Opts, PP);
- HasBegunSourceFile = true;
- }
- }
-
- void FinishCapture() {
- // Call EndSourceFile on DiagClient on completion of capture to
- // enable VerifyDiagnosticConsumer to check diagnostics *after*
- // it has received the diagnostic list.
- if (HasBegunSourceFile) {
- DiagClient.EndSourceFile();
- HasBegunSourceFile = false;
- }
- }
-
- ~CaptureDiagnosticConsumer() override {
- assert(!HasBegunSourceFile && "FinishCapture not called!");
- }
-
- void HandleDiagnostic(DiagnosticsEngine::Level level,
- const Diagnostic &Info) override {
- if (DiagnosticIDs::isARCDiagnostic(Info.getID()) ||
- level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) {
- if (Info.getLocation().isValid())
- CapturedDiags.push_back(StoredDiagnostic(level, Info));
- return;
- }
-
- // Non-ARC warnings are ignored.
- Diags.setLastDiagnosticIgnored(true);
- }
-};
-
-} // end anonymous namespace
-
-static bool HasARCRuntime(CompilerInvocation &origCI) {
- // This duplicates some functionality from Darwin::AddDeploymentTarget
- // but this function is well defined, so keep it decoupled from the driver
- // and avoid unrelated complications.
- llvm::Triple triple(origCI.getTargetOpts().Triple);
-
- if (triple.isiOS())
- return triple.getOSMajorVersion() >= 5;
-
- if (triple.isWatchOS())
- return true;
-
- if (triple.getOS() == llvm::Triple::Darwin)
- return triple.getOSMajorVersion() >= 11;
-
- if (triple.getOS() == llvm::Triple::MacOSX) {
- return triple.getOSVersion() >= VersionTuple(10, 7);
- }
-
- return false;
-}
-
-static CompilerInvocation *
-createInvocationForMigration(CompilerInvocation &origCI,
- const PCHContainerReader &PCHContainerRdr) {
- std::unique_ptr<CompilerInvocation> CInvok;
- CInvok.reset(new CompilerInvocation(origCI));
- PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
- if (!PPOpts.ImplicitPCHInclude.empty()) {
- // We can't use a PCH because it was likely built in non-ARC mode and we
- // want to parse in ARC. Include the original header.
- FileManager FileMgr(origCI.getFileSystemOpts());
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
- new IgnoringDiagConsumer()));
- std::string OriginalFile = ASTReader::getOriginalSourceFile(
- PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerRdr, *Diags);
- if (!OriginalFile.empty())
- PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile);
- PPOpts.ImplicitPCHInclude.clear();
- }
- std::string define = std::string(getARCMTMacroName());
- define += '=';
- CInvok->getPreprocessorOpts().addMacroDef(define);
- CInvok->getLangOpts().ObjCAutoRefCount = true;
- CInvok->getLangOpts().setGC(LangOptions::NonGC);
- CInvok->getDiagnosticOpts().ErrorLimit = 0;
- CInvok->getDiagnosticOpts().PedanticErrors = 0;
-
- // Ignore -Werror flags when migrating.
- std::vector<std::string> WarnOpts;
- for (std::vector<std::string>::iterator
- I = CInvok->getDiagnosticOpts().Warnings.begin(),
- E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
- if (!StringRef(*I).starts_with("error"))
- WarnOpts.push_back(*I);
- }
- WarnOpts.push_back("error=arc-unsafe-retained-assign");
- CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
-
- CInvok->getLangOpts().ObjCWeakRuntime = HasARCRuntime(origCI);
- CInvok->getLangOpts().ObjCWeak = CInvok->getLangOpts().ObjCWeakRuntime;
-
- return CInvok.release();
-}
-
-static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
- DiagnosticOptions *diagOpts,
- Preprocessor &PP) {
- TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, diagOpts, &printer,
- /*ShouldOwnClient=*/false));
- Diags->setSourceManager(&PP.getSourceManager());
-
- printer.BeginSourceFile(PP.getLangOpts(), &PP);
- arcDiags.reportDiagnostics(*Diags);
- printer.EndSourceFile();
-}
-
-//===----------------------------------------------------------------------===//
-// checkForManualIssues.
-//===----------------------------------------------------------------------===//
-
-bool arcmt::checkForManualIssues(
- CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors,
- StringRef plistOut) {
- if (!origCI.getLangOpts().ObjC)
- return false;
-
- LangOptions::GCMode OrigGCMode = origCI.getLangOpts().getGC();
- bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError;
- bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
-
- std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
- NoFinalizeRemoval);
- assert(!transforms.empty());
-
- std::unique_ptr<CompilerInvocation> CInvok;
- CInvok.reset(
- createInvocationForMigration(origCI, PCHContainerOps->getRawReader()));
- CInvok->getFrontendOpts().Inputs.clear();
- CInvok->getFrontendOpts().Inputs.push_back(Input);
-
- CapturedDiagList capturedDiags;
-
- assert(DiagClient);
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
- DiagClient, /*ShouldOwnClient=*/false));
-
- // Filter of all diagnostics.
- CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
- Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
-
- std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
- std::move(CInvok), PCHContainerOps, Diags));
- if (!Unit) {
- errRec.FinishCapture();
- return true;
- }
-
- // Don't filter diagnostics anymore.
- Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
-
- ASTContext &Ctx = Unit->getASTContext();
-
- if (Diags->hasFatalErrorOccurred()) {
- Diags->Reset();
- DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
- capturedDiags.reportDiagnostics(*Diags);
- DiagClient->EndSourceFile();
- errRec.FinishCapture();
- return true;
- }
-
- if (emitPremigrationARCErrors)
- emitPremigrationErrors(capturedDiags, &origCI.getDiagnosticOpts(),
- Unit->getPreprocessor());
- if (!plistOut.empty()) {
- SmallVector<StoredDiagnostic, 8> arcDiags;
- for (CapturedDiagList::iterator
- I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
- arcDiags.push_back(*I);
- writeARCDiagsToPlist(std::string(plistOut), arcDiags,
- Ctx.getSourceManager(), Ctx.getLangOpts());
- }
-
- // After parsing of source files ended, we want to reuse the
- // diagnostics objects to emit further diagnostics.
- // We call BeginSourceFile because DiagnosticConsumer requires that
- // diagnostics with source range information are emitted only in between
- // BeginSourceFile() and EndSourceFile().
- DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
-
- // No macros will be added since we are just checking and we won't modify
- // source code.
- std::vector<SourceLocation> ARCMTMacroLocs;
-
- TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
- MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
- ARCMTMacroLocs);
- pass.setNoFinalizeRemoval(NoFinalizeRemoval);
- if (!NoNSAllocReallocError)
- Diags->setSeverity(diag::warn_arcmt_nsalloc_realloc, diag::Severity::Error,
- SourceLocation());
-
- for (unsigned i=0, e = transforms.size(); i != e; ++i)
- transforms[i](pass);
-
- capturedDiags.reportDiagnostics(*Diags);
-
- DiagClient->EndSourceFile();
- errRec.FinishCapture();
-
- return capturedDiags.hasErrors() || testAct.hasReportedErrors();
-}
-
-//===----------------------------------------------------------------------===//
-// applyTransformations.
-//===----------------------------------------------------------------------===//
-
-static bool
-applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagClient, StringRef outputDir,
- bool emitPremigrationARCErrors, StringRef plistOut) {
- if (!origCI.getLangOpts().ObjC)
- return false;
-
- LangOptions::GCMode OrigGCMode = origCI.getLangOpts().getGC();
-
- // Make sure checking is successful first.
- CompilerInvocation CInvokForCheck(origCI);
- if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps,
- DiagClient, emitPremigrationARCErrors,
- plistOut))
- return true;
-
- CompilerInvocation CInvok(origCI);
- CInvok.getFrontendOpts().Inputs.clear();
- CInvok.getFrontendOpts().Inputs.push_back(Input);
-
- MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir);
- bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
-
- std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
- NoFinalizeRemoval);
- assert(!transforms.empty());
-
- for (unsigned i=0, e = transforms.size(); i != e; ++i) {
- bool err = migration.applyTransform(transforms[i]);
- if (err) return true;
- }
-
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(),
- DiagClient, /*ShouldOwnClient=*/false));
-
- if (outputDir.empty()) {
- origCI.getLangOpts().ObjCAutoRefCount = true;
- return migration.getRemapper().overwriteOriginal(*Diags);
- } else {
- return migration.getRemapper().flushToDisk(outputDir, *Diags);
- }
-}
-
-bool arcmt::applyTransformations(
- CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagClient) {
- return applyTransforms(origCI, Input, PCHContainerOps, DiagClient,
- StringRef(), false, StringRef());
-}
-
-bool arcmt::migrateWithTemporaryFiles(
- CompilerInvocation &origCI, const FrontendInputFile &Input,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagClient, StringRef outputDir,
- bool emitPremigrationARCErrors, StringRef plistOut) {
- assert(!outputDir.empty() && "Expected output directory path");
- return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
- emitPremigrationARCErrors, plistOut);
-}
-
-bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
- remap,
- StringRef outputDir,
- DiagnosticConsumer *DiagClient) {
- assert(!outputDir.empty());
-
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, new DiagnosticOptions,
- DiagClient, /*ShouldOwnClient=*/false));
-
- FileRemapper remapper;
- bool err = remapper.initFromDisk(outputDir, *Diags,
- /*ignoreIfFilesChanged=*/true);
- if (err)
- return true;
-
- remapper.forEachMapping(
- [&](StringRef From, StringRef To) {
- remap.push_back(std::make_pair(From.str(), To.str()));
- },
- [](StringRef, const llvm::MemoryBufferRef &) {});
-
- return false;
-}
-
-
-//===----------------------------------------------------------------------===//
-// CollectTransformActions.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class ARCMTMacroTrackerPPCallbacks : public PPCallbacks {
- std::vector<SourceLocation> &ARCMTMacroLocs;
-
-public:
- ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
- : ARCMTMacroLocs(ARCMTMacroLocs) { }
-
- void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
- SourceRange Range, const MacroArgs *Args) override {
- if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName())
- ARCMTMacroLocs.push_back(MacroNameTok.getLocation());
- }
-};
-
-class ARCMTMacroTrackerAction : public ASTFrontendAction {
- std::vector<SourceLocation> &ARCMTMacroLocs;
-
-public:
- ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
- : ARCMTMacroLocs(ARCMTMacroLocs) { }
-
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override {
- CI.getPreprocessor().addPPCallbacks(
- std::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
- return std::make_unique<ASTConsumer>();
- }
-};
-
-class RewritesApplicator : public TransformActions::RewriteReceiver {
- Rewriter &rewriter;
- MigrationProcess::RewriteListener *Listener;
-
-public:
- RewritesApplicator(Rewriter &rewriter, ASTContext &ctx,
- MigrationProcess::RewriteListener *listener)
- : rewriter(rewriter), Listener(listener) {
- if (Listener)
- Listener->start(ctx);
- }
- ~RewritesApplicator() override {
- if (Listener)
- Listener->finish();
- }
-
- void insert(SourceLocation loc, StringRef text) override {
- bool err = rewriter.InsertText(loc, text, /*InsertAfter=*/true,
- /*indentNewLines=*/true);
- if (!err && Listener)
- Listener->insert(loc, text);
- }
-
- void remove(CharSourceRange range) override {
- Rewriter::RewriteOptions removeOpts;
- removeOpts.IncludeInsertsAtBeginOfRange = false;
- removeOpts.IncludeInsertsAtEndOfRange = false;
- removeOpts.RemoveLineIfEmpty = true;
-
- bool err = rewriter.RemoveText(range, removeOpts);
- if (!err && Listener)
- Listener->remove(range);
- }
-
- void increaseIndentation(CharSourceRange range,
- SourceLocation parentIndent) override {
- rewriter.IncreaseIndentation(range, parentIndent);
- }
-};
-
-} // end anonymous namespace.
-
-/// Anchor for VTable.
-MigrationProcess::RewriteListener::~RewriteListener() { }
-
-MigrationProcess::MigrationProcess(
- CompilerInvocation &CI,
- std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *diagClient, StringRef outputDir)
- : OrigCI(CI), PCHContainerOps(std::move(PCHContainerOps)),
- DiagClient(diagClient), HadARCErrors(false) {
- if (!outputDir.empty()) {
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(),
- DiagClient, /*ShouldOwnClient=*/false));
- Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanged=*/true);
- }
-}
-
-bool MigrationProcess::applyTransform(TransformFn trans,
- RewriteListener *listener) {
- std::unique_ptr<CompilerInvocation> CInvok;
- CInvok.reset(
- createInvocationForMigration(OrigCI, PCHContainerOps->getRawReader()));
- CInvok->getDiagnosticOpts().IgnoreWarnings = true;
-
- Remapper.applyMappings(CInvok->getPreprocessorOpts());
-
- CapturedDiagList capturedDiags;
- std::vector<SourceLocation> ARCMTMacroLocs;
-
- assert(DiagClient);
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, new DiagnosticOptions,
- DiagClient, /*ShouldOwnClient=*/false));
-
- // Filter of all diagnostics.
- CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
- Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
-
- std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
- ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs));
-
- std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
- std::move(CInvok), PCHContainerOps, Diags, ASTAction.get()));
- if (!Unit) {
- errRec.FinishCapture();
- return true;
- }
- Unit->setOwnsRemappedFileBuffers(false); // FileRemapper manages that.
-
- HadARCErrors = HadARCErrors || capturedDiags.hasErrors();
-
- // Don't filter diagnostics anymore.
- Diags->setClient(DiagClient, /*ShouldOwnClient=*/false);
-
- ASTContext &Ctx = Unit->getASTContext();
-
- if (Diags->hasFatalErrorOccurred()) {
- Diags->Reset();
- DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
- capturedDiags.reportDiagnostics(*Diags);
- DiagClient->EndSourceFile();
- errRec.FinishCapture();
- return true;
- }
-
- // After parsing of source files ended, we want to reuse the
- // diagnostics objects to emit further diagnostics.
- // We call BeginSourceFile because DiagnosticConsumer requires that
- // diagnostics with source range information are emitted only in between
- // BeginSourceFile() and EndSourceFile().
- DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
-
- Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
- TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
- MigrationPass pass(Ctx, OrigCI.getLangOpts().getGC(),
- Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
-
- trans(pass);
-
- {
- RewritesApplicator applicator(rewriter, Ctx, listener);
- TA.applyRewrites(applicator);
- }
-
- DiagClient->EndSourceFile();
- errRec.FinishCapture();
-
- if (DiagClient->getNumErrors())
- return true;
-
- for (Rewriter::buffer_iterator
- I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
- FileID FID = I->first;
- llvm::RewriteBuffer &buf = I->second;
- OptionalFileEntryRef file =
- Ctx.getSourceManager().getFileEntryRefForID(FID);
- assert(file);
- std::string newFname = std::string(file->getName());
- newFname += "-trans";
- SmallString<512> newText;
- llvm::raw_svector_ostream vecOS(newText);
- buf.write(vecOS);
- std::unique_ptr<llvm::MemoryBuffer> memBuf(
- llvm::MemoryBuffer::getMemBufferCopy(newText.str(), newFname));
- SmallString<64> filePath(file->getName());
- Unit->getFileManager().FixupRelativePath(filePath);
- Remapper.remap(filePath.str(), std::move(memBuf));
- }
-
- return false;
-}
diff --git a/clang/lib/ARCMigrate/ARCMTActions.cpp b/clang/lib/ARCMigrate/ARCMTActions.cpp
deleted file mode 100644
index 0805d90..0000000
--- a/clang/lib/ARCMigrate/ARCMTActions.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//===--- ARCMTActions.cpp - ARC Migrate Tool Frontend Actions ---*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ARCMigrate/ARCMTActions.h"
-#include "clang/ARCMigrate/ARCMT.h"
-#include "clang/Frontend/CompilerInstance.h"
-
-using namespace clang;
-using namespace arcmt;
-
-bool CheckAction::BeginInvocation(CompilerInstance &CI) {
- if (arcmt::checkForManualIssues(CI.getInvocation(), getCurrentInput(),
- CI.getPCHContainerOperations(),
- CI.getDiagnostics().getClient()))
- return false; // errors, stop the action.
-
- // We only want to see warnings reported from arcmt::checkForManualIssues.
- CI.getDiagnostics().setIgnoreAllWarnings(true);
- return true;
-}
-
-CheckAction::CheckAction(std::unique_ptr<FrontendAction> WrappedAction)
- : WrapperFrontendAction(std::move(WrappedAction)) {}
-
-bool ModifyAction::BeginInvocation(CompilerInstance &CI) {
- return !arcmt::applyTransformations(CI.getInvocation(), getCurrentInput(),
- CI.getPCHContainerOperations(),
- CI.getDiagnostics().getClient());
-}
-
-ModifyAction::ModifyAction(std::unique_ptr<FrontendAction> WrappedAction)
- : WrapperFrontendAction(std::move(WrappedAction)) {}
-
-bool MigrateAction::BeginInvocation(CompilerInstance &CI) {
- if (arcmt::migrateWithTemporaryFiles(
- CI.getInvocation(), getCurrentInput(), CI.getPCHContainerOperations(),
- CI.getDiagnostics().getClient(), MigrateDir, EmitPremigrationARCErrors,
- PlistOut))
- return false; // errors, stop the action.
-
- // We only want to see diagnostics emitted by migrateWithTemporaryFiles.
- CI.getDiagnostics().setIgnoreAllWarnings(true);
- return true;
-}
-
-MigrateAction::MigrateAction(std::unique_ptr<FrontendAction> WrappedAction,
- StringRef migrateDir,
- StringRef plistOut,
- bool emitPremigrationARCErrors)
- : WrapperFrontendAction(std::move(WrappedAction)), MigrateDir(migrateDir),
- PlistOut(plistOut), EmitPremigrationARCErrors(emitPremigrationARCErrors) {
- if (MigrateDir.empty())
- MigrateDir = "."; // user current directory if none is given.
-}
diff --git a/clang/lib/ARCMigrate/CMakeLists.txt b/clang/lib/ARCMigrate/CMakeLists.txt
deleted file mode 100644
index 515d096..0000000
--- a/clang/lib/ARCMigrate/CMakeLists.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- TargetParser
- )
-
-# By default MSVC has a 2^16 limit on the number of sections in an object
-# file, and Transforms.cpp needs more than that.
-if (MSVC)
- set_source_files_properties(Transforms.cpp PROPERTIES COMPILE_FLAGS /bigobj)
-endif()
-
-add_clang_library(clangARCMigrate
- ARCMT.cpp
- ARCMTActions.cpp
- FileRemapper.cpp
- ObjCMT.cpp
- PlistReporter.cpp
- TransAPIUses.cpp
- TransARCAssign.cpp
- TransAutoreleasePool.cpp
- TransBlockObjCVariable.cpp
- TransEmptyStatementsAndDealloc.cpp
- TransGCAttrs.cpp
- TransGCCalls.cpp
- TransProperties.cpp
- TransProtectedScope.cpp
- TransRetainReleaseDealloc.cpp
- TransUnbridgedCasts.cpp
- TransUnusedInitDelegate.cpp
- TransZeroOutPropsInDealloc.cpp
- TransformActions.cpp
- Transforms.cpp
-
- LINK_LIBS
- clangAST
- clangAnalysis
- clangBasic
- clangEdit
- clangFrontend
- clangLex
- clangRewrite
- clangSema
- clangSerialization
-
- DEPENDS
- omp_gen
- ClangDriverOptions
- )
diff --git a/clang/lib/ARCMigrate/FileRemapper.cpp b/clang/lib/ARCMigrate/FileRemapper.cpp
deleted file mode 100644
index 84024c3..0000000
--- a/clang/lib/ARCMigrate/FileRemapper.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-//===--- FileRemapper.cpp - File Remapping Helper -------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ARCMigrate/FileRemapper.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Lex/PreprocessorOptions.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-#include <fstream>
-
-using namespace clang;
-using namespace arcmt;
-
-FileRemapper::FileRemapper() {
- FileMgr.reset(new FileManager(FileSystemOptions()));
-}
-
-FileRemapper::~FileRemapper() {
- clear();
-}
-
-void FileRemapper::clear(StringRef outputDir) {
- for (MappingsTy::iterator
- I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I)
- resetTarget(I->second);
- FromToMappings.clear();
- assert(ToFromMappings.empty());
- if (!outputDir.empty()) {
- std::string infoFile = getRemapInfoFile(outputDir);
- llvm::sys::fs::remove(infoFile);
- }
-}
-
-std::string FileRemapper::getRemapInfoFile(StringRef outputDir) {
- assert(!outputDir.empty());
- SmallString<128> InfoFile = outputDir;
- llvm::sys::path::append(InfoFile, "remap");
- return std::string(InfoFile);
-}
-
-bool FileRemapper::initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
- bool ignoreIfFilesChanged) {
- std::string infoFile = getRemapInfoFile(outputDir);
- return initFromFile(infoFile, Diag, ignoreIfFilesChanged);
-}
-
-bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
- bool ignoreIfFilesChanged) {
- assert(FromToMappings.empty() &&
- "initFromDisk should be called before any remap calls");
- std::string infoFile = std::string(filePath);
- if (!llvm::sys::fs::exists(infoFile))
- return false;
-
- std::vector<std::pair<FileEntryRef, FileEntryRef>> pairs;
-
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
- llvm::MemoryBuffer::getFile(infoFile, /*IsText=*/true);
- if (!fileBuf)
- return report("Error opening file: " + infoFile, Diag);
-
- SmallVector<StringRef, 64> lines;
- fileBuf.get()->getBuffer().split(lines, "\n");
-
- for (unsigned idx = 0; idx+3 <= lines.size(); idx += 3) {
- StringRef fromFilename = lines[idx];
- unsigned long long timeModified;
- if (lines[idx+1].getAsInteger(10, timeModified))
- return report("Invalid file data: '" + lines[idx+1] + "' not a number",
- Diag);
- StringRef toFilename = lines[idx+2];
-
- auto origFE = FileMgr->getOptionalFileRef(fromFilename);
- if (!origFE) {
- if (ignoreIfFilesChanged)
- continue;
- return report("File does not exist: " + fromFilename, Diag);
- }
- auto newFE = FileMgr->getOptionalFileRef(toFilename);
- if (!newFE) {
- if (ignoreIfFilesChanged)
- continue;
- return report("File does not exist: " + toFilename, Diag);
- }
-
- if ((uint64_t)origFE->getModificationTime() != timeModified) {
- if (ignoreIfFilesChanged)
- continue;
- return report("File was modified: " + fromFilename, Diag);
- }
-
- pairs.push_back(std::make_pair(*origFE, *newFE));
- }
-
- for (unsigned i = 0, e = pairs.size(); i != e; ++i)
- remap(pairs[i].first, pairs[i].second);
-
- return false;
-}
-
-bool FileRemapper::flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag) {
- using namespace llvm::sys;
-
- if (fs::create_directory(outputDir))
- return report("Could not create directory: " + outputDir, Diag);
-
- std::string infoFile = getRemapInfoFile(outputDir);
- return flushToFile(infoFile, Diag);
-}
-
-bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
- using namespace llvm::sys;
-
- std::error_code EC;
- std::string infoFile = std::string(outputPath);
- llvm::raw_fd_ostream infoOut(infoFile, EC, llvm::sys::fs::OF_Text);
- if (EC)
- return report(EC.message(), Diag);
-
- for (MappingsTy::iterator
- I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
-
- FileEntryRef origFE = I->first;
- SmallString<200> origPath = StringRef(origFE.getName());
- fs::make_absolute(origPath);
- infoOut << origPath << '\n';
- infoOut << (uint64_t)origFE.getModificationTime() << '\n';
-
- if (const auto *FE = std::get_if<FileEntryRef>(&I->second)) {
- SmallString<200> newPath = StringRef(FE->getName());
- fs::make_absolute(newPath);
- infoOut << newPath << '\n';
- } else {
-
- SmallString<64> tempPath;
- int fd;
- if (fs::createTemporaryFile(
- path::filename(origFE.getName()),
- path::extension(origFE.getName()).drop_front(), fd, tempPath,
- llvm::sys::fs::OF_Text))
- return report("Could not create file: " + tempPath.str(), Diag);
-
- llvm::raw_fd_ostream newOut(fd, /*shouldClose=*/true);
- llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(I->second);
- newOut.write(mem->getBufferStart(), mem->getBufferSize());
- newOut.close();
-
- auto newE = FileMgr->getOptionalFileRef(tempPath);
- if (newE) {
- remap(origFE, *newE);
- infoOut << newE->getName() << '\n';
- }
- }
- }
-
- infoOut.close();
- return false;
-}
-
-bool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag,
- StringRef outputDir) {
- using namespace llvm::sys;
-
- for (MappingsTy::iterator
- I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
- FileEntryRef origFE = I->first;
- assert(std::holds_alternative<llvm::MemoryBuffer *>(I->second));
- if (!fs::exists(origFE.getName()))
- return report(StringRef("File does not exist: ") + origFE.getName(),
- Diag);
-
- std::error_code EC;
- llvm::raw_fd_ostream Out(origFE.getName(), EC, llvm::sys::fs::OF_None);
- if (EC)
- return report(EC.message(), Diag);
-
- llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(I->second);
- Out.write(mem->getBufferStart(), mem->getBufferSize());
- Out.close();
- }
-
- clear(outputDir);
- return false;
-}
-
-void FileRemapper::forEachMapping(
- llvm::function_ref<void(StringRef, StringRef)> CaptureFile,
- llvm::function_ref<void(StringRef, const llvm::MemoryBufferRef &)>
- CaptureBuffer) const {
- for (auto &Mapping : FromToMappings) {
- if (const auto *FE = std::get_if<FileEntryRef>(&Mapping.second)) {
- CaptureFile(Mapping.first.getName(), FE->getName());
- continue;
- }
- CaptureBuffer(
- Mapping.first.getName(),
- std::get<llvm::MemoryBuffer *>(Mapping.second)->getMemBufferRef());
- }
-}
-
-void FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const {
- for (MappingsTy::const_iterator
- I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
- if (const auto *FE = std::get_if<FileEntryRef>(&I->second)) {
- PPOpts.addRemappedFile(I->first.getName(), FE->getName());
- } else {
- llvm::MemoryBuffer *mem = std::get<llvm::MemoryBuffer *>(I->second);
- PPOpts.addRemappedFile(I->first.getName(), mem);
- }
- }
-
- PPOpts.RetainRemappedFileBuffers = true;
-}
-
-void FileRemapper::remap(StringRef filePath,
- std::unique_ptr<llvm::MemoryBuffer> memBuf) {
- OptionalFileEntryRef File = getOriginalFile(filePath);
- assert(File);
- remap(*File, std::move(memBuf));
-}
-
-void FileRemapper::remap(FileEntryRef File,
- std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
- auto [It, New] = FromToMappings.insert({File, nullptr});
- if (!New)
- resetTarget(It->second);
- It->second = MemBuf.release();
-}
-
-void FileRemapper::remap(FileEntryRef File, FileEntryRef NewFile) {
- auto [It, New] = FromToMappings.insert({File, nullptr});
- if (!New)
- resetTarget(It->second);
- It->second = NewFile;
- ToFromMappings.insert({NewFile, File});
-}
-
-OptionalFileEntryRef FileRemapper::getOriginalFile(StringRef filePath) {
- OptionalFileEntryRef File = FileMgr->getOptionalFileRef(filePath);
- if (!File)
- return std::nullopt;
- // If we are updating a file that overridden an original file,
- // actually update the original file.
- auto I = ToFromMappings.find(*File);
- if (I != ToFromMappings.end()) {
- *File = I->second;
- assert(FromToMappings.contains(*File) && "Original file not in mappings!");
- }
- return File;
-}
-
-void FileRemapper::resetTarget(Target &targ) {
- if (std::holds_alternative<llvm::MemoryBuffer *>(targ)) {
- llvm::MemoryBuffer *oldmem = std::get<llvm::MemoryBuffer *>(targ);
- delete oldmem;
- } else {
- FileEntryRef toFE = std::get<FileEntryRef>(targ);
- ToFromMappings.erase(toFE);
- }
-}
-
-bool FileRemapper::report(const Twine &err, DiagnosticsEngine &Diag) {
- Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
- << err.str();
- return true;
-}
diff --git a/clang/lib/ARCMigrate/Internals.h b/clang/lib/ARCMigrate/Internals.h
deleted file mode 100644
index de6ebdc..0000000
--- a/clang/lib/ARCMigrate/Internals.h
+++ /dev/null
@@ -1,180 +0,0 @@
-//===-- Internals.h - Implementation Details---------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_ARCMIGRATE_INTERNALS_H
-#define LLVM_CLANG_LIB_ARCMIGRATE_INTERNALS_H
-
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Frontend/MigratorOptions.h"
-#include "llvm/ADT/ArrayRef.h"
-#include <list>
-#include <optional>
-
-namespace clang {
- class ASTContext;
- class Sema;
- class Stmt;
-
-namespace arcmt {
-
-class CapturedDiagList {
- typedef std::list<StoredDiagnostic> ListTy;
- ListTy List;
-
-public:
- void push_back(const StoredDiagnostic &diag) { List.push_back(diag); }
-
- bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
- bool hasDiagnostic(ArrayRef<unsigned> IDs, SourceRange range) const;
-
- void reportDiagnostics(DiagnosticsEngine &diags) const;
-
- bool hasErrors() const;
-
- typedef ListTy::const_iterator iterator;
- iterator begin() const { return List.begin(); }
- iterator end() const { return List.end(); }
-};
-
-void writeARCDiagsToPlist(const std::string &outPath,
- ArrayRef<StoredDiagnostic> diags,
- SourceManager &SM, const LangOptions &LangOpts);
-
-class TransformActions {
- DiagnosticsEngine &Diags;
- CapturedDiagList &CapturedDiags;
- void *Impl; // TransformActionsImpl.
-
-public:
- TransformActions(DiagnosticsEngine &diag, CapturedDiagList &capturedDiags,
- ASTContext &ctx, Preprocessor &PP);
- ~TransformActions();
-
- void startTransaction();
- bool commitTransaction();
- void abortTransaction();
-
- void insert(SourceLocation loc, StringRef text);
- void insertAfterToken(SourceLocation loc, StringRef text);
- void remove(SourceRange range);
- void removeStmt(Stmt *S);
- void replace(SourceRange range, StringRef text);
- void replace(SourceRange range, SourceRange replacementRange);
- void replaceStmt(Stmt *S, StringRef text);
- void replaceText(SourceLocation loc, StringRef text,
- StringRef replacementText);
- void increaseIndentation(SourceRange range,
- SourceLocation parentIndent);
-
- bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
- bool clearAllDiagnostics(SourceRange range) {
- return clearDiagnostic({}, range);
- }
- bool clearDiagnostic(unsigned ID1, unsigned ID2, SourceRange range) {
- unsigned IDs[] = { ID1, ID2 };
- return clearDiagnostic(IDs, range);
- }
- bool clearDiagnostic(unsigned ID1, unsigned ID2, unsigned ID3,
- SourceRange range) {
- unsigned IDs[] = { ID1, ID2, ID3 };
- return clearDiagnostic(IDs, range);
- }
-
- bool hasDiagnostic(unsigned ID, SourceRange range) {
- return CapturedDiags.hasDiagnostic(ID, range);
- }
-
- bool hasDiagnostic(unsigned ID1, unsigned ID2, SourceRange range) {
- unsigned IDs[] = { ID1, ID2 };
- return CapturedDiags.hasDiagnostic(IDs, range);
- }
-
- DiagnosticBuilder report(SourceLocation loc, unsigned diagId,
- SourceRange range = SourceRange());
- void reportError(StringRef error, SourceLocation loc,
- SourceRange range = SourceRange());
- void reportWarning(StringRef warning, SourceLocation loc,
- SourceRange range = SourceRange());
- void reportNote(StringRef note, SourceLocation loc,
- SourceRange range = SourceRange());
-
- bool hasReportedErrors() const {
- return Diags.hasUnrecoverableErrorOccurred();
- }
-
- class RewriteReceiver {
- public:
- virtual ~RewriteReceiver();
-
- virtual void insert(SourceLocation loc, StringRef text) = 0;
- virtual void remove(CharSourceRange range) = 0;
- virtual void increaseIndentation(CharSourceRange range,
- SourceLocation parentIndent) = 0;
- };
-
- void applyRewrites(RewriteReceiver &receiver);
-};
-
-class Transaction {
- TransformActions &TA;
- bool Aborted;
-
-public:
- Transaction(TransformActions &TA) : TA(TA), Aborted(false) {
- TA.startTransaction();
- }
-
- ~Transaction() {
- if (!isAborted())
- TA.commitTransaction();
- }
-
- void abort() {
- TA.abortTransaction();
- Aborted = true;
- }
-
- bool isAborted() const { return Aborted; }
-};
-
-class MigrationPass {
-public:
- ASTContext &Ctx;
- LangOptions::GCMode OrigGCMode;
- MigratorOptions MigOptions;
- Sema &SemaRef;
- TransformActions &TA;
- const CapturedDiagList &CapturedDiags;
- std::vector<SourceLocation> &ARCMTMacroLocs;
- std::optional<bool> EnableCFBridgeFns;
-
- MigrationPass(ASTContext &Ctx, LangOptions::GCMode OrigGCMode, Sema &sema,
- TransformActions &TA, const CapturedDiagList &capturedDiags,
- std::vector<SourceLocation> &ARCMTMacroLocs)
- : Ctx(Ctx), OrigGCMode(OrigGCMode), SemaRef(sema), TA(TA),
- CapturedDiags(capturedDiags), ARCMTMacroLocs(ARCMTMacroLocs) {}
-
- const CapturedDiagList &getDiags() const { return CapturedDiags; }
-
- bool isGCMigration() const { return OrigGCMode != LangOptions::NonGC; }
- bool noFinalizeRemoval() const { return MigOptions.NoFinalizeRemoval; }
- void setNoFinalizeRemoval(bool val) {MigOptions.NoFinalizeRemoval = val; }
-
- bool CFBridgingFunctionsDefined();
-};
-
-static inline StringRef getARCMTMacroName() {
- return "__IMPL_ARCMT_REMOVED_EXPR__";
-}
-
-} // end namespace arcmt
-
-} // end namespace clang
-
-#endif
diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp
deleted file mode 100644
index c1bc7c7..0000000
--- a/clang/lib/ARCMigrate/ObjCMT.cpp
+++ /dev/null
@@ -1,2262 +0,0 @@
-//===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "clang/Analysis/RetainSummaryManager.h"
-#include "clang/ARCMigrate/ARCMT.h"
-#include "clang/ARCMigrate/ARCMTActions.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/NSAPI.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Edit/Commit.h"
-#include "clang/Edit/EditedSource.h"
-#include "clang/Edit/EditsReceiver.h"
-#include "clang/Edit/Rewriters.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/Lex/PPConditionalDirectiveRecord.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Rewrite/Core/Rewriter.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/YAMLParser.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace ento;
-using llvm::RewriteBuffer;
-
-namespace {
-
-class ObjCMigrateASTConsumer : public ASTConsumer {
- enum CF_BRIDGING_KIND {
- CF_BRIDGING_NONE,
- CF_BRIDGING_ENABLE,
- CF_BRIDGING_MAY_INCLUDE
- };
-
- void migrateDecl(Decl *D);
- void migrateObjCContainerDecl(ASTContext &Ctx, ObjCContainerDecl *D);
- void migrateProtocolConformance(ASTContext &Ctx,
- const ObjCImplementationDecl *ImpDecl);
- void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
- bool migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
- const TypedefDecl *TypedefDcl);
- void migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
- void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
- ObjCMethodDecl *OM);
- bool migrateProperty(ASTContext &Ctx, ObjCContainerDecl *D, ObjCMethodDecl *OM);
- void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM);
- void migratePropertyNsReturnsInnerPointer(ASTContext &Ctx, ObjCPropertyDecl *P);
- void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
- ObjCMethodDecl *OM,
- ObjCInstanceTypeFamily OIT_Family = OIT_None);
-
- void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
- void AddCFAnnotations(ASTContext &Ctx,
- const RetainSummary *RS,
- const FunctionDecl *FuncDecl, bool ResultAnnotated);
- void AddCFAnnotations(ASTContext &Ctx,
- const RetainSummary *RS,
- const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
-
- void AnnotateImplicitBridging(ASTContext &Ctx);
-
- CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,
- const FunctionDecl *FuncDecl);
-
- void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl);
-
- void migrateAddMethodAnnotation(ASTContext &Ctx,
- const ObjCMethodDecl *MethodDecl);
-
- void inferDesignatedInitializers(ASTContext &Ctx,
- const ObjCImplementationDecl *ImplD);
-
- bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);
-
- std::unique_ptr<RetainSummaryManager> Summaries;
-
-public:
- std::string MigrateDir;
- unsigned ASTMigrateActions;
- FileID FileId;
- const TypedefDecl *NSIntegerTypedefed;
- const TypedefDecl *NSUIntegerTypedefed;
- std::unique_ptr<NSAPI> NSAPIObj;
- std::unique_ptr<edit::EditedSource> Editor;
- FileRemapper &Remapper;
- FileManager &FileMgr;
- const PPConditionalDirectiveRecord *PPRec;
- Preprocessor &PP;
- bool IsOutputFile;
- bool FoundationIncluded;
- llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
- llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
- llvm::StringSet<> AllowListFilenames;
-
- RetainSummaryManager &getSummaryManager(ASTContext &Ctx) {
- if (!Summaries)
- Summaries.reset(new RetainSummaryManager(Ctx,
- /*TrackNSCFObjects=*/true,
- /*trackOSObjects=*/false));
- return *Summaries;
- }
-
- ObjCMigrateASTConsumer(StringRef migrateDir, unsigned astMigrateActions,
- FileRemapper &remapper, FileManager &fileMgr,
- const PPConditionalDirectiveRecord *PPRec,
- Preprocessor &PP, bool isOutputFile,
- ArrayRef<std::string> AllowList)
- : MigrateDir(migrateDir), ASTMigrateActions(astMigrateActions),
- NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
- Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
- IsOutputFile(isOutputFile), FoundationIncluded(false) {
- AllowListFilenames.insert(AllowList.begin(), AllowList.end());
- }
-
-protected:
- void Initialize(ASTContext &Context) override {
- NSAPIObj.reset(new NSAPI(Context));
- Editor.reset(new edit::EditedSource(Context.getSourceManager(),
- Context.getLangOpts(),
- PPRec));
- }
-
- bool HandleTopLevelDecl(DeclGroupRef DG) override {
- for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
- migrateDecl(*I);
- return true;
- }
- void HandleInterestingDecl(DeclGroupRef DG) override {
- // Ignore decls from the PCH.
- }
- void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
- ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
- }
-
- void HandleTranslationUnit(ASTContext &Ctx) override;
-
- bool canModifyFile(StringRef Path) {
- if (AllowListFilenames.empty())
- return true;
- return AllowListFilenames.contains(llvm::sys::path::filename(Path));
- }
- bool canModifyFile(OptionalFileEntryRef FE) {
- if (!FE)
- return false;
- return canModifyFile(FE->getName());
- }
- bool canModifyFile(FileID FID) {
- if (FID.isInvalid())
- return false;
- return canModifyFile(PP.getSourceManager().getFileEntryRefForID(FID));
- }
-
- bool canModify(const Decl *D) {
- if (!D)
- return false;
- if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(D))
- return canModify(CatImpl->getCategoryDecl());
- if (const ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D))
- return canModify(Impl->getClassInterface());
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
- return canModify(cast<Decl>(MD->getDeclContext()));
-
- FileID FID = PP.getSourceManager().getFileID(D->getLocation());
- return canModifyFile(FID);
- }
-};
-
-} // end anonymous namespace
-
-ObjCMigrateAction::ObjCMigrateAction(
- std::unique_ptr<FrontendAction> WrappedAction, StringRef migrateDir,
- unsigned migrateAction)
- : WrapperFrontendAction(std::move(WrappedAction)), MigrateDir(migrateDir),
- ObjCMigAction(migrateAction), CompInst(nullptr) {
- if (MigrateDir.empty())
- MigrateDir = "."; // user current directory if none is given.
-}
-
-std::unique_ptr<ASTConsumer>
-ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
- PPConditionalDirectiveRecord *
- PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager());
- CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
- std::vector<std::unique_ptr<ASTConsumer>> Consumers;
- Consumers.push_back(WrapperFrontendAction::CreateASTConsumer(CI, InFile));
- Consumers.push_back(std::make_unique<ObjCMigrateASTConsumer>(
- MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec,
- CompInst->getPreprocessor(), false, std::nullopt));
- return std::make_unique<MultiplexConsumer>(std::move(Consumers));
-}
-
-bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
- Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
- /*ignoreIfFilesChanged=*/true);
- CompInst = &CI;
- CI.getDiagnostics().setIgnoreAllWarnings(true);
- return true;
-}
-
-namespace {
- // FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp
- bool subscriptOperatorNeedsParens(const Expr *FullExpr) {
- const Expr* Expr = FullExpr->IgnoreImpCasts();
- return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) ||
- isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) ||
- isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) ||
- isa<CXXTypeidExpr>(Expr) ||
- isa<CXXUnresolvedConstructExpr>(Expr) ||
- isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) ||
- isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) ||
- isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) ||
- isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr));
- }
-
- /// - Rewrite message expression for Objective-C setter and getters into
- /// property-dot syntax.
- bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg,
- Preprocessor &PP,
- const NSAPI &NS, edit::Commit &commit,
- const ParentMap *PMap) {
- if (!Msg || Msg->isImplicit() ||
- (Msg->getReceiverKind() != ObjCMessageExpr::Instance &&
- Msg->getReceiverKind() != ObjCMessageExpr::SuperInstance))
- return false;
- if (const Expr *Receiver = Msg->getInstanceReceiver())
- if (Receiver->getType()->isObjCBuiltinType())
- return false;
-
- const ObjCMethodDecl *Method = Msg->getMethodDecl();
- if (!Method)
- return false;
- if (!Method->isPropertyAccessor())
- return false;
-
- const ObjCPropertyDecl *Prop = Method->findPropertyDecl();
- if (!Prop)
- return false;
-
- SourceRange MsgRange = Msg->getSourceRange();
- bool ReceiverIsSuper =
- (Msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
- // for 'super' receiver is nullptr.
- const Expr *receiver = Msg->getInstanceReceiver();
- bool NeedsParen =
- ReceiverIsSuper ? false : subscriptOperatorNeedsParens(receiver);
- bool IsGetter = (Msg->getNumArgs() == 0);
- if (IsGetter) {
- // Find space location range between receiver expression and getter method.
- SourceLocation BegLoc =
- ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getEndLoc();
- BegLoc = PP.getLocForEndOfToken(BegLoc);
- SourceLocation EndLoc = Msg->getSelectorLoc(0);
- SourceRange SpaceRange(BegLoc, EndLoc);
- std::string PropertyDotString;
- // rewrite getter method expression into: receiver.property or
- // (receiver).property
- if (NeedsParen) {
- commit.insertBefore(receiver->getBeginLoc(), "(");
- PropertyDotString = ").";
- }
- else
- PropertyDotString = ".";
- PropertyDotString += Prop->getName();
- commit.replace(SpaceRange, PropertyDotString);
-
- // remove '[' ']'
- commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
- commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
- } else {
- if (NeedsParen)
- commit.insertWrap("(", receiver->getSourceRange(), ")");
- std::string PropertyDotString = ".";
- PropertyDotString += Prop->getName();
- PropertyDotString += " =";
- const Expr*const* Args = Msg->getArgs();
- const Expr *RHS = Args[0];
- if (!RHS)
- return false;
- SourceLocation BegLoc =
- ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getEndLoc();
- BegLoc = PP.getLocForEndOfToken(BegLoc);
- SourceLocation EndLoc = RHS->getBeginLoc();
- EndLoc = EndLoc.getLocWithOffset(-1);
- const char *colon = PP.getSourceManager().getCharacterData(EndLoc);
- // Add a space after '=' if there is no space between RHS and '='
- if (colon && colon[0] == ':')
- PropertyDotString += " ";
- SourceRange Range(BegLoc, EndLoc);
- commit.replace(Range, PropertyDotString);
- // remove '[' ']'
- commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
- commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
- }
- return true;
- }
-
-class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
- ObjCMigrateASTConsumer &Consumer;
- ParentMap &PMap;
-
-public:
- ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
- : Consumer(consumer), PMap(PMap) { }
-
- bool shouldVisitTemplateInstantiations() const { return false; }
- bool shouldWalkTypesOfTypeLocs() const { return false; }
-
- bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
- if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) {
- edit::Commit commit(*Consumer.Editor);
- edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
- Consumer.Editor->commit(commit);
- }
-
- if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) {
- edit::Commit commit(*Consumer.Editor);
- edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
- Consumer.Editor->commit(commit);
- }
-
- if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_PropertyDotSyntax) {
- edit::Commit commit(*Consumer.Editor);
- rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
- commit, &PMap);
- Consumer.Editor->commit(commit);
- }
-
- return true;
- }
-
- bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
- // Do depth first; we want to rewrite the subexpressions first so that if
- // we have to move expressions we will move them already rewritten.
- for (Stmt *SubStmt : E->children())
- if (!TraverseStmt(SubStmt))
- return false;
-
- return WalkUpFromObjCMessageExpr(E);
- }
-};
-
-class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
- ObjCMigrateASTConsumer &Consumer;
- std::unique_ptr<ParentMap> PMap;
-
-public:
- BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
-
- bool shouldVisitTemplateInstantiations() const { return false; }
- bool shouldWalkTypesOfTypeLocs() const { return false; }
-
- bool TraverseStmt(Stmt *S) {
- PMap.reset(new ParentMap(S));
- ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
- return true;
- }
-};
-} // end anonymous namespace
-
-void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
- if (!D)
- return;
- if (isa<ObjCMethodDecl>(D))
- return; // Wait for the ObjC container declaration.
-
- BodyMigrator(*this).TraverseDecl(D);
-}
-
-static void append_attr(std::string &PropertyString, const char *attr,
- bool &LParenAdded) {
- if (!LParenAdded) {
- PropertyString += "(";
- LParenAdded = true;
- }
- else
- PropertyString += ", ";
- PropertyString += attr;
-}
-
-static
-void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString,
- const std::string& TypeString,
- const char *name) {
- const char *argPtr = TypeString.c_str();
- int paren = 0;
- while (*argPtr) {
- switch (*argPtr) {
- case '(':
- PropertyString += *argPtr;
- paren++;
- break;
- case ')':
- PropertyString += *argPtr;
- paren--;
- break;
- case '^':
- case '*':
- PropertyString += (*argPtr);
- if (paren == 1) {
- PropertyString += name;
- name = "";
- }
- break;
- default:
- PropertyString += *argPtr;
- break;
- }
- argPtr++;
- }
-}
-
-static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType) {
- Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
- bool RetainableObject = ArgType->isObjCRetainableType();
- if (RetainableObject &&
- (propertyLifetime == Qualifiers::OCL_Strong
- || propertyLifetime == Qualifiers::OCL_None)) {
- if (const ObjCObjectPointerType *ObjPtrTy =
- ArgType->getAs<ObjCObjectPointerType>()) {
- ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
- if (IDecl &&
- IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
- return "copy";
- else
- return "strong";
- }
- else if (ArgType->isBlockPointerType())
- return "copy";
- } else if (propertyLifetime == Qualifiers::OCL_Weak)
- // TODO. More precise determination of 'weak' attribute requires
- // looking into setter's implementation for backing weak ivar.
- return "weak";
- else if (RetainableObject)
- return ArgType->isBlockPointerType() ? "copy" : "strong";
- return nullptr;
-}
-
-static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
- const ObjCMethodDecl *Setter,
- const NSAPI &NS, edit::Commit &commit,
- unsigned LengthOfPrefix,
- bool Atomic, bool UseNsIosOnlyMacro,
- bool AvailabilityArgsMatch) {
- ASTContext &Context = NS.getASTContext();
- bool LParenAdded = false;
- std::string PropertyString = "@property ";
- if (UseNsIosOnlyMacro && NS.isMacroDefined("NS_NONATOMIC_IOSONLY")) {
- PropertyString += "(NS_NONATOMIC_IOSONLY";
- LParenAdded = true;
- } else if (!Atomic) {
- PropertyString += "(nonatomic";
- LParenAdded = true;
- }
-
- std::string PropertyNameString = Getter->getNameAsString();
- StringRef PropertyName(PropertyNameString);
- if (LengthOfPrefix > 0) {
- if (!LParenAdded) {
- PropertyString += "(getter=";
- LParenAdded = true;
- }
- else
- PropertyString += ", getter=";
- PropertyString += PropertyNameString;
- }
- // Property with no setter may be suggested as a 'readonly' property.
- if (!Setter)
- append_attr(PropertyString, "readonly", LParenAdded);
-
-
- // Short circuit 'delegate' properties that contain the name "delegate" or
- // "dataSource", or have exact name "target" to have 'assign' attribute.
- if (PropertyName == "target" || PropertyName.contains("delegate") ||
- PropertyName.contains("dataSource")) {
- QualType QT = Getter->getReturnType();
- if (!QT->isRealType())
- append_attr(PropertyString, "assign", LParenAdded);
- } else if (!Setter) {
- QualType ResType = Context.getCanonicalType(Getter->getReturnType());
- if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType))
- append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
- } else {
- const ParmVarDecl *argDecl = *Setter->param_begin();
- QualType ArgType = Context.getCanonicalType(argDecl->getType());
- if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ArgType))
- append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
- }
- if (LParenAdded)
- PropertyString += ')';
- QualType RT = Getter->getReturnType();
- if (!RT->getAs<TypedefType>()) {
- // strip off any ARC lifetime qualifier.
- QualType CanResultTy = Context.getCanonicalType(RT);
- if (CanResultTy.getQualifiers().hasObjCLifetime()) {
- Qualifiers Qs = CanResultTy.getQualifiers();
- Qs.removeObjCLifetime();
- RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
- }
- }
- PropertyString += " ";
- PrintingPolicy SubPolicy(Context.getPrintingPolicy());
- SubPolicy.SuppressStrongLifetime = true;
- SubPolicy.SuppressLifetimeQualifiers = true;
- std::string TypeString = RT.getAsString(SubPolicy);
- if (LengthOfPrefix > 0) {
- // property name must strip off "is" and lower case the first character
- // after that; e.g. isContinuous will become continuous.
- StringRef PropertyNameStringRef(PropertyNameString);
- PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
- PropertyNameString = std::string(PropertyNameStringRef);
- bool NoLowering = (isUppercase(PropertyNameString[0]) &&
- PropertyNameString.size() > 1 &&
- isUppercase(PropertyNameString[1]));
- if (!NoLowering)
- PropertyNameString[0] = toLowercase(PropertyNameString[0]);
- }
- if (RT->isBlockPointerType() || RT->isFunctionPointerType())
- MigrateBlockOrFunctionPointerTypeVariable(PropertyString,
- TypeString,
- PropertyNameString.c_str());
- else {
- char LastChar = TypeString[TypeString.size()-1];
- PropertyString += TypeString;
- if (LastChar != '*')
- PropertyString += ' ';
- PropertyString += PropertyNameString;
- }
- SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc();
- Selector GetterSelector = Getter->getSelector();
-
- SourceLocation EndGetterSelectorLoc =
- StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size());
- commit.replace(CharSourceRange::getCharRange(Getter->getBeginLoc(),
- EndGetterSelectorLoc),
- PropertyString);
- if (Setter && AvailabilityArgsMatch) {
- SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
- // Get location past ';'
- EndLoc = EndLoc.getLocWithOffset(1);
- SourceLocation BeginOfSetterDclLoc = Setter->getBeginLoc();
- // FIXME. This assumes that setter decl; is immediately preceded by eoln.
- // It is trying to remove the setter method decl. line entirely.
- BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1);
- commit.remove(SourceRange(BeginOfSetterDclLoc, EndLoc));
- }
-}
-
-static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D) {
- if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D)) {
- StringRef Name = CatDecl->getName();
- return Name.ends_with("Deprecated");
- }
- return false;
-}
-
-void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,
- ObjCContainerDecl *D) {
- if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D))
- return;
-
- for (auto *Method : D->methods()) {
- if (Method->isDeprecated())
- continue;
- bool PropertyInferred = migrateProperty(Ctx, D, Method);
- // If a property is inferred, do not attempt to attach NS_RETURNS_INNER_POINTER to
- // the getter method as it ends up on the property itself which we don't want
- // to do unless -objcmt-returns-innerpointer-property option is on.
- if (!PropertyInferred ||
- (ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
- if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
- migrateNsReturnsInnerPointer(Ctx, Method);
- }
- if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
- return;
-
- for (auto *Prop : D->instance_properties()) {
- if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
- !Prop->isDeprecated())
- migratePropertyNsReturnsInnerPointer(Ctx, Prop);
- }
-}
-
-static bool
-ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
- const ObjCImplementationDecl *ImpDecl,
- const ObjCInterfaceDecl *IDecl,
- ObjCProtocolDecl *Protocol) {
- // In auto-synthesis, protocol properties are not synthesized. So,
- // a conforming protocol must have its required properties declared
- // in class interface.
- bool HasAtleastOneRequiredProperty = false;
- if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
- for (const auto *Property : PDecl->instance_properties()) {
- if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
- continue;
- HasAtleastOneRequiredProperty = true;
- DeclContext::lookup_result R = IDecl->lookup(Property->getDeclName());
- if (R.empty()) {
- // Relax the rule and look into class's implementation for a synthesize
- // or dynamic declaration. Class is implementing a property coming from
- // another protocol. This still makes the target protocol as conforming.
- if (!ImpDecl->FindPropertyImplDecl(
- Property->getDeclName().getAsIdentifierInfo(),
- Property->getQueryKind()))
- return false;
- } else if (auto *ClassProperty = R.find_first<ObjCPropertyDecl>()) {
- if ((ClassProperty->getPropertyAttributes() !=
- Property->getPropertyAttributes()) ||
- !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
- return false;
- } else
- return false;
- }
-
- // At this point, all required properties in this protocol conform to those
- // declared in the class.
- // Check that class implements the required methods of the protocol too.
- bool HasAtleastOneRequiredMethod = false;
- if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {
- if (PDecl->meth_begin() == PDecl->meth_end())
- return HasAtleastOneRequiredProperty;
- for (const auto *MD : PDecl->methods()) {
- if (MD->isImplicit())
- continue;
- if (MD->getImplementationControl() == ObjCImplementationControl::Optional)
- continue;
- DeclContext::lookup_result R = ImpDecl->lookup(MD->getDeclName());
- if (R.empty())
- return false;
- bool match = false;
- HasAtleastOneRequiredMethod = true;
- for (NamedDecl *ND : R)
- if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(ND))
- if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
- match = true;
- break;
- }
- if (!match)
- return false;
- }
- }
- return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;
-}
-
-static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
- llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
- const NSAPI &NS, edit::Commit &commit) {
- const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
- std::string ClassString;
- SourceLocation EndLoc =
- IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
-
- if (Protocols.empty()) {
- ClassString = '<';
- for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
- ClassString += ConformingProtocols[i]->getNameAsString();
- if (i != (e-1))
- ClassString += ", ";
- }
- ClassString += "> ";
- }
- else {
- ClassString = ", ";
- for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
- ClassString += ConformingProtocols[i]->getNameAsString();
- if (i != (e-1))
- ClassString += ", ";
- }
- ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
- EndLoc = *PL;
- }
-
- commit.insertAfterToken(EndLoc, ClassString);
- return true;
-}
-
-static StringRef GetUnsignedName(StringRef NSIntegerName) {
- StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
- .Case("int8_t", "uint8_t")
- .Case("int16_t", "uint16_t")
- .Case("int32_t", "uint32_t")
- .Case("NSInteger", "NSUInteger")
- .Case("int64_t", "uint64_t")
- .Default(NSIntegerName);
- return UnsignedName;
-}
-
-static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
- const TypedefDecl *TypedefDcl,
- const NSAPI &NS, edit::Commit &commit,
- StringRef NSIntegerName,
- bool NSOptions) {
- std::string ClassString;
- if (NSOptions) {
- ClassString = "typedef NS_OPTIONS(";
- ClassString += GetUnsignedName(NSIntegerName);
- }
- else {
- ClassString = "typedef NS_ENUM(";
- ClassString += NSIntegerName;
- }
- ClassString += ", ";
-
- ClassString += TypedefDcl->getIdentifier()->getName();
- ClassString += ')';
- SourceRange R(EnumDcl->getBeginLoc(), EnumDcl->getBeginLoc());
- commit.replace(R, ClassString);
- SourceLocation EndOfEnumDclLoc = EnumDcl->getEndLoc();
- EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
- NS.getASTContext(), /*IsDecl*/true);
- if (EndOfEnumDclLoc.isValid()) {
- SourceRange EnumDclRange(EnumDcl->getBeginLoc(), EndOfEnumDclLoc);
- commit.insertFromRange(TypedefDcl->getBeginLoc(), EnumDclRange);
- }
- else
- return false;
-
- SourceLocation EndTypedefDclLoc = TypedefDcl->getEndLoc();
- EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
- NS.getASTContext(), /*IsDecl*/true);
- if (EndTypedefDclLoc.isValid()) {
- SourceRange TDRange(TypedefDcl->getBeginLoc(), EndTypedefDclLoc);
- commit.remove(TDRange);
- }
- else
- return false;
-
- EndOfEnumDclLoc =
- trans::findLocationAfterSemi(EnumDcl->getEndLoc(), NS.getASTContext(),
- /*IsDecl*/ true);
- if (EndOfEnumDclLoc.isValid()) {
- SourceLocation BeginOfEnumDclLoc = EnumDcl->getBeginLoc();
- // FIXME. This assumes that enum decl; is immediately preceded by eoln.
- // It is trying to remove the enum decl. lines entirely.
- BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1);
- commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc));
- return true;
- }
- return false;
-}
-
-static void rewriteToNSMacroDecl(ASTContext &Ctx,
- const EnumDecl *EnumDcl,
- const TypedefDecl *TypedefDcl,
- const NSAPI &NS, edit::Commit &commit,
- bool IsNSIntegerType) {
- QualType DesignatedEnumType = EnumDcl->getIntegerType();
- assert(!DesignatedEnumType.isNull()
- && "rewriteToNSMacroDecl - underlying enum type is null");
-
- PrintingPolicy Policy(Ctx.getPrintingPolicy());
- std::string TypeString = DesignatedEnumType.getAsString(Policy);
- std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS(";
- ClassString += TypeString;
- ClassString += ", ";
-
- ClassString += TypedefDcl->getIdentifier()->getName();
- ClassString += ") ";
- SourceLocation EndLoc = EnumDcl->getBraceRange().getBegin();
- if (EndLoc.isInvalid())
- return;
- CharSourceRange R =
- CharSourceRange::getCharRange(EnumDcl->getBeginLoc(), EndLoc);
- commit.replace(R, ClassString);
- // This is to remove spaces between '}' and typedef name.
- SourceLocation StartTypedefLoc = EnumDcl->getEndLoc();
- StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1);
- SourceLocation EndTypedefLoc = TypedefDcl->getEndLoc();
-
- commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc));
-}
-
-static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx,
- const EnumDecl *EnumDcl) {
- bool PowerOfTwo = true;
- bool AllHexdecimalEnumerator = true;
- uint64_t MaxPowerOfTwoVal = 0;
- for (auto *Enumerator : EnumDcl->enumerators()) {
- const Expr *InitExpr = Enumerator->getInitExpr();
- if (!InitExpr) {
- PowerOfTwo = false;
- AllHexdecimalEnumerator = false;
- continue;
- }
- InitExpr = InitExpr->IgnoreParenCasts();
- if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
- if (BO->isShiftOp() || BO->isBitwiseOp())
- return true;
-
- uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
- if (PowerOfTwo && EnumVal) {
- if (!llvm::isPowerOf2_64(EnumVal))
- PowerOfTwo = false;
- else if (EnumVal > MaxPowerOfTwoVal)
- MaxPowerOfTwoVal = EnumVal;
- }
- if (AllHexdecimalEnumerator && EnumVal) {
- bool FoundHexdecimalEnumerator = false;
- SourceLocation EndLoc = Enumerator->getEndLoc();
- Token Tok;
- if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true))
- if (Tok.isLiteral() && Tok.getLength() > 2) {
- if (const char *StringLit = Tok.getLiteralData())
- FoundHexdecimalEnumerator =
- (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x'));
- }
- if (!FoundHexdecimalEnumerator)
- AllHexdecimalEnumerator = false;
- }
- }
- return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
-}
-
-void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
- const ObjCImplementationDecl *ImpDecl) {
- const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
- if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated())
- return;
- // Find all implicit conforming protocols for this class
- // and make them explicit.
- llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
- Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
- llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;
-
- for (ObjCProtocolDecl *ProtDecl : ObjCProtocolDecls)
- if (!ExplicitProtocols.count(ProtDecl))
- PotentialImplicitProtocols.push_back(ProtDecl);
-
- if (PotentialImplicitProtocols.empty())
- return;
-
- // go through list of non-optional methods and properties in each protocol
- // in the PotentialImplicitProtocols list. If class implements every one of the
- // methods and properties, then this class conforms to this protocol.
- llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
- for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
- if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
- PotentialImplicitProtocols[i]))
- ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
-
- if (ConformingProtocols.empty())
- return;
-
- // Further reduce number of conforming protocols. If protocol P1 is in the list
- // protocol P2 (P2<P1>), No need to include P1.
- llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols;
- for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
- bool DropIt = false;
- ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i];
- for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
- ObjCProtocolDecl *PDecl = ConformingProtocols[i1];
- if (PDecl == TargetPDecl)
- continue;
- if (PDecl->lookupProtocolNamed(
- TargetPDecl->getDeclName().getAsIdentifierInfo())) {
- DropIt = true;
- break;
- }
- }
- if (!DropIt)
- MinimalConformingProtocols.push_back(TargetPDecl);
- }
- if (MinimalConformingProtocols.empty())
- return;
- edit::Commit commit(*Editor);
- rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
- *NSAPIObj, commit);
- Editor->commit(commit);
-}
-
-void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
- const TypedefDecl *TypedefDcl) {
-
- QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
- if (NSAPIObj->isObjCNSIntegerType(qt))
- NSIntegerTypedefed = TypedefDcl;
- else if (NSAPIObj->isObjCNSUIntegerType(qt))
- NSUIntegerTypedefed = TypedefDcl;
-}
-
-bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
- const EnumDecl *EnumDcl,
- const TypedefDecl *TypedefDcl) {
- if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
- EnumDcl->isDeprecated())
- return false;
- if (!TypedefDcl) {
- if (NSIntegerTypedefed) {
- TypedefDcl = NSIntegerTypedefed;
- NSIntegerTypedefed = nullptr;
- }
- else if (NSUIntegerTypedefed) {
- TypedefDcl = NSUIntegerTypedefed;
- NSUIntegerTypedefed = nullptr;
- }
- else
- return false;
- FileID FileIdOfTypedefDcl =
- PP.getSourceManager().getFileID(TypedefDcl->getLocation());
- FileID FileIdOfEnumDcl =
- PP.getSourceManager().getFileID(EnumDcl->getLocation());
- if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
- return false;
- }
- if (TypedefDcl->isDeprecated())
- return false;
-
- QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
- StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
-
- if (NSIntegerName.empty()) {
- // Also check for typedef enum {...} TD;
- if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
- if (EnumTy->getDecl() == EnumDcl) {
- bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
- if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))
- return false;
- edit::Commit commit(*Editor);
- rewriteToNSMacroDecl(Ctx, EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
- Editor->commit(commit);
- return true;
- }
- }
- return false;
- }
-
- // We may still use NS_OPTIONS based on what we find in the enumertor list.
- bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
- if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))
- return false;
- edit::Commit commit(*Editor);
- bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj,
- commit, NSIntegerName, NSOptions);
- Editor->commit(commit);
- return Res;
-}
-
-static void ReplaceWithInstancetype(ASTContext &Ctx,
- const ObjCMigrateASTConsumer &ASTC,
- ObjCMethodDecl *OM) {
- if (OM->getReturnType() == Ctx.getObjCInstanceType())
- return; // already has instancetype.
-
- SourceRange R;
- std::string ClassString;
- if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
- TypeLoc TL = TSInfo->getTypeLoc();
- R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
- ClassString = "instancetype";
- }
- else {
- R = SourceRange(OM->getBeginLoc(), OM->getBeginLoc());
- ClassString = OM->isInstanceMethod() ? '-' : '+';
- ClassString += " (instancetype)";
- }
- edit::Commit commit(*ASTC.Editor);
- commit.replace(R, ClassString);
- ASTC.Editor->commit(commit);
-}
-
-static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC,
- ObjCMethodDecl *OM) {
- ObjCInterfaceDecl *IDecl = OM->getClassInterface();
- SourceRange R;
- std::string ClassString;
- if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
- TypeLoc TL = TSInfo->getTypeLoc();
- R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); {
- ClassString = std::string(IDecl->getName());
- ClassString += "*";
- }
- }
- else {
- R = SourceRange(OM->getBeginLoc(), OM->getBeginLoc());
- ClassString = "+ (";
- ClassString += IDecl->getName(); ClassString += "*)";
- }
- edit::Commit commit(*ASTC.Editor);
- commit.replace(R, ClassString);
- ASTC.Editor->commit(commit);
-}
-
-void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
- ObjCContainerDecl *CDecl,
- ObjCMethodDecl *OM) {
- ObjCInstanceTypeFamily OIT_Family =
- Selector::getInstTypeMethodFamily(OM->getSelector());
-
- std::string ClassName;
- switch (OIT_Family) {
- case OIT_None:
- migrateFactoryMethod(Ctx, CDecl, OM);
- return;
- case OIT_Array:
- ClassName = "NSArray";
- break;
- case OIT_Dictionary:
- ClassName = "NSDictionary";
- break;
- case OIT_Singleton:
- migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton);
- return;
- case OIT_Init:
- if (OM->getReturnType()->isObjCIdType())
- ReplaceWithInstancetype(Ctx, *this, OM);
- return;
- case OIT_ReturnsSelf:
- migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf);
- return;
- }
- if (!OM->getReturnType()->isObjCIdType())
- return;
-
- ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
- if (!IDecl) {
- if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
- IDecl = CatDecl->getClassInterface();
- else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
- IDecl = ImpDecl->getClassInterface();
- }
- if (!IDecl ||
- !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) {
- migrateFactoryMethod(Ctx, CDecl, OM);
- return;
- }
- ReplaceWithInstancetype(Ctx, *this, OM);
-}
-
-static bool TypeIsInnerPointer(QualType T) {
- if (!T->isAnyPointerType())
- return false;
- if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() ||
- T->isBlockPointerType() || T->isFunctionPointerType() ||
- ento::coreFoundation::isCFObjectRef(T))
- return false;
- // Also, typedef-of-pointer-to-incomplete-struct is something that we assume
- // is not an innter pointer type.
- QualType OrigT = T;
- while (const auto *TD = T->getAs<TypedefType>())
- T = TD->getDecl()->getUnderlyingType();
- if (OrigT == T || !T->isPointerType())
- return true;
- const PointerType* PT = T->getAs<PointerType>();
- QualType UPointeeT = PT->getPointeeType().getUnqualifiedType();
- if (UPointeeT->isRecordType()) {
- const RecordType *RecordTy = UPointeeT->getAs<RecordType>();
- if (!RecordTy->getDecl()->isCompleteDefinition())
- return false;
- }
- return true;
-}
-
-/// Check whether the two versions match.
-static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {
- return (X == Y);
-}
-
-/// AvailabilityAttrsMatch - This routine checks that if comparing two
-/// availability attributes, all their components match. It returns
-/// true, if not dealing with availability or when all components of
-/// availability attributes match. This routine is only called when
-/// the attributes are of the same kind.
-static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) {
- const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
- if (!AA1)
- return true;
- const AvailabilityAttr *AA2 = cast<AvailabilityAttr>(At2);
-
- VersionTuple Introduced1 = AA1->getIntroduced();
- VersionTuple Deprecated1 = AA1->getDeprecated();
- VersionTuple Obsoleted1 = AA1->getObsoleted();
- bool IsUnavailable1 = AA1->getUnavailable();
- VersionTuple Introduced2 = AA2->getIntroduced();
- VersionTuple Deprecated2 = AA2->getDeprecated();
- VersionTuple Obsoleted2 = AA2->getObsoleted();
- bool IsUnavailable2 = AA2->getUnavailable();
- return (versionsMatch(Introduced1, Introduced2) &&
- versionsMatch(Deprecated1, Deprecated2) &&
- versionsMatch(Obsoleted1, Obsoleted2) &&
- IsUnavailable1 == IsUnavailable2);
-}
-
-static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2,
- bool &AvailabilityArgsMatch) {
- // This list is very small, so this need not be optimized.
- for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {
- bool match = false;
- for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {
- // Matching attribute kind only. Except for Availability attributes,
- // we are not getting into details of the attributes. For all practical purposes
- // this is sufficient.
- if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) {
- if (AvailabilityArgsMatch)
- AvailabilityArgsMatch = AvailabilityAttrsMatch(Attrs1[i], Attrs2[j]);
- match = true;
- break;
- }
- }
- if (!match)
- return false;
- }
- return true;
-}
-
-/// AttributesMatch - This routine checks list of attributes for two
-/// decls. It returns false, if there is a mismatch in kind of
-/// attributes seen in the decls. It returns true if the two decls
-/// have list of same kind of attributes. Furthermore, when there
-/// are availability attributes in the two decls, it sets the
-/// AvailabilityArgsMatch to false if availability attributes have
-/// different versions, etc.
-static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2,
- bool &AvailabilityArgsMatch) {
- if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) {
- AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());
- return true;
- }
- AvailabilityArgsMatch = true;
- const AttrVec &Attrs1 = Decl1->getAttrs();
- const AttrVec &Attrs2 = Decl2->getAttrs();
- bool match = MatchTwoAttributeLists(Attrs1, Attrs2, AvailabilityArgsMatch);
- if (match && (Attrs2.size() > Attrs1.size()))
- return MatchTwoAttributeLists(Attrs2, Attrs1, AvailabilityArgsMatch);
- return match;
-}
-
-static bool IsValidIdentifier(ASTContext &Ctx,
- const char *Name) {
- if (!isAsciiIdentifierStart(Name[0]))
- return false;
- std::string NameString = Name;
- NameString[0] = toLowercase(NameString[0]);
- const IdentifierInfo *II = &Ctx.Idents.get(NameString);
- return II->getTokenID() == tok::identifier;
-}
-
-bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
- ObjCContainerDecl *D,
- ObjCMethodDecl *Method) {
- if (Method->isPropertyAccessor() || !Method->isInstanceMethod() ||
- Method->param_size() != 0)
- return false;
- // Is this method candidate to be a getter?
- QualType GRT = Method->getReturnType();
- if (GRT->isVoidType())
- return false;
-
- Selector GetterSelector = Method->getSelector();
- ObjCInstanceTypeFamily OIT_Family =
- Selector::getInstTypeMethodFamily(GetterSelector);
-
- if (OIT_Family != OIT_None)
- return false;
-
- const IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
- Selector SetterSelector =
- SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
- PP.getSelectorTable(),
- getterName);
- ObjCMethodDecl *SetterMethod = D->getInstanceMethod(SetterSelector);
- unsigned LengthOfPrefix = 0;
- if (!SetterMethod) {
- // try a different naming convention for getter: isXxxxx
- StringRef getterNameString = getterName->getName();
- bool IsPrefix = getterNameString.starts_with("is");
- // Note that we don't want to change an isXXX method of retainable object
- // type to property (readonly or otherwise).
- if (IsPrefix && GRT->isObjCRetainableType())
- return false;
- if (IsPrefix || getterNameString.starts_with("get")) {
- LengthOfPrefix = (IsPrefix ? 2 : 3);
- const char *CGetterName = getterNameString.data() + LengthOfPrefix;
- // Make sure that first character after "is" or "get" prefix can
- // start an identifier.
- if (!IsValidIdentifier(Ctx, CGetterName))
- return false;
- if (CGetterName[0] && isUppercase(CGetterName[0])) {
- getterName = &Ctx.Idents.get(CGetterName);
- SetterSelector =
- SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
- PP.getSelectorTable(),
- getterName);
- SetterMethod = D->getInstanceMethod(SetterSelector);
- }
- }
- }
-
- if (SetterMethod) {
- if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0)
- return false;
- bool AvailabilityArgsMatch;
- if (SetterMethod->isDeprecated() ||
- !AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))
- return false;
-
- // Is this a valid setter, matching the target getter?
- QualType SRT = SetterMethod->getReturnType();
- if (!SRT->isVoidType())
- return false;
- const ParmVarDecl *argDecl = *SetterMethod->param_begin();
- QualType ArgType = argDecl->getType();
- if (!Ctx.hasSameUnqualifiedType(ArgType, GRT))
- return false;
- edit::Commit commit(*Editor);
- rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
- LengthOfPrefix,
- (ASTMigrateActions &
- FrontendOptions::ObjCMT_AtomicProperty) != 0,
- (ASTMigrateActions &
- FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
- AvailabilityArgsMatch);
- Editor->commit(commit);
- return true;
- }
- else if (ASTMigrateActions & FrontendOptions::ObjCMT_ReadonlyProperty) {
- // Try a non-void method with no argument (and no setter or property of same name
- // as a 'readonly' property.
- edit::Commit commit(*Editor);
- rewriteToObjCProperty(Method, nullptr /*SetterMethod*/, *NSAPIObj, commit,
- LengthOfPrefix,
- (ASTMigrateActions &
- FrontendOptions::ObjCMT_AtomicProperty) != 0,
- (ASTMigrateActions &
- FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
- /*AvailabilityArgsMatch*/false);
- Editor->commit(commit);
- return true;
- }
- return false;
-}
-
-void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
- ObjCMethodDecl *OM) {
- if (OM->isImplicit() ||
- !OM->isInstanceMethod() ||
- OM->hasAttr<ObjCReturnsInnerPointerAttr>())
- return;
-
- QualType RT = OM->getReturnType();
- if (!TypeIsInnerPointer(RT) ||
- !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
- return;
-
- edit::Commit commit(*Editor);
- commit.insertBefore(OM->getEndLoc(), " NS_RETURNS_INNER_POINTER");
- Editor->commit(commit);
-}
-
-void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx,
- ObjCPropertyDecl *P) {
- QualType T = P->getType();
-
- if (!TypeIsInnerPointer(T) ||
- !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
- return;
- edit::Commit commit(*Editor);
- commit.insertBefore(P->getEndLoc(), " NS_RETURNS_INNER_POINTER ");
- Editor->commit(commit);
-}
-
-void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx,
- ObjCContainerDecl *CDecl) {
- if (CDecl->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(CDecl))
- return;
-
- // migrate methods which can have instancetype as their result type.
- for (auto *Method : CDecl->methods()) {
- if (Method->isDeprecated())
- continue;
- migrateMethodInstanceType(Ctx, CDecl, Method);
- }
-}
-
-void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
- ObjCContainerDecl *CDecl,
- ObjCMethodDecl *OM,
- ObjCInstanceTypeFamily OIT_Family) {
- if (OM->isInstanceMethod() ||
- OM->getReturnType() == Ctx.getObjCInstanceType() ||
- !OM->getReturnType()->isObjCIdType())
- return;
-
- // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
- // NSYYYNamE with matching names be at least 3 characters long.
- ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
- if (!IDecl) {
- if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
- IDecl = CatDecl->getClassInterface();
- else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
- IDecl = ImpDecl->getClassInterface();
- }
- if (!IDecl)
- return;
-
- std::string StringClassName = std::string(IDecl->getName());
- StringRef LoweredClassName(StringClassName);
- std::string StringLoweredClassName = LoweredClassName.lower();
- LoweredClassName = StringLoweredClassName;
-
- const IdentifierInfo *MethodIdName =
- OM->getSelector().getIdentifierInfoForSlot(0);
- // Handle method with no name at its first selector slot; e.g. + (id):(int)x.
- if (!MethodIdName)
- return;
-
- std::string MethodName = std::string(MethodIdName->getName());
- if (OIT_Family == OIT_Singleton || OIT_Family == OIT_ReturnsSelf) {
- StringRef STRefMethodName(MethodName);
- size_t len = 0;
- if (STRefMethodName.starts_with("standard"))
- len = strlen("standard");
- else if (STRefMethodName.starts_with("shared"))
- len = strlen("shared");
- else if (STRefMethodName.starts_with("default"))
- len = strlen("default");
- else
- return;
- MethodName = std::string(STRefMethodName.substr(len));
- }
- std::string MethodNameSubStr = MethodName.substr(0, 3);
- StringRef MethodNamePrefix(MethodNameSubStr);
- std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
- MethodNamePrefix = StringLoweredMethodNamePrefix;
- size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
- if (Ix == StringRef::npos)
- return;
- std::string ClassNamePostfix = std::string(LoweredClassName.substr(Ix));
- StringRef LoweredMethodName(MethodName);
- std::string StringLoweredMethodName = LoweredMethodName.lower();
- LoweredMethodName = StringLoweredMethodName;
- if (!LoweredMethodName.starts_with(ClassNamePostfix))
- return;
- if (OIT_Family == OIT_ReturnsSelf)
- ReplaceWithClasstype(*this, OM);
- else
- ReplaceWithInstancetype(Ctx, *this, OM);
-}
-
-static bool IsVoidStarType(QualType Ty) {
- if (!Ty->isPointerType())
- return false;
-
- // Is the type void*?
- const PointerType* PT = Ty->castAs<PointerType>();
- if (PT->getPointeeType().getUnqualifiedType()->isVoidType())
- return true;
- return IsVoidStarType(PT->getPointeeType());
-}
-
-/// AuditedType - This routine audits the type AT and returns false if it is one of known
-/// CF object types or of the "void *" variety. It returns true if we don't care about the type
-/// such as a non-pointer or pointers which have no ownership issues (such as "int *").
-static bool AuditedType (QualType AT) {
- if (!AT->isAnyPointerType() && !AT->isBlockPointerType())
- return true;
- // FIXME. There isn't much we can say about CF pointer type; or is there?
- if (ento::coreFoundation::isCFObjectRef(AT) ||
- IsVoidStarType(AT) ||
- // If an ObjC object is type, assuming that it is not a CF function and
- // that it is an un-audited function.
- AT->isObjCObjectPointerType() || AT->isObjCBuiltinType())
- return false;
- // All other pointers are assumed audited as harmless.
- return true;
-}
-
-void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
- if (CFFunctionIBCandidates.empty())
- return;
- if (!NSAPIObj->isMacroDefined("CF_IMPLICIT_BRIDGING_ENABLED")) {
- CFFunctionIBCandidates.clear();
- FileId = FileID();
- return;
- }
- // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED
- const Decl *FirstFD = CFFunctionIBCandidates[0];
- const Decl *LastFD =
- CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
- const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
- edit::Commit commit(*Editor);
- commit.insertBefore(FirstFD->getBeginLoc(), PragmaString);
- PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
- SourceLocation EndLoc = LastFD->getEndLoc();
- // get location just past end of function location.
- EndLoc = PP.getLocForEndOfToken(EndLoc);
- if (isa<FunctionDecl>(LastFD)) {
- // For Methods, EndLoc points to the ending semcolon. So,
- // not of these extra work is needed.
- Token Tok;
- // get locaiton of token that comes after end of function.
- bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true);
- if (!Failed)
- EndLoc = Tok.getLocation();
- }
- commit.insertAfterToken(EndLoc, PragmaString);
- Editor->commit(commit);
- FileId = FileID();
- CFFunctionIBCandidates.clear();
-}
-
-void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {
- if (Decl->isDeprecated())
- return;
-
- if (Decl->hasAttr<CFAuditedTransferAttr>()) {
- assert(CFFunctionIBCandidates.empty() &&
- "Cannot have audited functions/methods inside user "
- "provided CF_IMPLICIT_BRIDGING_ENABLE");
- return;
- }
-
- // Finction must be annotated first.
- if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
- CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
- if (AuditKind == CF_BRIDGING_ENABLE) {
- CFFunctionIBCandidates.push_back(Decl);
- if (FileId.isInvalid())
- FileId = PP.getSourceManager().getFileID(Decl->getLocation());
- }
- else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
- if (!CFFunctionIBCandidates.empty()) {
- CFFunctionIBCandidates.push_back(Decl);
- if (FileId.isInvalid())
- FileId = PP.getSourceManager().getFileID(Decl->getLocation());
- }
- }
- else
- AnnotateImplicitBridging(Ctx);
- }
- else {
- migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
- AnnotateImplicitBridging(Ctx);
- }
-}
-
-void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
- const RetainSummary *RS,
- const FunctionDecl *FuncDecl,
- bool ResultAnnotated) {
- // Annotate function.
- if (!ResultAnnotated) {
- RetEffect Ret = RS->getRetEffect();
- const char *AnnotationString = nullptr;
- if (Ret.getObjKind() == ObjKind::CF) {
- if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
- AnnotationString = " CF_RETURNS_RETAINED";
- else if (Ret.notOwned() &&
- NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
- AnnotationString = " CF_RETURNS_NOT_RETAINED";
- }
- else if (Ret.getObjKind() == ObjKind::ObjC) {
- if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
- AnnotationString = " NS_RETURNS_RETAINED";
- }
-
- if (AnnotationString) {
- edit::Commit commit(*Editor);
- commit.insertAfterToken(FuncDecl->getEndLoc(), AnnotationString);
- Editor->commit(commit);
- }
- }
- unsigned i = 0;
- for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
- pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
- const ParmVarDecl *pd = *pi;
- ArgEffect AE = RS->getArg(i);
- if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::CF &&
- !pd->hasAttr<CFConsumedAttr>() &&
- NSAPIObj->isMacroDefined("CF_CONSUMED")) {
- edit::Commit commit(*Editor);
- commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
- Editor->commit(commit);
- } else if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::ObjC &&
- !pd->hasAttr<NSConsumedAttr>() &&
- NSAPIObj->isMacroDefined("NS_CONSUMED")) {
- edit::Commit commit(*Editor);
- commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
- Editor->commit(commit);
- }
- }
-}
-
-ObjCMigrateASTConsumer::CF_BRIDGING_KIND
- ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
- ASTContext &Ctx,
- const FunctionDecl *FuncDecl) {
- if (FuncDecl->hasBody())
- return CF_BRIDGING_NONE;
-
- const RetainSummary *RS =
- getSummaryManager(Ctx).getSummary(AnyCall(FuncDecl));
- bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
- FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
- FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
- FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
- FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>());
-
- // Trivial case of when function is annotated and has no argument.
- if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
- return CF_BRIDGING_NONE;
-
- bool ReturnCFAudited = false;
- if (!FuncIsReturnAnnotated) {
- RetEffect Ret = RS->getRetEffect();
- if (Ret.getObjKind() == ObjKind::CF &&
- (Ret.isOwned() || Ret.notOwned()))
- ReturnCFAudited = true;
- else if (!AuditedType(FuncDecl->getReturnType()))
- return CF_BRIDGING_NONE;
- }
-
- // At this point result type is audited for potential inclusion.
- unsigned i = 0;
- bool ArgCFAudited = false;
- for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
- pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
- const ParmVarDecl *pd = *pi;
- ArgEffect AE = RS->getArg(i);
- if ((AE.getKind() == DecRef /*CFConsumed annotated*/ ||
- AE.getKind() == IncRef) && AE.getObjKind() == ObjKind::CF) {
- if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>())
- ArgCFAudited = true;
- else if (AE.getKind() == IncRef)
- ArgCFAudited = true;
- } else {
- QualType AT = pd->getType();
- if (!AuditedType(AT)) {
- AddCFAnnotations(Ctx, RS, FuncDecl, FuncIsReturnAnnotated);
- return CF_BRIDGING_NONE;
- }
- }
- }
- if (ReturnCFAudited || ArgCFAudited)
- return CF_BRIDGING_ENABLE;
-
- return CF_BRIDGING_MAY_INCLUDE;
-}
-
-void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
- ObjCContainerDecl *CDecl) {
- if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated())
- return;
-
- // migrate methods which can have instancetype as their result type.
- for (const auto *Method : CDecl->methods())
- migrateCFAnnotation(Ctx, Method);
-}
-
-void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
- const RetainSummary *RS,
- const ObjCMethodDecl *MethodDecl,
- bool ResultAnnotated) {
- // Annotate function.
- if (!ResultAnnotated) {
- RetEffect Ret = RS->getRetEffect();
- const char *AnnotationString = nullptr;
- if (Ret.getObjKind() == ObjKind::CF) {
- if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
- AnnotationString = " CF_RETURNS_RETAINED";
- else if (Ret.notOwned() &&
- NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
- AnnotationString = " CF_RETURNS_NOT_RETAINED";
- }
- else if (Ret.getObjKind() == ObjKind::ObjC) {
- ObjCMethodFamily OMF = MethodDecl->getMethodFamily();
- switch (OMF) {
- case clang::OMF_alloc:
- case clang::OMF_new:
- case clang::OMF_copy:
- case clang::OMF_init:
- case clang::OMF_mutableCopy:
- break;
-
- default:
- if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
- AnnotationString = " NS_RETURNS_RETAINED";
- break;
- }
- }
-
- if (AnnotationString) {
- edit::Commit commit(*Editor);
- commit.insertBefore(MethodDecl->getEndLoc(), AnnotationString);
- Editor->commit(commit);
- }
- }
- unsigned i = 0;
- for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
- pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
- const ParmVarDecl *pd = *pi;
- ArgEffect AE = RS->getArg(i);
- if (AE.getKind() == DecRef
- && AE.getObjKind() == ObjKind::CF
- && !pd->hasAttr<CFConsumedAttr>() &&
- NSAPIObj->isMacroDefined("CF_CONSUMED")) {
- edit::Commit commit(*Editor);
- commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
- Editor->commit(commit);
- }
- }
-}
-
-void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
- ASTContext &Ctx,
- const ObjCMethodDecl *MethodDecl) {
- if (MethodDecl->hasBody() || MethodDecl->isImplicit())
- return;
-
- const RetainSummary *RS =
- getSummaryManager(Ctx).getSummary(AnyCall(MethodDecl));
-
- bool MethodIsReturnAnnotated =
- (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
- MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
-
- if (RS->getReceiverEffect().getKind() == DecRef &&
- !MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
- MethodDecl->getMethodFamily() != OMF_init &&
- MethodDecl->getMethodFamily() != OMF_release &&
- NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {
- edit::Commit commit(*Editor);
- commit.insertBefore(MethodDecl->getEndLoc(), " NS_CONSUMES_SELF");
- Editor->commit(commit);
- }
-
- // Trivial case of when function is annotated and has no argument.
- if (MethodIsReturnAnnotated &&
- (MethodDecl->param_begin() == MethodDecl->param_end()))
- return;
-
- if (!MethodIsReturnAnnotated) {
- RetEffect Ret = RS->getRetEffect();
- if ((Ret.getObjKind() == ObjKind::CF ||
- Ret.getObjKind() == ObjKind::ObjC) &&
- (Ret.isOwned() || Ret.notOwned())) {
- AddCFAnnotations(Ctx, RS, MethodDecl, false);
- return;
- } else if (!AuditedType(MethodDecl->getReturnType()))
- return;
- }
-
- // At this point result type is either annotated or audited.
- unsigned i = 0;
- for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
- pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
- const ParmVarDecl *pd = *pi;
- ArgEffect AE = RS->getArg(i);
- if ((AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>()) ||
- AE.getKind() == IncRef || !AuditedType(pd->getType())) {
- AddCFAnnotations(Ctx, RS, MethodDecl, MethodIsReturnAnnotated);
- return;
- }
- }
-}
-
-namespace {
-class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> {
-public:
- bool shouldVisitTemplateInstantiations() const { return false; }
- bool shouldWalkTypesOfTypeLocs() const { return false; }
-
- bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
- if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
- if (E->getMethodFamily() == OMF_init)
- return false;
- }
- return true;
- }
-};
-} // end anonymous namespace
-
-static bool hasSuperInitCall(const ObjCMethodDecl *MD) {
- return !SuperInitChecker().TraverseStmt(MD->getBody());
-}
-
-void ObjCMigrateASTConsumer::inferDesignatedInitializers(
- ASTContext &Ctx,
- const ObjCImplementationDecl *ImplD) {
-
- const ObjCInterfaceDecl *IFace = ImplD->getClassInterface();
- if (!IFace || IFace->hasDesignatedInitializers())
- return;
- if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER"))
- return;
-
- for (const auto *MD : ImplD->instance_methods()) {
- if (MD->isDeprecated() ||
- MD->getMethodFamily() != OMF_init ||
- MD->isDesignatedInitializerForTheInterface())
- continue;
- const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(),
- /*isInstance=*/true);
- if (!IFaceM)
- continue;
- if (hasSuperInitCall(MD)) {
- edit::Commit commit(*Editor);
- commit.insert(IFaceM->getEndLoc(), " NS_DESIGNATED_INITIALIZER");
- Editor->commit(commit);
- }
- }
-}
-
-bool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx,
- SourceLocation Loc) {
- if (FoundationIncluded)
- return true;
- if (Loc.isInvalid())
- return false;
- auto *nsEnumId = &Ctx.Idents.get("NS_ENUM");
- if (PP.getMacroDefinitionAtLoc(nsEnumId, Loc)) {
- FoundationIncluded = true;
- return true;
- }
- edit::Commit commit(*Editor);
- if (Ctx.getLangOpts().Modules)
- commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
- else
- commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
- Editor->commit(commit);
- FoundationIncluded = true;
- return true;
-}
-
-namespace {
-
-class RewritesReceiver : public edit::EditsReceiver {
- Rewriter &Rewrite;
-
-public:
- RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
-
- void insert(SourceLocation loc, StringRef text) override {
- Rewrite.InsertText(loc, text);
- }
- void replace(CharSourceRange range, StringRef text) override {
- Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
- }
-};
-
-class JSONEditWriter : public edit::EditsReceiver {
- SourceManager &SourceMgr;
- llvm::raw_ostream &OS;
-
-public:
- JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS)
- : SourceMgr(SM), OS(OS) {
- OS << "[\n";
- }
- ~JSONEditWriter() override { OS << "]\n"; }
-
-private:
- struct EntryWriter {
- SourceManager &SourceMgr;
- llvm::raw_ostream &OS;
-
- EntryWriter(SourceManager &SM, llvm::raw_ostream &OS)
- : SourceMgr(SM), OS(OS) {
- OS << " {\n";
- }
- ~EntryWriter() {
- OS << " },\n";
- }
-
- void writeLoc(SourceLocation Loc) {
- FileID FID;
- unsigned Offset;
- std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc);
- assert(FID.isValid());
- SmallString<200> Path =
- StringRef(SourceMgr.getFileEntryRefForID(FID)->getName());
- llvm::sys::fs::make_absolute(Path);
- OS << " \"file\": \"";
- OS.write_escaped(Path.str()) << "\",\n";
- OS << " \"offset\": " << Offset << ",\n";
- }
-
- void writeRemove(CharSourceRange Range) {
- assert(Range.isCharRange());
- std::pair<FileID, unsigned> Begin =
- SourceMgr.getDecomposedLoc(Range.getBegin());
- std::pair<FileID, unsigned> End =
- SourceMgr.getDecomposedLoc(Range.getEnd());
- assert(Begin.first == End.first);
- assert(Begin.second <= End.second);
- unsigned Length = End.second - Begin.second;
-
- OS << " \"remove\": " << Length << ",\n";
- }
-
- void writeText(StringRef Text) {
- OS << " \"text\": \"";
- OS.write_escaped(Text) << "\",\n";
- }
- };
-
- void insert(SourceLocation Loc, StringRef Text) override {
- EntryWriter Writer(SourceMgr, OS);
- Writer.writeLoc(Loc);
- Writer.writeText(Text);
- }
-
- void replace(CharSourceRange Range, StringRef Text) override {
- EntryWriter Writer(SourceMgr, OS);
- Writer.writeLoc(Range.getBegin());
- Writer.writeRemove(Range);
- Writer.writeText(Text);
- }
-
- void remove(CharSourceRange Range) override {
- EntryWriter Writer(SourceMgr, OS);
- Writer.writeLoc(Range.getBegin());
- Writer.writeRemove(Range);
- }
-};
-
-} // end anonymous namespace
-
-void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
-
- TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
- if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) {
- for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
- D != DEnd; ++D) {
- FileID FID = PP.getSourceManager().getFileID((*D)->getLocation());
- if (FID.isValid())
- if (FileId.isValid() && FileId != FID) {
- if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
- AnnotateImplicitBridging(Ctx);
- }
-
- if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
- if (canModify(CDecl))
- migrateObjCContainerDecl(Ctx, CDecl);
- if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
- if (canModify(CatDecl))
- migrateObjCContainerDecl(Ctx, CatDecl);
- }
- else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) {
- ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
- if (canModify(PDecl))
- migrateObjCContainerDecl(Ctx, PDecl);
- }
- else if (const ObjCImplementationDecl *ImpDecl =
- dyn_cast<ObjCImplementationDecl>(*D)) {
- if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) &&
- canModify(ImpDecl))
- migrateProtocolConformance(Ctx, ImpDecl);
- }
- else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
- if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
- continue;
- if (!canModify(ED))
- continue;
- DeclContext::decl_iterator N = D;
- if (++N != DEnd) {
- const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
- if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
- D++;
- }
- else
- migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr);
- }
- else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
- if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
- continue;
- if (!canModify(TD))
- continue;
- DeclContext::decl_iterator N = D;
- if (++N == DEnd)
- continue;
- if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
- if (canModify(ED)) {
- if (++N != DEnd)
- if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
- // prefer typedef-follows-enum to enum-follows-typedef pattern.
- if (migrateNSEnumDecl(Ctx, ED, TDF)) {
- ++D; ++D;
- CacheObjCNSIntegerTypedefed(TD);
- continue;
- }
- }
- if (migrateNSEnumDecl(Ctx, ED, TD)) {
- ++D;
- continue;
- }
- }
- }
- CacheObjCNSIntegerTypedefed(TD);
- }
- else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
- if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
- canModify(FD))
- migrateCFAnnotation(Ctx, FD);
- }
-
- if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
- bool CanModify = canModify(CDecl);
- // migrate methods which can have instancetype as their result type.
- if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) &&
- CanModify)
- migrateAllMethodInstaceType(Ctx, CDecl);
- // annotate methods with CF annotations.
- if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
- CanModify)
- migrateARCSafeAnnotation(Ctx, CDecl);
- }
-
- if (const ObjCImplementationDecl *
- ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
- if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) &&
- canModify(ImplD))
- inferDesignatedInitializers(Ctx, ImplD);
- }
- }
- if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
- AnnotateImplicitBridging(Ctx);
- }
-
- if (IsOutputFile) {
- std::error_code EC;
- llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::OF_None);
- if (EC) {
- DiagnosticsEngine &Diags = Ctx.getDiagnostics();
- Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
- << EC.message();
- return;
- }
-
- JSONEditWriter Writer(Ctx.getSourceManager(), OS);
- Editor->applyRewrites(Writer);
- return;
- }
-
- Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
- RewritesReceiver Rec(rewriter);
- Editor->applyRewrites(Rec);
-
- for (Rewriter::buffer_iterator
- I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
- FileID FID = I->first;
- RewriteBuffer &buf = I->second;
- OptionalFileEntryRef file =
- Ctx.getSourceManager().getFileEntryRefForID(FID);
- assert(file);
- SmallString<512> newText;
- llvm::raw_svector_ostream vecOS(newText);
- buf.write(vecOS);
- std::unique_ptr<llvm::MemoryBuffer> memBuf(
- llvm::MemoryBuffer::getMemBufferCopy(newText.str(), file->getName()));
- SmallString<64> filePath(file->getName());
- FileMgr.FixupRelativePath(filePath);
- Remapper.remap(filePath.str(), std::move(memBuf));
- }
-
- if (IsOutputFile) {
- Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
- } else {
- Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
- }
-}
-
-bool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
- CI.getDiagnostics().setIgnoreAllWarnings(true);
- return true;
-}
-
-static std::vector<std::string> getAllowListFilenames(StringRef DirPath) {
- using namespace llvm::sys::fs;
- using namespace llvm::sys::path;
-
- std::vector<std::string> Filenames;
- if (DirPath.empty() || !is_directory(DirPath))
- return Filenames;
-
- std::error_code EC;
- directory_iterator DI = directory_iterator(DirPath, EC);
- directory_iterator DE;
- for (; !EC && DI != DE; DI = DI.increment(EC)) {
- if (is_regular_file(DI->path()))
- Filenames.push_back(std::string(filename(DI->path())));
- }
-
- return Filenames;
-}
-
-std::unique_ptr<ASTConsumer>
-MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
- PPConditionalDirectiveRecord *
- PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager());
- unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction;
- unsigned ObjCMTOpts = ObjCMTAction;
- // These are companion flags, they do not enable transformations.
- ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
- FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty);
- if (ObjCMTOpts == FrontendOptions::ObjCMT_None) {
- // If no specific option was given, enable literals+subscripting transforms
- // by default.
- ObjCMTAction |=
- FrontendOptions::ObjCMT_Literals | FrontendOptions::ObjCMT_Subscripting;
- }
- CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
- std::vector<std::string> AllowList =
- getAllowListFilenames(CI.getFrontendOpts().ObjCMTAllowListPath);
- return std::make_unique<ObjCMigrateASTConsumer>(
- CI.getFrontendOpts().OutputFile, ObjCMTAction, Remapper,
- CI.getFileManager(), PPRec, CI.getPreprocessor(),
- /*isOutputFile=*/true, AllowList);
-}
-
-namespace {
-struct EditEntry {
- OptionalFileEntryRef File;
- unsigned Offset = 0;
- unsigned RemoveLen = 0;
- std::string Text;
-};
-} // end anonymous namespace
-
-namespace llvm {
-template<> struct DenseMapInfo<EditEntry> {
- static inline EditEntry getEmptyKey() {
- EditEntry Entry;
- Entry.Offset = unsigned(-1);
- return Entry;
- }
- static inline EditEntry getTombstoneKey() {
- EditEntry Entry;
- Entry.Offset = unsigned(-2);
- return Entry;
- }
- static unsigned getHashValue(const EditEntry& Val) {
- return (unsigned)llvm::hash_combine(Val.File, Val.Offset, Val.RemoveLen,
- Val.Text);
- }
- static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) {
- return LHS.File == RHS.File &&
- LHS.Offset == RHS.Offset &&
- LHS.RemoveLen == RHS.RemoveLen &&
- LHS.Text == RHS.Text;
- }
-};
-} // end namespace llvm
-
-namespace {
-class RemapFileParser {
- FileManager &FileMgr;
-
-public:
- RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { }
-
- bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) {
- using namespace llvm::yaml;
-
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFile(File);
- if (!FileBufOrErr)
- return true;
-
- llvm::SourceMgr SM;
- Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM);
- document_iterator I = YAMLStream.begin();
- if (I == YAMLStream.end())
- return true;
- Node *Root = I->getRoot();
- if (!Root)
- return true;
-
- SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
- if (!SeqNode)
- return true;
-
- for (SequenceNode::iterator
- AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
- MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
- if (!MapNode)
- continue;
- parseEdit(MapNode, Entries);
- }
-
- return false;
- }
-
-private:
- void parseEdit(llvm::yaml::MappingNode *Node,
- SmallVectorImpl<EditEntry> &Entries) {
- using namespace llvm::yaml;
- EditEntry Entry;
- bool Ignore = false;
-
- for (MappingNode::iterator
- KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
- ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
- if (!KeyString)
- continue;
- SmallString<10> KeyStorage;
- StringRef Key = KeyString->getValue(KeyStorage);
-
- ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
- if (!ValueString)
- continue;
- SmallString<64> ValueStorage;
- StringRef Val = ValueString->getValue(ValueStorage);
-
- if (Key == "file") {
- if (auto File = FileMgr.getOptionalFileRef(Val))
- Entry.File = File;
- else
- Ignore = true;
- } else if (Key == "offset") {
- if (Val.getAsInteger(10, Entry.Offset))
- Ignore = true;
- } else if (Key == "remove") {
- if (Val.getAsInteger(10, Entry.RemoveLen))
- Ignore = true;
- } else if (Key == "text") {
- Entry.Text = std::string(Val);
- }
- }
-
- if (!Ignore)
- Entries.push_back(Entry);
- }
-};
-} // end anonymous namespace
-
-static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) {
- Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
- << Err.str();
- return true;
-}
-
-static std::string applyEditsToTemp(FileEntryRef FE,
- ArrayRef<EditEntry> Edits,
- FileManager &FileMgr,
- DiagnosticsEngine &Diag) {
- using namespace llvm::sys;
-
- SourceManager SM(Diag, FileMgr);
- FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
- LangOptions LangOpts;
- edit::EditedSource Editor(SM, LangOpts);
- for (ArrayRef<EditEntry>::iterator
- I = Edits.begin(), E = Edits.end(); I != E; ++I) {
- const EditEntry &Entry = *I;
- assert(Entry.File == FE);
- SourceLocation Loc =
- SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset);
- CharSourceRange Range;
- if (Entry.RemoveLen != 0) {
- Range = CharSourceRange::getCharRange(Loc,
- Loc.getLocWithOffset(Entry.RemoveLen));
- }
-
- edit::Commit commit(Editor);
- if (Range.isInvalid()) {
- commit.insert(Loc, Entry.Text);
- } else if (Entry.Text.empty()) {
- commit.remove(Range);
- } else {
- commit.replace(Range, Entry.Text);
- }
- Editor.commit(commit);
- }
-
- Rewriter rewriter(SM, LangOpts);
- RewritesReceiver Rec(rewriter);
- Editor.applyRewrites(Rec, /*adjustRemovals=*/false);
-
- const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID);
- SmallString<512> NewText;
- llvm::raw_svector_ostream OS(NewText);
- Buf->write(OS);
-
- SmallString<64> TempPath;
- int FD;
- if (fs::createTemporaryFile(path::filename(FE.getName()),
- path::extension(FE.getName()).drop_front(), FD,
- TempPath)) {
- reportDiag("Could not create file: " + TempPath.str(), Diag);
- return std::string();
- }
-
- llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true);
- TmpOut.write(NewText.data(), NewText.size());
- TmpOut.close();
-
- return std::string(TempPath);
-}
-
-bool arcmt::getFileRemappingsFromFileList(
- std::vector<std::pair<std::string,std::string> > &remap,
- ArrayRef<StringRef> remapFiles,
- DiagnosticConsumer *DiagClient) {
- bool hasErrorOccurred = false;
-
- FileSystemOptions FSOpts;
- FileManager FileMgr(FSOpts);
- RemapFileParser Parser(FileMgr);
-
- IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
- new DiagnosticsEngine(DiagID, new DiagnosticOptions,
- DiagClient, /*ShouldOwnClient=*/false));
-
- typedef llvm::DenseMap<FileEntryRef, std::vector<EditEntry> >
- FileEditEntriesTy;
- FileEditEntriesTy FileEditEntries;
-
- llvm::DenseSet<EditEntry> EntriesSet;
-
- for (ArrayRef<StringRef>::iterator
- I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
- SmallVector<EditEntry, 16> Entries;
- if (Parser.parse(*I, Entries))
- continue;
-
- for (SmallVectorImpl<EditEntry>::iterator
- EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
- EditEntry &Entry = *EI;
- if (!Entry.File)
- continue;
- std::pair<llvm::DenseSet<EditEntry>::iterator, bool>
- Insert = EntriesSet.insert(Entry);
- if (!Insert.second)
- continue;
-
- FileEditEntries[*Entry.File].push_back(Entry);
- }
- }
-
- for (FileEditEntriesTy::iterator
- I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
- std::string TempFile = applyEditsToTemp(I->first, I->second,
- FileMgr, *Diags);
- if (TempFile.empty()) {
- hasErrorOccurred = true;
- continue;
- }
-
- remap.emplace_back(std::string(I->first.getName()), TempFile);
- }
-
- return hasErrorOccurred;
-}
diff --git a/clang/lib/ARCMigrate/PlistReporter.cpp b/clang/lib/ARCMigrate/PlistReporter.cpp
deleted file mode 100644
index f78ca5e..0000000
--- a/clang/lib/ARCMigrate/PlistReporter.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-//===--- PlistReporter.cpp - ARC Migrate Tool Plist Reporter ----*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Internals.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/PlistSupport.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
-using namespace clang;
-using namespace arcmt;
-using namespace markup;
-
-static StringRef getLevelName(DiagnosticsEngine::Level Level) {
- switch (Level) {
- case DiagnosticsEngine::Ignored:
- llvm_unreachable("ignored");
- case DiagnosticsEngine::Note:
- return "note";
- case DiagnosticsEngine::Remark:
- case DiagnosticsEngine::Warning:
- return "warning";
- case DiagnosticsEngine::Fatal:
- case DiagnosticsEngine::Error:
- return "error";
- }
- llvm_unreachable("Invalid DiagnosticsEngine level!");
-}
-
-void arcmt::writeARCDiagsToPlist(const std::string &outPath,
- ArrayRef<StoredDiagnostic> diags,
- SourceManager &SM,
- const LangOptions &LangOpts) {
- DiagnosticIDs DiagIDs;
-
- // Build up a set of FIDs that we use by scanning the locations and
- // ranges of the diagnostics.
- FIDMap FM;
- SmallVector<FileID, 10> Fids;
-
- for (ArrayRef<StoredDiagnostic>::iterator
- I = diags.begin(), E = diags.end(); I != E; ++I) {
- const StoredDiagnostic &D = *I;
-
- AddFID(FM, Fids, SM, D.getLocation());
-
- for (StoredDiagnostic::range_iterator
- RI = D.range_begin(), RE = D.range_end(); RI != RE; ++RI) {
- AddFID(FM, Fids, SM, RI->getBegin());
- AddFID(FM, Fids, SM, RI->getEnd());
- }
- }
-
- std::error_code EC;
- llvm::raw_fd_ostream o(outPath, EC, llvm::sys::fs::OF_TextWithCRLF);
- if (EC) {
- llvm::errs() << "error: could not create file: " << outPath << '\n';
- return;
- }
-
- EmitPlistHeader(o);
-
- // Write the root object: a <dict> containing...
- // - "files", an <array> mapping from FIDs to file names
- // - "diagnostics", an <array> containing the diagnostics
- o << "<dict>\n"
- " <key>files</key>\n"
- " <array>\n";
-
- for (FileID FID : Fids)
- EmitString(o << " ", SM.getFileEntryRefForID(FID)->getName()) << '\n';
-
- o << " </array>\n"
- " <key>diagnostics</key>\n"
- " <array>\n";
-
- for (ArrayRef<StoredDiagnostic>::iterator
- DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) {
-
- const StoredDiagnostic &D = *DI;
-
- if (D.getLevel() == DiagnosticsEngine::Ignored)
- continue;
-
- o << " <dict>\n";
-
- // Output the diagnostic.
- o << " <key>description</key>";
- EmitString(o, D.getMessage()) << '\n';
- o << " <key>category</key>";
- EmitString(o, DiagIDs.getCategoryNameFromID(
- DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n';
- o << " <key>type</key>";
- EmitString(o, getLevelName(D.getLevel())) << '\n';
-
- // Output the location of the bug.
- o << " <key>location</key>\n";
- EmitLocation(o, SM, D.getLocation(), FM, 2);
-
- // Output the ranges (if any).
- if (!D.getRanges().empty()) {
- o << " <key>ranges</key>\n";
- o << " <array>\n";
- for (auto &R : D.getRanges()) {
- CharSourceRange ExpansionRange = SM.getExpansionRange(R);
- EmitRange(o, SM, Lexer::getAsCharRange(ExpansionRange, SM, LangOpts),
- FM, 4);
- }
- o << " </array>\n";
- }
-
- // Close up the entry.
- o << " </dict>\n";
- }
-
- o << " </array>\n";
-
- // Finish.
- o << "</dict>\n</plist>\n";
-}
diff --git a/clang/lib/ARCMigrate/TransAPIUses.cpp b/clang/lib/ARCMigrate/TransAPIUses.cpp
deleted file mode 100644
index 8f5d4f4..0000000
--- a/clang/lib/ARCMigrate/TransAPIUses.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-//===--- TransAPIUses.cpp - Transformations to ARC mode -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// checkAPIUses:
-//
-// Emits error/fix with some API uses that are obsolete or not safe in ARC mode:
-//
-// - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
-// with __unsafe_unretained objects.
-// - Calling -zone gets replaced with 'nil'.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Sema/SemaDiagnostic.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class APIChecker : public RecursiveASTVisitor<APIChecker> {
- MigrationPass &Pass;
-
- Selector getReturnValueSel, setReturnValueSel;
- Selector getArgumentSel, setArgumentSel;
-
- Selector zoneSel;
-public:
- APIChecker(MigrationPass &pass) : Pass(pass) {
- SelectorTable &sels = Pass.Ctx.Selectors;
- IdentifierTable &ids = Pass.Ctx.Idents;
- getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
- setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
-
- const IdentifierInfo *selIds[2];
- selIds[0] = &ids.get("getArgument");
- selIds[1] = &ids.get("atIndex");
- getArgumentSel = sels.getSelector(2, selIds);
- selIds[0] = &ids.get("setArgument");
- setArgumentSel = sels.getSelector(2, selIds);
-
- zoneSel = sels.getNullarySelector(&ids.get("zone"));
- }
-
- bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
- // NSInvocation.
- if (E->isInstanceMessage() &&
- E->getReceiverInterface() &&
- E->getReceiverInterface()->getName() == "NSInvocation") {
- StringRef selName;
- if (E->getSelector() == getReturnValueSel)
- selName = "getReturnValue";
- else if (E->getSelector() == setReturnValueSel)
- selName = "setReturnValue";
- else if (E->getSelector() == getArgumentSel)
- selName = "getArgument";
- else if (E->getSelector() == setArgumentSel)
- selName = "setArgument";
- else
- return true;
-
- Expr *parm = E->getArg(0)->IgnoreParenCasts();
- QualType pointee = parm->getType()->getPointeeType();
- if (pointee.isNull())
- return true;
-
- if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone)
- Pass.TA.report(parm->getBeginLoc(),
- diag::err_arcmt_nsinvocation_ownership,
- parm->getSourceRange())
- << selName;
-
- return true;
- }
-
- // -zone.
- if (E->isInstanceMessage() &&
- E->getInstanceReceiver() &&
- E->getSelector() == zoneSel &&
- Pass.TA.hasDiagnostic(diag::err_unavailable,
- diag::err_unavailable_message,
- E->getSelectorLoc(0))) {
- // Calling -zone is meaningless in ARC, change it to nil.
- Transaction Trans(Pass.TA);
- Pass.TA.clearDiagnostic(diag::err_unavailable,
- diag::err_unavailable_message,
- E->getSelectorLoc(0));
- Pass.TA.replace(E->getSourceRange(), getNilString(Pass));
- }
- return true;
- }
-};
-
-} // anonymous namespace
-
-void trans::checkAPIUses(MigrationPass &pass) {
- APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
-}
diff --git a/clang/lib/ARCMigrate/TransARCAssign.cpp b/clang/lib/ARCMigrate/TransARCAssign.cpp
deleted file mode 100644
index d1d5b9e..0000000
--- a/clang/lib/ARCMigrate/TransARCAssign.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//===--- TransARCAssign.cpp - Transformations to ARC mode -----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// makeAssignARCSafe:
-//
-// Add '__strong' where appropriate.
-//
-// for (id x in collection) {
-// x = 0;
-// }
-// ---->
-// for (__strong id x in collection) {
-// x = 0;
-// }
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Sema/SemaDiagnostic.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> {
- MigrationPass &Pass;
- llvm::DenseSet<VarDecl *> ModifiedVars;
-
-public:
- ARCAssignChecker(MigrationPass &pass) : Pass(pass) { }
-
- bool VisitBinaryOperator(BinaryOperator *Exp) {
- if (Exp->getType()->isDependentType())
- return true;
-
- Expr *E = Exp->getLHS();
- SourceLocation OrigLoc = E->getExprLoc();
- SourceLocation Loc = OrigLoc;
- DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
- if (declRef && isa<VarDecl>(declRef->getDecl())) {
- ASTContext &Ctx = Pass.Ctx;
- Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(Ctx, &Loc);
- if (IsLV != Expr::MLV_ConstQualified)
- return true;
- VarDecl *var = cast<VarDecl>(declRef->getDecl());
- if (var->isARCPseudoStrong()) {
- Transaction Trans(Pass.TA);
- if (Pass.TA.clearDiagnostic(diag::err_typecheck_arr_assign_enumeration,
- Exp->getOperatorLoc())) {
- if (!ModifiedVars.count(var)) {
- TypeLoc TLoc = var->getTypeSourceInfo()->getTypeLoc();
- Pass.TA.insert(TLoc.getBeginLoc(), "__strong ");
- ModifiedVars.insert(var);
- }
- }
- }
- }
-
- return true;
- }
-};
-
-} // anonymous namespace
-
-void trans::makeAssignARCSafe(MigrationPass &pass) {
- ARCAssignChecker assignCheck(pass);
- assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
-}
diff --git a/clang/lib/ARCMigrate/TransAutoreleasePool.cpp b/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
deleted file mode 100644
index 6d50122..0000000
--- a/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
-//===--- TransAutoreleasePool.cpp - Transformations to ARC mode -----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// rewriteAutoreleasePool:
-//
-// Calls to NSAutoreleasePools will be rewritten as an @autorelease scope.
-//
-// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-// ...
-// [pool release];
-// ---->
-// @autorelease {
-// ...
-// }
-//
-// An NSAutoreleasePool will not be touched if:
-// - There is not a corresponding -release/-drain in the same scope
-// - Not all references of the NSAutoreleasePool variable can be removed
-// - There is a variable that is declared inside the intended @autorelease scope
-// which is also used outside it.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include <map>
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class ReleaseCollector : public RecursiveASTVisitor<ReleaseCollector> {
- Decl *Dcl;
- SmallVectorImpl<ObjCMessageExpr *> &Releases;
-
-public:
- ReleaseCollector(Decl *D, SmallVectorImpl<ObjCMessageExpr *> &releases)
- : Dcl(D), Releases(releases) { }
-
- bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
- if (!E->isInstanceMessage())
- return true;
- if (E->getMethodFamily() != OMF_release)
- return true;
- Expr *instance = E->getInstanceReceiver()->IgnoreParenCasts();
- if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(instance)) {
- if (DE->getDecl() == Dcl)
- Releases.push_back(E);
- }
- return true;
- }
-};
-
-}
-
-namespace {
-
-class AutoreleasePoolRewriter
- : public RecursiveASTVisitor<AutoreleasePoolRewriter> {
-public:
- AutoreleasePoolRewriter(MigrationPass &pass)
- : Body(nullptr), Pass(pass) {
- PoolII = &pass.Ctx.Idents.get("NSAutoreleasePool");
- DrainSel = pass.Ctx.Selectors.getNullarySelector(
- &pass.Ctx.Idents.get("drain"));
- }
-
- void transformBody(Stmt *body, Decl *ParentD) {
- Body = body;
- TraverseStmt(body);
- }
-
- ~AutoreleasePoolRewriter() {
- SmallVector<VarDecl *, 8> VarsToHandle;
-
- for (std::map<VarDecl *, PoolVarInfo>::iterator
- I = PoolVars.begin(), E = PoolVars.end(); I != E; ++I) {
- VarDecl *var = I->first;
- PoolVarInfo &info = I->second;
-
- // Check that we can handle/rewrite all references of the pool.
-
- clearRefsIn(info.Dcl, info.Refs);
- for (SmallVectorImpl<PoolScope>::iterator
- scpI = info.Scopes.begin(),
- scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
- PoolScope &scope = *scpI;
- clearRefsIn(*scope.Begin, info.Refs);
- clearRefsIn(*scope.End, info.Refs);
- clearRefsIn(scope.Releases.begin(), scope.Releases.end(), info.Refs);
- }
-
- // Even if one reference is not handled we will not do anything about that
- // pool variable.
- if (info.Refs.empty())
- VarsToHandle.push_back(var);
- }
-
- for (unsigned i = 0, e = VarsToHandle.size(); i != e; ++i) {
- PoolVarInfo &info = PoolVars[VarsToHandle[i]];
-
- Transaction Trans(Pass.TA);
-
- clearUnavailableDiags(info.Dcl);
- Pass.TA.removeStmt(info.Dcl);
-
- // Add "@autoreleasepool { }"
- for (SmallVectorImpl<PoolScope>::iterator
- scpI = info.Scopes.begin(),
- scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
- PoolScope &scope = *scpI;
- clearUnavailableDiags(*scope.Begin);
- clearUnavailableDiags(*scope.End);
- if (scope.IsFollowedBySimpleReturnStmt) {
- // Include the return in the scope.
- Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
- Pass.TA.removeStmt(*scope.End);
- Stmt::child_iterator retI = scope.End;
- ++retI;
- SourceLocation afterSemi =
- findLocationAfterSemi((*retI)->getEndLoc(), Pass.Ctx);
- assert(afterSemi.isValid() &&
- "Didn't we check before setting IsFollowedBySimpleReturnStmt "
- "to true?");
- Pass.TA.insertAfterToken(afterSemi, "\n}");
- Pass.TA.increaseIndentation(
- SourceRange(scope.getIndentedRange().getBegin(),
- (*retI)->getEndLoc()),
- scope.CompoundParent->getBeginLoc());
- } else {
- Pass.TA.replaceStmt(*scope.Begin, "@autoreleasepool {");
- Pass.TA.replaceStmt(*scope.End, "}");
- Pass.TA.increaseIndentation(scope.getIndentedRange(),
- scope.CompoundParent->getBeginLoc());
- }
- }
-
- // Remove rest of pool var references.
- for (SmallVectorImpl<PoolScope>::iterator
- scpI = info.Scopes.begin(),
- scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
- PoolScope &scope = *scpI;
- for (SmallVectorImpl<ObjCMessageExpr *>::iterator
- relI = scope.Releases.begin(),
- relE = scope.Releases.end(); relI != relE; ++relI) {
- clearUnavailableDiags(*relI);
- Pass.TA.removeStmt(*relI);
- }
- }
- }
- }
-
- bool VisitCompoundStmt(CompoundStmt *S) {
- SmallVector<PoolScope, 4> Scopes;
-
- for (Stmt::child_iterator
- I = S->body_begin(), E = S->body_end(); I != E; ++I) {
- Stmt *child = getEssential(*I);
- if (DeclStmt *DclS = dyn_cast<DeclStmt>(child)) {
- if (DclS->isSingleDecl()) {
- if (VarDecl *VD = dyn_cast<VarDecl>(DclS->getSingleDecl())) {
- if (isNSAutoreleasePool(VD->getType())) {
- PoolVarInfo &info = PoolVars[VD];
- info.Dcl = DclS;
- collectRefs(VD, S, info.Refs);
- // Does this statement follow the pattern:
- // NSAutoreleasePool * pool = [NSAutoreleasePool new];
- if (isPoolCreation(VD->getInit())) {
- Scopes.push_back(PoolScope());
- Scopes.back().PoolVar = VD;
- Scopes.back().CompoundParent = S;
- Scopes.back().Begin = I;
- }
- }
- }
- }
- } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(child)) {
- if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(bop->getLHS())) {
- if (VarDecl *VD = dyn_cast<VarDecl>(dref->getDecl())) {
- // Does this statement follow the pattern:
- // pool = [NSAutoreleasePool new];
- if (isNSAutoreleasePool(VD->getType()) &&
- isPoolCreation(bop->getRHS())) {
- Scopes.push_back(PoolScope());
- Scopes.back().PoolVar = VD;
- Scopes.back().CompoundParent = S;
- Scopes.back().Begin = I;
- }
- }
- }
- }
-
- if (Scopes.empty())
- continue;
-
- if (isPoolDrain(Scopes.back().PoolVar, child)) {
- PoolScope &scope = Scopes.back();
- scope.End = I;
- handlePoolScope(scope, S);
- Scopes.pop_back();
- }
- }
- return true;
- }
-
-private:
- void clearUnavailableDiags(Stmt *S) {
- if (S)
- Pass.TA.clearDiagnostic(diag::err_unavailable,
- diag::err_unavailable_message,
- S->getSourceRange());
- }
-
- struct PoolScope {
- VarDecl *PoolVar;
- CompoundStmt *CompoundParent;
- Stmt::child_iterator Begin;
- Stmt::child_iterator End;
- bool IsFollowedBySimpleReturnStmt;
- SmallVector<ObjCMessageExpr *, 4> Releases;
-
- PoolScope()
- : PoolVar(nullptr), CompoundParent(nullptr),
- IsFollowedBySimpleReturnStmt(false) {}
-
- SourceRange getIndentedRange() const {
- Stmt::child_iterator rangeS = Begin;
- ++rangeS;
- if (rangeS == End)
- return SourceRange();
- Stmt::child_iterator rangeE = Begin;
- for (Stmt::child_iterator I = rangeS; I != End; ++I)
- ++rangeE;
- return SourceRange((*rangeS)->getBeginLoc(), (*rangeE)->getEndLoc());
- }
- };
-
- class NameReferenceChecker : public RecursiveASTVisitor<NameReferenceChecker>{
- ASTContext &Ctx;
- SourceRange ScopeRange;
- SourceLocation &referenceLoc, &declarationLoc;
-
- public:
- NameReferenceChecker(ASTContext &ctx, PoolScope &scope,
- SourceLocation &referenceLoc,
- SourceLocation &declarationLoc)
- : Ctx(ctx), referenceLoc(referenceLoc),
- declarationLoc(declarationLoc) {
- ScopeRange = SourceRange((*scope.Begin)->getBeginLoc(),
- (*scope.End)->getBeginLoc());
- }
-
- bool VisitDeclRefExpr(DeclRefExpr *E) {
- return checkRef(E->getLocation(), E->getDecl()->getLocation());
- }
-
- bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- return checkRef(TL.getBeginLoc(), TL.getTypedefNameDecl()->getLocation());
- }
-
- bool VisitTagTypeLoc(TagTypeLoc TL) {
- return checkRef(TL.getBeginLoc(), TL.getDecl()->getLocation());
- }
-
- private:
- bool checkRef(SourceLocation refLoc, SourceLocation declLoc) {
- if (isInScope(declLoc)) {
- referenceLoc = refLoc;
- declarationLoc = declLoc;
- return false;
- }
- return true;
- }
-
- bool isInScope(SourceLocation loc) {
- if (loc.isInvalid())
- return false;
-
- SourceManager &SM = Ctx.getSourceManager();
- if (SM.isBeforeInTranslationUnit(loc, ScopeRange.getBegin()))
- return false;
- return SM.isBeforeInTranslationUnit(loc, ScopeRange.getEnd());
- }
- };
-
- void handlePoolScope(PoolScope &scope, CompoundStmt *compoundS) {
- // Check that all names declared inside the scope are not used
- // outside the scope.
- {
- bool nameUsedOutsideScope = false;
- SourceLocation referenceLoc, declarationLoc;
- Stmt::child_iterator SI = scope.End, SE = compoundS->body_end();
- ++SI;
- // Check if the autoreleasepool scope is followed by a simple return
- // statement, in which case we will include the return in the scope.
- if (SI != SE)
- if (ReturnStmt *retS = dyn_cast<ReturnStmt>(*SI))
- if ((retS->getRetValue() == nullptr ||
- isa<DeclRefExpr>(retS->getRetValue()->IgnoreParenCasts())) &&
- findLocationAfterSemi(retS->getEndLoc(), Pass.Ctx).isValid()) {
- scope.IsFollowedBySimpleReturnStmt = true;
- ++SI; // the return will be included in scope, don't check it.
- }
-
- for (; SI != SE; ++SI) {
- nameUsedOutsideScope = !NameReferenceChecker(Pass.Ctx, scope,
- referenceLoc,
- declarationLoc).TraverseStmt(*SI);
- if (nameUsedOutsideScope)
- break;
- }
-
- // If not all references were cleared it means some variables/typenames/etc
- // declared inside the pool scope are used outside of it.
- // We won't try to rewrite the pool.
- if (nameUsedOutsideScope) {
- Pass.TA.reportError("a name is referenced outside the "
- "NSAutoreleasePool scope that it was declared in", referenceLoc);
- Pass.TA.reportNote("name declared here", declarationLoc);
- Pass.TA.reportNote("intended @autoreleasepool scope begins here",
- (*scope.Begin)->getBeginLoc());
- Pass.TA.reportNote("intended @autoreleasepool scope ends here",
- (*scope.End)->getBeginLoc());
- return;
- }
- }
-
- // Collect all releases of the pool; they will be removed.
- {
- ReleaseCollector releaseColl(scope.PoolVar, scope.Releases);
- Stmt::child_iterator I = scope.Begin;
- ++I;
- for (; I != scope.End; ++I)
- releaseColl.TraverseStmt(*I);
- }
-
- PoolVars[scope.PoolVar].Scopes.push_back(scope);
- }
-
- bool isPoolCreation(Expr *E) {
- if (!E) return false;
- E = getEssential(E);
- ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
- if (!ME) return false;
- if (ME->getMethodFamily() == OMF_new &&
- ME->getReceiverKind() == ObjCMessageExpr::Class &&
- isNSAutoreleasePool(ME->getReceiverInterface()))
- return true;
- if (ME->getReceiverKind() == ObjCMessageExpr::Instance &&
- ME->getMethodFamily() == OMF_init) {
- Expr *rec = getEssential(ME->getInstanceReceiver());
- if (ObjCMessageExpr *recME = dyn_cast_or_null<ObjCMessageExpr>(rec)) {
- if (recME->getMethodFamily() == OMF_alloc &&
- recME->getReceiverKind() == ObjCMessageExpr::Class &&
- isNSAutoreleasePool(recME->getReceiverInterface()))
- return true;
- }
- }
-
- return false;
- }
-
- bool isPoolDrain(VarDecl *poolVar, Stmt *S) {
- if (!S) return false;
- S = getEssential(S);
- ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S);
- if (!ME) return false;
- if (ME->getReceiverKind() == ObjCMessageExpr::Instance) {
- Expr *rec = getEssential(ME->getInstanceReceiver());
- if (DeclRefExpr *dref = dyn_cast<DeclRefExpr>(rec))
- if (dref->getDecl() == poolVar)
- return ME->getMethodFamily() == OMF_release ||
- ME->getSelector() == DrainSel;
- }
-
- return false;
- }
-
- bool isNSAutoreleasePool(ObjCInterfaceDecl *IDecl) {
- return IDecl && IDecl->getIdentifier() == PoolII;
- }
-
- bool isNSAutoreleasePool(QualType Ty) {
- QualType pointee = Ty->getPointeeType();
- if (pointee.isNull())
- return false;
- if (const ObjCInterfaceType *interT = pointee->getAs<ObjCInterfaceType>())
- return isNSAutoreleasePool(interT->getDecl());
- return false;
- }
-
- static Expr *getEssential(Expr *E) {
- return cast<Expr>(getEssential((Stmt*)E));
- }
- static Stmt *getEssential(Stmt *S) {
- if (FullExpr *FE = dyn_cast<FullExpr>(S))
- S = FE->getSubExpr();
- if (Expr *E = dyn_cast<Expr>(S))
- S = E->IgnoreParenCasts();
- return S;
- }
-
- Stmt *Body;
- MigrationPass &Pass;
-
- IdentifierInfo *PoolII;
- Selector DrainSel;
-
- struct PoolVarInfo {
- DeclStmt *Dcl = nullptr;
- ExprSet Refs;
- SmallVector<PoolScope, 2> Scopes;
-
- PoolVarInfo() = default;
- };
-
- std::map<VarDecl *, PoolVarInfo> PoolVars;
-};
-
-} // anonymous namespace
-
-void trans::rewriteAutoreleasePool(MigrationPass &pass) {
- BodyTransform<AutoreleasePoolRewriter> trans(pass);
- trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
-}
diff --git a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp b/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
deleted file mode 100644
index 1e4db33..0000000
--- a/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//===--- TransBlockObjCVariable.cpp - Transformations to ARC mode ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// rewriteBlockObjCVariable:
-//
-// Adding __block to an obj-c variable could be either because the variable
-// is used for output storage or the user wanted to break a retain cycle.
-// This transformation checks whether a reference of the variable for the block
-// is actually needed (it is assigned to or its address is taken) or not.
-// If the reference is not needed it will assume __block was added to break a
-// cycle so it will remove '__block' and add __weak/__unsafe_unretained.
-// e.g
-//
-// __block Foo *x;
-// bar(^ { [x cake]; });
-// ---->
-// __weak Foo *x;
-// bar(^ { [x cake]; });
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
-#include "clang/Basic/SourceManager.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class RootBlockObjCVarRewriter :
- public RecursiveASTVisitor<RootBlockObjCVarRewriter> {
- llvm::DenseSet<VarDecl *> &VarsToChange;
-
- class BlockVarChecker : public RecursiveASTVisitor<BlockVarChecker> {
- VarDecl *Var;
-
- typedef RecursiveASTVisitor<BlockVarChecker> base;
- public:
- BlockVarChecker(VarDecl *var) : Var(var) { }
-
- bool TraverseImplicitCastExpr(ImplicitCastExpr *castE) {
- if (DeclRefExpr *
- ref = dyn_cast<DeclRefExpr>(castE->getSubExpr())) {
- if (ref->getDecl() == Var) {
- if (castE->getCastKind() == CK_LValueToRValue)
- return true; // Using the value of the variable.
- if (castE->getCastKind() == CK_NoOp && castE->isLValue() &&
- Var->getASTContext().getLangOpts().CPlusPlus)
- return true; // Binding to const C++ reference.
- }
- }
-
- return base::TraverseImplicitCastExpr(castE);
- }
-
- bool VisitDeclRefExpr(DeclRefExpr *E) {
- if (E->getDecl() == Var)
- return false; // The reference of the variable, and not just its value,
- // is needed.
- return true;
- }
- };
-
-public:
- RootBlockObjCVarRewriter(llvm::DenseSet<VarDecl *> &VarsToChange)
- : VarsToChange(VarsToChange) { }
-
- bool VisitBlockDecl(BlockDecl *block) {
- SmallVector<VarDecl *, 4> BlockVars;
-
- for (const auto &I : block->captures()) {
- VarDecl *var = I.getVariable();
- if (I.isByRef() &&
- var->getType()->isObjCObjectPointerType() &&
- isImplicitStrong(var->getType())) {
- BlockVars.push_back(var);
- }
- }
-
- for (unsigned i = 0, e = BlockVars.size(); i != e; ++i) {
- VarDecl *var = BlockVars[i];
-
- BlockVarChecker checker(var);
- bool onlyValueOfVarIsNeeded = checker.TraverseStmt(block->getBody());
- if (onlyValueOfVarIsNeeded)
- VarsToChange.insert(var);
- else
- VarsToChange.erase(var);
- }
-
- return true;
- }
-
-private:
- bool isImplicitStrong(QualType ty) {
- if (isa<AttributedType>(ty.getTypePtr()))
- return false;
- return ty.getLocalQualifiers().getObjCLifetime() == Qualifiers::OCL_Strong;
- }
-};
-
-class BlockObjCVarRewriter : public RecursiveASTVisitor<BlockObjCVarRewriter> {
- llvm::DenseSet<VarDecl *> &VarsToChange;
-
-public:
- BlockObjCVarRewriter(llvm::DenseSet<VarDecl *> &VarsToChange)
- : VarsToChange(VarsToChange) { }
-
- bool TraverseBlockDecl(BlockDecl *block) {
- RootBlockObjCVarRewriter(VarsToChange).TraverseDecl(block);
- return true;
- }
-};
-
-} // anonymous namespace
-
-void BlockObjCVariableTraverser::traverseBody(BodyContext &BodyCtx) {
- MigrationPass &Pass = BodyCtx.getMigrationContext().Pass;
- llvm::DenseSet<VarDecl *> VarsToChange;
-
- BlockObjCVarRewriter trans(VarsToChange);
- trans.TraverseStmt(BodyCtx.getTopStmt());
-
- for (llvm::DenseSet<VarDecl *>::iterator
- I = VarsToChange.begin(), E = VarsToChange.end(); I != E; ++I) {
- VarDecl *var = *I;
- BlocksAttr *attr = var->getAttr<BlocksAttr>();
- if(!attr)
- continue;
- bool useWeak = canApplyWeak(Pass.Ctx, var->getType());
- SourceManager &SM = Pass.Ctx.getSourceManager();
- Transaction Trans(Pass.TA);
- Pass.TA.replaceText(SM.getExpansionLoc(attr->getLocation()),
- "__block",
- useWeak ? "__weak" : "__unsafe_unretained");
- }
-}
diff --git a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
deleted file mode 100644
index e9c21b8..0000000
--- a/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-//===-- TransEmptyStatementsAndDealloc.cpp - Transformations to ARC mode --===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// removeEmptyStatementsAndDealloc:
-//
-// Removes empty statements that are leftovers from previous transformations.
-// e.g for
-//
-// [x retain];
-//
-// removeRetainReleaseDealloc will leave an empty ";" that removeEmptyStatements
-// will remove.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/Basic/SourceManager.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-static bool isEmptyARCMTMacroStatement(NullStmt *S,
- std::vector<SourceLocation> &MacroLocs,
- ASTContext &Ctx) {
- if (!S->hasLeadingEmptyMacro())
- return false;
-
- SourceLocation SemiLoc = S->getSemiLoc();
- if (SemiLoc.isInvalid() || SemiLoc.isMacroID())
- return false;
-
- if (MacroLocs.empty())
- return false;
-
- SourceManager &SM = Ctx.getSourceManager();
- std::vector<SourceLocation>::iterator I = llvm::upper_bound(
- MacroLocs, SemiLoc, BeforeThanCompare<SourceLocation>(SM));
- --I;
- SourceLocation
- AfterMacroLoc = I->getLocWithOffset(getARCMTMacroName().size());
- assert(AfterMacroLoc.isFileID());
-
- if (AfterMacroLoc == SemiLoc)
- return true;
-
- SourceLocation::IntTy RelOffs = 0;
- if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs))
- return false;
- if (RelOffs < 0)
- return false;
-
- // We make the reasonable assumption that a semicolon after 100 characters
- // means that it is not the next token after our macro. If this assumption
- // fails it is not critical, we will just fail to clear out, e.g., an empty
- // 'if'.
- if (RelOffs - getARCMTMacroName().size() > 100)
- return false;
-
- SourceLocation AfterMacroSemiLoc = findSemiAfterLocation(AfterMacroLoc, Ctx);
- return AfterMacroSemiLoc == SemiLoc;
-}
-
-namespace {
-
-/// Returns true if the statement became empty due to previous
-/// transformations.
-class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
- ASTContext &Ctx;
- std::vector<SourceLocation> &MacroLocs;
-
-public:
- EmptyChecker(ASTContext &ctx, std::vector<SourceLocation> &macroLocs)
- : Ctx(ctx), MacroLocs(macroLocs) { }
-
- bool VisitNullStmt(NullStmt *S) {
- return isEmptyARCMTMacroStatement(S, MacroLocs, Ctx);
- }
- bool VisitCompoundStmt(CompoundStmt *S) {
- if (S->body_empty())
- return false; // was already empty, not because of transformations.
- for (auto *I : S->body())
- if (!Visit(I))
- return false;
- return true;
- }
- bool VisitIfStmt(IfStmt *S) {
- if (S->getConditionVariable())
- return false;
- Expr *condE = S->getCond();
- if (!condE)
- return false;
- if (hasSideEffects(condE, Ctx))
- return false;
- if (!S->getThen() || !Visit(S->getThen()))
- return false;
- return !S->getElse() || Visit(S->getElse());
- }
- bool VisitWhileStmt(WhileStmt *S) {
- if (S->getConditionVariable())
- return false;
- Expr *condE = S->getCond();
- if (!condE)
- return false;
- if (hasSideEffects(condE, Ctx))
- return false;
- if (!S->getBody())
- return false;
- return Visit(S->getBody());
- }
- bool VisitDoStmt(DoStmt *S) {
- Expr *condE = S->getCond();
- if (!condE)
- return false;
- if (hasSideEffects(condE, Ctx))
- return false;
- if (!S->getBody())
- return false;
- return Visit(S->getBody());
- }
- bool VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
- Expr *Exp = S->getCollection();
- if (!Exp)
- return false;
- if (hasSideEffects(Exp, Ctx))
- return false;
- if (!S->getBody())
- return false;
- return Visit(S->getBody());
- }
- bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
- if (!S->getSubStmt())
- return false;
- return Visit(S->getSubStmt());
- }
-};
-
-class EmptyStatementsRemover :
- public RecursiveASTVisitor<EmptyStatementsRemover> {
- MigrationPass &Pass;
-
-public:
- EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { }
-
- bool TraverseStmtExpr(StmtExpr *E) {
- CompoundStmt *S = E->getSubStmt();
- for (CompoundStmt::body_iterator
- I = S->body_begin(), E = S->body_end(); I != E; ++I) {
- if (I != E - 1)
- check(*I);
- TraverseStmt(*I);
- }
- return true;
- }
-
- bool VisitCompoundStmt(CompoundStmt *S) {
- for (auto *I : S->body())
- check(I);
- return true;
- }
-
- ASTContext &getContext() { return Pass.Ctx; }
-
-private:
- void check(Stmt *S) {
- if (!S) return;
- if (EmptyChecker(Pass.Ctx, Pass.ARCMTMacroLocs).Visit(S)) {
- Transaction Trans(Pass.TA);
- Pass.TA.removeStmt(S);
- }
- }
-};
-
-} // anonymous namespace
-
-static bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx,
- std::vector<SourceLocation> &MacroLocs) {
- for (auto *I : body->body())
- if (!EmptyChecker(Ctx, MacroLocs).Visit(I))
- return false;
-
- return true;
-}
-
-static void cleanupDeallocOrFinalize(MigrationPass &pass) {
- ASTContext &Ctx = pass.Ctx;
- TransformActions &TA = pass.TA;
- DeclContext *DC = Ctx.getTranslationUnitDecl();
- Selector FinalizeSel =
- Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
-
- typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
- impl_iterator;
- for (impl_iterator I = impl_iterator(DC->decls_begin()),
- E = impl_iterator(DC->decls_end()); I != E; ++I) {
- ObjCMethodDecl *DeallocM = nullptr;
- ObjCMethodDecl *FinalizeM = nullptr;
- for (auto *MD : I->instance_methods()) {
- if (!MD->hasBody())
- continue;
-
- if (MD->getMethodFamily() == OMF_dealloc) {
- DeallocM = MD;
- } else if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
- FinalizeM = MD;
- }
- }
-
- if (DeallocM) {
- if (isBodyEmpty(DeallocM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
- Transaction Trans(TA);
- TA.remove(DeallocM->getSourceRange());
- }
-
- if (FinalizeM) {
- Transaction Trans(TA);
- TA.remove(FinalizeM->getSourceRange());
- }
-
- } else if (FinalizeM) {
- if (isBodyEmpty(FinalizeM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
- Transaction Trans(TA);
- TA.remove(FinalizeM->getSourceRange());
- } else {
- Transaction Trans(TA);
- TA.replaceText(FinalizeM->getSelectorStartLoc(), "finalize", "dealloc");
- }
- }
- }
-}
-
-void trans::removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass) {
- EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
-
- cleanupDeallocOrFinalize(pass);
-
- for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
- Transaction Trans(pass.TA);
- pass.TA.remove(pass.ARCMTMacroLocs[i]);
- }
-}
diff --git a/clang/lib/ARCMigrate/TransGCAttrs.cpp b/clang/lib/ARCMigrate/TransGCAttrs.cpp
deleted file mode 100644
index 85e3fe7..0000000
--- a/clang/lib/ARCMigrate/TransGCAttrs.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-//===--- TransGCAttrs.cpp - Transformations to ARC mode -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/TinyPtrVector.h"
-#include "llvm/Support/SaveAndRestore.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-/// Collects all the places where GC attributes __strong/__weak occur.
-class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
- MigrationContext &MigrateCtx;
- bool FullyMigratable;
- std::vector<ObjCPropertyDecl *> &AllProps;
-
- typedef RecursiveASTVisitor<GCAttrsCollector> base;
-public:
- GCAttrsCollector(MigrationContext &ctx,
- std::vector<ObjCPropertyDecl *> &AllProps)
- : MigrateCtx(ctx), FullyMigratable(false),
- AllProps(AllProps) { }
-
- bool shouldWalkTypesOfTypeLocs() const { return false; }
-
- bool VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- handleAttr(TL);
- return true;
- }
-
- bool TraverseDecl(Decl *D) {
- if (!D || D->isImplicit())
- return true;
-
- SaveAndRestore Save(FullyMigratable, isMigratable(D));
-
- if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D)) {
- lookForAttribute(PropD, PropD->getTypeSourceInfo());
- AllProps.push_back(PropD);
- } else if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
- lookForAttribute(DD, DD->getTypeSourceInfo());
- }
- return base::TraverseDecl(D);
- }
-
- void lookForAttribute(Decl *D, TypeSourceInfo *TInfo) {
- if (!TInfo)
- return;
- TypeLoc TL = TInfo->getTypeLoc();
- while (TL) {
- if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>()) {
- TL = QL.getUnqualifiedLoc();
- } else if (AttributedTypeLoc Attr = TL.getAs<AttributedTypeLoc>()) {
- if (handleAttr(Attr, D))
- break;
- TL = Attr.getModifiedLoc();
- } else if (MacroQualifiedTypeLoc MDTL =
- TL.getAs<MacroQualifiedTypeLoc>()) {
- TL = MDTL.getInnerLoc();
- } else if (ArrayTypeLoc Arr = TL.getAs<ArrayTypeLoc>()) {
- TL = Arr.getElementLoc();
- } else if (PointerTypeLoc PT = TL.getAs<PointerTypeLoc>()) {
- TL = PT.getPointeeLoc();
- } else if (ReferenceTypeLoc RT = TL.getAs<ReferenceTypeLoc>())
- TL = RT.getPointeeLoc();
- else
- break;
- }
- }
-
- bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {
- auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>();
- if (!OwnershipAttr)
- return false;
-
- SourceLocation Loc = OwnershipAttr->getLocation();
- SourceLocation OrigLoc = Loc;
- if (MigrateCtx.AttrSet.count(OrigLoc))
- return true;
-
- ASTContext &Ctx = MigrateCtx.Pass.Ctx;
- SourceManager &SM = Ctx.getSourceManager();
- if (Loc.isMacroID())
- Loc = SM.getImmediateExpansionRange(Loc).getBegin();
- StringRef Spell = OwnershipAttr->getKind()->getName();
- MigrationContext::GCAttrOccurrence::AttrKind Kind;
- if (Spell == "strong")
- Kind = MigrationContext::GCAttrOccurrence::Strong;
- else if (Spell == "weak")
- Kind = MigrationContext::GCAttrOccurrence::Weak;
- else
- return false;
-
- MigrateCtx.AttrSet.insert(OrigLoc);
- MigrateCtx.GCAttrs.push_back(MigrationContext::GCAttrOccurrence());
- MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs.back();
-
- Attr.Kind = Kind;
- Attr.Loc = Loc;
- Attr.ModifiedType = TL.getModifiedLoc().getType();
- Attr.Dcl = D;
- Attr.FullyMigratable = FullyMigratable;
- return true;
- }
-
- bool isMigratable(Decl *D) {
- if (isa<TranslationUnitDecl>(D))
- return false;
-
- if (isInMainFile(D))
- return true;
-
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->hasBody();
-
- if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D))
- return hasObjCImpl(ContD);
-
- if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- for (const auto *MI : RD->methods()) {
- if (MI->isOutOfLine())
- return true;
- }
- return false;
- }
-
- return isMigratable(cast<Decl>(D->getDeclContext()));
- }
-
- static bool hasObjCImpl(Decl *D) {
- if (!D)
- return false;
- if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) {
- if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD))
- return ID->getImplementation() != nullptr;
- if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD))
- return CD->getImplementation() != nullptr;
- return isa<ObjCImplDecl>(ContD);
- }
- return false;
- }
-
- bool isInMainFile(Decl *D) {
- if (!D)
- return false;
-
- for (auto *I : D->redecls())
- if (!isInMainFile(I->getLocation()))
- return false;
-
- return true;
- }
-
- bool isInMainFile(SourceLocation Loc) {
- if (Loc.isInvalid())
- return false;
-
- SourceManager &SM = MigrateCtx.Pass.Ctx.getSourceManager();
- return SM.isInFileID(SM.getExpansionLoc(Loc), SM.getMainFileID());
- }
-};
-
-} // anonymous namespace
-
-static void errorForGCAttrsOnNonObjC(MigrationContext &MigrateCtx) {
- TransformActions &TA = MigrateCtx.Pass.TA;
-
- for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
- MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
- if (Attr.FullyMigratable && Attr.Dcl) {
- if (Attr.ModifiedType.isNull())
- continue;
- if (!Attr.ModifiedType->isObjCRetainableType()) {
- TA.reportError("GC managed memory will become unmanaged in ARC",
- Attr.Loc);
- }
- }
- }
-}
-
-static void checkWeakGCAttrs(MigrationContext &MigrateCtx) {
- TransformActions &TA = MigrateCtx.Pass.TA;
-
- for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
- MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
- if (Attr.Kind == MigrationContext::GCAttrOccurrence::Weak) {
- if (Attr.ModifiedType.isNull() ||
- !Attr.ModifiedType->isObjCRetainableType())
- continue;
- if (!canApplyWeak(MigrateCtx.Pass.Ctx, Attr.ModifiedType,
- /*AllowOnUnknownClass=*/true)) {
- Transaction Trans(TA);
- if (!MigrateCtx.RemovedAttrSet.count(Attr.Loc))
- TA.replaceText(Attr.Loc, "__weak", "__unsafe_unretained");
- TA.clearDiagnostic(diag::err_arc_weak_no_runtime,
- diag::err_arc_unsupported_weak_class,
- Attr.Loc);
- }
- }
- }
-}
-
-typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
-
-static void checkAllAtProps(MigrationContext &MigrateCtx,
- SourceLocation AtLoc,
- IndivPropsTy &IndProps) {
- if (IndProps.empty())
- return;
-
- for (IndivPropsTy::iterator
- PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
- QualType T = (*PI)->getType();
- if (T.isNull() || !T->isObjCRetainableType())
- return;
- }
-
- SmallVector<std::pair<AttributedTypeLoc, ObjCPropertyDecl *>, 4> ATLs;
- bool hasWeak = false, hasStrong = false;
- ObjCPropertyAttribute::Kind Attrs = ObjCPropertyAttribute::kind_noattr;
- for (IndivPropsTy::iterator
- PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
- ObjCPropertyDecl *PD = *PI;
- Attrs = PD->getPropertyAttributesAsWritten();
- TypeSourceInfo *TInfo = PD->getTypeSourceInfo();
- if (!TInfo)
- return;
- TypeLoc TL = TInfo->getTypeLoc();
- if (AttributedTypeLoc ATL =
- TL.getAs<AttributedTypeLoc>()) {
- ATLs.push_back(std::make_pair(ATL, PD));
- if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- hasWeak = true;
- } else if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Strong)
- hasStrong = true;
- else
- return;
- }
- }
- if (ATLs.empty())
- return;
- if (hasWeak && hasStrong)
- return;
-
- TransformActions &TA = MigrateCtx.Pass.TA;
- Transaction Trans(TA);
-
- if (GCAttrsCollector::hasObjCImpl(
- cast<Decl>(IndProps.front()->getDeclContext()))) {
- if (hasWeak)
- MigrateCtx.AtPropsWeak.insert(AtLoc);
-
- } else {
- StringRef toAttr = "strong";
- if (hasWeak) {
- if (canApplyWeak(MigrateCtx.Pass.Ctx, IndProps.front()->getType(),
- /*AllowOnUnknownClass=*/true))
- toAttr = "weak";
- else
- toAttr = "unsafe_unretained";
- }
- if (Attrs & ObjCPropertyAttribute::kind_assign)
- MigrateCtx.rewritePropertyAttribute("assign", toAttr, AtLoc);
- else
- MigrateCtx.addPropertyAttribute(toAttr, AtLoc);
- }
-
- for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
- SourceLocation Loc = ATLs[i].first.getAttr()->getLocation();
- if (Loc.isMacroID())
- Loc = MigrateCtx.Pass.Ctx.getSourceManager()
- .getImmediateExpansionRange(Loc)
- .getBegin();
- TA.remove(Loc);
- TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);
- TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,
- ATLs[i].second->getLocation());
- MigrateCtx.RemovedAttrSet.insert(Loc);
- }
-}
-
-static void checkAllProps(MigrationContext &MigrateCtx,
- std::vector<ObjCPropertyDecl *> &AllProps) {
- typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
- llvm::DenseMap<SourceLocation, IndivPropsTy> AtProps;
-
- for (unsigned i = 0, e = AllProps.size(); i != e; ++i) {
- ObjCPropertyDecl *PD = AllProps[i];
- if (PD->getPropertyAttributesAsWritten() &
- (ObjCPropertyAttribute::kind_assign |
- ObjCPropertyAttribute::kind_readonly)) {
- SourceLocation AtLoc = PD->getAtLoc();
- if (AtLoc.isInvalid())
- continue;
- AtProps[AtLoc].push_back(PD);
- }
- }
-
- for (auto I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
- SourceLocation AtLoc = I->first;
- IndivPropsTy &IndProps = I->second;
- checkAllAtProps(MigrateCtx, AtLoc, IndProps);
- }
-}
-
-void GCAttrsTraverser::traverseTU(MigrationContext &MigrateCtx) {
- std::vector<ObjCPropertyDecl *> AllProps;
- GCAttrsCollector(MigrateCtx, AllProps).TraverseDecl(
- MigrateCtx.Pass.Ctx.getTranslationUnitDecl());
-
- errorForGCAttrsOnNonObjC(MigrateCtx);
- checkAllProps(MigrateCtx, AllProps);
- checkWeakGCAttrs(MigrateCtx);
-}
-
-void MigrationContext::dumpGCAttrs() {
- llvm::errs() << "\n################\n";
- for (unsigned i = 0, e = GCAttrs.size(); i != e; ++i) {
- GCAttrOccurrence &Attr = GCAttrs[i];
- llvm::errs() << "KIND: "
- << (Attr.Kind == GCAttrOccurrence::Strong ? "strong" : "weak");
- llvm::errs() << "\nLOC: ";
- Attr.Loc.print(llvm::errs(), Pass.Ctx.getSourceManager());
- llvm::errs() << "\nTYPE: ";
- Attr.ModifiedType.dump();
- if (Attr.Dcl) {
- llvm::errs() << "DECL:\n";
- Attr.Dcl->dump();
- } else {
- llvm::errs() << "DECL: NONE";
- }
- llvm::errs() << "\nMIGRATABLE: " << Attr.FullyMigratable;
- llvm::errs() << "\n----------------\n";
- }
- llvm::errs() << "\n################\n";
-}
diff --git a/clang/lib/ARCMigrate/TransGCCalls.cpp b/clang/lib/ARCMigrate/TransGCCalls.cpp
deleted file mode 100644
index 43233e2..0000000
--- a/clang/lib/ARCMigrate/TransGCCalls.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-//===--- TransGCCalls.cpp - Transformations to ARC mode -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Sema/SemaDiagnostic.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class GCCollectableCallsChecker :
- public RecursiveASTVisitor<GCCollectableCallsChecker> {
- MigrationContext &MigrateCtx;
- IdentifierInfo *NSMakeCollectableII;
- IdentifierInfo *CFMakeCollectableII;
-
-public:
- GCCollectableCallsChecker(MigrationContext &ctx)
- : MigrateCtx(ctx) {
- IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
- NSMakeCollectableII = &Ids.get("NSMakeCollectable");
- CFMakeCollectableII = &Ids.get("CFMakeCollectable");
- }
-
- bool shouldWalkTypesOfTypeLocs() const { return false; }
-
- bool VisitCallExpr(CallExpr *E) {
- TransformActions &TA = MigrateCtx.Pass.TA;
-
- if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
- TA.report(E->getBeginLoc(), diag::warn_arcmt_nsalloc_realloc,
- E->getSourceRange());
- return true;
- }
-
- Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
- if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
- if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
- return true;
-
- if (FD->getIdentifier() == NSMakeCollectableII) {
- Transaction Trans(TA);
- TA.clearDiagnostic(diag::err_unavailable,
- diag::err_unavailable_message,
- diag::err_ovl_deleted_call, // ObjC++
- DRE->getSourceRange());
- TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
-
- } else if (FD->getIdentifier() == CFMakeCollectableII) {
- TA.reportError("CFMakeCollectable will leak the object that it "
- "receives in ARC", DRE->getLocation(),
- DRE->getSourceRange());
- }
- }
- }
-
- return true;
- }
-};
-
-} // anonymous namespace
-
-void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
- GCCollectableCallsChecker(BodyCtx.getMigrationContext())
- .TraverseStmt(BodyCtx.getTopStmt());
-}
diff --git a/clang/lib/ARCMigrate/TransProperties.cpp b/clang/lib/ARCMigrate/TransProperties.cpp
deleted file mode 100644
index 6d1d950..0000000
--- a/clang/lib/ARCMigrate/TransProperties.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-//===--- TransProperties.cpp - Transformations to ARC mode ----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// rewriteProperties:
-//
-// - Adds strong/weak/unsafe_unretained ownership specifier to properties that
-// are missing one.
-// - Migrates properties from (retain) to (strong) and (assign) to
-// (unsafe_unretained/weak).
-// - If a property is synthesized, adds the ownership specifier in the ivar
-// backing the property.
-//
-// @interface Foo : NSObject {
-// NSObject *x;
-// }
-// @property (assign) id x;
-// @end
-// ---->
-// @interface Foo : NSObject {
-// NSObject *__weak x;
-// }
-// @property (weak) id x;
-// @end
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include <map>
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class PropertiesRewriter {
- MigrationContext &MigrateCtx;
- MigrationPass &Pass;
- ObjCImplementationDecl *CurImplD = nullptr;
-
- enum PropActionKind {
- PropAction_None,
- PropAction_RetainReplacedWithStrong,
- PropAction_AssignRemoved,
- PropAction_AssignRewritten,
- PropAction_MaybeAddWeakOrUnsafe
- };
-
- struct PropData {
- ObjCPropertyDecl *PropD;
- ObjCIvarDecl *IvarD;
- ObjCPropertyImplDecl *ImplD;
-
- PropData(ObjCPropertyDecl *propD)
- : PropD(propD), IvarD(nullptr), ImplD(nullptr) {}
- };
-
- typedef SmallVector<PropData, 2> PropsTy;
- typedef std::map<SourceLocation, PropsTy> AtPropDeclsTy;
- AtPropDeclsTy AtProps;
- llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
-
-public:
- explicit PropertiesRewriter(MigrationContext &MigrateCtx)
- : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
-
- static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
- AtPropDeclsTy *PrevAtProps = nullptr) {
- for (auto *Prop : D->instance_properties()) {
- SourceLocation Loc = Prop->getAtLoc();
- if (Loc.isInvalid())
- continue;
- if (PrevAtProps)
- if (PrevAtProps->find(Loc) != PrevAtProps->end())
- continue;
- PropsTy &props = AtProps[Loc];
- props.push_back(Prop);
- }
- }
-
- void doTransform(ObjCImplementationDecl *D) {
- CurImplD = D;
- ObjCInterfaceDecl *iface = D->getClassInterface();
- if (!iface)
- return;
-
- collectProperties(iface, AtProps);
-
- // Look through extensions.
- for (auto *Ext : iface->visible_extensions())
- collectProperties(Ext, AtProps);
-
- typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
- prop_impl_iterator;
- for (prop_impl_iterator
- I = prop_impl_iterator(D->decls_begin()),
- E = prop_impl_iterator(D->decls_end()); I != E; ++I) {
- ObjCPropertyImplDecl *implD = *I;
- if (implD->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
- continue;
- ObjCPropertyDecl *propD = implD->getPropertyDecl();
- if (!propD || propD->isInvalidDecl())
- continue;
- ObjCIvarDecl *ivarD = implD->getPropertyIvarDecl();
- if (!ivarD || ivarD->isInvalidDecl())
- continue;
- AtPropDeclsTy::iterator findAtLoc = AtProps.find(propD->getAtLoc());
- if (findAtLoc == AtProps.end())
- continue;
-
- PropsTy &props = findAtLoc->second;
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (I->PropD == propD) {
- I->IvarD = ivarD;
- I->ImplD = implD;
- break;
- }
- }
- }
-
- for (AtPropDeclsTy::iterator
- I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
- SourceLocation atLoc = I->first;
- PropsTy &props = I->second;
- if (!getPropertyType(props)->isObjCRetainableType())
- continue;
- if (hasIvarWithExplicitARCOwnership(props))
- continue;
-
- Transaction Trans(Pass.TA);
- rewriteProperty(props, atLoc);
- }
- }
-
-private:
- void doPropAction(PropActionKind kind,
- PropsTy &props, SourceLocation atLoc,
- bool markAction = true) {
- if (markAction)
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
- ActionOnProp[I->PropD->getIdentifier()] = kind;
-
- switch (kind) {
- case PropAction_None:
- return;
- case PropAction_RetainReplacedWithStrong: {
- StringRef toAttr = "strong";
- MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
- return;
- }
- case PropAction_AssignRemoved:
- return removeAssignForDefaultStrong(props, atLoc);
- case PropAction_AssignRewritten:
- return rewriteAssign(props, atLoc);
- case PropAction_MaybeAddWeakOrUnsafe:
- return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
- }
- }
-
- void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
- ObjCPropertyAttribute::Kind propAttrs = getPropertyAttrs(props);
-
- if (propAttrs &
- (ObjCPropertyAttribute::kind_copy |
- ObjCPropertyAttribute::kind_unsafe_unretained |
- ObjCPropertyAttribute::kind_strong | ObjCPropertyAttribute::kind_weak))
- return;
-
- if (propAttrs & ObjCPropertyAttribute::kind_retain) {
- // strong is the default.
- return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
- }
-
- bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
-
- if (propAttrs & ObjCPropertyAttribute::kind_assign) {
- if (HasIvarAssignedAPlusOneObject)
- return doPropAction(PropAction_AssignRemoved, props, atLoc);
- return doPropAction(PropAction_AssignRewritten, props, atLoc);
- }
-
- if (HasIvarAssignedAPlusOneObject ||
- (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
- return; // 'strong' by default.
-
- return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
- }
-
- void removeAssignForDefaultStrong(PropsTy &props,
- SourceLocation atLoc) const {
- removeAttribute("retain", atLoc);
- if (!removeAttribute("assign", atLoc))
- return;
-
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (I->ImplD)
- Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
- diag::err_arc_assign_property_ownership,
- diag::err_arc_inconsistent_property_ownership,
- I->IvarD->getLocation());
- }
- }
-
- void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
- bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
- /*AllowOnUnknownClass=*/Pass.isGCMigration());
- const char *toWhich =
- (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
- (canUseWeak ? "weak" : "unsafe_unretained");
-
- bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
- if (!rewroteAttr)
- canUseWeak = false;
-
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (isUserDeclared(I->IvarD)) {
- if (I->IvarD &&
- I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
- const char *toWhich =
- (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
- (canUseWeak ? "__weak " : "__unsafe_unretained ");
- Pass.TA.insert(I->IvarD->getLocation(), toWhich);
- }
- }
- if (I->ImplD)
- Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
- diag::err_arc_assign_property_ownership,
- diag::err_arc_inconsistent_property_ownership,
- I->IvarD->getLocation());
- }
- }
-
- void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
- SourceLocation atLoc) const {
- bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
- /*AllowOnUnknownClass=*/Pass.isGCMigration());
-
- bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
- atLoc);
- if (!addedAttr)
- canUseWeak = false;
-
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (isUserDeclared(I->IvarD)) {
- if (I->IvarD &&
- I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
- Pass.TA.insert(I->IvarD->getLocation(),
- canUseWeak ? "__weak " : "__unsafe_unretained ");
- }
- if (I->ImplD) {
- Pass.TA.clearDiagnostic(diag::err_arc_strong_property_ownership,
- diag::err_arc_assign_property_ownership,
- diag::err_arc_inconsistent_property_ownership,
- I->IvarD->getLocation());
- Pass.TA.clearDiagnostic(
- diag::err_arc_objc_property_default_assign_on_object,
- I->ImplD->getLocation());
- }
- }
- }
-
- bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
- return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
- }
-
- bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
- SourceLocation atLoc) const {
- return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
- }
-
- bool addAttribute(StringRef attr, SourceLocation atLoc) const {
- return MigrateCtx.addPropertyAttribute(attr, atLoc);
- }
-
- class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
- ObjCIvarDecl *Ivar;
- public:
- PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
-
- bool VisitBinaryOperator(BinaryOperator *E) {
- if (E->getOpcode() != BO_Assign)
- return true;
-
- Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
- if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
- if (RE->getDecl() != Ivar)
- return true;
-
- if (isPlusOneAssign(E))
- return false;
- }
-
- return true;
- }
- };
-
- bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- PlusOneAssign oneAssign(I->IvarD);
- bool notFound = oneAssign.TraverseDecl(CurImplD);
- if (!notFound)
- return true;
- }
-
- return false;
- }
-
- bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
- if (Pass.isGCMigration())
- return false;
-
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (isUserDeclared(I->IvarD)) {
- if (isa<AttributedType>(I->IvarD->getType()))
- return true;
- if (I->IvarD->getType().getLocalQualifiers().getObjCLifetime()
- != Qualifiers::OCL_Strong)
- return true;
- }
- }
-
- return false;
- }
-
- // Returns true if all declarations in the @property have GC __weak.
- bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
- if (!Pass.isGCMigration())
- return false;
- if (props.empty())
- return false;
- return MigrateCtx.AtPropsWeak.count(atLoc);
- }
-
- bool isUserDeclared(ObjCIvarDecl *ivarD) const {
- return ivarD && !ivarD->getSynthesize();
- }
-
- QualType getPropertyType(PropsTy &props) const {
- assert(!props.empty());
- QualType ty = props[0].PropD->getType().getUnqualifiedType();
-
-#ifndef NDEBUG
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
- assert(ty == I->PropD->getType().getUnqualifiedType());
-#endif
-
- return ty;
- }
-
- ObjCPropertyAttribute::Kind getPropertyAttrs(PropsTy &props) const {
- assert(!props.empty());
- ObjCPropertyAttribute::Kind attrs =
- props[0].PropD->getPropertyAttributesAsWritten();
-
-#ifndef NDEBUG
- for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
- assert(attrs == I->PropD->getPropertyAttributesAsWritten());
-#endif
-
- return attrs;
- }
-};
-
-} // anonymous namespace
-
-void PropertyRewriteTraverser::traverseObjCImplementation(
- ObjCImplementationContext &ImplCtx) {
- PropertiesRewriter(ImplCtx.getMigrationContext())
- .doTransform(ImplCtx.getImplementationDecl());
-}
diff --git a/clang/lib/ARCMigrate/TransProtectedScope.cpp b/clang/lib/ARCMigrate/TransProtectedScope.cpp
deleted file mode 100644
index 154e0b5..0000000
--- a/clang/lib/ARCMigrate/TransProtectedScope.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-//===--- TransProtectedScope.cpp - Transformations to ARC mode ------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Adds brackets in case statements that "contain" initialization of retaining
-// variable, thus emitting the "switch case is in protected scope" error.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Internals.h"
-#include "Transforms.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Sema/SemaDiagnostic.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class LocalRefsCollector : public RecursiveASTVisitor<LocalRefsCollector> {
- SmallVectorImpl<DeclRefExpr *> &Refs;
-
-public:
- LocalRefsCollector(SmallVectorImpl<DeclRefExpr *> &refs)
- : Refs(refs) { }
-
- bool VisitDeclRefExpr(DeclRefExpr *E) {
- if (ValueDecl *D = E->getDecl())
- if (D->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
- Refs.push_back(E);
- return true;
- }
-};
-
-struct CaseInfo {
- SwitchCase *SC;
- SourceRange Range;
- enum {
- St_Unchecked,
- St_CannotFix,
- St_Fixed
- } State;
-
- CaseInfo() : SC(nullptr), State(St_Unchecked) {}
- CaseInfo(SwitchCase *S, SourceRange Range)
- : SC(S), Range(Range), State(St_Unchecked) {}
-};
-
-class CaseCollector : public RecursiveASTVisitor<CaseCollector> {
- ParentMap &PMap;
- SmallVectorImpl<CaseInfo> &Cases;
-
-public:
- CaseCollector(ParentMap &PMap, SmallVectorImpl<CaseInfo> &Cases)
- : PMap(PMap), Cases(Cases) { }
-
- bool VisitSwitchStmt(SwitchStmt *S) {
- SwitchCase *Curr = S->getSwitchCaseList();
- if (!Curr)
- return true;
- Stmt *Parent = getCaseParent(Curr);
- Curr = Curr->getNextSwitchCase();
- // Make sure all case statements are in the same scope.
- while (Curr) {
- if (getCaseParent(Curr) != Parent)
- return true;
- Curr = Curr->getNextSwitchCase();
- }
-
- SourceLocation NextLoc = S->getEndLoc();
- Curr = S->getSwitchCaseList();
- // We iterate over case statements in reverse source-order.
- while (Curr) {
- Cases.push_back(
- CaseInfo(Curr, SourceRange(Curr->getBeginLoc(), NextLoc)));
- NextLoc = Curr->getBeginLoc();
- Curr = Curr->getNextSwitchCase();
- }
- return true;
- }
-
- Stmt *getCaseParent(SwitchCase *S) {
- Stmt *Parent = PMap.getParent(S);
- while (Parent && (isa<SwitchCase>(Parent) || isa<LabelStmt>(Parent)))
- Parent = PMap.getParent(Parent);
- return Parent;
- }
-};
-
-class ProtectedScopeFixer {
- MigrationPass &Pass;
- SourceManager &SM;
- SmallVector<CaseInfo, 16> Cases;
- SmallVector<DeclRefExpr *, 16> LocalRefs;
-
-public:
- ProtectedScopeFixer(BodyContext &BodyCtx)
- : Pass(BodyCtx.getMigrationContext().Pass),
- SM(Pass.Ctx.getSourceManager()) {
-
- CaseCollector(BodyCtx.getParentMap(), Cases)
- .TraverseStmt(BodyCtx.getTopStmt());
- LocalRefsCollector(LocalRefs).TraverseStmt(BodyCtx.getTopStmt());
-
- SourceRange BodyRange = BodyCtx.getTopStmt()->getSourceRange();
- const CapturedDiagList &DiagList = Pass.getDiags();
- // Copy the diagnostics so we don't have to worry about invaliding iterators
- // from the diagnostic list.
- SmallVector<StoredDiagnostic, 16> StoredDiags;
- StoredDiags.append(DiagList.begin(), DiagList.end());
- SmallVectorImpl<StoredDiagnostic>::iterator
- I = StoredDiags.begin(), E = StoredDiags.end();
- while (I != E) {
- if (I->getID() == diag::err_switch_into_protected_scope &&
- isInRange(I->getLocation(), BodyRange)) {
- handleProtectedScopeError(I, E);
- continue;
- }
- ++I;
- }
- }
-
- void handleProtectedScopeError(
- SmallVectorImpl<StoredDiagnostic>::iterator &DiagI,
- SmallVectorImpl<StoredDiagnostic>::iterator DiagE){
- Transaction Trans(Pass.TA);
- assert(DiagI->getID() == diag::err_switch_into_protected_scope);
- SourceLocation ErrLoc = DiagI->getLocation();
- bool handledAllNotes = true;
- ++DiagI;
- for (; DiagI != DiagE && DiagI->getLevel() == DiagnosticsEngine::Note;
- ++DiagI) {
- if (!handleProtectedNote(*DiagI))
- handledAllNotes = false;
- }
-
- if (handledAllNotes)
- Pass.TA.clearDiagnostic(diag::err_switch_into_protected_scope, ErrLoc);
- }
-
- bool handleProtectedNote(const StoredDiagnostic &Diag) {
- assert(Diag.getLevel() == DiagnosticsEngine::Note);
-
- for (unsigned i = 0; i != Cases.size(); i++) {
- CaseInfo &info = Cases[i];
- if (isInRange(Diag.getLocation(), info.Range)) {
-
- if (info.State == CaseInfo::St_Unchecked)
- tryFixing(info);
- assert(info.State != CaseInfo::St_Unchecked);
-
- if (info.State == CaseInfo::St_Fixed) {
- Pass.TA.clearDiagnostic(Diag.getID(), Diag.getLocation());
- return true;
- }
- return false;
- }
- }
-
- return false;
- }
-
- void tryFixing(CaseInfo &info) {
- assert(info.State == CaseInfo::St_Unchecked);
- if (hasVarReferencedOutside(info)) {
- info.State = CaseInfo::St_CannotFix;
- return;
- }
-
- Pass.TA.insertAfterToken(info.SC->getColonLoc(), " {");
- Pass.TA.insert(info.Range.getEnd(), "}\n");
- info.State = CaseInfo::St_Fixed;
- }
-
- bool hasVarReferencedOutside(CaseInfo &info) {
- for (unsigned i = 0, e = LocalRefs.size(); i != e; ++i) {
- DeclRefExpr *DRE = LocalRefs[i];
- if (isInRange(DRE->getDecl()->getLocation(), info.Range) &&
- !isInRange(DRE->getLocation(), info.Range))
- return true;
- }
- return false;
- }
-
- bool isInRange(SourceLocation Loc, SourceRange R) {
- if (Loc.isInvalid())
- return false;
- return !SM.isBeforeInTranslationUnit(Loc, R.getBegin()) &&
- SM.isBeforeInTranslationUnit(Loc, R.getEnd());
- }
-};
-
-} // anonymous namespace
-
-void ProtectedScopeTraverser::traverseBody(BodyContext &BodyCtx) {
- ProtectedScopeFixer Fix(BodyCtx);
-}
diff --git a/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
deleted file mode 100644
index baa503d..0000000
--- a/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ /dev/null
@@ -1,459 +0,0 @@
-//===--- TransRetainReleaseDealloc.cpp - Transformations to ARC mode ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// removeRetainReleaseDealloc:
-//
-// Removes retain/release/autorelease/dealloc messages.
-//
-// return [[foo retain] autorelease];
-// ---->
-// return foo;
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "llvm/ADT/StringSwitch.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class RetainReleaseDeallocRemover :
- public RecursiveASTVisitor<RetainReleaseDeallocRemover> {
- Stmt *Body;
- MigrationPass &Pass;
-
- ExprSet Removables;
- std::unique_ptr<ParentMap> StmtMap;
-
- Selector DelegateSel, FinalizeSel;
-
-public:
- RetainReleaseDeallocRemover(MigrationPass &pass)
- : Body(nullptr), Pass(pass) {
- DelegateSel =
- Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("delegate"));
- FinalizeSel =
- Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
- }
-
- void transformBody(Stmt *body, Decl *ParentD) {
- Body = body;
- collectRemovables(body, Removables);
- StmtMap.reset(new ParentMap(body));
- TraverseStmt(body);
- }
-
- bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
- switch (E->getMethodFamily()) {
- default:
- if (E->isInstanceMessage() && E->getSelector() == FinalizeSel)
- break;
- return true;
- case OMF_autorelease:
- if (isRemovable(E)) {
- if (!isCommonUnusedAutorelease(E)) {
- // An unused autorelease is badness. If we remove it the receiver
- // will likely die immediately while previously it was kept alive
- // by the autorelease pool. This is bad practice in general, leave it
- // and emit an error to force the user to restructure their code.
- Pass.TA.reportError(
- "it is not safe to remove an unused 'autorelease' "
- "message; its receiver may be destroyed immediately",
- E->getBeginLoc(), E->getSourceRange());
- return true;
- }
- }
- // Pass through.
- [[fallthrough]];
- case OMF_retain:
- case OMF_release:
- if (E->getReceiverKind() == ObjCMessageExpr::Instance)
- if (Expr *rec = E->getInstanceReceiver()) {
- rec = rec->IgnoreParenImpCasts();
- if (rec->getType().getObjCLifetime() == Qualifiers::OCL_ExplicitNone &&
- (E->getMethodFamily() != OMF_retain || isRemovable(E))) {
- std::string err = "it is not safe to remove '";
- err += E->getSelector().getAsString() + "' message on "
- "an __unsafe_unretained type";
- Pass.TA.reportError(err, rec->getBeginLoc());
- return true;
- }
-
- if (isGlobalVar(rec) &&
- (E->getMethodFamily() != OMF_retain || isRemovable(E))) {
- std::string err = "it is not safe to remove '";
- err += E->getSelector().getAsString() + "' message on "
- "a global variable";
- Pass.TA.reportError(err, rec->getBeginLoc());
- return true;
- }
-
- if (E->getMethodFamily() == OMF_release && isDelegateMessage(rec)) {
- Pass.TA.reportError(
- "it is not safe to remove 'retain' "
- "message on the result of a 'delegate' message; "
- "the object that was passed to 'setDelegate:' may not be "
- "properly retained",
- rec->getBeginLoc());
- return true;
- }
- }
- break;
- case OMF_dealloc:
- break;
- }
-
- switch (E->getReceiverKind()) {
- default:
- return true;
- case ObjCMessageExpr::SuperInstance: {
- Transaction Trans(Pass.TA);
- clearDiagnostics(E->getSelectorLoc(0));
- if (tryRemoving(E))
- return true;
- Pass.TA.replace(E->getSourceRange(), "self");
- return true;
- }
- case ObjCMessageExpr::Instance:
- break;
- }
-
- Expr *rec = E->getInstanceReceiver();
- if (!rec) return true;
-
- Transaction Trans(Pass.TA);
- clearDiagnostics(E->getSelectorLoc(0));
-
- ObjCMessageExpr *Msg = E;
- Expr *RecContainer = Msg;
- SourceRange RecRange = rec->getSourceRange();
- checkForGCDOrXPC(Msg, RecContainer, rec, RecRange);
-
- if (Msg->getMethodFamily() == OMF_release &&
- isRemovable(RecContainer) && isInAtFinally(RecContainer)) {
- // Change the -release to "receiver = nil" in a finally to avoid a leak
- // when an exception is thrown.
- Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
- std::string str = " = ";
- str += getNilString(Pass);
- Pass.TA.insertAfterToken(RecRange.getEnd(), str);
- return true;
- }
-
- if (hasSideEffects(rec, Pass.Ctx) || !tryRemoving(RecContainer))
- Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
-
- return true;
- }
-
-private:
- /// Checks for idioms where an unused -autorelease is common.
- ///
- /// Returns true for this idiom which is common in property
- /// setters:
- ///
- /// [backingValue autorelease];
- /// backingValue = [newValue retain]; // in general a +1 assign
- ///
- /// For these as well:
- ///
- /// [[var retain] autorelease];
- /// return var;
- ///
- bool isCommonUnusedAutorelease(ObjCMessageExpr *E) {
- return isPlusOneAssignBeforeOrAfterAutorelease(E) ||
- isReturnedAfterAutorelease(E);
- }
-
- bool isReturnedAfterAutorelease(ObjCMessageExpr *E) {
- Expr *Rec = E->getInstanceReceiver();
- if (!Rec)
- return false;
-
- Decl *RefD = getReferencedDecl(Rec);
- if (!RefD)
- return false;
-
- Stmt *nextStmt = getNextStmt(E);
- if (!nextStmt)
- return false;
-
- // Check for "return <variable>;".
-
- if (ReturnStmt *RetS = dyn_cast<ReturnStmt>(nextStmt))
- return RefD == getReferencedDecl(RetS->getRetValue());
-
- return false;
- }
-
- bool isPlusOneAssignBeforeOrAfterAutorelease(ObjCMessageExpr *E) {
- Expr *Rec = E->getInstanceReceiver();
- if (!Rec)
- return false;
-
- Decl *RefD = getReferencedDecl(Rec);
- if (!RefD)
- return false;
-
- Stmt *prevStmt, *nextStmt;
- std::tie(prevStmt, nextStmt) = getPreviousAndNextStmt(E);
-
- return isPlusOneAssignToVar(prevStmt, RefD) ||
- isPlusOneAssignToVar(nextStmt, RefD);
- }
-
- bool isPlusOneAssignToVar(Stmt *S, Decl *RefD) {
- if (!S)
- return false;
-
- // Check for "RefD = [+1 retained object];".
-
- if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(S)) {
- return (RefD == getReferencedDecl(Bop->getLHS())) && isPlusOneAssign(Bop);
- }
-
- if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
- if (DS->isSingleDecl() && DS->getSingleDecl() == RefD) {
- if (VarDecl *VD = dyn_cast<VarDecl>(RefD))
- return isPlusOne(VD->getInit());
- }
- return false;
- }
-
- return false;
- }
-
- Stmt *getNextStmt(Expr *E) {
- return getPreviousAndNextStmt(E).second;
- }
-
- std::pair<Stmt *, Stmt *> getPreviousAndNextStmt(Expr *E) {
- Stmt *prevStmt = nullptr, *nextStmt = nullptr;
- if (!E)
- return std::make_pair(prevStmt, nextStmt);
-
- Stmt *OuterS = E, *InnerS;
- do {
- InnerS = OuterS;
- OuterS = StmtMap->getParent(InnerS);
- }
- while (OuterS && (isa<ParenExpr>(OuterS) ||
- isa<CastExpr>(OuterS) ||
- isa<FullExpr>(OuterS)));
-
- if (!OuterS)
- return std::make_pair(prevStmt, nextStmt);
-
- Stmt::child_iterator currChildS = OuterS->child_begin();
- Stmt::child_iterator childE = OuterS->child_end();
- Stmt::child_iterator prevChildS = childE;
- for (; currChildS != childE; ++currChildS) {
- if (*currChildS == InnerS)
- break;
- prevChildS = currChildS;
- }
-
- if (prevChildS != childE) {
- prevStmt = *prevChildS;
- if (auto *E = dyn_cast_or_null<Expr>(prevStmt))
- prevStmt = E->IgnoreImplicit();
- }
-
- if (currChildS == childE)
- return std::make_pair(prevStmt, nextStmt);
- ++currChildS;
- if (currChildS == childE)
- return std::make_pair(prevStmt, nextStmt);
-
- nextStmt = *currChildS;
- if (auto *E = dyn_cast_or_null<Expr>(nextStmt))
- nextStmt = E->IgnoreImplicit();
-
- return std::make_pair(prevStmt, nextStmt);
- }
-
- Decl *getReferencedDecl(Expr *E) {
- if (!E)
- return nullptr;
-
- E = E->IgnoreParenCasts();
- if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
- switch (ME->getMethodFamily()) {
- case OMF_copy:
- case OMF_autorelease:
- case OMF_release:
- case OMF_retain:
- return getReferencedDecl(ME->getInstanceReceiver());
- default:
- return nullptr;
- }
- }
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- return DRE->getDecl();
- if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
- return ME->getMemberDecl();
- if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(E))
- return IRE->getDecl();
-
- return nullptr;
- }
-
- /// Check if the retain/release is due to a GCD/XPC macro that are
- /// defined as:
- ///
- /// #define dispatch_retain(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); (void)[_o retain]; })
- /// #define dispatch_release(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); [_o release]; })
- /// #define xpc_retain(object) ({ xpc_object_t _o = (object); _xpc_object_validate(_o); [_o retain]; })
- /// #define xpc_release(object) ({ xpc_object_t _o = (object); _xpc_object_validate(_o); [_o release]; })
- ///
- /// and return the top container which is the StmtExpr and the macro argument
- /// expression.
- void checkForGCDOrXPC(ObjCMessageExpr *Msg, Expr *&RecContainer,
- Expr *&Rec, SourceRange &RecRange) {
- SourceLocation Loc = Msg->getExprLoc();
- if (!Loc.isMacroID())
- return;
- SourceManager &SM = Pass.Ctx.getSourceManager();
- StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM,
- Pass.Ctx.getLangOpts());
- bool isGCDOrXPC = llvm::StringSwitch<bool>(MacroName)
- .Case("dispatch_retain", true)
- .Case("dispatch_release", true)
- .Case("xpc_retain", true)
- .Case("xpc_release", true)
- .Default(false);
- if (!isGCDOrXPC)
- return;
-
- StmtExpr *StmtE = nullptr;
- Stmt *S = Msg;
- while (S) {
- if (StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
- StmtE = SE;
- break;
- }
- S = StmtMap->getParent(S);
- }
-
- if (!StmtE)
- return;
-
- Stmt::child_range StmtExprChild = StmtE->children();
- if (StmtExprChild.begin() == StmtExprChild.end())
- return;
- auto *CompS = dyn_cast_or_null<CompoundStmt>(*StmtExprChild.begin());
- if (!CompS)
- return;
-
- Stmt::child_range CompStmtChild = CompS->children();
- if (CompStmtChild.begin() == CompStmtChild.end())
- return;
- auto *DeclS = dyn_cast_or_null<DeclStmt>(*CompStmtChild.begin());
- if (!DeclS)
- return;
- if (!DeclS->isSingleDecl())
- return;
- VarDecl *VD = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl());
- if (!VD)
- return;
- Expr *Init = VD->getInit();
- if (!Init)
- return;
-
- RecContainer = StmtE;
- Rec = Init->IgnoreParenImpCasts();
- if (FullExpr *FE = dyn_cast<FullExpr>(Rec))
- Rec = FE->getSubExpr()->IgnoreParenImpCasts();
- RecRange = Rec->getSourceRange();
- if (SM.isMacroArgExpansion(RecRange.getBegin()))
- RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin()));
- if (SM.isMacroArgExpansion(RecRange.getEnd()))
- RecRange.setEnd(SM.getImmediateSpellingLoc(RecRange.getEnd()));
- }
-
- void clearDiagnostics(SourceLocation loc) const {
- Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
- diag::err_unavailable,
- diag::err_unavailable_message,
- loc);
- }
-
- bool isDelegateMessage(Expr *E) const {
- if (!E) return false;
-
- E = E->IgnoreParenCasts();
-
- // Also look through property-getter sugar.
- if (PseudoObjectExpr *pseudoOp = dyn_cast<PseudoObjectExpr>(E))
- E = pseudoOp->getResultExpr()->IgnoreImplicit();
-
- if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
- return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel);
-
- return false;
- }
-
- bool isInAtFinally(Expr *E) const {
- assert(E);
- Stmt *S = E;
- while (S) {
- if (isa<ObjCAtFinallyStmt>(S))
- return true;
- S = StmtMap->getParent(S);
- }
-
- return false;
- }
-
- bool isRemovable(Expr *E) const {
- return Removables.count(E);
- }
-
- bool tryRemoving(Expr *E) const {
- if (isRemovable(E)) {
- Pass.TA.removeStmt(E);
- return true;
- }
-
- Stmt *parent = StmtMap->getParent(E);
-
- if (ImplicitCastExpr *castE = dyn_cast_or_null<ImplicitCastExpr>(parent))
- return tryRemoving(castE);
-
- if (ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(parent))
- return tryRemoving(parenE);
-
- if (BinaryOperator *
- bopE = dyn_cast_or_null<BinaryOperator>(parent)) {
- if (bopE->getOpcode() == BO_Comma && bopE->getLHS() == E &&
- isRemovable(bopE)) {
- Pass.TA.replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange());
- return true;
- }
- }
-
- return false;
- }
-
-};
-
-} // anonymous namespace
-
-void trans::removeRetainReleaseDeallocFinalize(MigrationPass &pass) {
- BodyTransform<RetainReleaseDeallocRemover> trans(pass);
- trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
-}
diff --git a/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp b/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
deleted file mode 100644
index 7390ea17..0000000
--- a/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ /dev/null
@@ -1,466 +0,0 @@
-//===--- TransUnbridgedCasts.cpp - Transformations to ARC mode ------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// rewriteUnbridgedCasts:
-//
-// A cast of non-objc pointer to an objc one is checked. If the non-objc pointer
-// is from a file-level variable, __bridge cast is used to convert it.
-// For the result of a function call that we know is +1/+0,
-// __bridge/CFBridgingRelease is used.
-//
-// NSString *str = (NSString *)kUTTypePlainText;
-// str = b ? kUTTypeRTF : kUTTypePlainText;
-// NSString *_uuidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault,
-// _uuid);
-// ---->
-// NSString *str = (__bridge NSString *)kUTTypePlainText;
-// str = (__bridge NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
-// NSString *_uuidString = (NSString *)
-// CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, _uuid));
-//
-// For a C pointer to ObjC, for casting 'self', __bridge is used.
-//
-// CFStringRef str = (CFStringRef)self;
-// ---->
-// CFStringRef str = (__bridge CFStringRef)self;
-//
-// Uses of Block_copy/Block_release macros are rewritten:
-//
-// c = Block_copy(b);
-// Block_release(c);
-// ---->
-// c = [b copy];
-// <removed>
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "llvm/ADT/SmallString.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
- MigrationPass &Pass;
- IdentifierInfo *SelfII;
- std::unique_ptr<ParentMap> StmtMap;
- Decl *ParentD;
- Stmt *Body;
- mutable std::unique_ptr<ExprSet> Removables;
-
-public:
- UnbridgedCastRewriter(MigrationPass &pass)
- : Pass(pass), ParentD(nullptr), Body(nullptr) {
- SelfII = &Pass.Ctx.Idents.get("self");
- }
-
- void transformBody(Stmt *body, Decl *ParentD) {
- this->ParentD = ParentD;
- Body = body;
- StmtMap.reset(new ParentMap(body));
- TraverseStmt(body);
- }
-
- bool TraverseBlockDecl(BlockDecl *D) {
- // ParentMap does not enter into a BlockDecl to record its stmts, so use a
- // new UnbridgedCastRewriter to handle the block.
- UnbridgedCastRewriter(Pass).transformBody(D->getBody(), D);
- return true;
- }
-
- bool VisitCastExpr(CastExpr *E) {
- if (E->getCastKind() != CK_CPointerToObjCPointerCast &&
- E->getCastKind() != CK_BitCast &&
- E->getCastKind() != CK_AnyPointerToBlockPointerCast)
- return true;
-
- QualType castType = E->getType();
- Expr *castExpr = E->getSubExpr();
- QualType castExprType = castExpr->getType();
-
- if (castType->isObjCRetainableType() == castExprType->isObjCRetainableType())
- return true;
-
- bool exprRetainable = castExprType->isObjCIndirectLifetimeType();
- bool castRetainable = castType->isObjCIndirectLifetimeType();
- if (exprRetainable == castRetainable) return true;
-
- if (castExpr->isNullPointerConstant(Pass.Ctx,
- Expr::NPC_ValueDependentIsNull))
- return true;
-
- SourceLocation loc = castExpr->getExprLoc();
- if (loc.isValid() && Pass.Ctx.getSourceManager().isInSystemHeader(loc))
- return true;
-
- if (castType->isObjCRetainableType())
- transformNonObjCToObjCCast(E);
- else
- transformObjCToNonObjCCast(E);
-
- return true;
- }
-
-private:
- void transformNonObjCToObjCCast(CastExpr *E) {
- if (!E) return;
-
- // Global vars are assumed that are cast as unretained.
- if (isGlobalVar(E))
- if (E->getSubExpr()->getType()->isPointerType()) {
- castToObjCObject(E, /*retained=*/false);
- return;
- }
-
- // If the cast is directly over the result of a Core Foundation function
- // try to figure out whether it should be cast as retained or unretained.
- Expr *inner = E->IgnoreParenCasts();
- if (CallExpr *callE = dyn_cast<CallExpr>(inner)) {
- if (FunctionDecl *FD = callE->getDirectCallee()) {
- if (FD->hasAttr<CFReturnsRetainedAttr>()) {
- castToObjCObject(E, /*retained=*/true);
- return;
- }
- if (FD->hasAttr<CFReturnsNotRetainedAttr>()) {
- castToObjCObject(E, /*retained=*/false);
- return;
- }
- if (FD->isGlobal() &&
- FD->getIdentifier() &&
- ento::cocoa::isRefType(E->getSubExpr()->getType(), "CF",
- FD->getIdentifier()->getName())) {
- StringRef fname = FD->getIdentifier()->getName();
- if (fname.ends_with("Retain") || fname.contains("Create") ||
- fname.contains("Copy")) {
- // Do not migrate to couple of bridge transfer casts which
- // cancel each other out. Leave it unchanged so error gets user
- // attention instead.
- if (FD->getName() == "CFRetain" &&
- FD->getNumParams() == 1 &&
- FD->getParent()->isTranslationUnit() &&
- FD->isExternallyVisible()) {
- Expr *Arg = callE->getArg(0);
- if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
- const Expr *sub = ICE->getSubExpr();
- QualType T = sub->getType();
- if (T->isObjCObjectPointerType())
- return;
- }
- }
- castToObjCObject(E, /*retained=*/true);
- return;
- }
-
- if (fname.contains("Get")) {
- castToObjCObject(E, /*retained=*/false);
- return;
- }
- }
- }
- }
-
- // If returning an ivar or a member of an ivar from a +0 method, use
- // a __bridge cast.
- Expr *base = inner->IgnoreParenImpCasts();
- while (isa<MemberExpr>(base))
- base = cast<MemberExpr>(base)->getBase()->IgnoreParenImpCasts();
- if (isa<ObjCIvarRefExpr>(base) &&
- isa<ReturnStmt>(StmtMap->getParentIgnoreParenCasts(E))) {
- if (ObjCMethodDecl *method = dyn_cast_or_null<ObjCMethodDecl>(ParentD)) {
- if (!method->hasAttr<NSReturnsRetainedAttr>()) {
- castToObjCObject(E, /*retained=*/false);
- return;
- }
- }
- }
- }
-
- void castToObjCObject(CastExpr *E, bool retained) {
- rewriteToBridgedCast(E, retained ? OBC_BridgeTransfer : OBC_Bridge);
- }
-
- void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
- Transaction Trans(Pass.TA);
- rewriteToBridgedCast(E, Kind, Trans);
- }
-
- void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind,
- Transaction &Trans) {
- TransformActions &TA = Pass.TA;
-
- // We will remove the compiler diagnostic.
- if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
- diag::err_arc_cast_requires_bridge,
- E->getBeginLoc())) {
- Trans.abort();
- return;
- }
-
- StringRef bridge;
- switch(Kind) {
- case OBC_Bridge:
- bridge = "__bridge "; break;
- case OBC_BridgeTransfer:
- bridge = "__bridge_transfer "; break;
- case OBC_BridgeRetained:
- bridge = "__bridge_retained "; break;
- }
-
- TA.clearDiagnostic(diag::err_arc_mismatched_cast,
- diag::err_arc_cast_requires_bridge, E->getBeginLoc());
- if (Kind == OBC_Bridge || !Pass.CFBridgingFunctionsDefined()) {
- if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(E)) {
- TA.insertAfterToken(CCE->getLParenLoc(), bridge);
- } else {
- SourceLocation insertLoc = E->getSubExpr()->getBeginLoc();
- SmallString<128> newCast;
- newCast += '(';
- newCast += bridge;
- newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
- newCast += ')';
-
- if (isa<ParenExpr>(E->getSubExpr())) {
- TA.insert(insertLoc, newCast.str());
- } else {
- newCast += '(';
- TA.insert(insertLoc, newCast.str());
- TA.insertAfterToken(E->getEndLoc(), ")");
- }
- }
- } else {
- assert(Kind == OBC_BridgeTransfer || Kind == OBC_BridgeRetained);
- SmallString<32> BridgeCall;
-
- Expr *WrapE = E->getSubExpr();
- SourceLocation InsertLoc = WrapE->getBeginLoc();
-
- SourceManager &SM = Pass.Ctx.getSourceManager();
- char PrevChar = *SM.getCharacterData(InsertLoc.getLocWithOffset(-1));
- if (Lexer::isAsciiIdentifierContinueChar(PrevChar,
- Pass.Ctx.getLangOpts()))
- BridgeCall += ' ';
-
- if (Kind == OBC_BridgeTransfer)
- BridgeCall += "CFBridgingRelease";
- else
- BridgeCall += "CFBridgingRetain";
-
- if (isa<ParenExpr>(WrapE)) {
- TA.insert(InsertLoc, BridgeCall);
- } else {
- BridgeCall += '(';
- TA.insert(InsertLoc, BridgeCall);
- TA.insertAfterToken(WrapE->getEndLoc(), ")");
- }
- }
- }
-
- void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) {
- Transaction Trans(Pass.TA);
- Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange());
- rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
- }
-
- void getBlockMacroRanges(CastExpr *E, SourceRange &Outer, SourceRange &Inner) {
- SourceManager &SM = Pass.Ctx.getSourceManager();
- SourceLocation Loc = E->getExprLoc();
- assert(Loc.isMacroID());
- CharSourceRange MacroRange = SM.getImmediateExpansionRange(Loc);
- SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange();
- SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin());
- SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd());
-
- Outer = MacroRange.getAsRange();
- Inner = SourceRange(InnerBegin, InnerEnd);
- }
-
- void rewriteBlockCopyMacro(CastExpr *E) {
- SourceRange OuterRange, InnerRange;
- getBlockMacroRanges(E, OuterRange, InnerRange);
-
- Transaction Trans(Pass.TA);
- Pass.TA.replace(OuterRange, InnerRange);
- Pass.TA.insert(InnerRange.getBegin(), "[");
- Pass.TA.insertAfterToken(InnerRange.getEnd(), " copy]");
- Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
- diag::err_arc_cast_requires_bridge,
- OuterRange);
- }
-
- void removeBlockReleaseMacro(CastExpr *E) {
- SourceRange OuterRange, InnerRange;
- getBlockMacroRanges(E, OuterRange, InnerRange);
-
- Transaction Trans(Pass.TA);
- Pass.TA.clearDiagnostic(diag::err_arc_mismatched_cast,
- diag::err_arc_cast_requires_bridge,
- OuterRange);
- if (!hasSideEffects(E, Pass.Ctx)) {
- if (tryRemoving(cast<Expr>(StmtMap->getParentIgnoreParenCasts(E))))
- return;
- }
- Pass.TA.replace(OuterRange, InnerRange);
- }
-
- bool tryRemoving(Expr *E) const {
- if (!Removables) {
- Removables.reset(new ExprSet);
- collectRemovables(Body, *Removables);
- }
-
- if (Removables->count(E)) {
- Pass.TA.removeStmt(E);
- return true;
- }
-
- return false;
- }
-
- void transformObjCToNonObjCCast(CastExpr *E) {
- SourceLocation CastLoc = E->getExprLoc();
- if (CastLoc.isMacroID()) {
- StringRef MacroName = Lexer::getImmediateMacroName(CastLoc,
- Pass.Ctx.getSourceManager(),
- Pass.Ctx.getLangOpts());
- if (MacroName == "Block_copy") {
- rewriteBlockCopyMacro(E);
- return;
- }
- if (MacroName == "Block_release") {
- removeBlockReleaseMacro(E);
- return;
- }
- }
-
- if (isSelf(E->getSubExpr()))
- return rewriteToBridgedCast(E, OBC_Bridge);
-
- CallExpr *callE;
- if (isPassedToCFRetain(E, callE))
- return rewriteCastForCFRetain(E, callE);
-
- ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr());
- if (family == OMF_retain)
- return rewriteToBridgedCast(E, OBC_BridgeRetained);
-
- if (family == OMF_autorelease || family == OMF_release) {
- std::string err = "it is not safe to cast to '";
- err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
- err += "' the result of '";
- err += family == OMF_autorelease ? "autorelease" : "release";
- err += "' message; a __bridge cast may result in a pointer to a "
- "destroyed object and a __bridge_retained may leak the object";
- Pass.TA.reportError(err, E->getBeginLoc(),
- E->getSubExpr()->getSourceRange());
- Stmt *parent = E;
- do {
- parent = StmtMap->getParentIgnoreParenImpCasts(parent);
- } while (isa_and_nonnull<FullExpr>(parent));
-
- if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
- std::string note = "remove the cast and change return type of function "
- "to '";
- note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
- note += "' to have the object automatically autoreleased";
- Pass.TA.reportNote(note, retS->getBeginLoc());
- }
- }
-
- Expr *subExpr = E->getSubExpr();
-
- // Look through pseudo-object expressions.
- if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
- subExpr = pseudo->getResultExpr();
- assert(subExpr && "no result for pseudo-object of non-void type?");
- }
-
- if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
- if (implCE->getCastKind() == CK_ARCConsumeObject)
- return rewriteToBridgedCast(E, OBC_BridgeRetained);
- if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
- return rewriteToBridgedCast(E, OBC_Bridge);
- }
-
- bool isConsumed = false;
- if (isPassedToCParamWithKnownOwnership(E, isConsumed))
- return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
- : OBC_Bridge);
- }
-
- static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
- E = E->IgnoreParenCasts();
- if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
- return ME->getMethodFamily();
-
- return OMF_None;
- }
-
- bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const {
- if ((callE = dyn_cast_or_null<CallExpr>(
- StmtMap->getParentIgnoreParenImpCasts(E))))
- if (FunctionDecl *
- FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
- if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
- FD->getParent()->isTranslationUnit() &&
- FD->isExternallyVisible())
- return true;
-
- return false;
- }
-
- bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
- if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
- StmtMap->getParentIgnoreParenImpCasts(E)))
- if (FunctionDecl *
- FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
- unsigned i = 0;
- for (unsigned e = callE->getNumArgs(); i != e; ++i) {
- Expr *arg = callE->getArg(i);
- if (arg == E || arg->IgnoreParenImpCasts() == E)
- break;
- }
- if (i < callE->getNumArgs() && i < FD->getNumParams()) {
- ParmVarDecl *PD = FD->getParamDecl(i);
- if (PD->hasAttr<CFConsumedAttr>()) {
- isConsumed = true;
- return true;
- }
- }
- }
-
- return false;
- }
-
- bool isSelf(Expr *E) const {
- E = E->IgnoreParenLValueCasts();
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
- if (IPD->getIdentifier() == SelfII)
- return true;
-
- return false;
- }
-};
-
-} // end anonymous namespace
-
-void trans::rewriteUnbridgedCasts(MigrationPass &pass) {
- BodyTransform<UnbridgedCastRewriter> trans(pass);
- trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
-}
diff --git a/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp b/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp
deleted file mode 100644
index bac8dfa..0000000
--- a/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//===--- TransUnusedInitDelegate.cpp - Transformations to ARC mode --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// Transformations:
-//===----------------------------------------------------------------------===//
-//
-// rewriteUnusedInitDelegate:
-//
-// Rewrites an unused result of calling a delegate initialization, to assigning
-// the result to self.
-// e.g
-// [self init];
-// ---->
-// self = [self init];
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Sema/SemaDiagnostic.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class UnusedInitRewriter : public RecursiveASTVisitor<UnusedInitRewriter> {
- Stmt *Body;
- MigrationPass &Pass;
-
- ExprSet Removables;
-
-public:
- UnusedInitRewriter(MigrationPass &pass)
- : Body(nullptr), Pass(pass) { }
-
- void transformBody(Stmt *body, Decl *ParentD) {
- Body = body;
- collectRemovables(body, Removables);
- TraverseStmt(body);
- }
-
- bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
- if (ME->isDelegateInitCall() &&
- isRemovable(ME) &&
- Pass.TA.hasDiagnostic(diag::err_arc_unused_init_message,
- ME->getExprLoc())) {
- Transaction Trans(Pass.TA);
- Pass.TA.clearDiagnostic(diag::err_arc_unused_init_message,
- ME->getExprLoc());
- SourceRange ExprRange = ME->getSourceRange();
- Pass.TA.insert(ExprRange.getBegin(), "if (!(self = ");
- std::string retStr = ")) return ";
- retStr += getNilString(Pass);
- Pass.TA.insertAfterToken(ExprRange.getEnd(), retStr);
- }
- return true;
- }
-
-private:
- bool isRemovable(Expr *E) const {
- return Removables.count(E);
- }
-};
-
-} // anonymous namespace
-
-void trans::rewriteUnusedInitDelegate(MigrationPass &pass) {
- BodyTransform<UnusedInitRewriter> trans(pass);
- trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
-}
diff --git a/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
deleted file mode 100644
index 81e6762..0000000
--- a/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-//===--- TransZeroOutPropsInDealloc.cpp - Transformations to ARC mode -----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// removeZeroOutPropsInDealloc:
-//
-// Removes zero'ing out "strong" @synthesized properties in a -dealloc method.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-namespace {
-
-class ZeroOutInDeallocRemover :
- public RecursiveASTVisitor<ZeroOutInDeallocRemover> {
- typedef RecursiveASTVisitor<ZeroOutInDeallocRemover> base;
-
- MigrationPass &Pass;
-
- llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*> SynthesizedProperties;
- ImplicitParamDecl *SelfD;
- ExprSet Removables;
- Selector FinalizeSel;
-
-public:
- ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(nullptr) {
- FinalizeSel =
- Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
- }
-
- bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
- ASTContext &Ctx = Pass.Ctx;
- TransformActions &TA = Pass.TA;
-
- if (ME->getReceiverKind() != ObjCMessageExpr::Instance)
- return true;
- Expr *receiver = ME->getInstanceReceiver();
- if (!receiver)
- return true;
-
- DeclRefExpr *refE = dyn_cast<DeclRefExpr>(receiver->IgnoreParenCasts());
- if (!refE || refE->getDecl() != SelfD)
- return true;
-
- bool BackedBySynthesizeSetter = false;
- for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
- P = SynthesizedProperties.begin(),
- E = SynthesizedProperties.end(); P != E; ++P) {
- ObjCPropertyDecl *PropDecl = P->first;
- if (PropDecl->getSetterName() == ME->getSelector()) {
- BackedBySynthesizeSetter = true;
- break;
- }
- }
- if (!BackedBySynthesizeSetter)
- return true;
-
- // Remove the setter message if RHS is null
- Transaction Trans(TA);
- Expr *RHS = ME->getArg(0);
- bool RHSIsNull =
- RHS->isNullPointerConstant(Ctx,
- Expr::NPC_ValueDependentIsNull);
- if (RHSIsNull && isRemovable(ME))
- TA.removeStmt(ME);
-
- return true;
- }
-
- bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
- if (isZeroingPropIvar(POE) && isRemovable(POE)) {
- Transaction Trans(Pass.TA);
- Pass.TA.removeStmt(POE);
- }
-
- return true;
- }
-
- bool VisitBinaryOperator(BinaryOperator *BOE) {
- if (isZeroingPropIvar(BOE) && isRemovable(BOE)) {
- Transaction Trans(Pass.TA);
- Pass.TA.removeStmt(BOE);
- }
-
- return true;
- }
-
- bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
- if (D->getMethodFamily() != OMF_dealloc &&
- !(D->isInstanceMethod() && D->getSelector() == FinalizeSel))
- return true;
- if (!D->hasBody())
- return true;
-
- ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(D->getDeclContext());
- if (!IMD)
- return true;
-
- SelfD = D->getSelfDecl();
- collectRemovables(D->getBody(), Removables);
-
- // For a 'dealloc' method use, find all property implementations in
- // this class implementation.
- for (auto *PID : IMD->property_impls()) {
- if (PID->getPropertyImplementation() ==
- ObjCPropertyImplDecl::Synthesize) {
- ObjCPropertyDecl *PD = PID->getPropertyDecl();
- ObjCMethodDecl *setterM = PD->getSetterMethodDecl();
- if (!(setterM && setterM->isDefined())) {
- ObjCPropertyAttribute::Kind AttrKind = PD->getPropertyAttributes();
- if (AttrKind & (ObjCPropertyAttribute::kind_retain |
- ObjCPropertyAttribute::kind_copy |
- ObjCPropertyAttribute::kind_strong))
- SynthesizedProperties[PD] = PID;
- }
- }
- }
-
- // Now, remove all zeroing of ivars etc.
- base::TraverseObjCMethodDecl(D);
-
- // clear out for next method.
- SynthesizedProperties.clear();
- SelfD = nullptr;
- Removables.clear();
- return true;
- }
-
- bool TraverseFunctionDecl(FunctionDecl *D) { return true; }
- bool TraverseBlockDecl(BlockDecl *block) { return true; }
- bool TraverseBlockExpr(BlockExpr *block) { return true; }
-
-private:
- bool isRemovable(Expr *E) const {
- return Removables.count(E);
- }
-
- bool isZeroingPropIvar(Expr *E) {
- E = E->IgnoreParens();
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E))
- return isZeroingPropIvar(BO);
- if (PseudoObjectExpr *PO = dyn_cast<PseudoObjectExpr>(E))
- return isZeroingPropIvar(PO);
- return false;
- }
-
- bool isZeroingPropIvar(BinaryOperator *BOE) {
- if (BOE->getOpcode() == BO_Comma)
- return isZeroingPropIvar(BOE->getLHS()) &&
- isZeroingPropIvar(BOE->getRHS());
-
- if (BOE->getOpcode() != BO_Assign)
- return false;
-
- Expr *LHS = BOE->getLHS();
- if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(LHS)) {
- ObjCIvarDecl *IVDecl = IV->getDecl();
- if (!IVDecl->getType()->isObjCObjectPointerType())
- return false;
- bool IvarBacksPropertySynthesis = false;
- for (llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*>::iterator
- P = SynthesizedProperties.begin(),
- E = SynthesizedProperties.end(); P != E; ++P) {
- ObjCPropertyImplDecl *PropImpDecl = P->second;
- if (PropImpDecl && PropImpDecl->getPropertyIvarDecl() == IVDecl) {
- IvarBacksPropertySynthesis = true;
- break;
- }
- }
- if (!IvarBacksPropertySynthesis)
- return false;
- }
- else
- return false;
-
- return isZero(BOE->getRHS());
- }
-
- bool isZeroingPropIvar(PseudoObjectExpr *PO) {
- BinaryOperator *BO = dyn_cast<BinaryOperator>(PO->getSyntacticForm());
- if (!BO) return false;
- if (BO->getOpcode() != BO_Assign) return false;
-
- ObjCPropertyRefExpr *PropRefExp =
- dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParens());
- if (!PropRefExp) return false;
-
- // TODO: Using implicit property decl.
- if (PropRefExp->isImplicitProperty())
- return false;
-
- if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {
- if (!SynthesizedProperties.count(PDecl))
- return false;
- }
-
- return isZero(cast<OpaqueValueExpr>(BO->getRHS())->getSourceExpr());
- }
-
- bool isZero(Expr *E) {
- if (E->isNullPointerConstant(Pass.Ctx, Expr::NPC_ValueDependentIsNull))
- return true;
-
- return isZeroingPropIvar(E);
- }
-};
-
-} // anonymous namespace
-
-void trans::removeZeroOutPropsInDeallocFinalize(MigrationPass &pass) {
- ZeroOutInDeallocRemover trans(pass);
- trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
-}
diff --git a/clang/lib/ARCMigrate/TransformActions.cpp b/clang/lib/ARCMigrate/TransformActions.cpp
deleted file mode 100644
index 6bc6fed..0000000
--- a/clang/lib/ARCMigrate/TransformActions.cpp
+++ /dev/null
@@ -1,700 +0,0 @@
-//===-- TransformActions.cpp - Migration to ARC mode ----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Internals.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/DenseSet.h"
-#include <map>
-using namespace clang;
-using namespace arcmt;
-
-namespace {
-
-/// Collects transformations and merges them before applying them with
-/// with applyRewrites(). E.g. if the same source range
-/// is requested to be removed twice, only one rewriter remove will be invoked.
-/// Rewrites happen in "transactions"; if one rewrite in the transaction cannot
-/// be done (e.g. it resides in a macro) all rewrites in the transaction are
-/// aborted.
-/// FIXME: "Transactional" rewrites support should be baked in the Rewriter.
-class TransformActionsImpl {
- CapturedDiagList &CapturedDiags;
- ASTContext &Ctx;
- Preprocessor &PP;
-
- bool IsInTransaction;
-
- enum ActionKind {
- Act_Insert, Act_InsertAfterToken,
- Act_Remove, Act_RemoveStmt,
- Act_Replace, Act_ReplaceText,
- Act_IncreaseIndentation,
- Act_ClearDiagnostic
- };
-
- struct ActionData {
- ActionKind Kind;
- SourceLocation Loc;
- SourceRange R1, R2;
- StringRef Text1, Text2;
- Stmt *S;
- SmallVector<unsigned, 2> DiagIDs;
- };
-
- std::vector<ActionData> CachedActions;
-
- enum RangeComparison {
- Range_Before,
- Range_After,
- Range_Contains,
- Range_Contained,
- Range_ExtendsBegin,
- Range_ExtendsEnd
- };
-
- /// A range to remove. It is a character range.
- struct CharRange {
- FullSourceLoc Begin, End;
-
- CharRange(CharSourceRange range, SourceManager &srcMgr, Preprocessor &PP) {
- SourceLocation beginLoc = range.getBegin(), endLoc = range.getEnd();
- assert(beginLoc.isValid() && endLoc.isValid());
- if (range.isTokenRange()) {
- Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
- End = FullSourceLoc(getLocForEndOfToken(endLoc, srcMgr, PP), srcMgr);
- } else {
- Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
- End = FullSourceLoc(srcMgr.getExpansionLoc(endLoc), srcMgr);
- }
- assert(Begin.isValid() && End.isValid());
- }
-
- RangeComparison compareWith(const CharRange &RHS) const {
- if (End.isBeforeInTranslationUnitThan(RHS.Begin))
- return Range_Before;
- if (RHS.End.isBeforeInTranslationUnitThan(Begin))
- return Range_After;
- if (!Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
- !RHS.End.isBeforeInTranslationUnitThan(End))
- return Range_Contained;
- if (Begin.isBeforeInTranslationUnitThan(RHS.Begin) &&
- RHS.End.isBeforeInTranslationUnitThan(End))
- return Range_Contains;
- if (Begin.isBeforeInTranslationUnitThan(RHS.Begin))
- return Range_ExtendsBegin;
- else
- return Range_ExtendsEnd;
- }
-
- static RangeComparison compare(SourceRange LHS, SourceRange RHS,
- SourceManager &SrcMgr, Preprocessor &PP) {
- return CharRange(CharSourceRange::getTokenRange(LHS), SrcMgr, PP)
- .compareWith(CharRange(CharSourceRange::getTokenRange(RHS),
- SrcMgr, PP));
- }
- };
-
- typedef SmallVector<StringRef, 2> TextsVec;
- typedef std::map<FullSourceLoc, TextsVec, FullSourceLoc::BeforeThanCompare>
- InsertsMap;
- InsertsMap Inserts;
- /// A list of ranges to remove. They are always sorted and they never
- /// intersect with each other.
- std::list<CharRange> Removals;
-
- llvm::DenseSet<Stmt *> StmtRemovals;
-
- std::vector<std::pair<CharRange, SourceLocation> > IndentationRanges;
-
- /// Keeps text passed to transformation methods.
- llvm::StringMap<bool> UniqueText;
-
-public:
- TransformActionsImpl(CapturedDiagList &capturedDiags,
- ASTContext &ctx, Preprocessor &PP)
- : CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { }
-
- ASTContext &getASTContext() { return Ctx; }
-
- void startTransaction();
- bool commitTransaction();
- void abortTransaction();
-
- bool isInTransaction() const { return IsInTransaction; }
-
- void insert(SourceLocation loc, StringRef text);
- void insertAfterToken(SourceLocation loc, StringRef text);
- void remove(SourceRange range);
- void removeStmt(Stmt *S);
- void replace(SourceRange range, StringRef text);
- void replace(SourceRange range, SourceRange replacementRange);
- void replaceStmt(Stmt *S, StringRef text);
- void replaceText(SourceLocation loc, StringRef text,
- StringRef replacementText);
- void increaseIndentation(SourceRange range,
- SourceLocation parentIndent);
-
- bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
-
- void applyRewrites(TransformActions::RewriteReceiver &receiver);
-
-private:
- bool canInsert(SourceLocation loc);
- bool canInsertAfterToken(SourceLocation loc);
- bool canRemoveRange(SourceRange range);
- bool canReplaceRange(SourceRange range, SourceRange replacementRange);
- bool canReplaceText(SourceLocation loc, StringRef text);
-
- void commitInsert(SourceLocation loc, StringRef text);
- void commitInsertAfterToken(SourceLocation loc, StringRef text);
- void commitRemove(SourceRange range);
- void commitRemoveStmt(Stmt *S);
- void commitReplace(SourceRange range, SourceRange replacementRange);
- void commitReplaceText(SourceLocation loc, StringRef text,
- StringRef replacementText);
- void commitIncreaseIndentation(SourceRange range,SourceLocation parentIndent);
- void commitClearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
-
- void addRemoval(CharSourceRange range);
- void addInsertion(SourceLocation loc, StringRef text);
-
- /// Stores text passed to the transformation methods to keep the string
- /// "alive". Since the vast majority of text will be the same, we also unique
- /// the strings using a StringMap.
- StringRef getUniqueText(StringRef text);
-
- /// Computes the source location just past the end of the token at
- /// the given source location. If the location points at a macro, the whole
- /// macro expansion is skipped.
- static SourceLocation getLocForEndOfToken(SourceLocation loc,
- SourceManager &SM,Preprocessor &PP);
-};
-
-} // anonymous namespace
-
-void TransformActionsImpl::startTransaction() {
- assert(!IsInTransaction &&
- "Cannot start a transaction in the middle of another one");
- IsInTransaction = true;
-}
-
-bool TransformActionsImpl::commitTransaction() {
- assert(IsInTransaction && "No transaction started");
-
- if (CachedActions.empty()) {
- IsInTransaction = false;
- return false;
- }
-
- // Verify that all actions are possible otherwise abort the whole transaction.
- bool AllActionsPossible = true;
- for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
- ActionData &act = CachedActions[i];
- switch (act.Kind) {
- case Act_Insert:
- if (!canInsert(act.Loc))
- AllActionsPossible = false;
- break;
- case Act_InsertAfterToken:
- if (!canInsertAfterToken(act.Loc))
- AllActionsPossible = false;
- break;
- case Act_Remove:
- if (!canRemoveRange(act.R1))
- AllActionsPossible = false;
- break;
- case Act_RemoveStmt:
- assert(act.S);
- if (!canRemoveRange(act.S->getSourceRange()))
- AllActionsPossible = false;
- break;
- case Act_Replace:
- if (!canReplaceRange(act.R1, act.R2))
- AllActionsPossible = false;
- break;
- case Act_ReplaceText:
- if (!canReplaceText(act.Loc, act.Text1))
- AllActionsPossible = false;
- break;
- case Act_IncreaseIndentation:
- // This is not important, we don't care if it will fail.
- break;
- case Act_ClearDiagnostic:
- // We are just checking source rewrites.
- break;
- }
- if (!AllActionsPossible)
- break;
- }
-
- if (!AllActionsPossible) {
- abortTransaction();
- return true;
- }
-
- for (unsigned i = 0, e = CachedActions.size(); i != e; ++i) {
- ActionData &act = CachedActions[i];
- switch (act.Kind) {
- case Act_Insert:
- commitInsert(act.Loc, act.Text1);
- break;
- case Act_InsertAfterToken:
- commitInsertAfterToken(act.Loc, act.Text1);
- break;
- case Act_Remove:
- commitRemove(act.R1);
- break;
- case Act_RemoveStmt:
- commitRemoveStmt(act.S);
- break;
- case Act_Replace:
- commitReplace(act.R1, act.R2);
- break;
- case Act_ReplaceText:
- commitReplaceText(act.Loc, act.Text1, act.Text2);
- break;
- case Act_IncreaseIndentation:
- commitIncreaseIndentation(act.R1, act.Loc);
- break;
- case Act_ClearDiagnostic:
- commitClearDiagnostic(act.DiagIDs, act.R1);
- break;
- }
- }
-
- CachedActions.clear();
- IsInTransaction = false;
- return false;
-}
-
-void TransformActionsImpl::abortTransaction() {
- assert(IsInTransaction && "No transaction started");
- CachedActions.clear();
- IsInTransaction = false;
-}
-
-void TransformActionsImpl::insert(SourceLocation loc, StringRef text) {
- assert(IsInTransaction && "Actions only allowed during a transaction");
- text = getUniqueText(text);
- ActionData data;
- data.Kind = Act_Insert;
- data.Loc = loc;
- data.Text1 = text;
- CachedActions.push_back(data);
-}
-
-void TransformActionsImpl::insertAfterToken(SourceLocation loc, StringRef text) {
- assert(IsInTransaction && "Actions only allowed during a transaction");
- text = getUniqueText(text);
- ActionData data;
- data.Kind = Act_InsertAfterToken;
- data.Loc = loc;
- data.Text1 = text;
- CachedActions.push_back(data);
-}
-
-void TransformActionsImpl::remove(SourceRange range) {
- assert(IsInTransaction && "Actions only allowed during a transaction");
- ActionData data;
- data.Kind = Act_Remove;
- data.R1 = range;
- CachedActions.push_back(data);
-}
-
-void TransformActionsImpl::removeStmt(Stmt *S) {
- assert(IsInTransaction && "Actions only allowed during a transaction");
- ActionData data;
- data.Kind = Act_RemoveStmt;
- if (auto *E = dyn_cast<Expr>(S))
- S = E->IgnoreImplicit(); // important for uniquing
- data.S = S;
- CachedActions.push_back(data);
-}
-
-void TransformActionsImpl::replace(SourceRange range, StringRef text) {
- assert(IsInTransaction && "Actions only allowed during a transaction");
- text = getUniqueText(text);
- remove(range);
- insert(range.getBegin(), text);
-}
-
-void TransformActionsImpl::replace(SourceRange range,
- SourceRange replacementRange) {
- assert(IsInTransaction && "Actions only allowed during a transaction");
- ActionData data;
- data.Kind = Act_Replace;
- data.R1 = range;
- data.R2 = replacementRange;
- CachedActions.push_back(data);
-}
-
-void TransformActionsImpl::replaceText(SourceLocation loc, StringRef text,
- StringRef replacementText) {
- text = getUniqueText(text);
- replacementText = getUniqueText(replacementText);
- ActionData data;
- data.Kind = Act_ReplaceText;
- data.Loc = loc;
- data.Text1 = text;
- data.Text2 = replacementText;
- CachedActions.push_back(data);
-}
-
-void TransformActionsImpl::replaceStmt(Stmt *S, StringRef text) {
- assert(IsInTransaction && "Actions only allowed during a transaction");
- text = getUniqueText(text);
- insert(S->getBeginLoc(), text);
- removeStmt(S);
-}
-
-void TransformActionsImpl::increaseIndentation(SourceRange range,
- SourceLocation parentIndent) {
- if (range.isInvalid()) return;
- assert(IsInTransaction && "Actions only allowed during a transaction");
- ActionData data;
- data.Kind = Act_IncreaseIndentation;
- data.R1 = range;
- data.Loc = parentIndent;
- CachedActions.push_back(data);
-}
-
-bool TransformActionsImpl::clearDiagnostic(ArrayRef<unsigned> IDs,
- SourceRange range) {
- assert(IsInTransaction && "Actions only allowed during a transaction");
- if (!CapturedDiags.hasDiagnostic(IDs, range))
- return false;
-
- ActionData data;
- data.Kind = Act_ClearDiagnostic;
- data.R1 = range;
- data.DiagIDs.append(IDs.begin(), IDs.end());
- CachedActions.push_back(data);
- return true;
-}
-
-bool TransformActionsImpl::canInsert(SourceLocation loc) {
- if (loc.isInvalid())
- return false;
-
- SourceManager &SM = Ctx.getSourceManager();
- if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
- return false;
-
- if (loc.isFileID())
- return true;
- return PP.isAtStartOfMacroExpansion(loc);
-}
-
-bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) {
- if (loc.isInvalid())
- return false;
-
- SourceManager &SM = Ctx.getSourceManager();
- if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
- return false;
-
- if (loc.isFileID())
- return true;
- return PP.isAtEndOfMacroExpansion(loc);
-}
-
-bool TransformActionsImpl::canRemoveRange(SourceRange range) {
- return canInsert(range.getBegin()) && canInsertAfterToken(range.getEnd());
-}
-
-bool TransformActionsImpl::canReplaceRange(SourceRange range,
- SourceRange replacementRange) {
- return canRemoveRange(range) && canRemoveRange(replacementRange);
-}
-
-bool TransformActionsImpl::canReplaceText(SourceLocation loc, StringRef text) {
- if (!canInsert(loc))
- return false;
-
- SourceManager &SM = Ctx.getSourceManager();
- loc = SM.getExpansionLoc(loc);
-
- // Break down the source location.
- std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
-
- // Try to load the file buffer.
- bool invalidTemp = false;
- StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
- if (invalidTemp)
- return false;
-
- return file.substr(locInfo.second).starts_with(text);
-}
-
-void TransformActionsImpl::commitInsert(SourceLocation loc, StringRef text) {
- addInsertion(loc, text);
-}
-
-void TransformActionsImpl::commitInsertAfterToken(SourceLocation loc,
- StringRef text) {
- addInsertion(getLocForEndOfToken(loc, Ctx.getSourceManager(), PP), text);
-}
-
-void TransformActionsImpl::commitRemove(SourceRange range) {
- addRemoval(CharSourceRange::getTokenRange(range));
-}
-
-void TransformActionsImpl::commitRemoveStmt(Stmt *S) {
- assert(S);
- if (StmtRemovals.count(S))
- return; // already removed.
-
- if (Expr *E = dyn_cast<Expr>(S)) {
- commitRemove(E->getSourceRange());
- commitInsert(E->getSourceRange().getBegin(), getARCMTMacroName());
- } else
- commitRemove(S->getSourceRange());
-
- StmtRemovals.insert(S);
-}
-
-void TransformActionsImpl::commitReplace(SourceRange range,
- SourceRange replacementRange) {
- RangeComparison comp = CharRange::compare(replacementRange, range,
- Ctx.getSourceManager(), PP);
- assert(comp == Range_Contained);
- if (comp != Range_Contained)
- return; // Although we asserted, be extra safe for release build.
- if (range.getBegin() != replacementRange.getBegin())
- addRemoval(CharSourceRange::getCharRange(range.getBegin(),
- replacementRange.getBegin()));
- if (replacementRange.getEnd() != range.getEnd())
- addRemoval(CharSourceRange::getTokenRange(
- getLocForEndOfToken(replacementRange.getEnd(),
- Ctx.getSourceManager(), PP),
- range.getEnd()));
-}
-void TransformActionsImpl::commitReplaceText(SourceLocation loc,
- StringRef text,
- StringRef replacementText) {
- SourceManager &SM = Ctx.getSourceManager();
- loc = SM.getExpansionLoc(loc);
- // canReplaceText already checked if loc points at text.
- SourceLocation afterText = loc.getLocWithOffset(text.size());
-
- addRemoval(CharSourceRange::getCharRange(loc, afterText));
- commitInsert(loc, replacementText);
-}
-
-void TransformActionsImpl::commitIncreaseIndentation(SourceRange range,
- SourceLocation parentIndent) {
- SourceManager &SM = Ctx.getSourceManager();
- IndentationRanges.push_back(
- std::make_pair(CharRange(CharSourceRange::getTokenRange(range),
- SM, PP),
- SM.getExpansionLoc(parentIndent)));
-}
-
-void TransformActionsImpl::commitClearDiagnostic(ArrayRef<unsigned> IDs,
- SourceRange range) {
- CapturedDiags.clearDiagnostic(IDs, range);
-}
-
-void TransformActionsImpl::addInsertion(SourceLocation loc, StringRef text) {
- SourceManager &SM = Ctx.getSourceManager();
- loc = SM.getExpansionLoc(loc);
- for (const CharRange &I : llvm::reverse(Removals)) {
- if (!SM.isBeforeInTranslationUnit(loc, I.End))
- break;
- if (I.Begin.isBeforeInTranslationUnitThan(loc))
- return;
- }
-
- Inserts[FullSourceLoc(loc, SM)].push_back(text);
-}
-
-void TransformActionsImpl::addRemoval(CharSourceRange range) {
- CharRange newRange(range, Ctx.getSourceManager(), PP);
- if (newRange.Begin == newRange.End)
- return;
-
- Inserts.erase(Inserts.upper_bound(newRange.Begin),
- Inserts.lower_bound(newRange.End));
-
- std::list<CharRange>::iterator I = Removals.end();
- while (I != Removals.begin()) {
- std::list<CharRange>::iterator RI = I;
- --RI;
- RangeComparison comp = newRange.compareWith(*RI);
- switch (comp) {
- case Range_Before:
- --I;
- break;
- case Range_After:
- Removals.insert(I, newRange);
- return;
- case Range_Contained:
- return;
- case Range_Contains:
- RI->End = newRange.End;
- [[fallthrough]];
- case Range_ExtendsBegin:
- newRange.End = RI->End;
- Removals.erase(RI);
- break;
- case Range_ExtendsEnd:
- RI->End = newRange.End;
- return;
- }
- }
-
- Removals.insert(Removals.begin(), newRange);
-}
-
-void TransformActionsImpl::applyRewrites(
- TransformActions::RewriteReceiver &receiver) {
- for (InsertsMap::iterator I = Inserts.begin(), E = Inserts.end(); I!=E; ++I) {
- SourceLocation loc = I->first;
- for (TextsVec::iterator
- TI = I->second.begin(), TE = I->second.end(); TI != TE; ++TI) {
- receiver.insert(loc, *TI);
- }
- }
-
- for (std::vector<std::pair<CharRange, SourceLocation> >::iterator
- I = IndentationRanges.begin(), E = IndentationRanges.end(); I!=E; ++I) {
- CharSourceRange range = CharSourceRange::getCharRange(I->first.Begin,
- I->first.End);
- receiver.increaseIndentation(range, I->second);
- }
-
- for (std::list<CharRange>::iterator
- I = Removals.begin(), E = Removals.end(); I != E; ++I) {
- CharSourceRange range = CharSourceRange::getCharRange(I->Begin, I->End);
- receiver.remove(range);
- }
-}
-
-/// Stores text passed to the transformation methods to keep the string
-/// "alive". Since the vast majority of text will be the same, we also unique
-/// the strings using a StringMap.
-StringRef TransformActionsImpl::getUniqueText(StringRef text) {
- return UniqueText.insert(std::make_pair(text, false)).first->first();
-}
-
-/// Computes the source location just past the end of the token at
-/// the given source location. If the location points at a macro, the whole
-/// macro expansion is skipped.
-SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
- SourceManager &SM,
- Preprocessor &PP) {
- if (loc.isMacroID()) {
- CharSourceRange Exp = SM.getExpansionRange(loc);
- if (Exp.isCharRange())
- return Exp.getEnd();
- loc = Exp.getEnd();
- }
- return PP.getLocForEndOfToken(loc);
-}
-
-TransformActions::RewriteReceiver::~RewriteReceiver() { }
-
-TransformActions::TransformActions(DiagnosticsEngine &diag,
- CapturedDiagList &capturedDiags,
- ASTContext &ctx, Preprocessor &PP)
- : Diags(diag), CapturedDiags(capturedDiags) {
- Impl = new TransformActionsImpl(capturedDiags, ctx, PP);
-}
-
-TransformActions::~TransformActions() {
- delete static_cast<TransformActionsImpl*>(Impl);
-}
-
-void TransformActions::startTransaction() {
- static_cast<TransformActionsImpl*>(Impl)->startTransaction();
-}
-
-bool TransformActions::commitTransaction() {
- return static_cast<TransformActionsImpl*>(Impl)->commitTransaction();
-}
-
-void TransformActions::abortTransaction() {
- static_cast<TransformActionsImpl*>(Impl)->abortTransaction();
-}
-
-
-void TransformActions::insert(SourceLocation loc, StringRef text) {
- static_cast<TransformActionsImpl*>(Impl)->insert(loc, text);
-}
-
-void TransformActions::insertAfterToken(SourceLocation loc,
- StringRef text) {
- static_cast<TransformActionsImpl*>(Impl)->insertAfterToken(loc, text);
-}
-
-void TransformActions::remove(SourceRange range) {
- static_cast<TransformActionsImpl*>(Impl)->remove(range);
-}
-
-void TransformActions::removeStmt(Stmt *S) {
- static_cast<TransformActionsImpl*>(Impl)->removeStmt(S);
-}
-
-void TransformActions::replace(SourceRange range, StringRef text) {
- static_cast<TransformActionsImpl*>(Impl)->replace(range, text);
-}
-
-void TransformActions::replace(SourceRange range,
- SourceRange replacementRange) {
- static_cast<TransformActionsImpl*>(Impl)->replace(range, replacementRange);
-}
-
-void TransformActions::replaceStmt(Stmt *S, StringRef text) {
- static_cast<TransformActionsImpl*>(Impl)->replaceStmt(S, text);
-}
-
-void TransformActions::replaceText(SourceLocation loc, StringRef text,
- StringRef replacementText) {
- static_cast<TransformActionsImpl*>(Impl)->replaceText(loc, text,
- replacementText);
-}
-
-void TransformActions::increaseIndentation(SourceRange range,
- SourceLocation parentIndent) {
- static_cast<TransformActionsImpl*>(Impl)->increaseIndentation(range,
- parentIndent);
-}
-
-bool TransformActions::clearDiagnostic(ArrayRef<unsigned> IDs,
- SourceRange range) {
- return static_cast<TransformActionsImpl*>(Impl)->clearDiagnostic(IDs, range);
-}
-
-void TransformActions::applyRewrites(RewriteReceiver &receiver) {
- static_cast<TransformActionsImpl*>(Impl)->applyRewrites(receiver);
-}
-
-DiagnosticBuilder TransformActions::report(SourceLocation loc, unsigned diagId,
- SourceRange range) {
- assert(!static_cast<TransformActionsImpl *>(Impl)->isInTransaction() &&
- "Errors should be emitted out of a transaction");
- return Diags.Report(loc, diagId) << range;
-}
-
-void TransformActions::reportError(StringRef message, SourceLocation loc,
- SourceRange range) {
- report(loc, diag::err_mt_message, range) << message;
-}
-
-void TransformActions::reportWarning(StringRef message, SourceLocation loc,
- SourceRange range) {
- report(loc, diag::warn_mt_message, range) << message;
-}
-
-void TransformActions::reportNote(StringRef message, SourceLocation loc,
- SourceRange range) {
- report(loc, diag::note_mt_message, range) << message;
-}
diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp
deleted file mode 100644
index fda0e1c..0000000
--- a/clang/lib/ARCMigrate/Transforms.cpp
+++ /dev/null
@@ -1,594 +0,0 @@
-//===--- Transforms.cpp - Transformations to ARC mode ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Transforms.h"
-#include "Internals.h"
-#include "clang/ARCMigrate/ARCMT.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaObjC.h"
-
-using namespace clang;
-using namespace arcmt;
-using namespace trans;
-
-ASTTraverser::~ASTTraverser() { }
-
-bool MigrationPass::CFBridgingFunctionsDefined() {
- if (!EnableCFBridgeFns)
- EnableCFBridgeFns = SemaRef.ObjC().isKnownName("CFBridgingRetain") &&
- SemaRef.ObjC().isKnownName("CFBridgingRelease");
- return *EnableCFBridgeFns;
-}
-
-//===----------------------------------------------------------------------===//
-// Helpers.
-//===----------------------------------------------------------------------===//
-
-bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
- bool AllowOnUnknownClass) {
- if (!Ctx.getLangOpts().ObjCWeakRuntime)
- return false;
-
- QualType T = type;
- if (T.isNull())
- return false;
-
- // iOS is always safe to use 'weak'.
- if (Ctx.getTargetInfo().getTriple().isiOS() ||
- Ctx.getTargetInfo().getTriple().isWatchOS())
- AllowOnUnknownClass = true;
-
- while (const PointerType *ptr = T->getAs<PointerType>())
- T = ptr->getPointeeType();
- if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
- ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
- if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
- return false; // id/NSObject is not safe for weak.
- if (!AllowOnUnknownClass && !Class->hasDefinition())
- return false; // forward classes are not verifiable, therefore not safe.
- if (Class && Class->isArcWeakrefUnavailable())
- return false;
- }
-
- return true;
-}
-
-bool trans::isPlusOneAssign(const BinaryOperator *E) {
- if (E->getOpcode() != BO_Assign)
- return false;
-
- return isPlusOne(E->getRHS());
-}
-
-bool trans::isPlusOne(const Expr *E) {
- if (!E)
- return false;
- if (const FullExpr *FE = dyn_cast<FullExpr>(E))
- E = FE->getSubExpr();
-
- if (const ObjCMessageExpr *
- ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))
- if (ME->getMethodFamily() == OMF_retain)
- return true;
-
- if (const CallExpr *
- callE = dyn_cast<CallExpr>(E->IgnoreParenCasts())) {
- if (const FunctionDecl *FD = callE->getDirectCallee()) {
- if (FD->hasAttr<CFReturnsRetainedAttr>())
- return true;
-
- if (FD->isGlobal() &&
- FD->getIdentifier() &&
- FD->getParent()->isTranslationUnit() &&
- FD->isExternallyVisible() &&
- ento::cocoa::isRefType(callE->getType(), "CF",
- FD->getIdentifier()->getName())) {
- StringRef fname = FD->getIdentifier()->getName();
- if (fname.ends_with("Retain") || fname.contains("Create") ||
- fname.contains("Copy"))
- return true;
- }
- }
- }
-
- const ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E);
- while (implCE && implCE->getCastKind() == CK_BitCast)
- implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
-
- return implCE && implCE->getCastKind() == CK_ARCConsumeObject;
-}
-
-/// 'Loc' is the end of a statement range. This returns the location
-/// immediately after the semicolon following the statement.
-/// If no semicolon is found or the location is inside a macro, the returned
-/// source location will be invalid.
-SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
- ASTContext &Ctx, bool IsDecl) {
- SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx, IsDecl);
- if (SemiLoc.isInvalid())
- return SourceLocation();
- return SemiLoc.getLocWithOffset(1);
-}
-
-/// \arg Loc is the end of a statement range. This returns the location
-/// of the semicolon following the statement.
-/// If no semicolon is found or the location is inside a macro, the returned
-/// source location will be invalid.
-SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
- ASTContext &Ctx,
- bool IsDecl) {
- SourceManager &SM = Ctx.getSourceManager();
- if (loc.isMacroID()) {
- if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc))
- return SourceLocation();
- }
- loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts());
-
- // Break down the source location.
- std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
-
- // Try to load the file buffer.
- bool invalidTemp = false;
- StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
- if (invalidTemp)
- return SourceLocation();
-
- const char *tokenBegin = file.data() + locInfo.second;
-
- // Lex from the start of the given location.
- Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
- Ctx.getLangOpts(),
- file.begin(), tokenBegin, file.end());
- Token tok;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::semi)) {
- if (!IsDecl)
- return SourceLocation();
- // Declaration may be followed with other tokens; such as an __attribute,
- // before ending with a semicolon.
- return findSemiAfterLocation(tok.getLocation(), Ctx, /*IsDecl*/true);
- }
-
- return tok.getLocation();
-}
-
-bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
- if (!E || !E->HasSideEffects(Ctx))
- return false;
-
- E = E->IgnoreParenCasts();
- ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E);
- if (!ME)
- return true;
- switch (ME->getMethodFamily()) {
- case OMF_autorelease:
- case OMF_dealloc:
- case OMF_release:
- case OMF_retain:
- switch (ME->getReceiverKind()) {
- case ObjCMessageExpr::SuperInstance:
- return false;
- case ObjCMessageExpr::Instance:
- return hasSideEffects(ME->getInstanceReceiver(), Ctx);
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- return true;
-}
-
-bool trans::isGlobalVar(Expr *E) {
- E = E->IgnoreParenCasts();
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- return DRE->getDecl()->getDeclContext()->isFileContext() &&
- DRE->getDecl()->isExternallyVisible();
- if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
- return isGlobalVar(condOp->getTrueExpr()) &&
- isGlobalVar(condOp->getFalseExpr());
-
- return false;
-}
-
-StringRef trans::getNilString(MigrationPass &Pass) {
- return Pass.SemaRef.PP.isMacroDefined("nil") ? "nil" : "0";
-}
-
-namespace {
-
-class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
- ExprSet &Refs;
-public:
- ReferenceClear(ExprSet &refs) : Refs(refs) { }
- bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
-};
-
-class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
- ValueDecl *Dcl;
- ExprSet &Refs;
-
-public:
- ReferenceCollector(ValueDecl *D, ExprSet &refs)
- : Dcl(D), Refs(refs) { }
-
- bool VisitDeclRefExpr(DeclRefExpr *E) {
- if (E->getDecl() == Dcl)
- Refs.insert(E);
- return true;
- }
-};
-
-class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
- ExprSet &Removables;
-
-public:
- RemovablesCollector(ExprSet &removables)
- : Removables(removables) { }
-
- bool shouldWalkTypesOfTypeLocs() const { return false; }
-
- bool TraverseStmtExpr(StmtExpr *E) {
- CompoundStmt *S = E->getSubStmt();
- for (CompoundStmt::body_iterator
- I = S->body_begin(), E = S->body_end(); I != E; ++I) {
- if (I != E - 1)
- mark(*I);
- TraverseStmt(*I);
- }
- return true;
- }
-
- bool VisitCompoundStmt(CompoundStmt *S) {
- for (auto *I : S->body())
- mark(I);
- return true;
- }
-
- bool VisitIfStmt(IfStmt *S) {
- mark(S->getThen());
- mark(S->getElse());
- return true;
- }
-
- bool VisitWhileStmt(WhileStmt *S) {
- mark(S->getBody());
- return true;
- }
-
- bool VisitDoStmt(DoStmt *S) {
- mark(S->getBody());
- return true;
- }
-
- bool VisitForStmt(ForStmt *S) {
- mark(S->getInit());
- mark(S->getInc());
- mark(S->getBody());
- return true;
- }
-
-private:
- void mark(Stmt *S) {
- if (!S) return;
-
- while (auto *Label = dyn_cast<LabelStmt>(S))
- S = Label->getSubStmt();
- if (auto *E = dyn_cast<Expr>(S))
- S = E->IgnoreImplicit();
- if (auto *E = dyn_cast<Expr>(S))
- Removables.insert(E);
- }
-};
-
-} // end anonymous namespace
-
-void trans::clearRefsIn(Stmt *S, ExprSet &refs) {
- ReferenceClear(refs).TraverseStmt(S);
-}
-
-void trans::collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs) {
- ReferenceCollector(D, refs).TraverseStmt(S);
-}
-
-void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
- RemovablesCollector(exprs).TraverseStmt(S);
-}
-
-//===----------------------------------------------------------------------===//
-// MigrationContext
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
- MigrationContext &MigrateCtx;
- typedef RecursiveASTVisitor<ASTTransform> base;
-
-public:
- ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
-
- bool shouldWalkTypesOfTypeLocs() const { return false; }
-
- bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
- ObjCImplementationContext ImplCtx(MigrateCtx, D);
- for (MigrationContext::traverser_iterator
- I = MigrateCtx.traversers_begin(),
- E = MigrateCtx.traversers_end(); I != E; ++I)
- (*I)->traverseObjCImplementation(ImplCtx);
-
- return base::TraverseObjCImplementationDecl(D);
- }
-
- bool TraverseStmt(Stmt *rootS) {
- if (!rootS)
- return true;
-
- BodyContext BodyCtx(MigrateCtx, rootS);
- for (MigrationContext::traverser_iterator
- I = MigrateCtx.traversers_begin(),
- E = MigrateCtx.traversers_end(); I != E; ++I)
- (*I)->traverseBody(BodyCtx);
-
- return true;
- }
-};
-
-}
-
-MigrationContext::~MigrationContext() {
- for (traverser_iterator
- I = traversers_begin(), E = traversers_end(); I != E; ++I)
- delete *I;
-}
-
-bool MigrationContext::isGCOwnedNonObjC(QualType T) {
- while (!T.isNull()) {
- if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
- if (AttrT->getAttrKind() == attr::ObjCOwnership)
- return !AttrT->getModifiedType()->isObjCRetainableType();
- }
-
- if (T->isArrayType())
- T = Pass.Ctx.getBaseElementType(T);
- else if (const PointerType *PT = T->getAs<PointerType>())
- T = PT->getPointeeType();
- else if (const ReferenceType *RT = T->getAs<ReferenceType>())
- T = RT->getPointeeType();
- else
- break;
- }
-
- return false;
-}
-
-bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
- StringRef toAttr,
- SourceLocation atLoc) {
- if (atLoc.isMacroID())
- return false;
-
- SourceManager &SM = Pass.Ctx.getSourceManager();
-
- // Break down the source location.
- std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
-
- // Try to load the file buffer.
- bool invalidTemp = false;
- StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
- if (invalidTemp)
- return false;
-
- const char *tokenBegin = file.data() + locInfo.second;
-
- // Lex from the start of the given location.
- Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
- Pass.Ctx.getLangOpts(),
- file.begin(), tokenBegin, file.end());
- Token tok;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::at)) return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::raw_identifier)) return false;
- if (tok.getRawIdentifier() != "property")
- return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::l_paren)) return false;
-
- Token BeforeTok = tok;
- Token AfterTok;
- AfterTok.startToken();
- SourceLocation AttrLoc;
-
- lexer.LexFromRawLexer(tok);
- if (tok.is(tok::r_paren))
- return false;
-
- while (true) {
- if (tok.isNot(tok::raw_identifier)) return false;
- if (tok.getRawIdentifier() == fromAttr) {
- if (!toAttr.empty()) {
- Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
- return true;
- }
- // We want to remove the attribute.
- AttrLoc = tok.getLocation();
- }
-
- do {
- lexer.LexFromRawLexer(tok);
- if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
- AfterTok = tok;
- } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
- if (tok.is(tok::r_paren))
- break;
- if (AttrLoc.isInvalid())
- BeforeTok = tok;
- lexer.LexFromRawLexer(tok);
- }
-
- if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
- // We want to remove the attribute.
- if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
- Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
- AfterTok.getLocation()));
- } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
- Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
- } else {
- Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
- }
-
- return true;
- }
-
- return false;
-}
-
-bool MigrationContext::addPropertyAttribute(StringRef attr,
- SourceLocation atLoc) {
- if (atLoc.isMacroID())
- return false;
-
- SourceManager &SM = Pass.Ctx.getSourceManager();
-
- // Break down the source location.
- std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
-
- // Try to load the file buffer.
- bool invalidTemp = false;
- StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
- if (invalidTemp)
- return false;
-
- const char *tokenBegin = file.data() + locInfo.second;
-
- // Lex from the start of the given location.
- Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
- Pass.Ctx.getLangOpts(),
- file.begin(), tokenBegin, file.end());
- Token tok;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::at)) return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::raw_identifier)) return false;
- if (tok.getRawIdentifier() != "property")
- return false;
- lexer.LexFromRawLexer(tok);
-
- if (tok.isNot(tok::l_paren)) {
- Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
- return true;
- }
-
- lexer.LexFromRawLexer(tok);
- if (tok.is(tok::r_paren)) {
- Pass.TA.insert(tok.getLocation(), attr);
- return true;
- }
-
- if (tok.isNot(tok::raw_identifier)) return false;
-
- Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
- return true;
-}
-
-void MigrationContext::traverse(TranslationUnitDecl *TU) {
- for (traverser_iterator
- I = traversers_begin(), E = traversers_end(); I != E; ++I)
- (*I)->traverseTU(*this);
-
- ASTTransform(*this).TraverseDecl(TU);
-}
-
-static void GCRewriteFinalize(MigrationPass &pass) {
- ASTContext &Ctx = pass.Ctx;
- TransformActions &TA = pass.TA;
- DeclContext *DC = Ctx.getTranslationUnitDecl();
- Selector FinalizeSel =
- Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
-
- typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
- impl_iterator;
- for (impl_iterator I = impl_iterator(DC->decls_begin()),
- E = impl_iterator(DC->decls_end()); I != E; ++I) {
- for (const auto *MD : I->instance_methods()) {
- if (!MD->hasBody())
- continue;
-
- if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
- const ObjCMethodDecl *FinalizeM = MD;
- Transaction Trans(TA);
- TA.insert(FinalizeM->getSourceRange().getBegin(),
- "#if !__has_feature(objc_arc)\n");
- CharSourceRange::getTokenRange(FinalizeM->getSourceRange());
- const SourceManager &SM = pass.Ctx.getSourceManager();
- const LangOptions &LangOpts = pass.Ctx.getLangOpts();
- bool Invalid;
- std::string str = "\n#endif\n";
- str += Lexer::getSourceText(
- CharSourceRange::getTokenRange(FinalizeM->getSourceRange()),
- SM, LangOpts, &Invalid);
- TA.insertAfterToken(FinalizeM->getSourceRange().getEnd(), str);
-
- break;
- }
- }
- }
-}
-
-//===----------------------------------------------------------------------===//
-// getAllTransformations.
-//===----------------------------------------------------------------------===//
-
-static void traverseAST(MigrationPass &pass) {
- MigrationContext MigrateCtx(pass);
-
- if (pass.isGCMigration()) {
- MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
- MigrateCtx.addTraverser(new GCAttrsTraverser());
- }
- MigrateCtx.addTraverser(new PropertyRewriteTraverser());
- MigrateCtx.addTraverser(new BlockObjCVariableTraverser());
- MigrateCtx.addTraverser(new ProtectedScopeTraverser());
-
- MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
-}
-
-static void independentTransforms(MigrationPass &pass) {
- rewriteAutoreleasePool(pass);
- removeRetainReleaseDeallocFinalize(pass);
- rewriteUnusedInitDelegate(pass);
- removeZeroOutPropsInDeallocFinalize(pass);
- makeAssignARCSafe(pass);
- rewriteUnbridgedCasts(pass);
- checkAPIUses(pass);
- traverseAST(pass);
-}
-
-std::vector<TransformFn> arcmt::getAllTransformations(
- LangOptions::GCMode OrigGCMode,
- bool NoFinalizeRemoval) {
- std::vector<TransformFn> transforms;
-
- if (OrigGCMode == LangOptions::GCOnly && NoFinalizeRemoval)
- transforms.push_back(GCRewriteFinalize);
- transforms.push_back(independentTransforms);
- // This depends on previous transformations removing various expressions.
- transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
-
- return transforms;
-}
diff --git a/clang/lib/ARCMigrate/Transforms.h b/clang/lib/ARCMigrate/Transforms.h
deleted file mode 100644
index 37e2d6b..0000000
--- a/clang/lib/ARCMigrate/Transforms.h
+++ /dev/null
@@ -1,224 +0,0 @@
-//===-- Transforms.h - Transformations to ARC mode --------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
-#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
-
-#include "clang/AST/ParentMap.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/Support/SaveAndRestore.h"
-
-namespace clang {
- class Decl;
- class Stmt;
- class BlockDecl;
- class ObjCMethodDecl;
- class FunctionDecl;
-
-namespace arcmt {
- class MigrationPass;
-
-namespace trans {
-
- class MigrationContext;
-
-//===----------------------------------------------------------------------===//
-// Transformations.
-//===----------------------------------------------------------------------===//
-
-void rewriteAutoreleasePool(MigrationPass &pass);
-void rewriteUnbridgedCasts(MigrationPass &pass);
-void makeAssignARCSafe(MigrationPass &pass);
-void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
-void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
-void rewriteUnusedInitDelegate(MigrationPass &pass);
-void checkAPIUses(MigrationPass &pass);
-
-void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
-
-class BodyContext {
- MigrationContext &MigrateCtx;
- ParentMap PMap;
- Stmt *TopStmt;
-
-public:
- BodyContext(MigrationContext &MigrateCtx, Stmt *S)
- : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
-
- MigrationContext &getMigrationContext() { return MigrateCtx; }
- ParentMap &getParentMap() { return PMap; }
- Stmt *getTopStmt() { return TopStmt; }
-};
-
-class ObjCImplementationContext {
- MigrationContext &MigrateCtx;
- ObjCImplementationDecl *ImpD;
-
-public:
- ObjCImplementationContext(MigrationContext &MigrateCtx,
- ObjCImplementationDecl *D)
- : MigrateCtx(MigrateCtx), ImpD(D) {}
-
- MigrationContext &getMigrationContext() { return MigrateCtx; }
- ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
-};
-
-class ASTTraverser {
-public:
- virtual ~ASTTraverser();
- virtual void traverseTU(MigrationContext &MigrateCtx) { }
- virtual void traverseBody(BodyContext &BodyCtx) { }
- virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
-};
-
-class MigrationContext {
- std::vector<ASTTraverser *> Traversers;
-
-public:
- MigrationPass &Pass;
-
- struct GCAttrOccurrence {
- enum AttrKind { Weak, Strong } Kind;
- SourceLocation Loc;
- QualType ModifiedType;
- Decl *Dcl;
- /// true if the attribute is owned, e.g. it is in a body and not just
- /// in an interface.
- bool FullyMigratable;
- };
- std::vector<GCAttrOccurrence> GCAttrs;
- llvm::DenseSet<SourceLocation> AttrSet;
- llvm::DenseSet<SourceLocation> RemovedAttrSet;
-
- /// Set of raw '@' locations for 'assign' properties group that contain
- /// GC __weak.
- llvm::DenseSet<SourceLocation> AtPropsWeak;
-
- explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
- ~MigrationContext();
-
- typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
- traverser_iterator traversers_begin() { return Traversers.begin(); }
- traverser_iterator traversers_end() { return Traversers.end(); }
-
- void addTraverser(ASTTraverser *traverser) {
- Traversers.push_back(traverser);
- }
-
- bool isGCOwnedNonObjC(QualType T);
- bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
- return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
- }
- bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
- SourceLocation atLoc);
- bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
-
- void traverse(TranslationUnitDecl *TU);
-
- void dumpGCAttrs();
-};
-
-class PropertyRewriteTraverser : public ASTTraverser {
-public:
- void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override;
-};
-
-class BlockObjCVariableTraverser : public ASTTraverser {
-public:
- void traverseBody(BodyContext &BodyCtx) override;
-};
-
-class ProtectedScopeTraverser : public ASTTraverser {
-public:
- void traverseBody(BodyContext &BodyCtx) override;
-};
-
-// GC transformations
-
-class GCAttrsTraverser : public ASTTraverser {
-public:
- void traverseTU(MigrationContext &MigrateCtx) override;
-};
-
-class GCCollectableCallsTraverser : public ASTTraverser {
-public:
- void traverseBody(BodyContext &BodyCtx) override;
-};
-
-//===----------------------------------------------------------------------===//
-// Helpers.
-//===----------------------------------------------------------------------===//
-
-/// Determine whether we can add weak to the given type.
-bool canApplyWeak(ASTContext &Ctx, QualType type,
- bool AllowOnUnknownClass = false);
-
-bool isPlusOneAssign(const BinaryOperator *E);
-bool isPlusOne(const Expr *E);
-
-/// 'Loc' is the end of a statement range. This returns the location
-/// immediately after the semicolon following the statement.
-/// If no semicolon is found or the location is inside a macro, the returned
-/// source location will be invalid.
-SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx,
- bool IsDecl = false);
-
-/// 'Loc' is the end of a statement range. This returns the location
-/// of the semicolon following the statement.
-/// If no semicolon is found or the location is inside a macro, the returned
-/// source location will be invalid.
-SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx,
- bool IsDecl = false);
-
-bool hasSideEffects(Expr *E, ASTContext &Ctx);
-bool isGlobalVar(Expr *E);
-/// Returns "nil" or "0" if 'nil' macro is not actually defined.
-StringRef getNilString(MigrationPass &Pass);
-
-template <typename BODY_TRANS>
-class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
- MigrationPass &Pass;
- Decl *ParentD;
-
- typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base;
-public:
- BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { }
-
- bool TraverseStmt(Stmt *rootS) {
- if (rootS)
- BODY_TRANS(Pass).transformBody(rootS, ParentD);
- return true;
- }
-
- bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
- SaveAndRestore<Decl *> SetParent(ParentD, D);
- return base::TraverseObjCMethodDecl(D);
- }
-};
-
-typedef llvm::DenseSet<Expr *> ExprSet;
-
-void clearRefsIn(Stmt *S, ExprSet &refs);
-template <typename iterator>
-void clearRefsIn(iterator begin, iterator end, ExprSet &refs) {
- for (; begin != end; ++begin)
- clearRefsIn(*begin, refs);
-}
-
-void collectRefs(ValueDecl *D, Stmt *S, ExprSet &refs);
-
-void collectRemovables(Stmt *S, ExprSet &exprs);
-
-} // end namespace trans
-
-} // end namespace arcmt
-
-} // end namespace clang
-
-#endif
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index 14ba553..4f2218b 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -12,9 +12,6 @@ add_subdirectory(Analysis)
add_subdirectory(Edit)
add_subdirectory(ExtractAPI)
add_subdirectory(Rewrite)
-if(CLANG_ENABLE_ARCMT)
- add_subdirectory(ARCMigrate)
-endif()
add_subdirectory(Driver)
add_subdirectory(Serialization)
add_subdirectory(Frontend)
diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp
index 23dbceb..0899b8e 100644
--- a/clang/lib/Driver/Action.cpp
+++ b/clang/lib/Driver/Action.cpp
@@ -27,8 +27,8 @@ const char *Action::getClassName(ActionClass AC) {
case PrecompileJobClass: return "precompiler";
case ExtractAPIJobClass:
return "api-extractor";
- case AnalyzeJobClass: return "analyzer";
- case MigrateJobClass: return "migrator";
+ case AnalyzeJobClass:
+ return "analyzer";
case CompileJobClass: return "compiler";
case BackendJobClass: return "backend";
case AssembleJobClass: return "assembler";
@@ -373,11 +373,6 @@ void AnalyzeJobAction::anchor() {}
AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
: JobAction(AnalyzeJobClass, Input, OutputType) {}
-void MigrateJobAction::anchor() {}
-
-MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
- : JobAction(MigrateJobClass, Input, OutputType) {}
-
void CompileJobAction::anchor() {}
CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 684f771..612e44b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -413,12 +413,12 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
(PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_print_enabled_extensions)) ||
+ (PhaseArg =
+ DAL.getLastArg(options::OPT_print_enabled_extensions)) ||
(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
(PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
- (PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
(PhaseArg = DAL.getLastArg(options::OPT__analyze)) ||
(PhaseArg = DAL.getLastArg(options::OPT_emit_cir)) ||
(PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
@@ -5082,8 +5082,6 @@ Action *Driver::ConstructPhaseAction(
types::TY_RewrittenLegacyObjC);
if (Args.hasArg(options::OPT__analyze))
return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist);
- if (Args.hasArg(options::OPT__migrate))
- return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap);
if (Args.hasArg(options::OPT_emit_ast))
return C.MakeAction<CompileJobAction>(Input, types::TY_AST);
if (Args.hasArg(options::OPT_emit_cir))
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index acf9d26..ebc9820 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -646,7 +646,6 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::PreprocessJobClass:
case Action::ExtractAPIJobClass:
case Action::AnalyzeJobClass:
- case Action::MigrateJobClass:
case Action::VerifyPCHJobClass:
case Action::BackendJobClass:
return getClang();
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 70e5e98..9b5132c5 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3958,78 +3958,6 @@ static void RenderOpenACCOptions(const Driver &D, const ArgList &Args,
}
}
-static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
- ArgStringList &CmdArgs) {
- bool ARCMTEnabled = false;
- if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
- if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
- options::OPT_ccc_arcmt_modify,
- options::OPT_ccc_arcmt_migrate)) {
- ARCMTEnabled = true;
- switch (A->getOption().getID()) {
- default: llvm_unreachable("missed a case");
- case options::OPT_ccc_arcmt_check:
- CmdArgs.push_back("-arcmt-action=check");
- break;
- case options::OPT_ccc_arcmt_modify:
- CmdArgs.push_back("-arcmt-action=modify");
- break;
- case options::OPT_ccc_arcmt_migrate:
- CmdArgs.push_back("-arcmt-action=migrate");
- CmdArgs.push_back("-mt-migrate-directory");
- CmdArgs.push_back(A->getValue());
-
- Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
- Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
- break;
- }
- }
- } else {
- Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
- Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
- Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
- }
-
- if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
- if (ARCMTEnabled)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "-ccc-arcmt-migrate";
-
- CmdArgs.push_back("-mt-migrate-directory");
- CmdArgs.push_back(A->getValue());
-
- if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
- options::OPT_objcmt_migrate_subscripting,
- options::OPT_objcmt_migrate_property)) {
- // None specified, means enable them all.
- CmdArgs.push_back("-objcmt-migrate-literals");
- CmdArgs.push_back("-objcmt-migrate-subscripting");
- CmdArgs.push_back("-objcmt-migrate-property");
- } else {
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
- }
- } else {
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_allowlist_dir_path);
- }
-}
-
static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
const ArgList &Args, ArgStringList &CmdArgs) {
// -fbuiltin is default unless -mkernel is used.
@@ -5319,8 +5247,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (isa<AnalyzeJobAction>(JA)) {
assert(JA.getType() == types::TY_Plist && "Invalid output type.");
CmdArgs.push_back("-analyze");
- } else if (isa<MigrateJobAction>(JA)) {
- CmdArgs.push_back("-migrate");
} else if (isa<PreprocessJobAction>(JA)) {
if (Output.getType() == types::TY_Dependencies)
CmdArgs.push_back("-Eonly");
@@ -6445,8 +6371,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_working_directory);
- RenderARCMigrateToolOptions(D, Args, CmdArgs);
-
// Add preprocessing options like -I, -D, etc. if we are using the
// preprocessor.
//
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 55c55ba..9a276c5 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -588,20 +588,6 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// more information.
ArgStringList CmdArgs;
- /// Hack(tm) to ignore linking errors when we are doing ARC migration.
- if (Args.hasArg(options::OPT_ccc_arcmt_check,
- options::OPT_ccc_arcmt_migrate)) {
- for (const auto &Arg : Args)
- Arg->claim();
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("touch"));
- CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::None(), Exec,
- CmdArgs, std::nullopt, Output));
- return;
- }
-
VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);
bool LinkerIsLLD;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 8411217..11fd6ab 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2756,7 +2756,6 @@ static const auto &getFrontendActionTable() {
{frontend::RewriteObjC, OPT_rewrite_objc},
{frontend::RewriteTest, OPT_rewrite_test},
{frontend::RunAnalysis, OPT_analyze},
- {frontend::MigrateSource, OPT_migrate},
{frontend::RunPreprocessorOnly, OPT_Eonly},
{frontend::PrintDependencyDirectivesSourceMinimizerOutput,
OPT_print_dependency_directives_minimized_source},
@@ -3099,12 +3098,6 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_aux_target_feature))
Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature);
- if (Opts.ARCMTAction != FrontendOptions::ARCMT_None &&
- Opts.ObjCMTAction != FrontendOptions::ObjCMT_None) {
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << "ARC migration" << "ObjC migration";
- }
-
InputKind DashX(Language::Unknown);
if (const Arg *A = Args.getLastArg(OPT_x)) {
StringRef XValue = A->getValue();
@@ -4639,7 +4632,6 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
case frontend::RewriteTest:
case frontend::RunAnalysis:
case frontend::TemplightDump:
- case frontend::MigrateSource:
return false;
case frontend::DumpCompilerOptions:
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index bfc7652..d7a3699 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -21,12 +21,6 @@ if(CLANG_ENABLE_CIR)
)
endif()
-if(CLANG_ENABLE_ARCMT)
- list(APPEND link_libs
- clangARCMigrate
- )
-endif()
-
if(CLANG_ENABLE_STATIC_ANALYZER)
list(APPEND link_libs
clangStaticAnalyzerFrontend
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 3f95a1e..079bcd9 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ARCMigrate/ARCMTActions.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Config/config.h"
#include "clang/Driver/Options.h"
@@ -131,12 +130,6 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
#else
case RewriteObjC: Action = "RewriteObjC"; break;
#endif
-#if CLANG_ENABLE_ARCMT
- case MigrateSource:
- return std::make_unique<arcmt::MigrateSourceAction>();
-#else
- case MigrateSource: Action = "MigrateSource"; break;
-#endif
#if CLANG_ENABLE_STATIC_ANALYZER
case RunAnalysis: return std::make_unique<ento::AnalysisAction>();
#else
@@ -147,8 +140,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
return std::make_unique<PrintDependencyDirectivesSourceMinimizerAction>();
}
-#if !CLANG_ENABLE_ARCMT || !CLANG_ENABLE_STATIC_ANALYZER \
- || !CLANG_ENABLE_OBJC_REWRITER
+#if !CLANG_ENABLE_STATIC_ANALYZER || !CLANG_ENABLE_OBJC_REWRITER
CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action;
return 0;
#else
@@ -169,35 +161,6 @@ CreateFrontendAction(CompilerInstance &CI) {
Act = std::make_unique<FixItRecompile>(std::move(Act));
}
-#if CLANG_ENABLE_ARCMT
- if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource &&
- CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) {
- // Potentially wrap the base FE action in an ARC Migrate Tool action.
- switch (FEOpts.ARCMTAction) {
- case FrontendOptions::ARCMT_None:
- break;
- case FrontendOptions::ARCMT_Check:
- Act = std::make_unique<arcmt::CheckAction>(std::move(Act));
- break;
- case FrontendOptions::ARCMT_Modify:
- Act = std::make_unique<arcmt::ModifyAction>(std::move(Act));
- break;
- case FrontendOptions::ARCMT_Migrate:
- Act = std::make_unique<arcmt::MigrateAction>(std::move(Act),
- FEOpts.MTMigrateDir,
- FEOpts.ARCMTMigrateReportOut,
- FEOpts.ARCMTMigrateEmitARCErrors);
- break;
- }
-
- if (FEOpts.ObjCMTAction != FrontendOptions::ObjCMT_None) {
- Act = std::make_unique<arcmt::ObjCMigrateAction>(std::move(Act),
- FEOpts.MTMigrateDir,
- FEOpts.ObjCMTAction);
- }
- }
-#endif
-
// Wrap the base FE action in an extract api action to generate
// symbol graph as a biproduct of compilation (enabled with
// --emit-symbol-graph option)
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index 2e97cac..732de7b 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -214,9 +214,6 @@ makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
CI.getDependencyOutputOpts().Targets.clear();
CI.getFrontendOpts().ProgramAction = frontend::GenerateModule;
- CI.getFrontendOpts().ARCMTAction = FrontendOptions::ARCMT_None;
- CI.getFrontendOpts().ObjCMTAction = FrontendOptions::ObjCMT_None;
- CI.getFrontendOpts().MTMigrateDir.clear();
CI.getLangOpts().ModuleName.clear();
// Remove any macro definitions that are explicitly ignored.