1*0b57cec5SDimitry Andric //===--- TransGCAttrs.cpp - Transformations to ARC mode --------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "Transforms.h" 10*0b57cec5SDimitry Andric #include "Internals.h" 11*0b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 12*0b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 13*0b57cec5SDimitry Andric #include "clang/Lex/Lexer.h" 14*0b57cec5SDimitry Andric #include "clang/Sema/SemaDiagnostic.h" 15*0b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 16*0b57cec5SDimitry Andric #include "llvm/ADT/TinyPtrVector.h" 17*0b57cec5SDimitry Andric #include "llvm/Support/SaveAndRestore.h" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric using namespace clang; 20*0b57cec5SDimitry Andric using namespace arcmt; 21*0b57cec5SDimitry Andric using namespace trans; 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric namespace { 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric /// Collects all the places where GC attributes __strong/__weak occur. 26*0b57cec5SDimitry Andric class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> { 27*0b57cec5SDimitry Andric MigrationContext &MigrateCtx; 28*0b57cec5SDimitry Andric bool FullyMigratable; 29*0b57cec5SDimitry Andric std::vector<ObjCPropertyDecl *> &AllProps; 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric typedef RecursiveASTVisitor<GCAttrsCollector> base; 32*0b57cec5SDimitry Andric public: 33*0b57cec5SDimitry Andric GCAttrsCollector(MigrationContext &ctx, 34*0b57cec5SDimitry Andric std::vector<ObjCPropertyDecl *> &AllProps) 35*0b57cec5SDimitry Andric : MigrateCtx(ctx), FullyMigratable(false), 36*0b57cec5SDimitry Andric AllProps(AllProps) { } 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric bool shouldWalkTypesOfTypeLocs() const { return false; } 39*0b57cec5SDimitry Andric 40*0b57cec5SDimitry Andric bool VisitAttributedTypeLoc(AttributedTypeLoc TL) { 41*0b57cec5SDimitry Andric handleAttr(TL); 42*0b57cec5SDimitry Andric return true; 43*0b57cec5SDimitry Andric } 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric bool TraverseDecl(Decl *D) { 46*0b57cec5SDimitry Andric if (!D || D->isImplicit()) 47*0b57cec5SDimitry Andric return true; 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric SaveAndRestore<bool> Save(FullyMigratable, isMigratable(D)); 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D)) { 52*0b57cec5SDimitry Andric lookForAttribute(PropD, PropD->getTypeSourceInfo()); 53*0b57cec5SDimitry Andric AllProps.push_back(PropD); 54*0b57cec5SDimitry Andric } else if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { 55*0b57cec5SDimitry Andric lookForAttribute(DD, DD->getTypeSourceInfo()); 56*0b57cec5SDimitry Andric } 57*0b57cec5SDimitry Andric return base::TraverseDecl(D); 58*0b57cec5SDimitry Andric } 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric void lookForAttribute(Decl *D, TypeSourceInfo *TInfo) { 61*0b57cec5SDimitry Andric if (!TInfo) 62*0b57cec5SDimitry Andric return; 63*0b57cec5SDimitry Andric TypeLoc TL = TInfo->getTypeLoc(); 64*0b57cec5SDimitry Andric while (TL) { 65*0b57cec5SDimitry Andric if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>()) { 66*0b57cec5SDimitry Andric TL = QL.getUnqualifiedLoc(); 67*0b57cec5SDimitry Andric } else if (AttributedTypeLoc Attr = TL.getAs<AttributedTypeLoc>()) { 68*0b57cec5SDimitry Andric if (handleAttr(Attr, D)) 69*0b57cec5SDimitry Andric break; 70*0b57cec5SDimitry Andric TL = Attr.getModifiedLoc(); 71*0b57cec5SDimitry Andric } else if (MacroQualifiedTypeLoc MDTL = 72*0b57cec5SDimitry Andric TL.getAs<MacroQualifiedTypeLoc>()) { 73*0b57cec5SDimitry Andric TL = MDTL.getInnerLoc(); 74*0b57cec5SDimitry Andric } else if (ArrayTypeLoc Arr = TL.getAs<ArrayTypeLoc>()) { 75*0b57cec5SDimitry Andric TL = Arr.getElementLoc(); 76*0b57cec5SDimitry Andric } else if (PointerTypeLoc PT = TL.getAs<PointerTypeLoc>()) { 77*0b57cec5SDimitry Andric TL = PT.getPointeeLoc(); 78*0b57cec5SDimitry Andric } else if (ReferenceTypeLoc RT = TL.getAs<ReferenceTypeLoc>()) 79*0b57cec5SDimitry Andric TL = RT.getPointeeLoc(); 80*0b57cec5SDimitry Andric else 81*0b57cec5SDimitry Andric break; 82*0b57cec5SDimitry Andric } 83*0b57cec5SDimitry Andric } 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) { 86*0b57cec5SDimitry Andric auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>(); 87*0b57cec5SDimitry Andric if (!OwnershipAttr) 88*0b57cec5SDimitry Andric return false; 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric SourceLocation Loc = OwnershipAttr->getLocation(); 91*0b57cec5SDimitry Andric unsigned RawLoc = Loc.getRawEncoding(); 92*0b57cec5SDimitry Andric if (MigrateCtx.AttrSet.count(RawLoc)) 93*0b57cec5SDimitry Andric return true; 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric ASTContext &Ctx = MigrateCtx.Pass.Ctx; 96*0b57cec5SDimitry Andric SourceManager &SM = Ctx.getSourceManager(); 97*0b57cec5SDimitry Andric if (Loc.isMacroID()) 98*0b57cec5SDimitry Andric Loc = SM.getImmediateExpansionRange(Loc).getBegin(); 99*0b57cec5SDimitry Andric StringRef Spell = OwnershipAttr->getKind()->getName(); 100*0b57cec5SDimitry Andric MigrationContext::GCAttrOccurrence::AttrKind Kind; 101*0b57cec5SDimitry Andric if (Spell == "strong") 102*0b57cec5SDimitry Andric Kind = MigrationContext::GCAttrOccurrence::Strong; 103*0b57cec5SDimitry Andric else if (Spell == "weak") 104*0b57cec5SDimitry Andric Kind = MigrationContext::GCAttrOccurrence::Weak; 105*0b57cec5SDimitry Andric else 106*0b57cec5SDimitry Andric return false; 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric MigrateCtx.AttrSet.insert(RawLoc); 109*0b57cec5SDimitry Andric MigrateCtx.GCAttrs.push_back(MigrationContext::GCAttrOccurrence()); 110*0b57cec5SDimitry Andric MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs.back(); 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric Attr.Kind = Kind; 113*0b57cec5SDimitry Andric Attr.Loc = Loc; 114*0b57cec5SDimitry Andric Attr.ModifiedType = TL.getModifiedLoc().getType(); 115*0b57cec5SDimitry Andric Attr.Dcl = D; 116*0b57cec5SDimitry Andric Attr.FullyMigratable = FullyMigratable; 117*0b57cec5SDimitry Andric return true; 118*0b57cec5SDimitry Andric } 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric bool isMigratable(Decl *D) { 121*0b57cec5SDimitry Andric if (isa<TranslationUnitDecl>(D)) 122*0b57cec5SDimitry Andric return false; 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric if (isInMainFile(D)) 125*0b57cec5SDimitry Andric return true; 126*0b57cec5SDimitry Andric 127*0b57cec5SDimitry Andric if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 128*0b57cec5SDimitry Andric return FD->hasBody(); 129*0b57cec5SDimitry Andric 130*0b57cec5SDimitry Andric if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) 131*0b57cec5SDimitry Andric return hasObjCImpl(ContD); 132*0b57cec5SDimitry Andric 133*0b57cec5SDimitry Andric if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { 134*0b57cec5SDimitry Andric for (const auto *MI : RD->methods()) { 135*0b57cec5SDimitry Andric if (MI->isOutOfLine()) 136*0b57cec5SDimitry Andric return true; 137*0b57cec5SDimitry Andric } 138*0b57cec5SDimitry Andric return false; 139*0b57cec5SDimitry Andric } 140*0b57cec5SDimitry Andric 141*0b57cec5SDimitry Andric return isMigratable(cast<Decl>(D->getDeclContext())); 142*0b57cec5SDimitry Andric } 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric static bool hasObjCImpl(Decl *D) { 145*0b57cec5SDimitry Andric if (!D) 146*0b57cec5SDimitry Andric return false; 147*0b57cec5SDimitry Andric if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) { 148*0b57cec5SDimitry Andric if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD)) 149*0b57cec5SDimitry Andric return ID->getImplementation() != nullptr; 150*0b57cec5SDimitry Andric if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD)) 151*0b57cec5SDimitry Andric return CD->getImplementation() != nullptr; 152*0b57cec5SDimitry Andric return isa<ObjCImplDecl>(ContD); 153*0b57cec5SDimitry Andric } 154*0b57cec5SDimitry Andric return false; 155*0b57cec5SDimitry Andric } 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric bool isInMainFile(Decl *D) { 158*0b57cec5SDimitry Andric if (!D) 159*0b57cec5SDimitry Andric return false; 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric for (auto I : D->redecls()) 162*0b57cec5SDimitry Andric if (!isInMainFile(I->getLocation())) 163*0b57cec5SDimitry Andric return false; 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric return true; 166*0b57cec5SDimitry Andric } 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric bool isInMainFile(SourceLocation Loc) { 169*0b57cec5SDimitry Andric if (Loc.isInvalid()) 170*0b57cec5SDimitry Andric return false; 171*0b57cec5SDimitry Andric 172*0b57cec5SDimitry Andric SourceManager &SM = MigrateCtx.Pass.Ctx.getSourceManager(); 173*0b57cec5SDimitry Andric return SM.isInFileID(SM.getExpansionLoc(Loc), SM.getMainFileID()); 174*0b57cec5SDimitry Andric } 175*0b57cec5SDimitry Andric }; 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric } // anonymous namespace 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric static void errorForGCAttrsOnNonObjC(MigrationContext &MigrateCtx) { 180*0b57cec5SDimitry Andric TransformActions &TA = MigrateCtx.Pass.TA; 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) { 183*0b57cec5SDimitry Andric MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i]; 184*0b57cec5SDimitry Andric if (Attr.FullyMigratable && Attr.Dcl) { 185*0b57cec5SDimitry Andric if (Attr.ModifiedType.isNull()) 186*0b57cec5SDimitry Andric continue; 187*0b57cec5SDimitry Andric if (!Attr.ModifiedType->isObjCRetainableType()) { 188*0b57cec5SDimitry Andric TA.reportError("GC managed memory will become unmanaged in ARC", 189*0b57cec5SDimitry Andric Attr.Loc); 190*0b57cec5SDimitry Andric } 191*0b57cec5SDimitry Andric } 192*0b57cec5SDimitry Andric } 193*0b57cec5SDimitry Andric } 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric static void checkWeakGCAttrs(MigrationContext &MigrateCtx) { 196*0b57cec5SDimitry Andric TransformActions &TA = MigrateCtx.Pass.TA; 197*0b57cec5SDimitry Andric 198*0b57cec5SDimitry Andric for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) { 199*0b57cec5SDimitry Andric MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i]; 200*0b57cec5SDimitry Andric if (Attr.Kind == MigrationContext::GCAttrOccurrence::Weak) { 201*0b57cec5SDimitry Andric if (Attr.ModifiedType.isNull() || 202*0b57cec5SDimitry Andric !Attr.ModifiedType->isObjCRetainableType()) 203*0b57cec5SDimitry Andric continue; 204*0b57cec5SDimitry Andric if (!canApplyWeak(MigrateCtx.Pass.Ctx, Attr.ModifiedType, 205*0b57cec5SDimitry Andric /*AllowOnUnknownClass=*/true)) { 206*0b57cec5SDimitry Andric Transaction Trans(TA); 207*0b57cec5SDimitry Andric if (!MigrateCtx.RemovedAttrSet.count(Attr.Loc.getRawEncoding())) 208*0b57cec5SDimitry Andric TA.replaceText(Attr.Loc, "__weak", "__unsafe_unretained"); 209*0b57cec5SDimitry Andric TA.clearDiagnostic(diag::err_arc_weak_no_runtime, 210*0b57cec5SDimitry Andric diag::err_arc_unsupported_weak_class, 211*0b57cec5SDimitry Andric Attr.Loc); 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric } 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric } 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy; 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric static void checkAllAtProps(MigrationContext &MigrateCtx, 220*0b57cec5SDimitry Andric SourceLocation AtLoc, 221*0b57cec5SDimitry Andric IndivPropsTy &IndProps) { 222*0b57cec5SDimitry Andric if (IndProps.empty()) 223*0b57cec5SDimitry Andric return; 224*0b57cec5SDimitry Andric 225*0b57cec5SDimitry Andric for (IndivPropsTy::iterator 226*0b57cec5SDimitry Andric PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) { 227*0b57cec5SDimitry Andric QualType T = (*PI)->getType(); 228*0b57cec5SDimitry Andric if (T.isNull() || !T->isObjCRetainableType()) 229*0b57cec5SDimitry Andric return; 230*0b57cec5SDimitry Andric } 231*0b57cec5SDimitry Andric 232*0b57cec5SDimitry Andric SmallVector<std::pair<AttributedTypeLoc, ObjCPropertyDecl *>, 4> ATLs; 233*0b57cec5SDimitry Andric bool hasWeak = false, hasStrong = false; 234*0b57cec5SDimitry Andric ObjCPropertyDecl::PropertyAttributeKind 235*0b57cec5SDimitry Andric Attrs = ObjCPropertyDecl::OBJC_PR_noattr; 236*0b57cec5SDimitry Andric for (IndivPropsTy::iterator 237*0b57cec5SDimitry Andric PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) { 238*0b57cec5SDimitry Andric ObjCPropertyDecl *PD = *PI; 239*0b57cec5SDimitry Andric Attrs = PD->getPropertyAttributesAsWritten(); 240*0b57cec5SDimitry Andric TypeSourceInfo *TInfo = PD->getTypeSourceInfo(); 241*0b57cec5SDimitry Andric if (!TInfo) 242*0b57cec5SDimitry Andric return; 243*0b57cec5SDimitry Andric TypeLoc TL = TInfo->getTypeLoc(); 244*0b57cec5SDimitry Andric if (AttributedTypeLoc ATL = 245*0b57cec5SDimitry Andric TL.getAs<AttributedTypeLoc>()) { 246*0b57cec5SDimitry Andric ATLs.push_back(std::make_pair(ATL, PD)); 247*0b57cec5SDimitry Andric if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { 248*0b57cec5SDimitry Andric hasWeak = true; 249*0b57cec5SDimitry Andric } else if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Strong) 250*0b57cec5SDimitry Andric hasStrong = true; 251*0b57cec5SDimitry Andric else 252*0b57cec5SDimitry Andric return; 253*0b57cec5SDimitry Andric } 254*0b57cec5SDimitry Andric } 255*0b57cec5SDimitry Andric if (ATLs.empty()) 256*0b57cec5SDimitry Andric return; 257*0b57cec5SDimitry Andric if (hasWeak && hasStrong) 258*0b57cec5SDimitry Andric return; 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andric TransformActions &TA = MigrateCtx.Pass.TA; 261*0b57cec5SDimitry Andric Transaction Trans(TA); 262*0b57cec5SDimitry Andric 263*0b57cec5SDimitry Andric if (GCAttrsCollector::hasObjCImpl( 264*0b57cec5SDimitry Andric cast<Decl>(IndProps.front()->getDeclContext()))) { 265*0b57cec5SDimitry Andric if (hasWeak) 266*0b57cec5SDimitry Andric MigrateCtx.AtPropsWeak.insert(AtLoc.getRawEncoding()); 267*0b57cec5SDimitry Andric 268*0b57cec5SDimitry Andric } else { 269*0b57cec5SDimitry Andric StringRef toAttr = "strong"; 270*0b57cec5SDimitry Andric if (hasWeak) { 271*0b57cec5SDimitry Andric if (canApplyWeak(MigrateCtx.Pass.Ctx, IndProps.front()->getType(), 272*0b57cec5SDimitry Andric /*AllowOnUnknownClass=*/true)) 273*0b57cec5SDimitry Andric toAttr = "weak"; 274*0b57cec5SDimitry Andric else 275*0b57cec5SDimitry Andric toAttr = "unsafe_unretained"; 276*0b57cec5SDimitry Andric } 277*0b57cec5SDimitry Andric if (Attrs & ObjCPropertyDecl::OBJC_PR_assign) 278*0b57cec5SDimitry Andric MigrateCtx.rewritePropertyAttribute("assign", toAttr, AtLoc); 279*0b57cec5SDimitry Andric else 280*0b57cec5SDimitry Andric MigrateCtx.addPropertyAttribute(toAttr, AtLoc); 281*0b57cec5SDimitry Andric } 282*0b57cec5SDimitry Andric 283*0b57cec5SDimitry Andric for (unsigned i = 0, e = ATLs.size(); i != e; ++i) { 284*0b57cec5SDimitry Andric SourceLocation Loc = ATLs[i].first.getAttr()->getLocation(); 285*0b57cec5SDimitry Andric if (Loc.isMacroID()) 286*0b57cec5SDimitry Andric Loc = MigrateCtx.Pass.Ctx.getSourceManager() 287*0b57cec5SDimitry Andric .getImmediateExpansionRange(Loc) 288*0b57cec5SDimitry Andric .getBegin(); 289*0b57cec5SDimitry Andric TA.remove(Loc); 290*0b57cec5SDimitry Andric TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc); 291*0b57cec5SDimitry Andric TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership, 292*0b57cec5SDimitry Andric ATLs[i].second->getLocation()); 293*0b57cec5SDimitry Andric MigrateCtx.RemovedAttrSet.insert(Loc.getRawEncoding()); 294*0b57cec5SDimitry Andric } 295*0b57cec5SDimitry Andric } 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric static void checkAllProps(MigrationContext &MigrateCtx, 298*0b57cec5SDimitry Andric std::vector<ObjCPropertyDecl *> &AllProps) { 299*0b57cec5SDimitry Andric typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy; 300*0b57cec5SDimitry Andric llvm::DenseMap<unsigned, IndivPropsTy> AtProps; 301*0b57cec5SDimitry Andric 302*0b57cec5SDimitry Andric for (unsigned i = 0, e = AllProps.size(); i != e; ++i) { 303*0b57cec5SDimitry Andric ObjCPropertyDecl *PD = AllProps[i]; 304*0b57cec5SDimitry Andric if (PD->getPropertyAttributesAsWritten() & 305*0b57cec5SDimitry Andric (ObjCPropertyDecl::OBJC_PR_assign | 306*0b57cec5SDimitry Andric ObjCPropertyDecl::OBJC_PR_readonly)) { 307*0b57cec5SDimitry Andric SourceLocation AtLoc = PD->getAtLoc(); 308*0b57cec5SDimitry Andric if (AtLoc.isInvalid()) 309*0b57cec5SDimitry Andric continue; 310*0b57cec5SDimitry Andric unsigned RawAt = AtLoc.getRawEncoding(); 311*0b57cec5SDimitry Andric AtProps[RawAt].push_back(PD); 312*0b57cec5SDimitry Andric } 313*0b57cec5SDimitry Andric } 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric for (llvm::DenseMap<unsigned, IndivPropsTy>::iterator 316*0b57cec5SDimitry Andric I = AtProps.begin(), E = AtProps.end(); I != E; ++I) { 317*0b57cec5SDimitry Andric SourceLocation AtLoc = SourceLocation::getFromRawEncoding(I->first); 318*0b57cec5SDimitry Andric IndivPropsTy &IndProps = I->second; 319*0b57cec5SDimitry Andric checkAllAtProps(MigrateCtx, AtLoc, IndProps); 320*0b57cec5SDimitry Andric } 321*0b57cec5SDimitry Andric } 322*0b57cec5SDimitry Andric 323*0b57cec5SDimitry Andric void GCAttrsTraverser::traverseTU(MigrationContext &MigrateCtx) { 324*0b57cec5SDimitry Andric std::vector<ObjCPropertyDecl *> AllProps; 325*0b57cec5SDimitry Andric GCAttrsCollector(MigrateCtx, AllProps).TraverseDecl( 326*0b57cec5SDimitry Andric MigrateCtx.Pass.Ctx.getTranslationUnitDecl()); 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric errorForGCAttrsOnNonObjC(MigrateCtx); 329*0b57cec5SDimitry Andric checkAllProps(MigrateCtx, AllProps); 330*0b57cec5SDimitry Andric checkWeakGCAttrs(MigrateCtx); 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric void MigrationContext::dumpGCAttrs() { 334*0b57cec5SDimitry Andric llvm::errs() << "\n################\n"; 335*0b57cec5SDimitry Andric for (unsigned i = 0, e = GCAttrs.size(); i != e; ++i) { 336*0b57cec5SDimitry Andric GCAttrOccurrence &Attr = GCAttrs[i]; 337*0b57cec5SDimitry Andric llvm::errs() << "KIND: " 338*0b57cec5SDimitry Andric << (Attr.Kind == GCAttrOccurrence::Strong ? "strong" : "weak"); 339*0b57cec5SDimitry Andric llvm::errs() << "\nLOC: "; 340*0b57cec5SDimitry Andric Attr.Loc.print(llvm::errs(), Pass.Ctx.getSourceManager()); 341*0b57cec5SDimitry Andric llvm::errs() << "\nTYPE: "; 342*0b57cec5SDimitry Andric Attr.ModifiedType.dump(); 343*0b57cec5SDimitry Andric if (Attr.Dcl) { 344*0b57cec5SDimitry Andric llvm::errs() << "DECL:\n"; 345*0b57cec5SDimitry Andric Attr.Dcl->dump(); 346*0b57cec5SDimitry Andric } else { 347*0b57cec5SDimitry Andric llvm::errs() << "DECL: NONE"; 348*0b57cec5SDimitry Andric } 349*0b57cec5SDimitry Andric llvm::errs() << "\nMIGRATABLE: " << Attr.FullyMigratable; 350*0b57cec5SDimitry Andric llvm::errs() << "\n----------------\n"; 351*0b57cec5SDimitry Andric } 352*0b57cec5SDimitry Andric llvm::errs() << "\n################\n"; 353*0b57cec5SDimitry Andric } 354