Bug 9866 - static nested class refers to private member of outer class
Summary: static nested class refers to private member of outer class
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libgcj (show other bugs)
Version: 3.2
: P3 normal
Target Milestone: 4.3.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on: 28067
Blocks: 18131
  Show dependency treegraph
 
Reported: 2003-02-26 17:56 UTC by brian_252
Modified: 2007-01-09 20:44 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-07-13 02:39:57


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description brian_252 2003-02-26 17:56:00 UTC
This bug comes from compiling ant-1.5.1, specifically  ProjectHelperImpl.java.  They create a nested static class.  In the nested class, they make an explicit reference to the outer class.  And finally they refer to a private member of the outer class.

Here's a simplification of the code:

public class PHI
        {
        public static void main( String args[] )
                {
                PHI phi = new PHI();
                RH rh = new RH( phi );
                rh.setLocator( "TheHound" );
                }

        private String locator;

        static class RH
                {
                PHI phi;
                public RH( PHI phi )
                        {
                        this.phi = phi;
                        }
                public void setLocator( String locator )
                        {
                        phi.locator = locator;
                        }
                }
        }

brian@mahogany:Personal/Workshop/Test/ :) gcj -C PHI.java
brian@mahogany:Personal/Workshop/Test/ :) gij PHI
Exception in thread "main" java.lang.IllegalAccessError
   at 0x40174218: java.lang.Throwable.Throwable() (/usr/lib/libgcj.so.2)
   at 0x4016a7c4: java.lang.Error.Error() (/usr/lib/libgcj.so.2)
   at 0x4016c908: java.lang.LinkageError.LinkageError() (/usr/lib/libgcj.so.2)
   at 0x4016b6a4: java.lang.IncompatibleClassChangeError.IncompatibleClassChangeError() (/usr/lib/libgcj.so.2)
   at 0x4016b404: java.lang.IllegalAccessError.IllegalAccessError() (/usr/lib/libgcj.so.2)
   at 0x40149d5a: _Jv_ResolvePoolEntry(java.lang.Class, int) (/usr/lib/libgcj.so.2)
   at 0x401516f0: _Jv_InterpMethod.continue1(_Jv_InterpMethodInvocation) (/usr/lib/libgcj.so.2)
   at 0x40152703: _Jv_InterpMethod.run(ffi_cif, void, ffi_raw, _Jv_InterpMethodInvocation) (/usr/lib/libgcj.so.2)
   at 0x4014e671: _Jv_InterpMethod.run_normal(ffi_cif, void, ffi_raw, void) (/usr/lib/libgcj.so.2)
   at 0x4023b114: ?? (??:0)
   at 0x4023b25f: ffi_call_SYSV (/usr/lib/libgcj.so.2)
   at 0x4023b227: ffi_raw_call (/usr/lib/libgcj.so.2)
   at 0x4014e8db: _Jv_InterpMethod.continue1(_Jv_InterpMethodInvocation) (/usr/lib/libgcj.so.2)
   at 0x40152703: _Jv_InterpMethod.run(ffi_cif, void, ffi_raw, _Jv_InterpMethodInvocation) (/usr/lib/libgcj.so.2)
   at 0x4014e671: _Jv_InterpMethod.run_normal(ffi_cif, void, ffi_raw, void) (/usr/lib/libgcj.so.2)
   at 0x4023b114: ?? (??:0)
   at 0x4015565f: gnu.gcj.runtime.FirstThread.run() (/usr/lib/libgcj.so.2)
   at 0x4015fb63: java.lang.Thread.run_(java.lang.Object) (/usr/lib/libgcj.so.2)
   at 0x4023a6a4: ?? (??:0)
   at 0x403dff76: GC_start_routine (/usr/lib/libgcjgc.so.1)
   at 0x403f7fa5: ?? (??:0)
   at 0x4050c8ea: __clone (/lib/libc.so.6)

In my personal opinion, i don't think this is a bug.  The inner class does have access to the private members of the outer class, but this is through an implicit reference.  Static classes don't have the implicit reference.  The question is, what is the definied behavior of an explicit reference.

