1*0fca6ea1SDimitry Andric //===--- TransGCAttrs.cpp - Transformations to ARC mode -------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "Transforms.h"
100b57cec5SDimitry Andric #include "Internals.h"
110b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
120b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
130b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
140b57cec5SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
160b57cec5SDimitry Andric #include "llvm/ADT/TinyPtrVector.h"
170b57cec5SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric using namespace clang;
200b57cec5SDimitry Andric using namespace arcmt;
210b57cec5SDimitry Andric using namespace trans;
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric namespace {
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric /// Collects all the places where GC attributes __strong/__weak occur.
260b57cec5SDimitry Andric class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
270b57cec5SDimitry Andric MigrationContext &MigrateCtx;
280b57cec5SDimitry Andric bool FullyMigratable;
290b57cec5SDimitry Andric std::vector<ObjCPropertyDecl *> &AllProps;
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric typedef RecursiveASTVisitor<GCAttrsCollector> base;
320b57cec5SDimitry Andric public:
GCAttrsCollector(MigrationContext & ctx,std::vector<ObjCPropertyDecl * > & AllProps)330b57cec5SDimitry Andric GCAttrsCollector(MigrationContext &ctx,
340b57cec5SDimitry Andric std::vector<ObjCPropertyDecl *> &AllProps)
350b57cec5SDimitry Andric : MigrateCtx(ctx), FullyMigratable(false),
360b57cec5SDimitry Andric AllProps(AllProps) { }
370b57cec5SDimitry Andric
shouldWalkTypesOfTypeLocs() const380b57cec5SDimitry Andric bool shouldWalkTypesOfTypeLocs() const { return false; }
390b57cec5SDimitry Andric
VisitAttributedTypeLoc(AttributedTypeLoc TL)400b57cec5SDimitry Andric bool VisitAttributedTypeLoc(AttributedTypeLoc TL) {
410b57cec5SDimitry Andric handleAttr(TL);
420b57cec5SDimitry Andric return true;
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric
TraverseDecl(Decl * D)450b57cec5SDimitry Andric bool TraverseDecl(Decl *D) {
460b57cec5SDimitry Andric if (!D || D->isImplicit())
470b57cec5SDimitry Andric return true;
480b57cec5SDimitry Andric
49bdd1243dSDimitry Andric SaveAndRestore Save(FullyMigratable, isMigratable(D));
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D)) {
520b57cec5SDimitry Andric lookForAttribute(PropD, PropD->getTypeSourceInfo());
530b57cec5SDimitry Andric AllProps.push_back(PropD);
540b57cec5SDimitry Andric } else if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
550b57cec5SDimitry Andric lookForAttribute(DD, DD->getTypeSourceInfo());
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric return base::TraverseDecl(D);
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric
lookForAttribute(Decl * D,TypeSourceInfo * TInfo)600b57cec5SDimitry Andric void lookForAttribute(Decl *D, TypeSourceInfo *TInfo) {
610b57cec5SDimitry Andric if (!TInfo)
620b57cec5SDimitry Andric return;
630b57cec5SDimitry Andric TypeLoc TL = TInfo->getTypeLoc();
640b57cec5SDimitry Andric while (TL) {
650b57cec5SDimitry Andric if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>()) {
660b57cec5SDimitry Andric TL = QL.getUnqualifiedLoc();
670b57cec5SDimitry Andric } else if (AttributedTypeLoc Attr = TL.getAs<AttributedTypeLoc>()) {
680b57cec5SDimitry Andric if (handleAttr(Attr, D))
690b57cec5SDimitry Andric break;
700b57cec5SDimitry Andric TL = Attr.getModifiedLoc();
710b57cec5SDimitry Andric } else if (MacroQualifiedTypeLoc MDTL =
720b57cec5SDimitry Andric TL.getAs<MacroQualifiedTypeLoc>()) {
730b57cec5SDimitry Andric TL = MDTL.getInnerLoc();
740b57cec5SDimitry Andric } else if (ArrayTypeLoc Arr = TL.getAs<ArrayTypeLoc>()) {
750b57cec5SDimitry Andric TL = Arr.getElementLoc();
760b57cec5SDimitry Andric } else if (PointerTypeLoc PT = TL.getAs<PointerTypeLoc>()) {
770b57cec5SDimitry Andric TL = PT.getPointeeLoc();
780b57cec5SDimitry Andric } else if (ReferenceTypeLoc RT = TL.getAs<ReferenceTypeLoc>())
790b57cec5SDimitry Andric TL = RT.getPointeeLoc();
800b57cec5SDimitry Andric else
810b57cec5SDimitry Andric break;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric
handleAttr(AttributedTypeLoc TL,Decl * D=nullptr)850b57cec5SDimitry Andric bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {
860b57cec5SDimitry Andric auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>();
870b57cec5SDimitry Andric if (!OwnershipAttr)
880b57cec5SDimitry Andric return false;
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric SourceLocation Loc = OwnershipAttr->getLocation();
91e8d8bef9SDimitry Andric SourceLocation OrigLoc = Loc;
92e8d8bef9SDimitry Andric if (MigrateCtx.AttrSet.count(OrigLoc))
930b57cec5SDimitry Andric return true;
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric ASTContext &Ctx = MigrateCtx.Pass.Ctx;
960b57cec5SDimitry Andric SourceManager &SM = Ctx.getSourceManager();
970b57cec5SDimitry Andric if (Loc.isMacroID())
980b57cec5SDimitry Andric Loc = SM.getImmediateExpansionRange(Loc).getBegin();
990b57cec5SDimitry Andric StringRef Spell = OwnershipAttr->getKind()->getName();
1000b57cec5SDimitry Andric MigrationContext::GCAttrOccurrence::AttrKind Kind;
1010b57cec5SDimitry Andric if (Spell == "strong")
1020b57cec5SDimitry Andric Kind = MigrationContext::GCAttrOccurrence::Strong;
1030b57cec5SDimitry Andric else if (Spell == "weak")
1040b57cec5SDimitry Andric Kind = MigrationContext::GCAttrOccurrence::Weak;
1050b57cec5SDimitry Andric else
1060b57cec5SDimitry Andric return false;
1070b57cec5SDimitry Andric
108e8d8bef9SDimitry Andric MigrateCtx.AttrSet.insert(OrigLoc);
1090b57cec5SDimitry Andric MigrateCtx.GCAttrs.push_back(MigrationContext::GCAttrOccurrence());
1100b57cec5SDimitry Andric MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs.back();
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric Attr.Kind = Kind;
1130b57cec5SDimitry Andric Attr.Loc = Loc;
1140b57cec5SDimitry Andric Attr.ModifiedType = TL.getModifiedLoc().getType();
1150b57cec5SDimitry Andric Attr.Dcl = D;
1160b57cec5SDimitry Andric Attr.FullyMigratable = FullyMigratable;
1170b57cec5SDimitry Andric return true;
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric
isMigratable(Decl * D)1200b57cec5SDimitry Andric bool isMigratable(Decl *D) {
1210b57cec5SDimitry Andric if (isa<TranslationUnitDecl>(D))
1220b57cec5SDimitry Andric return false;
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric if (isInMainFile(D))
1250b57cec5SDimitry Andric return true;
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
1280b57cec5SDimitry Andric return FD->hasBody();
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D))
1310b57cec5SDimitry Andric return hasObjCImpl(ContD);
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
1340b57cec5SDimitry Andric for (const auto *MI : RD->methods()) {
1350b57cec5SDimitry Andric if (MI->isOutOfLine())
1360b57cec5SDimitry Andric return true;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric return false;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric return isMigratable(cast<Decl>(D->getDeclContext()));
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
hasObjCImpl(Decl * D)1440b57cec5SDimitry Andric static bool hasObjCImpl(Decl *D) {
1450b57cec5SDimitry Andric if (!D)
1460b57cec5SDimitry Andric return false;
1470b57cec5SDimitry Andric if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) {
1480b57cec5SDimitry Andric if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD))
1490b57cec5SDimitry Andric return ID->getImplementation() != nullptr;
1500b57cec5SDimitry Andric if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD))
1510b57cec5SDimitry Andric return CD->getImplementation() != nullptr;
1520b57cec5SDimitry Andric return isa<ObjCImplDecl>(ContD);
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric return false;
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric
isInMainFile(Decl * D)1570b57cec5SDimitry Andric bool isInMainFile(Decl *D) {
1580b57cec5SDimitry Andric if (!D)
1590b57cec5SDimitry Andric return false;
1600b57cec5SDimitry Andric
161bdd1243dSDimitry Andric for (auto *I : D->redecls())
1620b57cec5SDimitry Andric if (!isInMainFile(I->getLocation()))
1630b57cec5SDimitry Andric return false;
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric return true;
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
isInMainFile(SourceLocation Loc)1680b57cec5SDimitry Andric bool isInMainFile(SourceLocation Loc) {
1690b57cec5SDimitry Andric if (Loc.isInvalid())
1700b57cec5SDimitry Andric return false;
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric SourceManager &SM = MigrateCtx.Pass.Ctx.getSourceManager();
1730b57cec5SDimitry Andric return SM.isInFileID(SM.getExpansionLoc(Loc), SM.getMainFileID());
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric };
1760b57cec5SDimitry Andric
1770b57cec5SDimitry Andric } // anonymous namespace
1780b57cec5SDimitry Andric
errorForGCAttrsOnNonObjC(MigrationContext & MigrateCtx)1790b57cec5SDimitry Andric static void errorForGCAttrsOnNonObjC(MigrationContext &MigrateCtx) {
1800b57cec5SDimitry Andric TransformActions &TA = MigrateCtx.Pass.TA;
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
1830b57cec5SDimitry Andric MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
1840b57cec5SDimitry Andric if (Attr.FullyMigratable && Attr.Dcl) {
1850b57cec5SDimitry Andric if (Attr.ModifiedType.isNull())
1860b57cec5SDimitry Andric continue;
1870b57cec5SDimitry Andric if (!Attr.ModifiedType->isObjCRetainableType()) {
1880b57cec5SDimitry Andric TA.reportError("GC managed memory will become unmanaged in ARC",
1890b57cec5SDimitry Andric Attr.Loc);
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric
checkWeakGCAttrs(MigrationContext & MigrateCtx)1950b57cec5SDimitry Andric static void checkWeakGCAttrs(MigrationContext &MigrateCtx) {
1960b57cec5SDimitry Andric TransformActions &TA = MigrateCtx.Pass.TA;
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
1990b57cec5SDimitry Andric MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
2000b57cec5SDimitry Andric if (Attr.Kind == MigrationContext::GCAttrOccurrence::Weak) {
2010b57cec5SDimitry Andric if (Attr.ModifiedType.isNull() ||
2020b57cec5SDimitry Andric !Attr.ModifiedType->isObjCRetainableType())
2030b57cec5SDimitry Andric continue;
2040b57cec5SDimitry Andric if (!canApplyWeak(MigrateCtx.Pass.Ctx, Attr.ModifiedType,
2050b57cec5SDimitry Andric /*AllowOnUnknownClass=*/true)) {
2060b57cec5SDimitry Andric Transaction Trans(TA);
207e8d8bef9SDimitry Andric if (!MigrateCtx.RemovedAttrSet.count(Attr.Loc))
2080b57cec5SDimitry Andric TA.replaceText(Attr.Loc, "__weak", "__unsafe_unretained");
2090b57cec5SDimitry Andric TA.clearDiagnostic(diag::err_arc_weak_no_runtime,
2100b57cec5SDimitry Andric diag::err_arc_unsupported_weak_class,
2110b57cec5SDimitry Andric Attr.Loc);
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
2180b57cec5SDimitry Andric
checkAllAtProps(MigrationContext & MigrateCtx,SourceLocation AtLoc,IndivPropsTy & IndProps)2190b57cec5SDimitry Andric static void checkAllAtProps(MigrationContext &MigrateCtx,
2200b57cec5SDimitry Andric SourceLocation AtLoc,
2210b57cec5SDimitry Andric IndivPropsTy &IndProps) {
2220b57cec5SDimitry Andric if (IndProps.empty())
2230b57cec5SDimitry Andric return;
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric for (IndivPropsTy::iterator
2260b57cec5SDimitry Andric PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
2270b57cec5SDimitry Andric QualType T = (*PI)->getType();
2280b57cec5SDimitry Andric if (T.isNull() || !T->isObjCRetainableType())
2290b57cec5SDimitry Andric return;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric SmallVector<std::pair<AttributedTypeLoc, ObjCPropertyDecl *>, 4> ATLs;
2330b57cec5SDimitry Andric bool hasWeak = false, hasStrong = false;
2345ffd83dbSDimitry Andric ObjCPropertyAttribute::Kind Attrs = ObjCPropertyAttribute::kind_noattr;
2350b57cec5SDimitry Andric for (IndivPropsTy::iterator
2360b57cec5SDimitry Andric PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
2370b57cec5SDimitry Andric ObjCPropertyDecl *PD = *PI;
2380b57cec5SDimitry Andric Attrs = PD->getPropertyAttributesAsWritten();
2390b57cec5SDimitry Andric TypeSourceInfo *TInfo = PD->getTypeSourceInfo();
2400b57cec5SDimitry Andric if (!TInfo)
2410b57cec5SDimitry Andric return;
2420b57cec5SDimitry Andric TypeLoc TL = TInfo->getTypeLoc();
2430b57cec5SDimitry Andric if (AttributedTypeLoc ATL =
2440b57cec5SDimitry Andric TL.getAs<AttributedTypeLoc>()) {
2450b57cec5SDimitry Andric ATLs.push_back(std::make_pair(ATL, PD));
2460b57cec5SDimitry Andric if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
2470b57cec5SDimitry Andric hasWeak = true;
2480b57cec5SDimitry Andric } else if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Strong)
2490b57cec5SDimitry Andric hasStrong = true;
2500b57cec5SDimitry Andric else
2510b57cec5SDimitry Andric return;
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric if (ATLs.empty())
2550b57cec5SDimitry Andric return;
2560b57cec5SDimitry Andric if (hasWeak && hasStrong)
2570b57cec5SDimitry Andric return;
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric TransformActions &TA = MigrateCtx.Pass.TA;
2600b57cec5SDimitry Andric Transaction Trans(TA);
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric if (GCAttrsCollector::hasObjCImpl(
2630b57cec5SDimitry Andric cast<Decl>(IndProps.front()->getDeclContext()))) {
2640b57cec5SDimitry Andric if (hasWeak)
265e8d8bef9SDimitry Andric MigrateCtx.AtPropsWeak.insert(AtLoc);
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric } else {
2680b57cec5SDimitry Andric StringRef toAttr = "strong";
2690b57cec5SDimitry Andric if (hasWeak) {
2700b57cec5SDimitry Andric if (canApplyWeak(MigrateCtx.Pass.Ctx, IndProps.front()->getType(),
2710b57cec5SDimitry Andric /*AllowOnUnknownClass=*/true))
2720b57cec5SDimitry Andric toAttr = "weak";
2730b57cec5SDimitry Andric else
2740b57cec5SDimitry Andric toAttr = "unsafe_unretained";
2750b57cec5SDimitry Andric }
2765ffd83dbSDimitry Andric if (Attrs & ObjCPropertyAttribute::kind_assign)
2770b57cec5SDimitry Andric MigrateCtx.rewritePropertyAttribute("assign", toAttr, AtLoc);
2780b57cec5SDimitry Andric else
2790b57cec5SDimitry Andric MigrateCtx.addPropertyAttribute(toAttr, AtLoc);
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric
2820b57cec5SDimitry Andric for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
2830b57cec5SDimitry Andric SourceLocation Loc = ATLs[i].first.getAttr()->getLocation();
2840b57cec5SDimitry Andric if (Loc.isMacroID())
2850b57cec5SDimitry Andric Loc = MigrateCtx.Pass.Ctx.getSourceManager()
2860b57cec5SDimitry Andric .getImmediateExpansionRange(Loc)
2870b57cec5SDimitry Andric .getBegin();
2880b57cec5SDimitry Andric TA.remove(Loc);
2890b57cec5SDimitry Andric TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);
2900b57cec5SDimitry Andric TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,
2910b57cec5SDimitry Andric ATLs[i].second->getLocation());
292e8d8bef9SDimitry Andric MigrateCtx.RemovedAttrSet.insert(Loc);
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
checkAllProps(MigrationContext & MigrateCtx,std::vector<ObjCPropertyDecl * > & AllProps)2960b57cec5SDimitry Andric static void checkAllProps(MigrationContext &MigrateCtx,
2970b57cec5SDimitry Andric std::vector<ObjCPropertyDecl *> &AllProps) {
2980b57cec5SDimitry Andric typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
299e8d8bef9SDimitry Andric llvm::DenseMap<SourceLocation, IndivPropsTy> AtProps;
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric for (unsigned i = 0, e = AllProps.size(); i != e; ++i) {
3020b57cec5SDimitry Andric ObjCPropertyDecl *PD = AllProps[i];
3030b57cec5SDimitry Andric if (PD->getPropertyAttributesAsWritten() &
3045ffd83dbSDimitry Andric (ObjCPropertyAttribute::kind_assign |
3055ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_readonly)) {
3060b57cec5SDimitry Andric SourceLocation AtLoc = PD->getAtLoc();
3070b57cec5SDimitry Andric if (AtLoc.isInvalid())
3080b57cec5SDimitry Andric continue;
309e8d8bef9SDimitry Andric AtProps[AtLoc].push_back(PD);
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric
313e8d8bef9SDimitry Andric for (auto I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
314e8d8bef9SDimitry Andric SourceLocation AtLoc = I->first;
3150b57cec5SDimitry Andric IndivPropsTy &IndProps = I->second;
3160b57cec5SDimitry Andric checkAllAtProps(MigrateCtx, AtLoc, IndProps);
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric
traverseTU(MigrationContext & MigrateCtx)3200b57cec5SDimitry Andric void GCAttrsTraverser::traverseTU(MigrationContext &MigrateCtx) {
3210b57cec5SDimitry Andric std::vector<ObjCPropertyDecl *> AllProps;
3220b57cec5SDimitry Andric GCAttrsCollector(MigrateCtx, AllProps).TraverseDecl(
3230b57cec5SDimitry Andric MigrateCtx.Pass.Ctx.getTranslationUnitDecl());
3240b57cec5SDimitry Andric
3250b57cec5SDimitry Andric errorForGCAttrsOnNonObjC(MigrateCtx);
3260b57cec5SDimitry Andric checkAllProps(MigrateCtx, AllProps);
3270b57cec5SDimitry Andric checkWeakGCAttrs(MigrateCtx);
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric
dumpGCAttrs()3300b57cec5SDimitry Andric void MigrationContext::dumpGCAttrs() {
3310b57cec5SDimitry Andric llvm::errs() << "\n################\n";
3320b57cec5SDimitry Andric for (unsigned i = 0, e = GCAttrs.size(); i != e; ++i) {
3330b57cec5SDimitry Andric GCAttrOccurrence &Attr = GCAttrs[i];
3340b57cec5SDimitry Andric llvm::errs() << "KIND: "
3350b57cec5SDimitry Andric << (Attr.Kind == GCAttrOccurrence::Strong ? "strong" : "weak");
3360b57cec5SDimitry Andric llvm::errs() << "\nLOC: ";
3370b57cec5SDimitry Andric Attr.Loc.print(llvm::errs(), Pass.Ctx.getSourceManager());
3380b57cec5SDimitry Andric llvm::errs() << "\nTYPE: ";
3390b57cec5SDimitry Andric Attr.ModifiedType.dump();
3400b57cec5SDimitry Andric if (Attr.Dcl) {
3410b57cec5SDimitry Andric llvm::errs() << "DECL:\n";
3420b57cec5SDimitry Andric Attr.Dcl->dump();
3430b57cec5SDimitry Andric } else {
3440b57cec5SDimitry Andric llvm::errs() << "DECL: NONE";
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric llvm::errs() << "\nMIGRATABLE: " << Attr.FullyMigratable;
3470b57cec5SDimitry Andric llvm::errs() << "\n----------------\n";
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric llvm::errs() << "\n################\n";
3500b57cec5SDimitry Andric }
351