Bug 9866

Summary: static nested class refers to private member of outer class
Product: gcc Reporter: brian_252
Component: libgcjAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs, java-prs, mark, phil, pmladek
Priority: P3    
Version: 3.2   
Target Milestone: 4.3.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2005-07-13 02:39:57
Bug Depends on: 28067    
Bug Blocks: 18131    

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.