So why do i report it?  Because obviously other compilers have compiled and executed ProjectHelperImpl successfully.

A related PR is 9369.

Just hypothetically here, if the compiler does generate a function void setLocator( String Locator )
	{ this.Locator = Locator }
in the outer class PHI, does this function become accessible to the public (or to subclasses)?  I hope not, since this would change the definition of the class.

Release:
gcj-3.2, gij-3.2

Environment:
GNU/Debian Linux (woody mostly)

How-To-Repeat:
gcj -C PHI.java
gij PHI
Comment 1 brian_252 2003-02-26 17:56:00 UTC
Fix:
If the outer data member is protected, there's no error.
Comment 2 Andrew Pinski 2003-05-25 20:48:54 UTC
still an error on the mainline ():

tin:~/src/gnu/gcctest>gcj -C PHI.java 
tin:~/src/gnu/gcctest>gij PHI
Exception in thread "main" java.lang.IllegalAccessError
   at _Jv_ResolvePoolEntry(java.lang.Class, int) (/home/gates/pinskia/linux/lib/
libgcj.so.4.0.0)
   at PHI$RH.setLocator(java.lang.String) (Unknown Source)
   at PHI.main(java.lang.String[]) (Unknown Source)
tin:~/src/gnu/gcctest>gcj -C PHI.java -g
tin:~/src/gnu/gcctest>gij PHI
Exception in thread "main" java.lang.IllegalAccessError
   at _Jv_ResolvePoolEntry(java.lang.Class, int) (/home/gates/pinskia/linux/lib/
libgcj.so.4.0.0)
   at PHI$RH.setLocator(java.lang.String) (Unknown Source)
   at PHI.main(java.lang.String[]) (Unknown Source)
tin:~/src/gnu/gcctest>javac PHI.java 
tin:~/src/gnu/gcctest>!gij
gij PHI
tin:~/src/gnu/gcctest>gcj -C PHI.java
tin:~/src/gnu/gcctest>java PHI
tin:~/src/gnu/gcctest>

Comment 3 Andrew Pinski 2003-08-03 18:30:54 UTC
The native compiler works but gij does not so changing component to libgcj which is 
where gij is part of.
Comment 4 Tom Tromey 2003-08-04 03:13:05 UTC
The JDK java interpreter does accept the code gcj
generates.  However, javac generates an explicit
package-private settor method.  That is what gcj
should do as well.  So, this is probably two bugs:
one in libgcj's access checking, and another in
gcj itself.  The latter is, I believe, a duplicate.
Comment 5 Phil Shaw 2004-11-15 18:03:38 UTC
This bug also affects GCJ 3.3.2 on GNU/Linux and 3.3.3 on Cygwin.

The class org.w3c.tidy.ParserImpl in the JTidy tool is another test case.

http://sourceforge.net/projects/jtidy/

Comment 6 pmladek 2006-11-09 14:16:21 UTC
I still see the problem with gcj (GCC) 4.1.2 20061018 (prerelease) (SUSE Linux). 

It makes problems also with OpenOffice.org when the internally used hsqldb is compiled and used with gcj/gij.

Note that it is really a bug. The java documentation says at http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html:
--- cut ---
A nested class is a member of its enclosing class and, as such, has access to other members of the enclosing class, even if they are declared private.
--- cut ---

There is another definition in the "Java Language Specification" at
http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.1:
--- cut ---
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (ยง7.6) that encloses the declaration of the member or constructor.
--- cut ---

Note that also C++ works this way. The OPOSITE problem is even mentioned in the "Frequently reported non-bugs" at http://gcc.gnu.org/bugs.html#nonbugs_cxx:
--- cut ---
Nested classes can access private members and types of the containing class.

    Defect report 45 clarifies that nested classes are members of the class they are nested in, and so are granted access to private members of that class.
--- cut ---
Comment 7 Tom Tromey 2007-01-09 20:44:59 UTC
All gcj front end bugs have been fixed by the gcj-eclipse branch merge.
I'm mass-closing the affected PRs.
If you believe one of these was closed in error, please reopen it
with a note explaining why.
Thanks.