From: Daniel Dunbar Date: Wed, 3 Sep 2008 01:05:41 +0000 (+0000) Subject: Restore Objective-C dot-syntax access of methods. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2307d312f779b204468ac36aab3b153e66a853c0;p=clang Restore Objective-C dot-syntax access of methods. - Now also searches for correct setter method. - There are still some issues regarding validation of the setter method and access of read-only properties. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55686 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fe9a13e464..479c8412fd 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -801,6 +801,25 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc, return VT; // should never get here (a typedef type should always be found). } +/// constructSetterName - Return the setter name for the given +/// identifier, i.e. "set" + Name where the initial character of Name +/// has been capitalized. +// FIXME: Merge with same routine in Parser. But where should this +// live? +static IdentifierInfo *constructSetterName(IdentifierTable &Idents, + const IdentifierInfo *Name) { + unsigned N = Name->getLength(); + char *SelectorName = new char[3 + N]; + memcpy(SelectorName, "set", 3); + memcpy(&SelectorName[3], Name->getName(), N); + SelectorName[3] = toupper(SelectorName[3]); + + IdentifierInfo *Setter = + &Idents.get(SelectorName, &SelectorName[3 + N]); + delete[] SelectorName; + return Setter; +} + Action::ExprResult Sema:: ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation MemberLoc, @@ -866,47 +885,58 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, if (OpKind == tok::period && (PTy = BaseType->getAsPointerType()) && (IFTy = PTy->getPointeeType()->getAsObjCInterfaceType())) { ObjCInterfaceDecl *IFace = IFTy->getDecl(); - - // FIXME: The logic for looking up nullary and unary selectors should be - // shared with the code in ActOnInstanceMessage. - // FIXME: This logic is not correct, we should search for - // properties first. Additionally, the AST node doesn't currently - // have enough information to store the setter argument. -#if 0 - // Before we look for explicit property declarations, we check for - // nullary methods (which allow '.' notation). - Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); - if (ObjCMethodDecl *MD = IFace->lookupInstanceMethod(Sel)) - return new ObjCPropertyRefExpr(MD, MD->getResultType(), - MemberLoc, BaseExpr); - - // If this reference is in an @implementation, check for 'private' methods. - if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { - if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) - if (ObjCImplementationDecl *ImpDecl = - ObjCImplementations[ClassDecl->getIdentifier()]) - if (ObjCMethodDecl *MD = ImpDecl->getInstanceMethod(Sel)) - return new ObjCPropertyRefExpr(MD, MD->getResultType(), - MemberLoc, BaseExpr); - } -#endif - - // FIXME: Need to deal with setter methods that take 1 argument. E.g.: - // @interface NSBundle : NSObject {} - // - (NSString *)bundlePath; - // - (void)setBundlePath:(NSString *)x; - // @end - // void someMethod() { frameworkBundle.bundlePath = 0; } - // + // Search for a declared property first. if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(&Member)) return new ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr); - // Lastly, check protocols on qualified interfaces. + // Check protocols on qualified interfaces. for (ObjCInterfaceType::qual_iterator I = IFTy->qual_begin(), E = IFTy->qual_end(); I != E; ++I) if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) return new 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) + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) + if (ObjCImplementationDecl *ImpDecl = + ObjCImplementations[ClassDecl->getIdentifier()]) + Getter = ImpDecl->getInstanceMethod(Sel); + + if (Getter) { + // If we found a getter then this may be a valid dot-reference, we + // need to also look for the matching setter. + IdentifierInfo *SetterName = constructSetterName(PP.getIdentifierTable(), + &Member); + Selector SetterSel = PP.getSelectorTable().getUnarySelector(SetterName); + ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); + + if (!Setter) { + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) + if (ObjCImplementationDecl *ImpDecl = + ObjCImplementations[ClassDecl->getIdentifier()]) + Setter = ImpDecl->getInstanceMethod(SetterSel); + } + + // FIXME: There are some issues here. First, we are not + // diagnosing accesses to read-only properties because we do not + // know if this is a getter or setter yet. Second, we are + // checking that the type of the setter matches the type we + // expect. + return new ObjCPropertyRefExpr(Getter, Setter, Getter->getResultType(), + MemberLoc, BaseExpr); + } } // Handle 'field access' to vectors, such as 'V.xx'. diff --git a/test/SemaObjC/property-6.m b/test/SemaObjC/property-6.m index 6173d52603..a51994d3d4 100644 --- a/test/SemaObjC/property-6.m +++ b/test/SemaObjC/property-6.m @@ -1,4 +1,4 @@ -// RUNX: clang -fsyntax-only -verify %s +// RUN: clang -fsyntax-only -verify %s # 1 "" # 1 "/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h" 1 3 typedef signed char BOOL; diff --git a/test/SemaObjC/property-9-impl-method.m b/test/SemaObjC/property-9-impl-method.m index f08fc9de06..bb13d01b74 100644 --- a/test/SemaObjC/property-9-impl-method.m +++ b/test/SemaObjC/property-9-impl-method.m @@ -1,4 +1,4 @@ -// RUNX: clang %s -fsyntax-only -verify +// RUN: clang %s -fsyntax-only -verify // rdar://5967199 typedef signed char BOOL;