xref: /freebsd-src/contrib/llvm-project/clang/lib/ARCMigrate/TransGCAttrs.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
330b57cec5SDimitry Andric   GCAttrsCollector(MigrationContext &ctx,
340b57cec5SDimitry Andric                    std::vector<ObjCPropertyDecl *> &AllProps)
350b57cec5SDimitry Andric     : MigrateCtx(ctx), FullyMigratable(false),
360b57cec5SDimitry Andric       AllProps(AllProps) { }
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   bool shouldWalkTypesOfTypeLocs() const { return false; }
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   bool VisitAttributedTypeLoc(AttributedTypeLoc TL) {
410b57cec5SDimitry Andric     handleAttr(TL);
420b57cec5SDimitry Andric     return true;
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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