From c70e8d90d192af8f4e8caca4d20c85b843f7d699 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Thu, 16 Jul 2009 00:25:06 +0000 Subject: [PATCH] Avoid crashing for the enclosed test case. This is fallout from the recent ObjCObjectPointerType rework. I'll work on fixing this tomorrow. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75870 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 100 ++++++++++++++++++++----------------- test/SemaObjC/id-isa-ref.m | 17 +++++++ 2 files changed, 70 insertions(+), 47 deletions(-) create mode 100644 test/SemaObjC/id-isa-ref.m diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 19d890851a..d6224f1f7b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2285,58 +2285,64 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, const ObjCObjectPointerType *OPT = BaseType->getAsObjCObjectPointerType(); const ObjCInterfaceType *IFaceT = OPT ? OPT->getInterfaceType() : BaseType->getAsObjCInterfaceType(); - ObjCInterfaceDecl *IDecl = IFaceT->getDecl(); - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(&Member, - ClassDeclared)) { - // If the decl being referenced had an error, return an error for this - // sub-expr without emitting another error, in order to avoid cascading - // error cases. - if (IV->isInvalidDecl()) - return ExprError(); + if (IFaceT) { + ObjCInterfaceDecl *IDecl = IFaceT->getDecl(); + ObjCInterfaceDecl *ClassDeclared; + ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(&Member, ClassDeclared); + + if (IV) { + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (IV->isInvalidDecl()) + return ExprError(); - // Check whether we can reference this field. - if (DiagnoseUseOfDecl(IV, MemberLoc)) - return ExprError(); - if (IV->getAccessControl() != ObjCIvarDecl::Public && - IV->getAccessControl() != ObjCIvarDecl::Package) { - ObjCInterfaceDecl *ClassOfMethodDecl = 0; - if (ObjCMethodDecl *MD = getCurMethodDecl()) - ClassOfMethodDecl = MD->getClassInterface(); - else if (ObjCImpDecl && getCurFunctionDecl()) { - // Case of a c-function declared inside an objc implementation. - // FIXME: For a c-style function nested inside an objc implementation - // class, there is no implementation context available, so we pass - // down the context as argument to this routine. Ideally, this context - // need be passed down in the AST node and somehow calculated from the - // AST for a function decl. - Decl *ImplDecl = ObjCImpDecl.getAs(); - if (ObjCImplementationDecl *IMPD = - dyn_cast(ImplDecl)) - ClassOfMethodDecl = IMPD->getClassInterface(); - else if (ObjCCategoryImplDecl* CatImplClass = - dyn_cast(ImplDecl)) - ClassOfMethodDecl = CatImplClass->getClassInterface(); - } - - if (IV->getAccessControl() == ObjCIvarDecl::Private) { - if (ClassDeclared != IDecl || - ClassOfMethodDecl != ClassDeclared) - Diag(MemberLoc, diag::error_private_ivar_access) << IV->getDeclName(); + // Check whether we can reference this field. + if (DiagnoseUseOfDecl(IV, MemberLoc)) + return ExprError(); + if (IV->getAccessControl() != ObjCIvarDecl::Public && + IV->getAccessControl() != ObjCIvarDecl::Package) { + ObjCInterfaceDecl *ClassOfMethodDecl = 0; + if (ObjCMethodDecl *MD = getCurMethodDecl()) + ClassOfMethodDecl = MD->getClassInterface(); + else if (ObjCImpDecl && getCurFunctionDecl()) { + // Case of a c-function declared inside an objc implementation. + // FIXME: For a c-style function nested inside an objc implementation + // class, there is no implementation context available, so we pass + // down the context as argument to this routine. Ideally, this context + // need be passed down in the AST node and somehow calculated from the + // AST for a function decl. + Decl *ImplDecl = ObjCImpDecl.getAs(); + if (ObjCImplementationDecl *IMPD = + dyn_cast(ImplDecl)) + ClassOfMethodDecl = IMPD->getClassInterface(); + else if (ObjCCategoryImplDecl* CatImplClass = + dyn_cast(ImplDecl)) + ClassOfMethodDecl = CatImplClass->getClassInterface(); + } + + if (IV->getAccessControl() == ObjCIvarDecl::Private) { + if (ClassDeclared != IDecl || + ClassOfMethodDecl != ClassDeclared) + Diag(MemberLoc, diag::error_private_ivar_access) + << IV->getDeclName(); + } + // @protected + else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) + Diag(MemberLoc, diag::error_protected_ivar_access) + << IV->getDeclName(); } - // @protected - else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) - Diag(MemberLoc, diag::error_protected_ivar_access) << IV->getDeclName(); - } - return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), - MemberLoc, BaseExpr, - OpKind == tok::arrow)); + return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), + MemberLoc, BaseExpr, + OpKind == tok::arrow)); + } + return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) + << IDecl->getDeclName() << &Member + << BaseExpr->getSourceRange()); } - return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) - << IDecl->getDeclName() << &Member - << BaseExpr->getSourceRange()); + // We don't have an interface. FIXME: deal with ObjC builtin 'id' type. } // Handle properties on 'id' and qualified "id". if (OpKind == tok::period && (BaseType->isObjCIdType() || diff --git a/test/SemaObjC/id-isa-ref.m b/test/SemaObjC/id-isa-ref.m new file mode 100644 index 0000000000..1480a52e4a --- /dev/null +++ b/test/SemaObjC/id-isa-ref.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef struct objc_object { + struct objc_class *isa; +} *id; + +@interface Whatever ++self; +@end + +static void func() { + + id x; + + // FIXME: The following needs to compile without error. I will fix this tomorrow (7/15/09). Until I do, we will produce an error. + [x->isa self]; // expected-error {{member reference base type 'id' is not a structure or union}} +} -- 2.50.1