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