From: Chris Lattner Date: Sun, 11 Apr 2010 07:45:24 +0000 (+0000) Subject: factor the code that handles "expr.field" when expr is a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7f81652f97a69ae8b514893a69c0245253687e55;p=clang factor the code that handles "expr.field" when expr is a pointer to an objc interface out to a method in SemaExprObjC. This is *much* uglier than it should be due to grossness in LookupMemberExpr :( git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100957 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3250870d63..989215948b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3845,6 +3845,13 @@ public: ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel, ObjCInterfaceDecl *ClassDecl); + Action::OwningExprResult + HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, + Expr *&BaseExpr, bool &IsArrow, + DeclarationName MemberName, + SourceLocation MemberLoc, SourceLocation OpLoc, + CXXScopeSpec &SS, DeclPtrTy ObjCImpDecl); + virtual OwningExprResult ActOnClassPropertyRefExpr( IdentifierInfo &receiverName, IdentifierInfo &propertyName, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6820449e1c..c350bb9a78 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3140,105 +3140,12 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, } // Handle Objective-C property access, which is "Obj.property" where Obj is a // pointer to a (potentially qualified) interface type. - const ObjCObjectPointerType *OPT; - if (!IsArrow && (OPT = BaseType->getAsObjCInterfacePointerType())) { - const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); - ObjCInterfaceDecl *IFace = IFaceT->getDecl(); - IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); - - // 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(); - return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, - 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(); - - return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), - 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); - - // If this reference is in an @implementation, check for 'private' methods. - if (!Getter) - Getter = IFace->lookupPrivateInstanceMethod(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); - if (!Setter) { - // If this reference is in an @implementation, also check for 'private' - // methods. - Setter = IFace->lookupPrivateInstanceMethod(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) { - QualType PType; - PType = Getter->getResultType(); - return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType, - Setter, MemberLoc, BaseExpr)); - } - - // Attempt to correct for typos in property names. - LookupResult Res(*this, R.getLookupName(), R.getNameLoc(), - LookupOrdinaryName); - if (CorrectTypo(Res, 0, 0, IFace, false, OPT) && - Res.getAsSingle()) { - Diag(R.getNameLoc(), diag::err_property_not_found_suggest) - << MemberName << BaseType << Res.getLookupName() - << FixItHint::CreateReplacement(R.getNameLoc(), - Res.getLookupName().getAsString()); - ObjCPropertyDecl *Property = Res.getAsSingle(); - Diag(Property->getLocation(), diag::note_previous_decl) - << Property->getDeclName(); - - return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS, - ObjCImpDecl); - } - Diag(MemberLoc, diag::err_property_not_found) - << MemberName << BaseType; - if (Setter && !Getter) - Diag(Setter->getLocation(), diag::note_getter_unavailable) - << MemberName << BaseExpr->getSourceRange(); - return ExprError(); - } + if (!IsArrow) + if (const ObjCObjectPointerType *OPT = + BaseType->getAsObjCInterfacePointerType()) + return HandleExprPropertyRefExpr(OPT, BaseExpr, IsArrow, + MemberName, MemberLoc, + OpLoc, SS, ObjCImpDecl); // Handle the following exceptional case (*Obj).isa. if (!IsArrow && diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index a05687e0cb..86d69388e2 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "Lookup.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" @@ -289,6 +290,114 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, return Method; } +/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an +/// objective C interface. This is a property reference expression. +Action::OwningExprResult Sema:: +HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, + Expr *&BaseExpr, bool &IsArrow, + DeclarationName MemberName, + SourceLocation MemberLoc, SourceLocation OpLoc, + CXXScopeSpec &SS, DeclPtrTy ObjCImpDecl) { + assert(!IsArrow && "Should only be called with '.' expressions"); + const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); + ObjCInterfaceDecl *IFace = IFaceT->getDecl(); + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + + // 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(); + return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, + 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(); + + return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), + 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); + + // If this reference is in an @implementation, check for 'private' methods. + if (!Getter) + Getter = IFace->lookupPrivateInstanceMethod(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); + if (!Setter) { + // If this reference is in an @implementation, also check for 'private' + // methods. + Setter = IFace->lookupPrivateInstanceMethod(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) { + QualType PType; + PType = Getter->getResultType(); + return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType, + Setter, MemberLoc, BaseExpr)); + } + + // Attempt to correct for typos in property names. + LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName); + if (CorrectTypo(Res, 0, 0, IFace, false, OPT) && + Res.getAsSingle()) { + Diag(MemberLoc, diag::err_property_not_found_suggest) + << MemberName << QualType(OPT, 0) << Res.getLookupName() + << FixItHint::CreateReplacement(MemberLoc, + Res.getLookupName().getAsString()); + ObjCPropertyDecl *Property = Res.getAsSingle(); + Diag(Property->getLocation(), diag::note_previous_decl) + << Property->getDeclName(); + + return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl); + } + Diag(MemberLoc, diag::err_property_not_found) + << MemberName << QualType(OPT, 0); + if (Setter && !Getter) + Diag(Setter->getLocation(), diag::note_getter_unavailable) + << MemberName << BaseExpr->getSourceRange(); + return ExprError(); + +} + + + Action::OwningExprResult Sema::ActOnClassPropertyRefExpr( IdentifierInfo &receiverName, IdentifierInfo &propertyName,