aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-03-03 01:21:12 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-03-03 01:21:12 +0000
commit935fd768f95edc21f03c6c61f8b48ee99ff8bab6 (patch)
tree4ef40d56f446dc161d9a26ce8980fc4ac7b94262
parentc97fb9a394ce2cc5e664fcb472e93553528378ad (diff)
Check of ivar access access control.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65912 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.def5
-rw-r--r--lib/Sema/SemaExpr.cpp31
-rw-r--r--test/SemaObjC/ivar-access-tests.m80
-rw-r--r--test/SemaObjC/static-ivar-ref-1.m1
4 files changed, 112 insertions, 5 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def
index 4648a7d314..781daad31a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.def
+++ b/include/clang/Basic/DiagnosticSemaKinds.def
@@ -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")
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 32ef0f7b35..6252bcaef5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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
index 0000000000..ee232dd1c0
--- /dev/null
+++ b/test/SemaObjC/ivar-access-tests.m
@@ -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;
+}
+
diff --git a/test/SemaObjC/static-ivar-ref-1.m b/test/SemaObjC/static-ivar-ref-1.m
index d01a7fb6da..a0b389e1ad 100644
--- a/test/SemaObjC/static-ivar-ref-1.m
+++ b/test/SemaObjC/static-ivar-ref-1.m
@@ -2,6 +2,7 @@
@interface current
{
+@public
int ivar;
int ivar1;
int ivar2;