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