Nicola Pero - PATCH: fix objc/7993 (shadowing private ivars in subclasses) (original) (raw)
This is the mail archive of the gcc-patches@gcc.gnu.orgmailing list for the GCC project.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] |
- From: Nicola Pero
- To: shebs at apple dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 25 Sep 2002 14:35:02 +0100 (BST)
- Subject: PATCH: fix objc/7993 (shadowing private ivars in subclasses)
Here is a patch for objc/7993 - just to remind you, objc/7993 is a bug report we just received, which says -
"If an instance variable is declared @private, the same variable name can't be reused as name for local variables when implementing methods of subclasses.
This is wrong, because when writing subclasses you should not have to worry about private implementation details of the superclass, such as names of private variables. (I don't know, however, any official specification of the Objective-C language, and therefore can't refer to any document confirming my claim about the purpose of @private.)"
Actually, yes I do agree with the reporter in this instance. In the pure GNU ObjC tradition, I don't like @private variables at all :-) but if we have support for them, it makes sense to have them work properly.
I'd say (just to set the policy in stone) that a meaningful policy would be that, if an instance variable is private,
the class in which it is declared can access it without hassle;
a subclass can't access the variable - it's hidden, invisible, and if you try accessing it you get an 'undeclared' type of error; you can declare a local variable with the same name and get no error or warning whatsoever - it is as if the private variables didn't exist.
the same level of protection as for @protected variables is in place: if you try accessing the instance via ->, as for protected variables, you get an error; but of course if you get the @defs of the object, you can still access it
a subclass can't declare an instance variable with the same name (this condition is somewhat unfortunate, but can't be removed without messing up ObjC)
If there is agreement that this is the correct behaviour, I attach a couple of testcases, and a patch for objc/objc-act.c to implement this behaviour. Basically the only change is that a private variable in a subclass is no longer {existing but generating an error if you access/refer it}; it is now completely hidden/undeclared (and so can be shadowed with local variables without warnings).
I'd also like to document this behaviour in the documentation ... but where ? I was wondering if, as part of the GCC documentation, we could start writing a 'reference/specification' of exactly how GNU ObjC/the GNU ObjC compiler is supposed to behave - where we document all these details ... what generates a warning, what does not, and in the end what is valid ObjC and what is not. This might end up becoming a reference / specification on ObjC - at least on the GNU/Apple ObjC variant - but I wouldn't mind that, since there is none. And yes, I quite like writing documentation about ObjC. :-)
Let me know if the patch makes sense to you :-)
Wed Sep 25 14:33:22 2002 Nicola Pero n.pero@mi.flashnet.it
Fix PR objc/7993:
* objc-act.c (is_private): Do not emit the 'instance variable %s
is declared private' error.
(is_public): Emit the error after calling is_private.
(lookup_objc_ivar): If the instance variable is private, return 0
- the instance variable is invisible here.
Index: objc-act.c
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v retrieving revision 1.159 diff -u -r1.159 objc-act.c --- objc-act.c 17 Sep 2002 13:59:30 -0000 1.159 +++ objc-act.c 25 Sep 2002 13:28:34 -0000 @@ -5851,8 +5851,6 @@ if (TREE_PRIVATE (decl) && ! is_ivar (CLASS_IVARS (implementation_template), DECL_NAME (decl))) {
error ("instance variable `%s' is declared private",
} else @@ -5896,7 +5894,17 @@ == CATEGORY_IMPLEMENTATION_TYPE)) && (CLASS_NAME (objc_implementation_context) == TYPE_NAME (basetype))))IDENTIFIER_POINTER (DECL_NAME (decl))); return 1;return ! is_private (decl);
{int private = is_private (decl);if (private){error ("instance variable `%s' is declared private",IDENTIFIER_POINTER (DECL_NAME (decl)));}return ! private;} error ("instance variable `%s' is declared %s", IDENTIFIER_POINTER (identifier),
@@ -8526,7 +8534,7 @@ else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id))) { if (is_private (decl))
return error_mark_node;
}return 0; else return build_ivar_reference (id);
== now the testcases ==
Wed Sep 25 15:28:28 2002 Nicola Pero n.pero@mi.flashnet.it
* objc.dg/private-1.m: New test.
* objc.dg/private-2.m: New test.private-1.m:
/* Test errors for accessing @private and @protected variables. / / Author: Nicola Pero nicola@brainstorm.co.uk. / / { dg-do compile } */ #include <objc/objc.h>
@interface MySuperClass { @private int private;
@protected int protected;
@public int public; }
- (void) test; @end
@implementation MySuperClass
- (void) test { private = 12; /* Ok / protected = 12; / Ok / public = 12; / Ok */ } @end
@interface MyClass : MySuperClass @end
@implementation MyClass
(void) test { /* Private variables simply don't exist in the subclass. / private = 12;/ { dg-error "undeclared" } / / { dg-error "function it appears in" "" { target --* } { 36 } } */
protected = 12; /* Ok / public = 12; / Ok */
} @end
int main (void) { MyClass *m = nil;
if (m != nil) { int access;
access = m->private; /* { dg-error "is declared private" } */
access = m->protected; /* { dg-error "is declared protected" } */
access = m->public; /* Ok */
}return 0; }
private-2.m:
/* Test warnings for shadowing instance variables. / / Author: Nicola Pero nicola@brainstorm.co.uk. / / { dg-do compile } */ #include <objc/objc.h>
@interface MySuperClass { @private int private;
@protected int protected;
@public int public; }
- (void) test; @end
@implementation MySuperClass
(void) test { /* FIXME: I wonder if the warnings shouldn't be better generated when the variable is declared, rather than used! */ int private = 12; int protected = 12; int public = 12; int a;
a = private; /* { dg-warning "hides instance variable" } / a = protected; / { dg-warning "hides instance variable" } / a = public; / { dg-warning "hides instance variable" } */
} @end
@interface MyClass : MySuperClass @end
@implementation MyClass
(void) test { int private = 12; int protected = 12; int public = 12; int a;
/* The private variable can be shadowed without warnings, because
- it's invisible, and not accessible, to the subclass! / a = private; / Ok / a = protected; / { dg-warning "hides instance variable" } / a = public; / { dg-warning "hides instance variable" } */
} @end
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |