[cfe-commits] r75870 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/SemaObjC/id-isa-ref.m

Steve Naroff snaroff at apple.com
Wed Jul 15 17:25:07 PDT 2009


Author: snaroff
Date: Wed Jul 15 19:25:06 2009
New Revision: 75870

URL: http://llvm.org/viewvc/llvm-project?rev=75870&view=rev
Log:
Avoid crashing for the enclosed test case.

This is fallout from the recent ObjCObjectPointerType rework. I'll work on fixing this tomorrow.

Added:
    cfe/trunk/test/SemaObjC/id-isa-ref.m
Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=75870&r1=75869&r2=75870&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jul 15 19:25:06 2009
@@ -2285,58 +2285,64 @@
     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<Decl>();
-          if (ObjCImplementationDecl *IMPD = 
-              dyn_cast<ObjCImplementationDecl>(ImplDecl))
-            ClassOfMethodDecl = IMPD->getClassInterface();
-          else if (ObjCCategoryImplDecl* CatImplClass =
-                      dyn_cast<ObjCCategoryImplDecl>(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<Decl>();
+            if (ObjCImplementationDecl *IMPD = 
+                dyn_cast<ObjCImplementationDecl>(ImplDecl))
+              ClassOfMethodDecl = IMPD->getClassInterface();
+            else if (ObjCCategoryImplDecl* CatImplClass =
+                        dyn_cast<ObjCCategoryImplDecl>(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 ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
-                       << IDecl->getDeclName() << &Member
-                       << BaseExpr->getSourceRange());
+        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());
+    }
+    // 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() || 

Added: cfe/trunk/test/SemaObjC/id-isa-ref.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/id-isa-ref.m?rev=75870&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/id-isa-ref.m (added)
+++ cfe/trunk/test/SemaObjC/id-isa-ref.m Wed Jul 15 19:25:06 2009
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef struct objc_object {
+  struct objc_class *isa;
+} *id;
+
+ at interface Whatever
++self;
+ at 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}}
+}





More information about the cfe-commits mailing list