On Sep 17, 2011, at 12:23 PM, Fariborz Jahanian wrote: > Author: fjahanian > Date: Sat Sep 17 14:23:40 2011 > New Revision: 139989 > > URL: http://llvm.org/viewvc/llvm-project?rev=139989&view=rev > Log: > objc - Treat type of 'self' in class methods as root of > class of this method. // rdar://10109725
I'm still quite dubious about the semantics behind this change, because it seems very NeXT-runtime centric, but we can take discussion that off-line. Another comment below… > Added: > cfe/trunk/test/SemaObjC/class-type-conversion.m > Modified: > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/Sema/SemaExpr.cpp > cfe/trunk/lib/Sema/SemaExprObjC.cpp > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=139989&r1=139988&r2=139989&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Sat Sep 17 14:23:40 2011 > @@ -675,8 +675,9 @@ > > GlobalMethodPool::iterator ReadMethodPool(Selector Sel); > > - /// Private Helper predicate to check for 'self'. > - bool isSelfExpr(Expr *RExpr); > + /// Private Helper predicate to check for 'self'. Upon success, it > + /// returns method declaration where 'self' is referenced. > + const ObjCMethodDecl *GetMethodIfSelfExpr(Expr *RExpr); > public: > Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, > TranslationUnitKind TUKind = TU_Complete, > > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=139989&r1=139988&r2=139989&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Sep 17 14:23:40 2011 > @@ -5074,6 +5074,23 @@ > OK)); > } > > +/// SelfInClassMethodType - convet type of 'self' in class method > +/// to pointer to root of method's class. > +static void > +SelfInClassMethodType(Sema &S, Expr *selfExpr, QualType &SelfType) { > + if (const ObjCMethodDecl *MD = S.GetMethodIfSelfExpr(selfExpr)) > + if (MD->isClassMethod()) { > + const ObjCInterfaceDecl *Root = 0; > + if (const ObjCInterfaceDecl * IDecl = MD->getClassInterface()) > + do { > + Root = IDecl; > + } while ((IDecl = IDecl->getSuperClass())); > + if (Root) > + SelfType = S.Context.getObjCObjectPointerType( > + > S.Context.getObjCInterfaceType(Root)); > + } > +} I suggest returning a QualType with the requested result; it's cleaner than modifying the parameter. Also, can the function name say something about returning the root? That's not at all apparent from the interface (nor is it particularly intuitive). > // checkPointerTypesForAssignment - This is a very tricky routine (despite > // being closely modeled after the C99 spec:-). The odd characteristic of this > // routine is it effectively iqnores the qualifiers on the top level pointee. > @@ -5309,6 +5326,8 @@ > return Compatible; > } > > + SelfInClassMethodType(*this, RHS.get(), RHSType); I'm not a big fan of speculatively modifying the RHSType here, because that has an impact on *all* of the checking that follows. This special conversion should be checked in isolation, down where we're checking the other Objective-C conversions. > // If the left-hand side is a reference type, then we are in a > // (rare!) case where we've allowed the use of references in C, > // e.g., as a parameter type in a built-in function. In this case, > @@ -9564,7 +9583,7 @@ > Selector Sel = ME->getSelector(); > > // self = [<foo> init...] > - if (isSelfExpr(Op->getLHS()) && > Sel.getNameForSlot(0).startswith("init")) > + if (GetMethodIfSelfExpr(Op->getLHS()) && > Sel.getNameForSlot(0).startswith("init")) > diagnostic = diag::warn_condition_is_idiomatic_assignment; > > // <foo> = [<bar> nextObject] > > Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=139989&r1=139988&r2=139989&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Sat Sep 17 14:23:40 2011 > @@ -457,18 +457,20 @@ > return IsError; > } > > -bool Sema::isSelfExpr(Expr *receiver) { > +/// GetMethodIfSelfExpr - Check if receiver is an objc 'self' expression > +/// and return its method declaration if so; else return 0. > +const ObjCMethodDecl *Sema::GetMethodIfSelfExpr(Expr *receiver) { > // 'self' is objc 'self' in an objc method only. > DeclContext *DC = CurContext; > while (isa<BlockDecl>(DC)) > DC = DC->getParent(); > if (DC && !isa<ObjCMethodDecl>(DC)) > - return false; > + return 0; > receiver = receiver->IgnoreParenLValueCasts(); > if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(receiver)) > if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self")) > - return true; > - return false; > + return static_cast<ObjCMethodDecl*>(DC); > + return 0; > } > > // Helper method for ActOnClassMethod/ActOnInstanceMethod. > @@ -1272,7 +1274,7 @@ > } > if (!Method) { > // If not messaging 'self', look for any factory method named 'Sel'. > - if (!Receiver || !isSelfExpr(Receiver)) { > + if (!Receiver || !GetMethodIfSelfExpr(Receiver)) { > Method = LookupFactoryMethodInGlobalPool(Sel, > SourceRange(LBracLoc, > RBracLoc), > true); > @@ -1336,7 +1338,7 @@ > return ExprError(); > } > > - if (!Method && (!Receiver || !isSelfExpr(Receiver))) { > + if (!Method && (!Receiver || !GetMethodIfSelfExpr(Receiver))) { > // If we still haven't found a method, look in the global pool. > This > // behavior isn't very desirable, however we need it for GCC > // compatibility. FIXME: should we deviate?? > @@ -1507,7 +1509,7 @@ > if (getLangOptions().ObjCAutoRefCount) { > // In ARC, annotate delegate init calls. > if (Result->getMethodFamily() == OMF_init && > - (SuperLoc.isValid() || isSelfExpr(Receiver))) { > + (SuperLoc.isValid() || GetMethodIfSelfExpr(Receiver))) { > // Only consider init calls *directly* in init implementations, > // not within blocks. > ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(CurContext); > > Added: cfe/trunk/test/SemaObjC/class-type-conversion.m > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/class-type-conversion.m?rev=139989&view=auto > ============================================================================== > --- cfe/trunk/test/SemaObjC/class-type-conversion.m (added) > +++ cfe/trunk/test/SemaObjC/class-type-conversion.m Sat Sep 17 14:23:40 2011 > @@ -0,0 +1,44 @@ > +// RUN: %clang_cc1 -fsyntax-only -verify %s > +// rdar://10109725 > + > +@interface NSObject { > + Class isa; > +} > +- (id)addObserver:(NSObject *)observer; // expected-note 2 {{passing > argument to parameter 'observer' here}} > +@end > + > +@interface MyClass : NSObject { > +} > +@end > + > +@implementation NSObject > ++ (void)initialize > +{ > + NSObject *obj = 0; > + [obj addObserver:self]; > +} > + > +- init > +{ > + NSObject *obj = 0; > + [obj addObserver:self]; > + return [obj addObserver:(Class)0]; // expected-warning > {{incompatible pointer types sending 'Class' to parameter of type 'NSObject > *'}} > +} > +- (id)addObserver:(NSObject *)observer { return 0; } > +@end > + > +@implementation MyClass > + > ++ (void)initialize > +{ > + NSObject *obj = 0; > + [obj addObserver:self]; > +} > + > +- init > +{ > + NSObject *obj = 0; > + [obj addObserver:self]; > + return [obj addObserver:(Class)0]; // expected-warning > {{incompatible pointer types sending 'Class' to parameter of type 'NSObject > *'}} > +} > +@end > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
