]> granicus.if.org Git - clang/commitdiff
Check of ivar access access control.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 3 Mar 2009 01:21:12 +0000 (01:21 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 3 Mar 2009 01:21:12 +0000 (01:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65912 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.def
lib/Sema/SemaExpr.cpp
test/SemaObjC/ivar-access-tests.m [new file with mode: 0644]
test/SemaObjC/static-ivar-ref-1.m

index 4648a7d314bc780784deda090827710c2f20a59d..781daad31a37139d439c89b0e7f454a167dd4824 100644 (file)
@@ -1440,4 +1440,7 @@ DIAG(warn_ivar_use_hidden, WARNING,
      "local declaration of %0 hides instance variable")
 DIAG(error_ivar_use_in_class_method, ERROR,
      "instance variable %0 accessed in class method")
-
+DIAG(error_private_ivar_access, ERROR,
+     "instance variable %0 is private")
+DIAG(error_protected_ivar_access, ERROR,
+     "instance variable %0 is protected")
index 32ef0f7b35190b5da900323ed01112f0600b3466..6252bcaef5bfd3510bfe00d5aca7d38bef02cc29 100644 (file)
@@ -632,7 +632,8 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
     // this name, if the lookup sucedes, we replace it our current decl.
     if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) {
       ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
-      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II)) {
+      ObjCInterfaceDecl *ClassDeclared;
+      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
         // Check if referencing a field with __attribute__((deprecated)).
         if (DiagnoseUseOfDecl(IV, Loc))
           return ExprError();
@@ -645,6 +646,9 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
         // If a class method uses a global variable, even if an ivar with
         // same name exists, use the global.
         if (!IsClsMethod) {
+          if (IV->getAccessControl() == ObjCIvarDecl::Private &&
+              ClassDeclared != IFace)
+           Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
           // FIXME: This should use a new expr for a direct reference, don't turn
           // this into Self->ivar, just return a BareIVarExpr or something.
           IdentifierInfo &II = Context.Idents.get("self");
@@ -660,8 +664,12 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
     else if (getCurMethodDecl()->isInstanceMethod()) {
       // We should warn if a local variable hides an ivar.
       ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
-      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II))
-        Diag(Loc, diag::warn_ivar_use_hidden)<<IV->getDeclName();
+      ObjCInterfaceDecl *ClassDeclared;
+      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+        if (IV->getAccessControl() != ObjCIvarDecl::Private ||
+            IFace == ClassDeclared)
+          Diag(Loc, diag::warn_ivar_use_hidden)<<IV->getDeclName();
+      }
     }
     // Needed to implement property "super.method" notation.
     if (D == 0 && II->isStr("super")) {
@@ -1773,7 +1781,9 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
   // Handle access to Objective-C instance variables, such as "Obj->ivar" and
   // (*Obj).ivar.
   if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) {
-    if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(&Member)) {
+    ObjCInterfaceDecl *ClassDeclared;
+    if (ObjCIvarDecl *IV = IFTy->getDecl()->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.
@@ -1783,6 +1793,19 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
       // Check whether we can reference this field.
       if (DiagnoseUseOfDecl(IV, MemberLoc))
         return ExprError();
+      if (IV->getAccessControl() != ObjCIvarDecl::Public) {
+        ObjCInterfaceDecl *ClassOfMethodDecl = 0;
+        if (ObjCMethodDecl *MD = getCurMethodDecl())
+          ClassOfMethodDecl =  MD->getClassInterface();
+        if (IV->getAccessControl() == ObjCIvarDecl::Private) { 
+          if (ClassDeclared != IFTy->getDecl() || 
+              ClassOfMethodDecl != ClassDeclared)
+            Diag(MemberLoc, diag::error_private_ivar_access) << IV->getDeclName();
+        }
+        // @protected
+        else if (!IFTy->getDecl()->isSuperClassOf(ClassOfMethodDecl))
+          Diag(MemberLoc, diag::error_protected_ivar_access) << IV->getDeclName();
+      }
 
       ObjCIvarRefExpr *MRef= new (Context) ObjCIvarRefExpr(IV, IV->getType(),
                                                  MemberLoc, BaseExpr,
diff --git a/test/SemaObjC/ivar-access-tests.m b/test/SemaObjC/ivar-access-tests.m
new file mode 100644 (file)
index 0000000..ee232dd
--- /dev/null
@@ -0,0 +1,80 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@interface MySuperClass
+{
+@private
+  int private;
+
+@protected
+  int protected;
+
+@public
+  int public;
+}
+@end
+
+@implementation MySuperClass
+- (void) test {
+    int access;
+    MySuperClass *s = 0;
+    access = s->private;   
+    access = s->protected;
+}
+@end
+
+
+@interface MyClass : MySuperClass 
+@end
+
+@implementation MyClass
+- (void) test {
+    int access;
+    MySuperClass *s = 0;
+    access = s->private; // expected-error {{instance variable 'private' is private}}
+    access = s->protected;
+    MyClass *m=0;
+    access = m->private; // expected-error {{instance variable 'private' is private}}
+    access = m->protected;
+}
+@end
+
+
+@interface Deeper : MyClass
+@end
+
+@implementation Deeper 
+- (void) test {
+    int access;
+    MySuperClass *s = 0;
+    access = s->private; // expected-error {{instance variable 'private' is private}}
+    access = s->protected;
+    MyClass *m=0;
+    access = m->private; // expected-error {{instance variable 'private' is private}}
+    access = m->protected;
+}
+@end
+
+@interface Unrelated
+@end
+
+@implementation Unrelated 
+- (void) test {
+    int access;
+    MySuperClass *s = 0;
+    access = s->private; // expected-error {{instance variable 'private' is private}}
+    access = s->protected; // expected-error {{instance variable 'protected' is protected}}
+    MyClass *m=0;
+    access = m->private; // expected-error {{instance variable 'private' is private}}
+    access = m->protected; // expected-error {{instance variable 'protected' is protected}}
+}
+@end
+
+int main (void)
+{
+  MySuperClass *s = 0;
+  int access;
+  access = s->private;   // expected-error {{instance variable 'private' is private}}
+  access = s->protected; // expected-error {{instance variable 'protected' is protected}}
+  return 0;
+}
+
index d01a7fb6da0c507c8d991c9eaa47163e0a8d9c66..a0b389e1ad6c63202aad8c465ef4a66e2f6be857 100644 (file)
@@ -2,6 +2,7 @@
 
 @interface current 
 {
+@public
   int ivar;
   int ivar1;
   int ivar2;