From 935fd768f95edc21f03c6c61f8b48ee99ff8bab6 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 3 Mar 2009 01:21:12 +0000 Subject: [PATCH] Check of ivar access access control. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65912 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.def | 5 +- lib/Sema/SemaExpr.cpp | 31 ++++++-- test/SemaObjC/ivar-access-tests.m | 80 +++++++++++++++++++++ test/SemaObjC/static-ivar-ref-1.m | 1 + 4 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 test/SemaObjC/ivar-access-tests.m 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)<getDeclName(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + if (IV->getAccessControl() != ObjCIvarDecl::Private || + IFace == ClassDeclared) + Diag(Loc, diag::warn_ivar_use_hidden)<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; -- 2.40.0