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