ObjCMT.cpp revision d0f2921c3211299a80c043a3251e6b34dddba061
1//===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "Transforms.h" 11#include "clang/ARCMigrate/ARCMTActions.h" 12#include "clang/AST/ASTConsumer.h" 13#include "clang/AST/ASTContext.h" 14#include "clang/AST/NSAPI.h" 15#include "clang/AST/ParentMap.h" 16#include "clang/AST/RecursiveASTVisitor.h" 17#include "clang/Basic/FileManager.h" 18#include "clang/Edit/Commit.h" 19#include "clang/Edit/EditedSource.h" 20#include "clang/Edit/EditsReceiver.h" 21#include "clang/Edit/Rewriters.h" 22#include "clang/Frontend/CompilerInstance.h" 23#include "clang/Frontend/MultiplexConsumer.h" 24#include "clang/Lex/PPConditionalDirectiveRecord.h" 25#include "clang/Lex/Preprocessor.h" 26#include "clang/Rewrite/Core/Rewriter.h" 27#include "clang/Analysis/DomainSpecific/CocoaConventions.h" 28#include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h" 29#include "clang/AST/Attr.h" 30#include "llvm/ADT/SmallString.h" 31 32using namespace clang; 33using namespace arcmt; 34using namespace ento::objc_retain; 35 36namespace { 37 38class ObjCMigrateASTConsumer : public ASTConsumer { 39 enum CF_BRIDGING_KIND { 40 CF_BRIDGING_NONE, 41 CF_BRIDGING_ENABLE, 42 CF_BRIDGING_MAY_INCLUDE 43 }; 44 45 void migrateDecl(Decl *D); 46 void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCInterfaceDecl *D); 47 void migrateProtocolConformance(ASTContext &Ctx, 48 const ObjCImplementationDecl *ImpDecl); 49 void migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl, 50 const TypedefDecl *TypedefDcl); 51 void migrateInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl); 52 void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl, 53 ObjCMethodDecl *OM); 54 void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl, 55 ObjCMethodDecl *OM, 56 ObjCInstanceTypeFamily OIT_Family = OIT_None); 57 58 void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl); 59 void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE, 60 const FunctionDecl *FuncDecl, bool ResultAnnotated); 61 void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE, 62 const ObjCMethodDecl *MethodDecl, bool ResultAnnotated); 63 64 void AnnotateImplicitBridging(ASTContext &Ctx); 65 66 CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx, 67 const FunctionDecl *FuncDecl); 68 69 void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl); 70 71 CF_BRIDGING_KIND migrateAddMethodAnnotation(ASTContext &Ctx, 72 const ObjCMethodDecl *MethodDecl); 73public: 74 std::string MigrateDir; 75 bool MigrateLiterals; 76 bool MigrateSubscripting; 77 bool MigrateProperty; 78 bool MigrateReadonlyProperty; 79 unsigned FileId; 80 OwningPtr<NSAPI> NSAPIObj; 81 OwningPtr<edit::EditedSource> Editor; 82 FileRemapper &Remapper; 83 FileManager &FileMgr; 84 const PPConditionalDirectiveRecord *PPRec; 85 Preprocessor &PP; 86 bool IsOutputFile; 87 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls; 88 llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates; 89 90 ObjCMigrateASTConsumer(StringRef migrateDir, 91 bool migrateLiterals, 92 bool migrateSubscripting, 93 bool migrateProperty, 94 bool migrateReadonlyProperty, 95 FileRemapper &remapper, 96 FileManager &fileMgr, 97 const PPConditionalDirectiveRecord *PPRec, 98 Preprocessor &PP, 99 bool isOutputFile = false) 100 : MigrateDir(migrateDir), 101 MigrateLiterals(migrateLiterals), 102 MigrateSubscripting(migrateSubscripting), 103 MigrateProperty(migrateProperty), 104 MigrateReadonlyProperty(migrateReadonlyProperty), 105 FileId(0), Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP), 106 IsOutputFile(isOutputFile) { } 107 108protected: 109 virtual void Initialize(ASTContext &Context) { 110 NSAPIObj.reset(new NSAPI(Context)); 111 Editor.reset(new edit::EditedSource(Context.getSourceManager(), 112 Context.getLangOpts(), 113 PPRec)); 114 } 115 116 virtual bool HandleTopLevelDecl(DeclGroupRef DG) { 117 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 118 migrateDecl(*I); 119 return true; 120 } 121 virtual void HandleInterestingDecl(DeclGroupRef DG) { 122 // Ignore decls from the PCH. 123 } 124 virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) { 125 ObjCMigrateASTConsumer::HandleTopLevelDecl(DG); 126 } 127 128 virtual void HandleTranslationUnit(ASTContext &Ctx); 129}; 130 131} 132 133ObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction, 134 StringRef migrateDir, 135 bool migrateLiterals, 136 bool migrateSubscripting, 137 bool migrateProperty, 138 bool migrateReadonlyProperty) 139 : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir), 140 MigrateLiterals(migrateLiterals), MigrateSubscripting(migrateSubscripting), 141 MigrateProperty(migrateProperty), 142 MigrateReadonlyProperty(migrateReadonlyProperty), 143 CompInst(0) { 144 if (MigrateDir.empty()) 145 MigrateDir = "."; // user current directory if none is given. 146} 147 148ASTConsumer *ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, 149 StringRef InFile) { 150 PPConditionalDirectiveRecord * 151 PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager()); 152 CompInst->getPreprocessor().addPPCallbacks(PPRec); 153 ASTConsumer * 154 WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); 155 ASTConsumer *MTConsumer = new ObjCMigrateASTConsumer(MigrateDir, 156 MigrateLiterals, 157 MigrateSubscripting, 158 MigrateProperty, 159 MigrateReadonlyProperty, 160 Remapper, 161 CompInst->getFileManager(), 162 PPRec, 163 CompInst->getPreprocessor()); 164 ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer }; 165 return new MultiplexConsumer(Consumers); 166} 167 168bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) { 169 Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(), 170 /*ignoreIfFilesChanges=*/true); 171 CompInst = &CI; 172 CI.getDiagnostics().setIgnoreAllWarnings(true); 173 return true; 174} 175 176namespace { 177class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> { 178 ObjCMigrateASTConsumer &Consumer; 179 ParentMap &PMap; 180 181public: 182 ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap) 183 : Consumer(consumer), PMap(PMap) { } 184 185 bool shouldVisitTemplateInstantiations() const { return false; } 186 bool shouldWalkTypesOfTypeLocs() const { return false; } 187 188 bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 189 if (Consumer.MigrateLiterals) { 190 edit::Commit commit(*Consumer.Editor); 191 edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap); 192 Consumer.Editor->commit(commit); 193 } 194 195 if (Consumer.MigrateSubscripting) { 196 edit::Commit commit(*Consumer.Editor); 197 edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit); 198 Consumer.Editor->commit(commit); 199 } 200 201 return true; 202 } 203 204 bool TraverseObjCMessageExpr(ObjCMessageExpr *E) { 205 // Do depth first; we want to rewrite the subexpressions first so that if 206 // we have to move expressions we will move them already rewritten. 207 for (Stmt::child_range range = E->children(); range; ++range) 208 if (!TraverseStmt(*range)) 209 return false; 210 211 return WalkUpFromObjCMessageExpr(E); 212 } 213}; 214 215class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> { 216 ObjCMigrateASTConsumer &Consumer; 217 OwningPtr<ParentMap> PMap; 218 219public: 220 BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { } 221 222 bool shouldVisitTemplateInstantiations() const { return false; } 223 bool shouldWalkTypesOfTypeLocs() const { return false; } 224 225 bool TraverseStmt(Stmt *S) { 226 PMap.reset(new ParentMap(S)); 227 ObjCMigrator(Consumer, *PMap).TraverseStmt(S); 228 return true; 229 } 230}; 231} 232 233void ObjCMigrateASTConsumer::migrateDecl(Decl *D) { 234 if (!D) 235 return; 236 if (isa<ObjCMethodDecl>(D)) 237 return; // Wait for the ObjC container declaration. 238 239 BodyMigrator(*this).TraverseDecl(D); 240} 241 242static void append_attr(std::string &PropertyString, const char *attr) { 243 PropertyString += ", "; 244 PropertyString += attr; 245} 246 247static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, 248 const ObjCMethodDecl *Setter, 249 const NSAPI &NS, edit::Commit &commit, 250 bool GetterHasIsPrefix) { 251 ASTContext &Context = NS.getASTContext(); 252 std::string PropertyString = "@property(nonatomic"; 253 std::string PropertyNameString = Getter->getNameAsString(); 254 StringRef PropertyName(PropertyNameString); 255 if (GetterHasIsPrefix) { 256 PropertyString += ", getter="; 257 PropertyString += PropertyNameString; 258 } 259 // Property with no setter may be suggested as a 'readonly' property. 260 if (!Setter) 261 append_attr(PropertyString, "readonly"); 262 263 // Short circuit properties that contain the name "delegate" or "dataSource", 264 // or have exact name "target" to have unsafe_unretained attribute. 265 if (PropertyName.equals("target") || 266 (PropertyName.find("delegate") != StringRef::npos) || 267 (PropertyName.find("dataSource") != StringRef::npos)) 268 append_attr(PropertyString, "unsafe_unretained"); 269 else if (Setter) { 270 const ParmVarDecl *argDecl = *Setter->param_begin(); 271 QualType ArgType = Context.getCanonicalType(argDecl->getType()); 272 Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime(); 273 bool RetainableObject = ArgType->isObjCRetainableType(); 274 if (RetainableObject && propertyLifetime == Qualifiers::OCL_Strong) { 275 if (const ObjCObjectPointerType *ObjPtrTy = 276 ArgType->getAs<ObjCObjectPointerType>()) { 277 ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); 278 if (IDecl && 279 IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying"))) 280 append_attr(PropertyString, "copy"); 281 else 282 append_attr(PropertyString, "retain"); 283 } 284 } else if (propertyLifetime == Qualifiers::OCL_Weak) 285 // TODO. More precise determination of 'weak' attribute requires 286 // looking into setter's implementation for backing weak ivar. 287 append_attr(PropertyString, "weak"); 288 else if (RetainableObject) 289 append_attr(PropertyString, "retain"); 290 } 291 PropertyString += ')'; 292 293 QualType RT = Getter->getResultType(); 294 if (!isa<TypedefType>(RT)) { 295 // strip off any ARC lifetime qualifier. 296 QualType CanResultTy = Context.getCanonicalType(RT); 297 if (CanResultTy.getQualifiers().hasObjCLifetime()) { 298 Qualifiers Qs = CanResultTy.getQualifiers(); 299 Qs.removeObjCLifetime(); 300 RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); 301 } 302 } 303 PropertyString += " "; 304 PropertyString += RT.getAsString(Context.getPrintingPolicy()); 305 PropertyString += " "; 306 if (GetterHasIsPrefix) { 307 // property name must strip off "is" and lower case the first character 308 // after that; e.g. isContinuous will become continuous. 309 StringRef PropertyNameStringRef(PropertyNameString); 310 PropertyNameStringRef = PropertyNameStringRef.drop_front(2); 311 PropertyNameString = PropertyNameStringRef; 312 std::string NewPropertyNameString = PropertyNameString; 313 NewPropertyNameString[0] = toLowercase(NewPropertyNameString[0]); 314 PropertyString += NewPropertyNameString; 315 } 316 else 317 PropertyString += PropertyNameString; 318 commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(), 319 Getter->getDeclaratorEndLoc()), 320 PropertyString); 321 if (Setter) { 322 SourceLocation EndLoc = Setter->getDeclaratorEndLoc(); 323 // Get location past ';' 324 EndLoc = EndLoc.getLocWithOffset(1); 325 commit.remove(CharSourceRange::getCharRange(Setter->getLocStart(), EndLoc)); 326 } 327 return true; 328} 329 330void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx, 331 ObjCInterfaceDecl *D) { 332 for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end(); 333 M != MEnd; ++M) { 334 ObjCMethodDecl *Method = (*M); 335 if (Method->isPropertyAccessor() || !Method->isInstanceMethod() || 336 Method->param_size() != 0) 337 continue; 338 // Is this method candidate to be a getter? 339 QualType GRT = Method->getResultType(); 340 if (GRT->isVoidType()) 341 continue; 342 // FIXME. Don't know what todo with attributes, skip for now. 343 if (Method->hasAttrs()) 344 continue; 345 346 Selector GetterSelector = Method->getSelector(); 347 IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0); 348 Selector SetterSelector = 349 SelectorTable::constructSetterSelector(PP.getIdentifierTable(), 350 PP.getSelectorTable(), 351 getterName); 352 ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true); 353 bool GetterHasIsPrefix = false; 354 if (!SetterMethod) { 355 // try a different naming convention for getter: isXxxxx 356 StringRef getterNameString = getterName->getName(); 357 if (getterNameString.startswith("is") && !GRT->isObjCRetainableType()) { 358 GetterHasIsPrefix = true; 359 const char *CGetterName = getterNameString.data() + 2; 360 if (CGetterName[0] && isUppercase(CGetterName[0])) { 361 getterName = &Ctx.Idents.get(CGetterName); 362 SetterSelector = 363 SelectorTable::constructSetterSelector(PP.getIdentifierTable(), 364 PP.getSelectorTable(), 365 getterName); 366 SetterMethod = D->lookupMethod(SetterSelector, true); 367 } 368 } 369 } 370 if (SetterMethod) { 371 // Is this a valid setter, matching the target getter? 372 QualType SRT = SetterMethod->getResultType(); 373 if (!SRT->isVoidType()) 374 continue; 375 const ParmVarDecl *argDecl = *SetterMethod->param_begin(); 376 QualType ArgType = argDecl->getType(); 377 if (!Ctx.hasSameUnqualifiedType(ArgType, GRT) || 378 SetterMethod->hasAttrs()) 379 continue; 380 edit::Commit commit(*Editor); 381 rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit, 382 GetterHasIsPrefix); 383 Editor->commit(commit); 384 } 385 else if (MigrateReadonlyProperty) { 386 // Try a non-void method with no argument (and no setter or property of same name 387 // as a 'readonly' property. 388 edit::Commit commit(*Editor); 389 rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit, 390 false /*GetterHasIsPrefix*/); 391 Editor->commit(commit); 392 } 393 } 394} 395 396static bool 397ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, 398 const ObjCImplementationDecl *ImpDecl, 399 const ObjCInterfaceDecl *IDecl, 400 ObjCProtocolDecl *Protocol) { 401 // In auto-synthesis, protocol properties are not synthesized. So, 402 // a conforming protocol must have its required properties declared 403 // in class interface. 404 bool HasAtleastOneRequiredProperty = false; 405 if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) 406 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 407 E = PDecl->prop_end(); P != E; ++P) { 408 ObjCPropertyDecl *Property = *P; 409 if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional) 410 continue; 411 HasAtleastOneRequiredProperty = true; 412 DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName()); 413 if (R.size() == 0) { 414 // Relax the rule and look into class's implementation for a synthesize 415 // or dynamic declaration. Class is implementing a property coming from 416 // another protocol. This still makes the target protocol as conforming. 417 if (!ImpDecl->FindPropertyImplDecl( 418 Property->getDeclName().getAsIdentifierInfo())) 419 return false; 420 } 421 else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) { 422 if ((ClassProperty->getPropertyAttributes() 423 != Property->getPropertyAttributes()) || 424 !Ctx.hasSameType(ClassProperty->getType(), Property->getType())) 425 return false; 426 } 427 else 428 return false; 429 } 430 431 // At this point, all required properties in this protocol conform to those 432 // declared in the class. 433 // Check that class implements the required methods of the protocol too. 434 bool HasAtleastOneRequiredMethod = false; 435 if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) { 436 if (PDecl->meth_begin() == PDecl->meth_end()) 437 return HasAtleastOneRequiredProperty; 438 for (ObjCContainerDecl::method_iterator M = PDecl->meth_begin(), 439 MEnd = PDecl->meth_end(); M != MEnd; ++M) { 440 ObjCMethodDecl *MD = (*M); 441 if (MD->isImplicit()) 442 continue; 443 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) 444 continue; 445 DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName()); 446 if (R.size() == 0) 447 return false; 448 bool match = false; 449 HasAtleastOneRequiredMethod = true; 450 for (unsigned I = 0, N = R.size(); I != N; ++I) 451 if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0])) 452 if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) { 453 match = true; 454 break; 455 } 456 if (!match) 457 return false; 458 } 459 } 460 if (HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod) 461 return true; 462 return false; 463} 464 465static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, 466 llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols, 467 const NSAPI &NS, edit::Commit &commit) { 468 const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols(); 469 std::string ClassString; 470 SourceLocation EndLoc = 471 IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation(); 472 473 if (Protocols.empty()) { 474 ClassString = '<'; 475 for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 476 ClassString += ConformingProtocols[i]->getNameAsString(); 477 if (i != (e-1)) 478 ClassString += ", "; 479 } 480 ClassString += "> "; 481 } 482 else { 483 ClassString = ", "; 484 for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 485 ClassString += ConformingProtocols[i]->getNameAsString(); 486 if (i != (e-1)) 487 ClassString += ", "; 488 } 489 ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1; 490 EndLoc = *PL; 491 } 492 493 commit.insertAfterToken(EndLoc, ClassString); 494 return true; 495} 496 497static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, 498 const TypedefDecl *TypedefDcl, 499 const NSAPI &NS, edit::Commit &commit, 500 bool IsNSIntegerType) { 501 std::string ClassString = 502 IsNSIntegerType ? "typedef NS_ENUM(NSInteger, " : "typedef NS_OPTIONS(NSUInteger, "; 503 ClassString += TypedefDcl->getIdentifier()->getName(); 504 ClassString += ')'; 505 SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart()); 506 commit.replace(R, ClassString); 507 SourceLocation EndOfTypedefLoc = TypedefDcl->getLocEnd(); 508 EndOfTypedefLoc = trans::findLocationAfterSemi(EndOfTypedefLoc, NS.getASTContext()); 509 if (!EndOfTypedefLoc.isInvalid()) { 510 commit.remove(SourceRange(TypedefDcl->getLocStart(), EndOfTypedefLoc)); 511 return true; 512 } 513 return false; 514} 515 516static bool rewriteToNSMacroDecl(const EnumDecl *EnumDcl, 517 const TypedefDecl *TypedefDcl, 518 const NSAPI &NS, edit::Commit &commit, 519 bool IsNSIntegerType) { 520 std::string ClassString = 521 IsNSIntegerType ? "NS_ENUM(NSInteger, " : "NS_OPTIONS(NSUInteger, "; 522 ClassString += TypedefDcl->getIdentifier()->getName(); 523 ClassString += ')'; 524 SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart()); 525 commit.replace(R, ClassString); 526 SourceLocation TypedefLoc = TypedefDcl->getLocEnd(); 527 commit.remove(SourceRange(TypedefLoc, TypedefLoc)); 528 return true; 529} 530 531static bool UseNSOptionsMacro(ASTContext &Ctx, 532 const EnumDecl *EnumDcl) { 533 bool PowerOfTwo = true; 534 uint64_t MaxPowerOfTwoVal = 0; 535 for (EnumDecl::enumerator_iterator EI = EnumDcl->enumerator_begin(), 536 EE = EnumDcl->enumerator_end(); EI != EE; ++EI) { 537 EnumConstantDecl *Enumerator = (*EI); 538 const Expr *InitExpr = Enumerator->getInitExpr(); 539 if (!InitExpr) { 540 PowerOfTwo = false; 541 continue; 542 } 543 InitExpr = InitExpr->IgnoreImpCasts(); 544 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr)) 545 if (BO->isShiftOp() || BO->isBitwiseOp()) 546 return true; 547 548 uint64_t EnumVal = Enumerator->getInitVal().getZExtValue(); 549 if (PowerOfTwo && EnumVal) { 550 if (!llvm::isPowerOf2_64(EnumVal)) 551 PowerOfTwo = false; 552 else if (EnumVal > MaxPowerOfTwoVal) 553 MaxPowerOfTwoVal = EnumVal; 554 } 555 } 556 return PowerOfTwo && (MaxPowerOfTwoVal > 2); 557} 558 559void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx, 560 const ObjCImplementationDecl *ImpDecl) { 561 const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface(); 562 if (!IDecl || ObjCProtocolDecls.empty()) 563 return; 564 // Find all implicit conforming protocols for this class 565 // and make them explicit. 566 llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols; 567 Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols); 568 llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols; 569 570 for (llvm::SmallPtrSet<ObjCProtocolDecl*, 32>::iterator I = 571 ObjCProtocolDecls.begin(), 572 E = ObjCProtocolDecls.end(); I != E; ++I) 573 if (!ExplicitProtocols.count(*I)) 574 PotentialImplicitProtocols.push_back(*I); 575 576 if (PotentialImplicitProtocols.empty()) 577 return; 578 579 // go through list of non-optional methods and properties in each protocol 580 // in the PotentialImplicitProtocols list. If class implements every one of the 581 // methods and properties, then this class conforms to this protocol. 582 llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols; 583 for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++) 584 if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl, 585 PotentialImplicitProtocols[i])) 586 ConformingProtocols.push_back(PotentialImplicitProtocols[i]); 587 588 if (ConformingProtocols.empty()) 589 return; 590 591 // Further reduce number of conforming protocols. If protocol P1 is in the list 592 // protocol P2 (P2<P1>), No need to include P1. 593 llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols; 594 for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 595 bool DropIt = false; 596 ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i]; 597 for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) { 598 ObjCProtocolDecl *PDecl = ConformingProtocols[i1]; 599 if (PDecl == TargetPDecl) 600 continue; 601 if (PDecl->lookupProtocolNamed( 602 TargetPDecl->getDeclName().getAsIdentifierInfo())) { 603 DropIt = true; 604 break; 605 } 606 } 607 if (!DropIt) 608 MinimalConformingProtocols.push_back(TargetPDecl); 609 } 610 edit::Commit commit(*Editor); 611 rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols, 612 *NSAPIObj, commit); 613 Editor->commit(commit); 614} 615 616void ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, 617 const EnumDecl *EnumDcl, 618 const TypedefDecl *TypedefDcl) { 619 if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() || 620 !TypedefDcl->getIdentifier()) 621 return; 622 623 QualType qt = TypedefDcl->getTypeSourceInfo()->getType(); 624 bool IsNSIntegerType = NSAPIObj->isObjCNSIntegerType(qt); 625 bool IsNSUIntegerType = !IsNSIntegerType && NSAPIObj->isObjCNSUIntegerType(qt); 626 627 if (!IsNSIntegerType && !IsNSUIntegerType) { 628 // Also check for typedef enum {...} TD; 629 if (const EnumType *EnumTy = qt->getAs<EnumType>()) { 630 if (EnumTy->getDecl() == EnumDcl) { 631 bool NSOptions = UseNSOptionsMacro(Ctx, EnumDcl); 632 if (NSOptions) { 633 if (!Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition()) 634 return; 635 } 636 else if (!Ctx.Idents.get("NS_ENUM").hasMacroDefinition()) 637 return; 638 edit::Commit commit(*Editor); 639 rewriteToNSMacroDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions); 640 Editor->commit(commit); 641 } 642 } 643 return; 644 } 645 if (IsNSIntegerType && UseNSOptionsMacro(Ctx, EnumDcl)) { 646 // We may still use NS_OPTIONS based on what we find in the enumertor list. 647 IsNSIntegerType = false; 648 IsNSUIntegerType = true; 649 } 650 651 // NS_ENUM must be available. 652 if (IsNSIntegerType && !Ctx.Idents.get("NS_ENUM").hasMacroDefinition()) 653 return; 654 // NS_OPTIONS must be available. 655 if (IsNSUIntegerType && !Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition()) 656 return; 657 edit::Commit commit(*Editor); 658 rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, IsNSIntegerType); 659 Editor->commit(commit); 660} 661 662static void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC, 663 ObjCMethodDecl *OM) { 664 SourceRange R; 665 std::string ClassString; 666 if (TypeSourceInfo *TSInfo = OM->getResultTypeSourceInfo()) { 667 TypeLoc TL = TSInfo->getTypeLoc(); 668 R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); 669 ClassString = "instancetype"; 670 } 671 else { 672 R = SourceRange(OM->getLocStart(), OM->getLocStart()); 673 ClassString = OM->isInstanceMethod() ? '-' : '+'; 674 ClassString += " (instancetype)"; 675 } 676 edit::Commit commit(*ASTC.Editor); 677 commit.replace(R, ClassString); 678 ASTC.Editor->commit(commit); 679} 680 681void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx, 682 ObjCContainerDecl *CDecl, 683 ObjCMethodDecl *OM) { 684 // bail out early and do not suggest 'instancetype' when the method already 685 // has a related result type, 686 if (OM->hasRelatedResultType()) 687 return; 688 689 ObjCInstanceTypeFamily OIT_Family = 690 Selector::getInstTypeMethodFamily(OM->getSelector()); 691 692 std::string ClassName; 693 switch (OIT_Family) { 694 case OIT_None: 695 migrateFactoryMethod(Ctx, CDecl, OM); 696 return; 697 case OIT_Array: 698 ClassName = "NSArray"; 699 break; 700 case OIT_Dictionary: 701 ClassName = "NSDictionary"; 702 break; 703 case OIT_Singleton: 704 migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton); 705 return; 706 } 707 if (!OM->getResultType()->isObjCIdType()) 708 return; 709 710 ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 711 if (!IDecl) { 712 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 713 IDecl = CatDecl->getClassInterface(); 714 else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl)) 715 IDecl = ImpDecl->getClassInterface(); 716 } 717 if (!IDecl || 718 !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) { 719 migrateFactoryMethod(Ctx, CDecl, OM); 720 return; 721 } 722 ReplaceWithInstancetype(*this, OM); 723} 724 725void ObjCMigrateASTConsumer::migrateInstanceType(ASTContext &Ctx, 726 ObjCContainerDecl *CDecl) { 727 // migrate methods which can have instancetype as their result type. 728 for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(), 729 MEnd = CDecl->meth_end(); 730 M != MEnd; ++M) { 731 ObjCMethodDecl *Method = (*M); 732 migrateMethodInstanceType(Ctx, CDecl, Method); 733 } 734} 735 736void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx, 737 ObjCContainerDecl *CDecl, 738 ObjCMethodDecl *OM, 739 ObjCInstanceTypeFamily OIT_Family) { 740 if (OM->isInstanceMethod() || 741 OM->getResultType() == Ctx.getObjCInstanceType() || 742 !OM->getResultType()->isObjCIdType()) 743 return; 744 745 // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class 746 // NSYYYNamE with matching names be at least 3 characters long. 747 ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 748 if (!IDecl) { 749 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 750 IDecl = CatDecl->getClassInterface(); 751 else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl)) 752 IDecl = ImpDecl->getClassInterface(); 753 } 754 if (!IDecl) 755 return; 756 757 std::string StringClassName = IDecl->getName(); 758 StringRef LoweredClassName(StringClassName); 759 std::string StringLoweredClassName = LoweredClassName.lower(); 760 LoweredClassName = StringLoweredClassName; 761 762 IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0); 763 // Handle method with no name at its first selector slot; e.g. + (id):(int)x. 764 if (!MethodIdName) 765 return; 766 767 std::string MethodName = MethodIdName->getName(); 768 if (OIT_Family == OIT_Singleton) { 769 StringRef STRefMethodName(MethodName); 770 size_t len = 0; 771 if (STRefMethodName.startswith("standard")) 772 len = strlen("standard"); 773 else if (STRefMethodName.startswith("shared")) 774 len = strlen("shared"); 775 else if (STRefMethodName.startswith("default")) 776 len = strlen("default"); 777 else 778 return; 779 MethodName = STRefMethodName.substr(len); 780 } 781 std::string MethodNameSubStr = MethodName.substr(0, 3); 782 StringRef MethodNamePrefix(MethodNameSubStr); 783 std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower(); 784 MethodNamePrefix = StringLoweredMethodNamePrefix; 785 size_t Ix = LoweredClassName.rfind(MethodNamePrefix); 786 if (Ix == StringRef::npos) 787 return; 788 std::string ClassNamePostfix = LoweredClassName.substr(Ix); 789 StringRef LoweredMethodName(MethodName); 790 std::string StringLoweredMethodName = LoweredMethodName.lower(); 791 LoweredMethodName = StringLoweredMethodName; 792 if (!LoweredMethodName.startswith(ClassNamePostfix)) 793 return; 794 ReplaceWithInstancetype(*this, OM); 795} 796 797static bool IsVoidStarType(QualType Ty) { 798 if (!Ty->isPointerType()) 799 return false; 800 801 while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr())) 802 Ty = TD->getDecl()->getUnderlyingType(); 803 804 // Is the type void*? 805 const PointerType* PT = Ty->getAs<PointerType>(); 806 if (PT->getPointeeType().getUnqualifiedType()->isVoidType()) 807 return true; 808 return IsVoidStarType(PT->getPointeeType()); 809} 810 811/// AuditedType - This routine audits the type AT and returns false if it is one of known 812/// CF object types or of the "void *" variety. It returns true if we don't care about the type 813/// such as a non-pointer or pointers which have no ownership issues (such as "int *"). 814static bool AuditedType (QualType AT) { 815 if (!AT->isAnyPointerType() && !AT->isBlockPointerType()) 816 return true; 817 // FIXME. There isn't much we can say about CF pointer type; or is there? 818 if (ento::coreFoundation::isCFObjectRef(AT) || 819 IsVoidStarType(AT) || 820 // If an ObjC object is type, assuming that it is not a CF function and 821 // that it is an un-audited function. 822 AT->isObjCObjectPointerType() || AT->isObjCBuiltinType()) 823 return false; 824 // All other pointers are assumed audited as harmless. 825 return true; 826} 827 828void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) { 829 if (CFFunctionIBCandidates.empty()) 830 return; 831 if (!Ctx.Idents.get("CF_IMPLICIT_BRIDGING_ENABLED").hasMacroDefinition()) { 832 CFFunctionIBCandidates.clear(); 833 FileId = 0; 834 return; 835 } 836 // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED 837 const Decl *FirstFD = CFFunctionIBCandidates[0]; 838 const Decl *LastFD = 839 CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1]; 840 const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n"; 841 edit::Commit commit(*Editor); 842 commit.insertBefore(FirstFD->getLocStart(), PragmaString); 843 PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n"; 844 SourceLocation EndLoc = LastFD->getLocEnd(); 845 // get location just past end of function location. 846 EndLoc = PP.getLocForEndOfToken(EndLoc); 847 if (isa<FunctionDecl>(LastFD)) { 848 // For Methods, EndLoc points to the ending semcolon. So, 849 // not of these extra work is needed. 850 Token Tok; 851 // get locaiton of token that comes after end of function. 852 bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true); 853 if (!Failed) 854 EndLoc = Tok.getLocation(); 855 } 856 commit.insertAfterToken(EndLoc, PragmaString); 857 Editor->commit(commit); 858 FileId = 0; 859 CFFunctionIBCandidates.clear(); 860} 861 862void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) { 863 if (Decl->hasAttr<CFAuditedTransferAttr>()) { 864 assert(CFFunctionIBCandidates.empty() && 865 "Cannot have audited functions/methods inside user " 866 "provided CF_IMPLICIT_BRIDGING_ENABLE"); 867 return; 868 } 869 870 // Finction must be annotated first. 871 CF_BRIDGING_KIND AuditKind; 872 if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) 873 AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl); 874 else 875 AuditKind = migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl)); 876 if (AuditKind == CF_BRIDGING_ENABLE) { 877 CFFunctionIBCandidates.push_back(Decl); 878 if (!FileId) 879 FileId = PP.getSourceManager().getFileID(Decl->getLocation()).getHashValue(); 880 } 881 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) { 882 if (!CFFunctionIBCandidates.empty()) { 883 CFFunctionIBCandidates.push_back(Decl); 884 if (!FileId) 885 FileId = PP.getSourceManager().getFileID(Decl->getLocation()).getHashValue(); 886 } 887 } 888 else 889 AnnotateImplicitBridging(Ctx); 890} 891 892void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, 893 const CallEffects &CE, 894 const FunctionDecl *FuncDecl, 895 bool ResultAnnotated) { 896 // Annotate function. 897 if (!ResultAnnotated) { 898 RetEffect Ret = CE.getReturnValue(); 899 const char *AnnotationString = 0; 900 if (Ret.getObjKind() == RetEffect::CF && Ret.isOwned()) { 901 if (Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition()) 902 AnnotationString = " CF_RETURNS_RETAINED"; 903 } 904 else if (Ret.getObjKind() == RetEffect::CF && !Ret.isOwned()) { 905 if (Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition()) 906 AnnotationString = " CF_RETURNS_NOT_RETAINED"; 907 } 908 if (AnnotationString) { 909 edit::Commit commit(*Editor); 910 commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString); 911 Editor->commit(commit); 912 } 913 } 914 llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 915 unsigned i = 0; 916 for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(), 917 pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { 918 const ParmVarDecl *pd = *pi; 919 ArgEffect AE = AEArgs[i]; 920 if (AE == DecRef && !pd->getAttr<CFConsumedAttr>() && 921 Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) { 922 edit::Commit commit(*Editor); 923 commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); 924 Editor->commit(commit); 925 } 926 } 927} 928 929 930ObjCMigrateASTConsumer::CF_BRIDGING_KIND 931 ObjCMigrateASTConsumer::migrateAddFunctionAnnotation( 932 ASTContext &Ctx, 933 const FunctionDecl *FuncDecl) { 934 if (FuncDecl->hasBody()) 935 return CF_BRIDGING_NONE; 936 937 CallEffects CE = CallEffects::getEffect(FuncDecl); 938 bool FuncIsReturnAnnotated = (FuncDecl->getAttr<CFReturnsRetainedAttr>() || 939 FuncDecl->getAttr<CFReturnsNotRetainedAttr>()); 940 941 // Trivial case of when funciton is annotated and has no argument. 942 if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0) 943 return CF_BRIDGING_NONE; 944 945 bool ReturnCFAudited = false; 946 if (!FuncIsReturnAnnotated) { 947 RetEffect Ret = CE.getReturnValue(); 948 if (Ret.getObjKind() == RetEffect::CF && 949 (Ret.isOwned() || !Ret.isOwned())) 950 ReturnCFAudited = true; 951 else if (!AuditedType(FuncDecl->getResultType())) 952 return CF_BRIDGING_NONE; 953 } 954 955 // At this point result type is audited for potential inclusion. 956 // Now, how about argument types. 957 llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 958 unsigned i = 0; 959 bool ArgCFAudited = false; 960 for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(), 961 pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { 962 const ParmVarDecl *pd = *pi; 963 ArgEffect AE = AEArgs[i]; 964 if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) { 965 if (AE == DecRef && !pd->getAttr<CFConsumedAttr>()) 966 ArgCFAudited = true; 967 else if (AE == IncRef) 968 ArgCFAudited = true; 969 } 970 else { 971 QualType AT = pd->getType(); 972 if (!AuditedType(AT)) { 973 AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated); 974 return CF_BRIDGING_NONE; 975 } 976 } 977 } 978 if (ReturnCFAudited || ArgCFAudited) 979 return CF_BRIDGING_ENABLE; 980 981 return CF_BRIDGING_MAY_INCLUDE; 982} 983 984void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx, 985 ObjCContainerDecl *CDecl) { 986 if (!isa<ObjCInterfaceDecl>(CDecl)) 987 return; 988 989 // migrate methods which can have instancetype as their result type. 990 for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(), 991 MEnd = CDecl->meth_end(); 992 M != MEnd; ++M) { 993 ObjCMethodDecl *Method = (*M); 994 migrateCFAnnotation(Ctx, Method); 995 } 996} 997 998void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, 999 const CallEffects &CE, 1000 const ObjCMethodDecl *MethodDecl, 1001 bool ResultAnnotated) { 1002 // Annotate function. 1003 if (!ResultAnnotated) { 1004 RetEffect Ret = CE.getReturnValue(); 1005 const char *AnnotationString = 0; 1006 if (Ret.getObjKind() == RetEffect::CF && Ret.isOwned()) { 1007 if (Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition()) 1008 AnnotationString = " CF_RETURNS_RETAINED"; 1009 } 1010 else if (Ret.getObjKind() == RetEffect::CF && !Ret.isOwned()) { 1011 if (Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition()) 1012 AnnotationString = " CF_RETURNS_NOT_RETAINED"; 1013 } 1014 if (AnnotationString) { 1015 edit::Commit commit(*Editor); 1016 commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString); 1017 Editor->commit(commit); 1018 } 1019 } 1020 llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 1021 unsigned i = 0; 1022 for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(), 1023 pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { 1024 const ParmVarDecl *pd = *pi; 1025 ArgEffect AE = AEArgs[i]; 1026 if (AE == DecRef && !pd->getAttr<CFConsumedAttr>() && 1027 Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) { 1028 edit::Commit commit(*Editor); 1029 commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); 1030 Editor->commit(commit); 1031 } 1032 } 1033} 1034 1035ObjCMigrateASTConsumer::CF_BRIDGING_KIND 1036 ObjCMigrateASTConsumer::migrateAddMethodAnnotation( 1037 ASTContext &Ctx, 1038 const ObjCMethodDecl *MethodDecl) { 1039 if (MethodDecl->hasBody()) 1040 return CF_BRIDGING_NONE; 1041 1042 CallEffects CE = CallEffects::getEffect(MethodDecl); 1043 bool MethodIsReturnAnnotated = (MethodDecl->getAttr<CFReturnsRetainedAttr>() || 1044 MethodDecl->getAttr<CFReturnsNotRetainedAttr>()); 1045 1046 // Trivial case of when funciton is annotated and has no argument. 1047 if (MethodIsReturnAnnotated && 1048 (MethodDecl->param_begin() == MethodDecl->param_end())) 1049 return CF_BRIDGING_NONE; 1050 1051 bool ReturnCFAudited = false; 1052 if (!MethodIsReturnAnnotated) { 1053 RetEffect Ret = CE.getReturnValue(); 1054 if (Ret.getObjKind() == RetEffect::CF && (Ret.isOwned() || !Ret.isOwned())) 1055 ReturnCFAudited = true; 1056 else if (!AuditedType(MethodDecl->getResultType())) 1057 return CF_BRIDGING_NONE; 1058 } 1059 1060 // At this point result type is either annotated or audited. 1061 // Now, how about argument types. 1062 llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 1063 unsigned i = 0; 1064 bool ArgCFAudited = false; 1065 for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(), 1066 pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { 1067 const ParmVarDecl *pd = *pi; 1068 ArgEffect AE = AEArgs[i]; 1069 if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) { 1070 if (AE == DecRef && !pd->getAttr<CFConsumedAttr>()) 1071 ArgCFAudited = true; 1072 else if (AE == IncRef) 1073 ArgCFAudited = true; 1074 } 1075 else { 1076 QualType AT = pd->getType(); 1077 if (!AuditedType(AT)) { 1078 AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated); 1079 return CF_BRIDGING_NONE; 1080 } 1081 } 1082 } 1083 if (ReturnCFAudited || ArgCFAudited) 1084 return CF_BRIDGING_ENABLE; 1085 1086 return CF_BRIDGING_MAY_INCLUDE; 1087} 1088 1089namespace { 1090 1091class RewritesReceiver : public edit::EditsReceiver { 1092 Rewriter &Rewrite; 1093 1094public: 1095 RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { } 1096 1097 virtual void insert(SourceLocation loc, StringRef text) { 1098 Rewrite.InsertText(loc, text); 1099 } 1100 virtual void replace(CharSourceRange range, StringRef text) { 1101 Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text); 1102 } 1103}; 1104 1105} 1106 1107void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { 1108 1109 TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl(); 1110 if (MigrateProperty) { 1111 for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end(); 1112 D != DEnd; ++D) { 1113 if (unsigned FID = 1114 PP.getSourceManager().getFileID((*D)->getLocation()).getHashValue()) 1115 if (FileId && FileId != FID) { 1116 assert(!CFFunctionIBCandidates.empty()); 1117 AnnotateImplicitBridging(Ctx); 1118 } 1119 1120 if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D)) 1121 migrateObjCInterfaceDecl(Ctx, CDecl); 1122 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) 1123 ObjCProtocolDecls.insert(PDecl); 1124 else if (const ObjCImplementationDecl *ImpDecl = 1125 dyn_cast<ObjCImplementationDecl>(*D)) 1126 migrateProtocolConformance(Ctx, ImpDecl); 1127 else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) { 1128 DeclContext::decl_iterator N = D; 1129 ++N; 1130 if (N != DEnd) 1131 if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N)) 1132 migrateNSEnumDecl(Ctx, ED, TD); 1133 } 1134 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) 1135 migrateCFAnnotation(Ctx, FD); 1136 1137 if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) { 1138 // migrate methods which can have instancetype as their result type. 1139 migrateInstanceType(Ctx, CDecl); 1140 // annotate methods with CF annotations. 1141 migrateARCSafeAnnotation(Ctx, CDecl); 1142 } 1143 } 1144 AnnotateImplicitBridging(Ctx); 1145 } 1146 1147 Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); 1148 RewritesReceiver Rec(rewriter); 1149 Editor->applyRewrites(Rec); 1150 1151 for (Rewriter::buffer_iterator 1152 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { 1153 FileID FID = I->first; 1154 RewriteBuffer &buf = I->second; 1155 const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); 1156 assert(file); 1157 SmallString<512> newText; 1158 llvm::raw_svector_ostream vecOS(newText); 1159 buf.write(vecOS); 1160 vecOS.flush(); 1161 llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy( 1162 StringRef(newText.data(), newText.size()), file->getName()); 1163 SmallString<64> filePath(file->getName()); 1164 FileMgr.FixupRelativePath(filePath); 1165 Remapper.remap(filePath.str(), memBuf); 1166 } 1167 1168 if (IsOutputFile) { 1169 Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics()); 1170 } else { 1171 Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics()); 1172 } 1173} 1174 1175bool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) { 1176 CI.getDiagnostics().setIgnoreAllWarnings(true); 1177 return true; 1178} 1179 1180ASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, 1181 StringRef InFile) { 1182 PPConditionalDirectiveRecord * 1183 PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager()); 1184 CI.getPreprocessor().addPPCallbacks(PPRec); 1185 return new ObjCMigrateASTConsumer(CI.getFrontendOpts().OutputFile, 1186 /*MigrateLiterals=*/true, 1187 /*MigrateSubscripting=*/true, 1188 /*MigrateProperty*/true, 1189 /*MigrateReadonlyProperty*/true, 1190 Remapper, 1191 CI.getFileManager(), 1192 PPRec, 1193 CI.getPreprocessor(), 1194 /*isOutputFile=*/true); 1195} 1196