void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCInterfaceDecl *D) { for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end(); M != MEnd; ++M) { ObjCMethodDecl *Method = (*M); if (Method->isPropertyAccessor() || Method->param_size() != 0) continue; // Is this method candidate to be a getter? QualType GRT = Method->getResultType(); if (GRT->isVoidType()) continue; Selector GetterSelector = Method->getSelector(); IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0); Selector SetterSelector = SelectorTable::constructSetterSelector(PP.getIdentifierTable(), PP.getSelectorTable(), getterName); if (ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true)) { // Is this a valid setter, matching the target getter? QualType SRT = SetterMethod->getResultType(); if (!SRT->isVoidType()) continue; const ParmVarDecl *argDecl = *SetterMethod->param_begin(); QualType ArgType = argDecl->getType(); if (!Ctx.hasSameType(ArgType, GRT)) continue; edit::Commit commit(*Editor); edit::rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit); Editor->commit(commit); } } }
/// ObjCGetTypeForMethodDefinition - Builds the type for a method definition /// declarator QualType Sema::ObjCGetTypeForMethodDefinition(DeclPtrTy D) { ObjCMethodDecl *MDecl = cast<ObjCMethodDecl>(D.getAs<Decl>()); QualType T = MDecl->getResultType(); llvm::SmallVector<QualType, 16> ArgTys; // Add the first two invisible argument types for self and _cmd. if (MDecl->isInstanceMethod()) { QualType selfTy = Context.getObjCInterfaceType(MDecl->getClassInterface()); selfTy = Context.getPointerType(selfTy); ArgTys.push_back(selfTy); } else ArgTys.push_back(Context.getObjCIdType()); ArgTys.push_back(Context.getObjCSelType()); for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(), E = MDecl->param_end(); PI != E; ++PI) { QualType ArgTy = (*PI)->getType(); assert(!ArgTy.isNull() && "Couldn't parse type?"); ArgTy = adjustParameterType(ArgTy); ArgTys.push_back(ArgTy); } T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(), MDecl->isVariadic(), 0); return T; }
void NSErrorChecker::CheckSignature(const ObjCMethodDecl& M, QualType& ResultTy, llvm::SmallVectorImpl<VarDecl*>& ErrorParams) { ResultTy = M.getResultType(); for (ObjCMethodDecl::param_iterator I=M.param_begin(), E=M.param_end(); I!=E; ++I) { QualType T = (*I)->getType(); if (isNSErrorWarning) { if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I); } else if (CheckCFErrorArgument(T)) ErrorParams.push_back(*I); } }
/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. ExprResult Sema:: HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Expr *BaseExpr, DeclarationName MemberName, SourceLocation MemberLoc, SourceLocation SuperLoc, QualType SuperType, bool Super) { const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); ObjCInterfaceDecl *IFace = IFaceT->getDecl(); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); if (IFace->isForwardDecl()) { Diag(MemberLoc, diag::err_property_not_found_forward_class) << MemberName << QualType(OPT, 0); Diag(IFace->getLocation(), diag::note_forward_class); return ExprError(); } // Search for a declared property first. if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); QualType ResTy = PD->getType(); Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) ResTy = Getter->getResultType(); if (Super) return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, VK_LValue, OK_ObjCProperty, MemberLoc, SuperLoc, SuperType)); else return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr)); } // Check protocols on qualified interfaces. for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), E = OPT->qual_end(); I != E; ++I) if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); if (Super) return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), VK_LValue, OK_ObjCProperty, MemberLoc, SuperLoc, SuperType)); else return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr)); } // If that failed, look for an "implicit" property by seeing if the nullary // selector is implemented. // FIXME: The logic for looking up nullary and unary selectors should be // shared with the code in ActOnInstanceMessage. Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); // May be founf in property's qualified list. if (!Getter) Getter = LookupMethodInQualifiedType(Sel, OPT, true); // If this reference is in an @implementation, check for 'private' methods. if (!Getter) Getter = IFace->lookupPrivateMethod(Sel); // Look through local category implementations associated with the class. if (!Getter) Getter = IFace->getCategoryInstanceMethod(Sel); if (Getter) { // Check if we can reference this property. if (DiagnoseUseOfDecl(Getter, MemberLoc)) return ExprError(); } // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. Selector SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), Member); ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); // May be founf in property's qualified list. if (!Setter) Setter = LookupMethodInQualifiedType(SetterSel, OPT, true); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. Setter = IFace->lookupPrivateMethod(SetterSel); } // Look through local category implementations associated with the class. if (!Setter) Setter = IFace->getCategoryInstanceMethod(SetterSel); if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); if (Getter || Setter) { QualType PType; if (Getter) PType = Getter->getSendResultType(); else { ParmVarDecl *ArgDecl = *Setter->param_begin(); PType = ArgDecl->getType(); } ExprValueKind VK = VK_LValue; ExprObjectKind OK = OK_ObjCProperty; if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() && PType->isVoidType()) VK = VK_RValue, OK = OK_Ordinary; if (Super) return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, PType, VK, OK, MemberLoc, SuperLoc, SuperType)); else return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, PType, VK, OK, MemberLoc, BaseExpr)); } // Attempt to correct for typos in property names. LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName); if (CorrectTypo(Res, 0, 0, IFace, false, CTC_NoKeywords, OPT) && Res.getAsSingle<ObjCPropertyDecl>()) { DeclarationName TypoResult = Res.getLookupName(); Diag(MemberLoc, diag::err_property_not_found_suggest) << MemberName << QualType(OPT, 0) << TypoResult << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString()); ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>(); Diag(Property->getLocation(), diag::note_previous_decl) << Property->getDeclName(); return HandleExprPropertyRefExpr(OPT, BaseExpr, TypoResult, MemberLoc, SuperLoc, SuperType, Super); } ObjCInterfaceDecl *ClassDeclared; if (ObjCIvarDecl *Ivar = IFace->lookupInstanceVariable(Member, ClassDeclared)) { QualType T = Ivar->getType(); if (const ObjCObjectPointerType * OBJPT = T->getAsObjCInterfacePointerType()) { const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); if (ObjCInterfaceDecl *IFace = IFaceT->getDecl()) if (IFace->isForwardDecl()) { Diag(MemberLoc, diag::err_property_not_as_forward_class) << MemberName << IFace; Diag(IFace->getLocation(), diag::note_forward_class); return ExprError(); } } } Diag(MemberLoc, diag::err_property_not_found) << MemberName << QualType(OPT, 0); if (Setter) Diag(Setter->getLocation(), diag::note_getter_unavailable) << MemberName << BaseExpr->getSourceRange(); return ExprError(); }