]> granicus.if.org Git - clang/commitdiff
Avoid crashing for the enclosed test case.
authorSteve Naroff <snaroff@apple.com>
Thu, 16 Jul 2009 00:25:06 +0000 (00:25 +0000)
committerSteve Naroff <snaroff@apple.com>
Thu, 16 Jul 2009 00:25:06 +0000 (00:25 +0000)
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
test/SemaObjC/id-isa-ref.m [new file with mode: 0644]

index 19d890851ac79cfc1791591fc6946722d2e1225d..d6224f1f7bd5f3ff98c0a5d0c76f59e0dab73977 100644 (file)
@@ -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<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 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 (file)
index 0000000..1480a52
--- /dev/null
@@ -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}}
+}