1f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis//===--- TransGCAttrs.cpp - Transformations to ARC mode --------------------===//
2f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis//
3f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
4f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis//
5f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
6f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis// License. See LICENSE.TXT for details.
7f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis//
8f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
9f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
10f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis#include "Transforms.h"
11f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis#include "Internals.h"
12471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h"
13f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis#include "clang/Basic/SourceManager.h"
14471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/Lex/Lexer.h"
1512192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis#include "clang/Sema/SemaDiagnostic.h"
168fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h"
17b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis#include "llvm/ADT/TinyPtrVector.h"
18471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "llvm/Support/SaveAndRestore.h"
19f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
20f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidisusing namespace clang;
21f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidisusing namespace arcmt;
22f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidisusing namespace trans;
23f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
24f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidisnamespace {
25f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
26f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis/// \brief Collects all the places where GC attributes __strong/__weak occur.
27f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidisclass GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
28f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  MigrationContext &MigrateCtx;
29f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool FullyMigratable;
30b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  std::vector<ObjCPropertyDecl *> &AllProps;
31f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
32f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  typedef RecursiveASTVisitor<GCAttrsCollector> base;
33f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidispublic:
34b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  GCAttrsCollector(MigrationContext &ctx,
35b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                   std::vector<ObjCPropertyDecl *> &AllProps)
36b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    : MigrateCtx(ctx), FullyMigratable(false),
37b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      AllProps(AllProps) { }
38f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
39f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool shouldWalkTypesOfTypeLocs() const { return false; }
40f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
41f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool VisitAttributedTypeLoc(AttributedTypeLoc TL) {
42f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    handleAttr(TL);
43f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    return true;
44f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  }
45f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
46f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool TraverseDecl(Decl *D) {
47f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (!D || D->isImplicit())
48f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return true;
49f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
50b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    SaveAndRestore<bool> Save(FullyMigratable, isMigratable(D));
51f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
52b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D)) {
53f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      lookForAttribute(PropD, PropD->getTypeSourceInfo());
54b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      AllProps.push_back(PropD);
55b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    } else if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
56b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      lookForAttribute(DD, DD->getTypeSourceInfo());
57b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
58f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    return base::TraverseDecl(D);
59f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  }
60f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
61f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  void lookForAttribute(Decl *D, TypeSourceInfo *TInfo) {
62f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (!TInfo)
63f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return;
64f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    TypeLoc TL = TInfo->getTypeLoc();
65f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    while (TL) {
6639e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie      if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>()) {
6739e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie        TL = QL.getUnqualifiedLoc();
6839e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie      } else if (AttributedTypeLoc Attr = TL.getAs<AttributedTypeLoc>()) {
6939e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie        if (handleAttr(Attr, D))
70f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis          break;
7139e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie        TL = Attr.getModifiedLoc();
7239e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie      } else if (ArrayTypeLoc Arr = TL.getAs<ArrayTypeLoc>()) {
7339e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie        TL = Arr.getElementLoc();
7439e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie      } else if (PointerTypeLoc PT = TL.getAs<PointerTypeLoc>()) {
7539e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie        TL = PT.getPointeeLoc();
7639e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie      } else if (ReferenceTypeLoc RT = TL.getAs<ReferenceTypeLoc>())
7739e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie        TL = RT.getPointeeLoc();
78f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      else
79f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis        break;
80f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    }
81f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  }
82f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {
84f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (TL.getAttrKind() != AttributedType::attr_objc_ownership)
85f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return false;
86f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
87f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    SourceLocation Loc = TL.getAttrNameLoc();
88f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    unsigned RawLoc = Loc.getRawEncoding();
89f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (MigrateCtx.AttrSet.count(RawLoc))
90f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return true;
91f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
92f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    ASTContext &Ctx = MigrateCtx.Pass.Ctx;
93f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    SourceManager &SM = Ctx.getSourceManager();
9412192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis    if (Loc.isMacroID())
9512192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis      Loc = SM.getImmediateExpansionRange(Loc).first;
96f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    SmallString<32> Buf;
97f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    bool Invalid = false;
98f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    StringRef Spell = Lexer::getSpelling(
99f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis                                  SM.getSpellingLoc(TL.getAttrEnumOperandLoc()),
1004e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie                                  Buf, SM, Ctx.getLangOpts(), &Invalid);
101f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (Invalid)
102f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return false;
103f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    MigrationContext::GCAttrOccurrence::AttrKind Kind;
104f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (Spell == "strong")
105f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      Kind = MigrationContext::GCAttrOccurrence::Strong;
106f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    else if (Spell == "weak")
107f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      Kind = MigrationContext::GCAttrOccurrence::Weak;
108f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    else
109f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return false;
110f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
111f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    MigrateCtx.AttrSet.insert(RawLoc);
112f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    MigrateCtx.GCAttrs.push_back(MigrationContext::GCAttrOccurrence());
113f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs.back();
114f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
115f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    Attr.Kind = Kind;
11612192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis    Attr.Loc = Loc;
117f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    Attr.ModifiedType = TL.getModifiedLoc().getType();
118f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    Attr.Dcl = D;
119f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    Attr.FullyMigratable = FullyMigratable;
120f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    return true;
121f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  }
122f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
123f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool isMigratable(Decl *D) {
124f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (isa<TranslationUnitDecl>(D))
125f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return false;
126f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
127f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (isInMainFile(D))
128f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return true;
129f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
130f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
131f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return FD->hasBody();
132f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
133b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D))
134b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return hasObjCImpl(ContD);
135f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
136f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      for (const auto *MI : RD->methods()) {
138262bc18e32500558af7cb0afa205b34bd37bafedDavid Blaikie        if (MI->isOutOfLine())
139f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis          return true;
140f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      }
141f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return false;
142f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    }
143f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
144f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    return isMigratable(cast<Decl>(D->getDeclContext()));
145f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  }
146f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
147b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  static bool hasObjCImpl(Decl *D) {
148b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!D)
149b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return false;
150b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) {
151b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD))
1526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        return ID->getImplementation() != nullptr;
153b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD))
1546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        return CD->getImplementation() != nullptr;
155a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar      return isa<ObjCImplDecl>(ContD);
156b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
157b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return false;
158b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
159b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
160f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool isInMainFile(Decl *D) {
161f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (!D)
162f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return false;
163f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (auto I : D->redecls())
165bd4fa45e7cf6a2f0adcb0ab66d5b3d338ec56c3cDavid Blaikie      if (!isInMainFile(I->getLocation()))
166f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis        return false;
167f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
168f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    return true;
169f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  }
170f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
171f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  bool isInMainFile(SourceLocation Loc) {
172f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (Loc.isInvalid())
173f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      return false;
174f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
175f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    SourceManager &SM = MigrateCtx.Pass.Ctx.getSourceManager();
176f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    return SM.isInFileID(SM.getExpansionLoc(Loc), SM.getMainFileID());
177f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  }
178f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis};
179f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
180f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis} // anonymous namespace
181f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis
182280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidisstatic void errorForGCAttrsOnNonObjC(MigrationContext &MigrateCtx) {
183280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis  TransformActions &TA = MigrateCtx.Pass.TA;
184280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis
185280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis  for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
186280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis    MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
187280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis    if (Attr.FullyMigratable && Attr.Dcl) {
188280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis      if (Attr.ModifiedType.isNull())
189280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis        continue;
190280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis      if (!Attr.ModifiedType->isObjCRetainableType()) {
191280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis        TA.reportError("GC managed memory will become unmanaged in ARC",
192280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis                       Attr.Loc);
193280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis      }
194280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis    }
195280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis  }
196280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis}
197280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis
19812192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidisstatic void checkWeakGCAttrs(MigrationContext &MigrateCtx) {
19912192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis  TransformActions &TA = MigrateCtx.Pass.TA;
20012192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis
20112192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis  for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
20212192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis    MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
203b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (Attr.Kind == MigrationContext::GCAttrOccurrence::Weak) {
20412192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis      if (Attr.ModifiedType.isNull() ||
20512192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis          !Attr.ModifiedType->isObjCRetainableType())
20612192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis        continue;
20712192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis      if (!canApplyWeak(MigrateCtx.Pass.Ctx, Attr.ModifiedType,
20812192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis                        /*AllowOnUnknownClass=*/true)) {
20912192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis        Transaction Trans(TA);
2107cfd7fe020144afe61ffe4de6c43c10340c415a7Argyrios Kyrtzidis        if (!MigrateCtx.RemovedAttrSet.count(Attr.Loc.getRawEncoding()))
2117cfd7fe020144afe61ffe4de6c43c10340c415a7Argyrios Kyrtzidis          TA.replaceText(Attr.Loc, "__weak", "__unsafe_unretained");
21212192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis        TA.clearDiagnostic(diag::err_arc_weak_no_runtime,
21312192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis                           diag::err_arc_unsupported_weak_class,
21412192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis                           Attr.Loc);
21512192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis      }
21612192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis    }
21712192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis  }
21812192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis}
21912192cf50a96cb59a3039af044b7fa97f043101cArgyrios Kyrtzidis
220b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidistypedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
221b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
222b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidisstatic void checkAllAtProps(MigrationContext &MigrateCtx,
223b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                            SourceLocation AtLoc,
224b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                            IndivPropsTy &IndProps) {
225b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (IndProps.empty())
226b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return;
227b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
228b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  for (IndivPropsTy::iterator
229b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis         PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
230b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    QualType T = (*PI)->getType();
231b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (T.isNull() || !T->isObjCRetainableType())
232b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return;
233b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
234b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
235b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  SmallVector<std::pair<AttributedTypeLoc, ObjCPropertyDecl *>, 4> ATLs;
236b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  bool hasWeak = false, hasStrong = false;
2376da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis  ObjCPropertyDecl::PropertyAttributeKind
2386da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    Attrs = ObjCPropertyDecl::OBJC_PR_noattr;
239b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  for (IndivPropsTy::iterator
240b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis         PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
241b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    ObjCPropertyDecl *PD = *PI;
2426da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    Attrs = PD->getPropertyAttributesAsWritten();
243b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    TypeSourceInfo *TInfo = PD->getTypeSourceInfo();
244b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (!TInfo)
245b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      return;
246b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    TypeLoc TL = TInfo->getTypeLoc();
24739e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie    if (AttributedTypeLoc ATL =
24839e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie            TL.getAs<AttributedTypeLoc>()) {
24939e6ab4be93d9c5e729a578ddd9d415cd2d49872David Blaikie      ATLs.push_back(std::make_pair(ATL, PD));
250b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
251b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        hasWeak = true;
252b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      } else if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Strong)
253b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        hasStrong = true;
254b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      else
255b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        return;
256b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
257b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
258b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (ATLs.empty())
259b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return;
260b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (hasWeak && hasStrong)
261b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    return;
262b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
263b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  TransformActions &TA = MigrateCtx.Pass.TA;
264b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  Transaction Trans(TA);
265b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
266b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  if (GCAttrsCollector::hasObjCImpl(
267b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                              cast<Decl>(IndProps.front()->getDeclContext()))) {
268b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (hasWeak)
269b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      MigrateCtx.AtPropsWeak.insert(AtLoc.getRawEncoding());
270b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
271b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  } else {
272b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    StringRef toAttr = "strong";
273b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (hasWeak) {
274b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (canApplyWeak(MigrateCtx.Pass.Ctx, IndProps.front()->getType(),
275b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                       /*AllowOnUnkwownClass=*/true))
276b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        toAttr = "weak";
277b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      else
278b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        toAttr = "unsafe_unretained";
279b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
2806da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    if (Attrs & ObjCPropertyDecl::OBJC_PR_assign)
2816da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis      MigrateCtx.rewritePropertyAttribute("assign", toAttr, AtLoc);
2826da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis    else
2836da4274724f6bd0f24f0fbfd1af076cd14b14710Argyrios Kyrtzidis      MigrateCtx.addPropertyAttribute(toAttr, AtLoc);
284b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
285b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
286b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
287b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
288b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (Loc.isMacroID())
289b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      Loc = MigrateCtx.Pass.Ctx.getSourceManager()
290b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                                         .getImmediateExpansionRange(Loc).first;
291b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    TA.remove(Loc);
292b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);
293b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,
294b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                       ATLs[i].second->getLocation());
2957cfd7fe020144afe61ffe4de6c43c10340c415a7Argyrios Kyrtzidis    MigrateCtx.RemovedAttrSet.insert(Loc.getRawEncoding());
296b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
297b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis}
298b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
299b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidisstatic void checkAllProps(MigrationContext &MigrateCtx,
300b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis                          std::vector<ObjCPropertyDecl *> &AllProps) {
301b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
302b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  llvm::DenseMap<unsigned, IndivPropsTy> AtProps;
303b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
304b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  for (unsigned i = 0, e = AllProps.size(); i != e; ++i) {
305b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    ObjCPropertyDecl *PD = AllProps[i];
306b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    if (PD->getPropertyAttributesAsWritten() &
3076d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis          (ObjCPropertyDecl::OBJC_PR_assign |
3086d7d16d45c1d601483e46a77bd2fa1d199219721Argyrios Kyrtzidis           ObjCPropertyDecl::OBJC_PR_readonly)) {
309b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      SourceLocation AtLoc = PD->getAtLoc();
310b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      if (AtLoc.isInvalid())
311b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis        continue;
312b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      unsigned RawAt = AtLoc.getRawEncoding();
313b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis      AtProps[RawAt].push_back(PD);
314b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    }
315b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
316b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
317b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  for (llvm::DenseMap<unsigned, IndivPropsTy>::iterator
318b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis         I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
319b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    SourceLocation AtLoc = SourceLocation::getFromRawEncoding(I->first);
320b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    IndivPropsTy &IndProps = I->second;
321b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis    checkAllAtProps(MigrateCtx, AtLoc, IndProps);
322b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  }
323b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis}
324b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis
325f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidisvoid GCAttrsTraverser::traverseTU(MigrationContext &MigrateCtx) {
326b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  std::vector<ObjCPropertyDecl *> AllProps;
327b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  GCAttrsCollector(MigrateCtx, AllProps).TraverseDecl(
328f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis                                  MigrateCtx.Pass.Ctx.getTranslationUnitDecl());
329280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis
330280b4ada965f89607684446e826d830f0b8a7864Argyrios Kyrtzidis  errorForGCAttrsOnNonObjC(MigrateCtx);
331b0e1e121b32a9a04b39f1b77b3068bce2f3be05aArgyrios Kyrtzidis  checkAllProps(MigrateCtx, AllProps);
3327cfd7fe020144afe61ffe4de6c43c10340c415a7Argyrios Kyrtzidis  checkWeakGCAttrs(MigrateCtx);
33317ac3197941b9f135424dfe3900577a04407c5c2Argyrios Kyrtzidis}
33417ac3197941b9f135424dfe3900577a04407c5c2Argyrios Kyrtzidis
33517ac3197941b9f135424dfe3900577a04407c5c2Argyrios Kyrtzidisvoid MigrationContext::dumpGCAttrs() {
336f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  llvm::errs() << "\n################\n";
33717ac3197941b9f135424dfe3900577a04407c5c2Argyrios Kyrtzidis  for (unsigned i = 0, e = GCAttrs.size(); i != e; ++i) {
33817ac3197941b9f135424dfe3900577a04407c5c2Argyrios Kyrtzidis    GCAttrOccurrence &Attr = GCAttrs[i];
339f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    llvm::errs() << "KIND: "
34017ac3197941b9f135424dfe3900577a04407c5c2Argyrios Kyrtzidis        << (Attr.Kind == GCAttrOccurrence::Strong ? "strong" : "weak");
341f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    llvm::errs() << "\nLOC: ";
34217ac3197941b9f135424dfe3900577a04407c5c2Argyrios Kyrtzidis    Attr.Loc.dump(Pass.Ctx.getSourceManager());
343f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    llvm::errs() << "\nTYPE: ";
344f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    Attr.ModifiedType.dump();
345f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    if (Attr.Dcl) {
346f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      llvm::errs() << "DECL:\n";
347f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      Attr.Dcl->dump();
348f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    } else {
349f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis      llvm::errs() << "DECL: NONE";
350f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    }
351f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    llvm::errs() << "\nMIGRATABLE: " << Attr.FullyMigratable;
352f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis    llvm::errs() << "\n----------------\n";
353f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  }
354f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis  llvm::errs() << "\n################\n";
355f38fa73e605587abfa32ab6a39887cdebc0a320aArgyrios Kyrtzidis}
356