1 /*
2  * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.tools.java;
27 
28 import java.util.*;
29 import java.io.OutputStream;
30 import java.io.PrintStream;
31 import sun.tools.tree.Context;
32 import sun.tools.tree.Vset;
33 import sun.tools.tree.Expression;
34 import sun.tools.tree.LocalMember;
35 import sun.tools.tree.UplevelReference;
36 
37 /**
38  * This class is a Java class definition
39  *
40  * WARNING: The contents of this source file are not part of any
41  * supported API.  Code that depends on them does so at its own risk:
42  * they are subject to change or removal without notice.
43  */
44 @SuppressWarnings("deprecation")
45 public
46 class ClassDefinition implements Constants {
47 
48     protected Object source;
49     protected long where;
50     protected int modifiers;
51     protected Identifier localName; // for local classes
52     protected ClassDeclaration declaration;
53     protected IdentifierToken superClassId;
54     protected IdentifierToken interfaceIds[];
55     protected ClassDeclaration superClass;
56     protected ClassDeclaration interfaces[];
57     protected ClassDefinition outerClass;
58     protected MemberDefinition outerMember;
59     protected MemberDefinition innerClassMember;        // field for me in outerClass
60     protected MemberDefinition firstMember;
61     protected MemberDefinition lastMember;
62     protected boolean resolved;
63     protected String documentation;
64     protected boolean error;
65     protected boolean nestError;
66     protected UplevelReference references;
67     protected boolean referencesFrozen;
68     private Hashtable<Identifier, MemberDefinition> fieldHash = new Hashtable<>(31);
69     private int abstr;
70 
71     // Table of local and anonymous classes whose internal names are constructed
72     // using the current class as a prefix.  This is part of a fix for
73     // bugid 4054523 and 4030421.  See also 'Environment.getClassDefinition'
74     // and 'BatchEnvironment.makeClassDefinition'.  Allocated on demand.
75     private Hashtable<String, ClassDefinition> localClasses = null;
76     private final int LOCAL_CLASSES_SIZE = 31;
77 
78     // The immediately surrounding context in which the class appears.
79     // Set at the beginning of checking, upon entry to 'SourceClass.checkInternal'.
80     // Null for classes that are not local or inside a local class.
81     // At present, this field exists only for the benefit of 'resolveName' as part
82     // of the fix for 4095716.
83     protected Context classContext;
84 
85     // The saved class context is now also used in 'SourceClass.getAccessMember'.
86     // Provide read-only access via this method.  Part of fix for 4098093.
getClassContext()87     public Context getClassContext() {
88         return classContext;
89     }
90 
91 
92     /**
93      * Constructor
94      */
ClassDefinition(Object source, long where, ClassDeclaration declaration, int modifiers, IdentifierToken superClass, IdentifierToken interfaces[])95     protected ClassDefinition(Object source, long where, ClassDeclaration declaration,
96                               int modifiers, IdentifierToken superClass, IdentifierToken interfaces[]) {
97         this.source = source;
98         this.where = where;
99         this.declaration = declaration;
100         this.modifiers = modifiers;
101         this.superClassId = superClass;
102         this.interfaceIds = interfaces;
103     }
104 
105     /**
106      * Get the source of the class
107      */
getSource()108     public final Object getSource() {
109         return source;
110     }
111 
112     /**
113      * Check if there were any errors in this class.
114      */
getError()115     public final boolean getError() {
116         return error;
117     }
118 
119     /**
120      * Mark this class to be erroneous.
121      */
setError()122     public final void setError() {
123         this.error = true;
124         setNestError();
125     }
126 
127     /**
128      * Check if there were any errors in our class nest.
129      */
getNestError()130     public final boolean getNestError() {
131         // Check to see if our error value is set, or if any of our
132         // outer classes' error values are set.  This will work in
133         // conjunction with setError(), which sets the error value
134         // of its outer class, to yield true is any of our nest
135         // siblings has an error.  This addresses bug 4111488: either
136         // code should be generated for all classes in a nest, or
137         // none of them.
138         return nestError || ((outerClass != null) ? outerClass.getNestError() : false);
139     }
140 
141     /**
142      * Mark this class, and all siblings in its class nest, to be
143      * erroneous.
144      */
setNestError()145     public final void setNestError() {
146         this.nestError = true;
147         if (outerClass != null) {
148             // If we have an outer class, set it to be erroneous as well.
149             // This will work in conjunction with getError(), which checks
150             // the error value of its outer class, to set the whole class
151             // nest to be erroneous.  This address bug 4111488: either
152             // code should be generated for all classes in a nest, or
153             // none of them.
154             outerClass.setNestError();
155         }
156     }
157 
158     /**
159      * Get the position in the input
160      */
getWhere()161     public final long getWhere() {
162         return where;
163     }
164 
165     /**
166      * Get the class declaration
167      */
getClassDeclaration()168     public final ClassDeclaration getClassDeclaration() {
169         return declaration;
170     }
171 
172     /**
173      * Get the class' modifiers
174      */
getModifiers()175     public final int getModifiers() {
176         return modifiers;
177     }
subModifiers(int mod)178     public final void subModifiers(int mod) {
179         modifiers &= ~mod;
180     }
addModifiers(int mod)181     public final void addModifiers(int mod) {
182         modifiers |= mod;
183     }
184 
185     // *** DEBUG ***
186     protected boolean supersCheckStarted = !(this instanceof sun.tools.javac.SourceClass);
187 
188     /**
189      * Get the class' super class
190      */
getSuperClass()191     public final ClassDeclaration getSuperClass() {
192         /*---
193         if (superClass == null && superClassId != null)
194             throw new CompilerError("getSuperClass "+superClassId);
195         // There are obscure cases where null is the right answer,
196         // in order to enable some error reporting later on.
197         // For example:  class T extends T.N { class N { } }
198         ---*/
199 
200         // *** DEBUG ***
201         // This method should not be called if the superclass has not been resolved.
202         if (!supersCheckStarted) throw new CompilerError("unresolved super");
203 
204         return superClass;
205     }
206 
207     /**
208      * Get the super class, and resolve names now if necessary.
209      *
210      * It is only possible to resolve names at this point if we are
211      * a source class.  The provision of this method at this level
212      * in the class hierarchy is dubious, but see 'getInnerClass' below.
213      * All other calls to 'getSuperClass(env)' appear in 'SourceClass'.
214      * NOTE: An older definition of this method has been moved to
215      * 'SourceClass', where it overrides this one.
216      *
217      * @see #resolveTypeStructure
218      */
219 
getSuperClass(Environment env)220     public ClassDeclaration getSuperClass(Environment env) {
221         return getSuperClass();
222     }
223 
224     /**
225      * Get the class' interfaces
226      */
getInterfaces()227     public final ClassDeclaration getInterfaces()[] {
228         if (interfaces == null)  throw new CompilerError("getInterfaces");
229         return interfaces;
230     }
231 
232     /**
233      * Get the class' enclosing class (or null if not inner)
234      */
getOuterClass()235     public final ClassDefinition getOuterClass() {
236         return outerClass;
237     }
238 
239     /**
240      * Set the class' enclosing class.  Must be done at most once.
241      */
setOuterClass(ClassDefinition outerClass)242     protected final void setOuterClass(ClassDefinition outerClass) {
243         if (this.outerClass != null)  throw new CompilerError("setOuterClass");
244         this.outerClass = outerClass;
245     }
246 
247     /**
248      * Set the class' enclosing current instance pointer.
249      * Must be done at most once.
250      */
setOuterMember(MemberDefinition outerMember)251     protected final void setOuterMember(MemberDefinition outerMember) {
252 
253         if (isStatic() || !isInnerClass())  throw new CompilerError("setOuterField");
254         if (this.outerMember != null)  throw new CompilerError("setOuterField");
255         this.outerMember = outerMember;
256     }
257 
258     /**
259      * Tell if the class is inner.
260      * This predicate also returns true for top-level nested types.
261      * To test for a true inner class as seen by the programmer,
262      * use {@code !isTopLevel()}.
263      */
isInnerClass()264     public final boolean isInnerClass() {
265         return outerClass != null;
266     }
267 
268     /**
269      * Tell if the class is a member of another class.
270      * This is false for package members and for block-local classes.
271      */
isMember()272     public final boolean isMember() {
273         return outerClass != null && !isLocal();
274     }
275 
276     /**
277      * Tell if the class is "top-level", which is either a package member,
278      * or a static member of another top-level class.
279      */
isTopLevel()280     public final boolean isTopLevel() {
281         return outerClass == null || isStatic() || isInterface();
282     }
283 
284     /**
285      * Tell if the class is local or inside a local class,
286      * which means it cannot be mentioned outside of its file.
287      */
288 
289     // The comment above is true only because M_LOCAL is set
290     // whenever M_ANONYMOUS is.  I think it is risky to assume that
291     // isAnonymous(x) => isLocal(x).
292 
isInsideLocal()293     public final boolean isInsideLocal() {
294         return isLocal() ||
295             (outerClass != null && outerClass.isInsideLocal());
296     }
297 
298     /**
299      * Tell if the class is local or anonymous class, or inside
300      * such a class, which means it cannot be mentioned outside of
301      * its file.
302      */
isInsideLocalOrAnonymous()303     public final boolean isInsideLocalOrAnonymous() {
304         return isLocal() || isAnonymous () ||
305             (outerClass != null && outerClass.isInsideLocalOrAnonymous());
306     }
307 
308     /**
309      * Return a simple identifier for this class (idNull if anonymous).
310      */
getLocalName()311     public Identifier getLocalName() {
312         if (localName != null) {
313             return localName;
314         }
315         // This is also the name of the innerClassMember, if any:
316         return getName().getFlatName().getName();
317     }
318 
319     /**
320      * Set the local name of a class.  Must be a local class.
321      */
setLocalName(Identifier name)322     public void setLocalName(Identifier name) {
323         if (isLocal()) {
324             localName = name;
325         }
326     }
327 
328     /**
329      * If inner, get the field for this class in the enclosing class
330      */
getInnerClassMember()331     public final MemberDefinition getInnerClassMember() {
332         if (outerClass == null)
333             return null;
334         if (innerClassMember == null) {
335             // We must find the field in the outer class.
336             Identifier nm = getName().getFlatName().getName();
337             for (MemberDefinition field = outerClass.getFirstMatch(nm);
338                  field != null; field = field.getNextMatch()) {
339                 if (field.isInnerClass()) {
340                     innerClassMember = field;
341                     break;
342                 }
343             }
344             if (innerClassMember == null)
345                 throw new CompilerError("getInnerClassField");
346         }
347         return innerClassMember;
348     }
349 
350     /**
351      * If inner, return an innermost uplevel self pointer, if any exists.
352      * Otherwise, return null.
353      */
findOuterMember()354     public final MemberDefinition findOuterMember() {
355         return outerMember;
356     }
357 
358     /**
359      * See if this is a (nested) static class.
360      */
isStatic()361     public final boolean isStatic() {
362         return (modifiers & ACC_STATIC) != 0;
363     }
364 
365     /**
366      * Get the class' top-level enclosing class
367      */
getTopClass()368     public final ClassDefinition getTopClass() {
369         ClassDefinition p, q;
370         for (p = this; (q = p.outerClass) != null; p = q)
371             ;
372         return p;
373     }
374 
375     /**
376      * Get the class' first field or first match
377      */
getFirstMember()378     public final MemberDefinition getFirstMember() {
379         return firstMember;
380     }
getFirstMatch(Identifier name)381     public final MemberDefinition getFirstMatch(Identifier name) {
382         return fieldHash.get(name);
383     }
384 
385     /**
386      * Get the class' name
387      */
getName()388     public final Identifier getName() {
389         return declaration.getName();
390     }
391 
392     /**
393      * Get the class' type
394      */
getType()395     public final Type getType() {
396         return declaration.getType();
397     }
398 
399     /**
400      * Get the class' documentation
401      */
getDocumentation()402     public String getDocumentation() {
403         return documentation;
404     }
405 
406     /**
407      * Return true if the given documentation string contains a deprecation
408      * paragraph.  This is true if the string contains the tag @deprecated
409      * is the first word in a line.
410      */
containsDeprecated(String documentation)411     public static boolean containsDeprecated(String documentation) {
412         if (documentation == null) {
413             return false;
414         }
415     doScan:
416         for (int scan = 0;
417              (scan = documentation.indexOf(paraDeprecated, scan)) >= 0;
418              scan += paraDeprecated.length()) {
419             // make sure there is only whitespace between this word
420             // and the beginning of the line
421             for (int beg = scan-1; beg >= 0; beg--) {
422                 char ch = documentation.charAt(beg);
423                 if (ch == '\n' || ch == '\r') {
424                     break;      // OK
425                 }
426                 if (!Character.isSpace(ch)) {
427                     continue doScan;
428                 }
429             }
430             // make sure the char after the word is space or end of line
431             int end = scan+paraDeprecated.length();
432             if (end < documentation.length()) {
433                 char ch = documentation.charAt(end);
434                 if (!(ch == '\n' || ch == '\r') && !Character.isSpace(ch)) {
435                     continue doScan;
436                 }
437             }
438             return true;
439         }
440         return false;
441     }
442 
inSamePackage(ClassDeclaration c)443     public final boolean inSamePackage(ClassDeclaration c) {
444         // find out if the class stored in c is defined in the same
445         // package as the current class.
446         return inSamePackage(c.getName().getQualifier());
447     }
448 
inSamePackage(ClassDefinition c)449     public final boolean inSamePackage(ClassDefinition c) {
450         // find out if the class stored in c is defined in the same
451         // package as the current class.
452         return inSamePackage(c.getName().getQualifier());
453     }
454 
inSamePackage(Identifier packageName)455     public final boolean inSamePackage(Identifier packageName) {
456         return (getName().getQualifier().equals(packageName));
457     }
458 
459     /**
460      * Checks
461      */
isInterface()462     public final boolean isInterface() {
463         return (getModifiers() & M_INTERFACE) != 0;
464     }
isClass()465     public final boolean isClass() {
466         return (getModifiers() & M_INTERFACE) == 0;
467     }
isPublic()468     public final boolean isPublic() {
469         return (getModifiers() & M_PUBLIC) != 0;
470     }
isPrivate()471     public final boolean isPrivate() {
472         return (getModifiers() & M_PRIVATE) != 0;
473     }
isProtected()474     public final boolean isProtected() {
475         return (getModifiers() & M_PROTECTED) != 0;
476     }
isPackagePrivate()477     public final boolean isPackagePrivate() {
478         return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0;
479     }
isFinal()480     public final boolean isFinal() {
481         return (getModifiers() & M_FINAL) != 0;
482     }
isAbstract()483     public final boolean isAbstract() {
484         return (getModifiers() & M_ABSTRACT) != 0;
485     }
isSynthetic()486     public final boolean isSynthetic() {
487         return (getModifiers() & M_SYNTHETIC) != 0;
488     }
isDeprecated()489     public final boolean isDeprecated() {
490         return (getModifiers() & M_DEPRECATED) != 0;
491     }
isAnonymous()492     public final boolean isAnonymous() {
493         return (getModifiers() & M_ANONYMOUS) != 0;
494     }
isLocal()495     public final boolean isLocal() {
496         return (getModifiers() & M_LOCAL) != 0;
497     }
hasConstructor()498     public final boolean hasConstructor() {
499         return getFirstMatch(idInit) != null;
500     }
501 
502 
503     /**
504      * Check to see if a class must be abstract.  This method replaces
505      * isAbstract(env)
506      */
mustBeAbstract(Environment env)507     public final boolean mustBeAbstract(Environment env) {
508         // If it is declared abstract, return true.
509         // (Fix for 4110534.)
510         if (isAbstract()) {
511             return true;
512         }
513 
514         // Check to see if the class should have been declared to be
515         // abstract.
516 
517         // We make sure that the inherited method collection has been
518         // performed.
519         collectInheritedMethods(env);
520 
521         // We check for any abstract methods inherited or declared
522         // by this class.
523         Iterator<MemberDefinition> methods = getMethods();
524         while (methods.hasNext()) {
525             MemberDefinition method = methods.next();
526 
527             if (method.isAbstract()) {
528                 return true;
529             }
530         }
531 
532         // We check for hidden "permanently abstract" methods in
533         // our superclasses.
534         return getPermanentlyAbstractMethods().hasNext();
535     }
536 
537     /**
538      * Check if this is a super class of another class
539      */
superClassOf(Environment env, ClassDeclaration otherClass)540     public boolean superClassOf(Environment env, ClassDeclaration otherClass)
541                                                                 throws ClassNotFound {
542         while (otherClass != null) {
543             if (getClassDeclaration().equals(otherClass)) {
544                 return true;
545             }
546             otherClass = otherClass.getClassDefinition(env).getSuperClass();
547         }
548         return false;
549     }
550 
551     /**
552      * Check if this is an enclosing class of another class
553      */
enclosingClassOf(ClassDefinition otherClass)554     public boolean enclosingClassOf(ClassDefinition otherClass) {
555         while ((otherClass = otherClass.getOuterClass()) != null) {
556             if (this == otherClass) {
557                 return true;
558             }
559         }
560         return false;
561     }
562 
563     /**
564      * Check if this is a sub class of another class
565      */
subClassOf(Environment env, ClassDeclaration otherClass)566     public boolean subClassOf(Environment env, ClassDeclaration otherClass) throws ClassNotFound {
567         ClassDeclaration c = getClassDeclaration();
568         while (c != null) {
569             if (c.equals(otherClass)) {
570                 return true;
571             }
572             c = c.getClassDefinition(env).getSuperClass();
573         }
574         return false;
575     }
576 
577     /**
578      * Check if this class is implemented by another class
579      */
implementedBy(Environment env, ClassDeclaration c)580     public boolean implementedBy(Environment env, ClassDeclaration c) throws ClassNotFound {
581         for (; c != null ; c = c.getClassDefinition(env).getSuperClass()) {
582             if (getClassDeclaration().equals(c)) {
583                 return true;
584             }
585             ClassDeclaration intf[] = c.getClassDefinition(env).getInterfaces();
586             for (int i = 0 ; i < intf.length ; i++) {
587                 if (implementedBy(env, intf[i])) {
588                     return true;
589                 }
590             }
591         }
592         return false;
593     }
594 
595     /**
596      * Check to see if a class which implements interface `this' could
597      * possibly implement the interface `intDef'.  Note that the only
598      * way that this can fail is if `this' and `intDef' have methods
599      * which are of the same signature and different return types.  This
600      * method is used by Environment.explicitCast() to determine if a
601      * cast between two interfaces is legal.
602      *
603      * This method should only be called on a class after it has been
604      * basicCheck()'ed.
605      */
couldImplement(ClassDefinition intDef)606     public boolean couldImplement(ClassDefinition intDef) {
607         // Check to see if we could have done the necessary checks.
608         if (!doInheritanceChecks) {
609             throw new CompilerError("couldImplement: no checks");
610         }
611 
612         // This method should only be called for interfaces.
613         if (!isInterface() || !intDef.isInterface()) {
614             throw new CompilerError("couldImplement: not interface");
615         }
616 
617         // Make sure we are not called before we have collected our
618         // inheritance information.
619         if (allMethods == null) {
620             throw new CompilerError("couldImplement: called early");
621         }
622 
623         // Get the other classes' methods.  getMethods() in
624         // general can return methods which are not visible to the
625         // current package.  We need to make sure that these do not
626         // prevent this class from being implemented.
627         Iterator<MemberDefinition> otherMethods = intDef.getMethods();
628 
629         while (otherMethods.hasNext()) {
630             // Get one of the methods from intDef...
631             MemberDefinition method = otherMethods.next();
632 
633             Identifier name = method.getName();
634             Type type = method.getType();
635 
636             // See if we implement a method of the same signature...
637             MemberDefinition myMethod = allMethods.lookupSig(name, type);
638 
639             //System.out.println("Comparing\n\t" + myMethod +
640             //                   "\nand\n\t" + method);
641 
642             if (myMethod != null) {
643                 // We do.  Make sure the methods have the same return type.
644                 if (!myMethod.sameReturnType(method)) {
645                     return false;
646                 }
647             }
648         }
649 
650         return true;
651     }
652 
653     /**
654      * Check if another class can be accessed from the 'extends' or 'implements'
655      * clause of this class.
656      */
extendsCanAccess(Environment env, ClassDeclaration c)657     public boolean extendsCanAccess(Environment env, ClassDeclaration c) throws ClassNotFound {
658 
659         // Names in the 'extends' or 'implements' clause of an inner class
660         // are checked as if they appeared in the body of the surrounding class.
661         if (outerClass != null) {
662             return outerClass.canAccess(env, c);
663         }
664 
665         // We are a package member.
666 
667         ClassDefinition cdef = c.getClassDefinition(env);
668 
669         if (cdef.isLocal()) {
670             // No locals should be in scope in the 'extends' or
671             // 'implements' clause of a package member.
672             throw new CompilerError("top local");
673         }
674 
675         if (cdef.isInnerClass()) {
676             MemberDefinition f = cdef.getInnerClassMember();
677 
678             // Access to public member is always allowed.
679             if (f.isPublic()) {
680                 return true;
681             }
682 
683             // Private access is ok only from the same class nest.  This can
684             // happen only if the class represented by 'this' encloses the inner
685             // class represented by 'f'.
686             if (f.isPrivate()) {
687                 return getClassDeclaration().equals(f.getTopClass().getClassDeclaration());
688             }
689 
690             // Protected or default access -- allow access if in same package.
691             return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());
692         }
693 
694         // Access to public member is always allowed.
695         if (cdef.isPublic()) {
696             return true;
697         }
698 
699         // Default access -- allow access if in same package.
700         return getName().getQualifier().equals(c.getName().getQualifier());
701     }
702 
703     /**
704      * Check if another class can be accessed from within the body of this class.
705      */
canAccess(Environment env, ClassDeclaration c)706     public boolean canAccess(Environment env, ClassDeclaration c) throws ClassNotFound {
707         ClassDefinition cdef = c.getClassDefinition(env);
708 
709         if (cdef.isLocal()) {
710             // if it's in scope, it's accessible
711             return true;
712         }
713 
714         if (cdef.isInnerClass()) {
715             return canAccess(env, cdef.getInnerClassMember());
716         }
717 
718         // Public access is always ok
719         if (cdef.isPublic()) {
720             return true;
721         }
722 
723         // It must be in the same package
724         return getName().getQualifier().equals(c.getName().getQualifier());
725     }
726 
727     /**
728      * Check if a field can be accessed from a class
729      */
730 
canAccess(Environment env, MemberDefinition f)731     public boolean canAccess(Environment env, MemberDefinition f)
732                 throws ClassNotFound {
733 
734         // Public access is always ok
735         if (f.isPublic()) {
736             return true;
737         }
738         // Protected access is ok from a subclass
739         if (f.isProtected() && subClassOf(env, f.getClassDeclaration())) {
740             return true;
741         }
742         // Private access is ok only from the same class nest
743         if (f.isPrivate()) {
744             return getTopClass().getClassDeclaration()
745                 .equals(f.getTopClass().getClassDeclaration());
746         }
747         // It must be in the same package
748         return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());
749     }
750 
751     /**
752      * Check if a class is entitled to inline access to a class from
753      * another class.
754      */
permitInlinedAccess(Environment env, ClassDeclaration c)755     public boolean permitInlinedAccess(Environment env, ClassDeclaration c)
756                        throws ClassNotFound {
757 
758         return (env.opt() && c.equals(declaration)) ||
759                (env.opt_interclass() && canAccess(env, c));
760     }
761 
762     /**
763      * Check if a class is entitled to inline access to a method from
764      * another class.
765      */
permitInlinedAccess(Environment env, MemberDefinition f)766     public boolean permitInlinedAccess(Environment env, MemberDefinition f)
767                        throws ClassNotFound {
768         return (env.opt()
769                     && (f.clazz.getClassDeclaration().equals(declaration))) ||
770                (env.opt_interclass() && canAccess(env, f));
771     }
772 
773     /**
774      * We know the field is marked protected (and not public) and that
775      * the field is visible (as per canAccess).  Can we access the field as
776      * <accessor>.<field>, where <accessor> has the type <accessorType>?
777      *
778      * Protected fields can only be accessed when the accessorType is a
779      * subclass of the current class
780      */
protectedAccess(Environment env, MemberDefinition f, Type accessorType)781     public boolean protectedAccess(Environment env, MemberDefinition f,
782                                    Type accessorType)
783         throws ClassNotFound
784     {
785 
786         return
787                // static protected fields are accessible
788                f.isStatic()
789             || // allow array.clone()
790                (accessorType.isType(TC_ARRAY) && (f.getName() == idClone)
791                  && (f.getType().getArgumentTypes().length == 0))
792             || // <accessorType> is a subtype of the current class
793                (accessorType.isType(TC_CLASS)
794                  && env.getClassDefinition(accessorType.getClassName())
795                          .subClassOf(env, getClassDeclaration()))
796             || // we are accessing the field from a friendly class (same package)
797                (getName().getQualifier()
798                    .equals(f.getClassDeclaration().getName().getQualifier()));
799     }
800 
801 
802     /**
803      * Find or create an access method for a private member,
804      * or return null if this is not possible.
805      */
getAccessMember(Environment env, Context ctx, MemberDefinition field, boolean isSuper)806     public MemberDefinition getAccessMember(Environment env, Context ctx,
807                                           MemberDefinition field, boolean isSuper) {
808         throw new CompilerError("binary getAccessMember");
809     }
810 
811     /**
812      * Find or create an update method for a private member,
813      * or return null if this is not possible.
814      */
getUpdateMember(Environment env, Context ctx, MemberDefinition field, boolean isSuper)815     public MemberDefinition getUpdateMember(Environment env, Context ctx,
816                                             MemberDefinition field, boolean isSuper) {
817         throw new CompilerError("binary getUpdateMember");
818     }
819 
820     /**
821      * Get a field from this class.  Report ambiguous fields.
822      * If no accessible field is found, this method may return an
823      * inaccessible field to allow a useful error message.
824      *
825      * getVariable now takes the source class `source' as an argument.
826      * This allows getVariable to check whether a field is inaccessible
827      * before it signals that a field is ambiguous.  The compiler used to
828      * signal an ambiguity even when one of the fields involved was not
829      * accessible.  (bug 4053724)
830      */
getVariable(Environment env, Identifier nm, ClassDefinition source)831     public MemberDefinition getVariable(Environment env,
832                                         Identifier nm,
833                                         ClassDefinition source)
834         throws AmbiguousMember, ClassNotFound {
835 
836         return getVariable0(env, nm, source, true, true);
837     }
838 
839     /*
840      * private fields are never inherited.  package-private fields are
841      * not inherited across package boundaries.  To capture this, we
842      * take two booleans as parameters: showPrivate indicates whether
843      * we have passed a class boundary, and showPackage indicates whether
844      * we have crossed a package boundary.
845      */
getVariable0(Environment env, Identifier nm, ClassDefinition source, boolean showPrivate, boolean showPackage)846     private MemberDefinition getVariable0(Environment env,
847                                           Identifier nm,
848                                           ClassDefinition source,
849                                           boolean showPrivate,
850                                           boolean showPackage)
851         throws AmbiguousMember, ClassNotFound {
852 
853         // Check to see if this field is defined in the current class
854         for (MemberDefinition member = getFirstMatch(nm);
855              member != null;
856              member = member.getNextMatch()) {
857             if (member.isVariable()) {
858                 if ((showPrivate || !member.isPrivate()) &&
859                     (showPackage || !member.isPackagePrivate())) {
860                     // It is defined in this class.
861                     return member;
862                 } else {
863                     // Even though this definition is not inherited,
864                     // it hides all definitions in supertypes.
865                     return null;
866                 }
867             }
868         }
869 
870         // Find the field in our superclass.
871         ClassDeclaration sup = getSuperClass();
872         MemberDefinition field = null;
873         if (sup != null) {
874             field =
875                 sup.getClassDefinition(env)
876                   .getVariable0(env, nm, source,
877                                 false,
878                                 showPackage && inSamePackage(sup));
879         }
880 
881         // Find the field in our superinterfaces.
882         for (int i = 0 ; i < interfaces.length ; i++) {
883             // Try to look up the field in an interface.  Since interfaces
884             // only have public fields, the values of the two boolean
885             // arguments are not important.
886             MemberDefinition field2 =
887                 interfaces[i].getClassDefinition(env)
888                   .getVariable0(env, nm, source, true, true);
889 
890             if (field2 != null) {
891                 // If we have two different, accessible fields, then
892                 // we've found an ambiguity.
893                 if (field != null &&
894                     source.canAccess(env, field) &&
895                     field2 != field) {
896 
897                     throw new AmbiguousMember(field2, field);
898                 }
899                 field = field2;
900             }
901         }
902         return field;
903     }
904 
905     /**
906      * Tells whether to report a deprecation error for this class.
907      */
reportDeprecated(Environment env)908     public boolean reportDeprecated(Environment env) {
909         return (isDeprecated()
910                 || (outerClass != null && outerClass.reportDeprecated(env)));
911     }
912 
913     /**
914      * Note that this class is being used somehow by {@code ref}.
915      * Report deprecation errors, etc.
916      */
noteUsedBy(ClassDefinition ref, long where, Environment env)917     public void noteUsedBy(ClassDefinition ref, long where, Environment env) {
918         // (Have this deal with canAccess() checks, too?)
919         if (reportDeprecated(env)) {
920             env.error(where, "warn.class.is.deprecated", this);
921         }
922     }
923 
924    /**
925      * Get an inner class.
926      * Look in supers but not outers.
927      * (This is used directly to resolve expressions like "site.K", and
928      * inside a loop to resolve lone names like "K" or the "K" in "K.L".)
929      *
930      * Called from 'Context' and 'FieldExpression' as well as this class.
931      *
932      * @see FieldExpression.checkCommon
933      * @see resolveName
934      */
getInnerClass(Environment env, Identifier nm)935     public MemberDefinition getInnerClass(Environment env, Identifier nm)
936                                                         throws ClassNotFound {
937         // Note:  AmbiguousClass will not be thrown unless and until
938         // inner classes can be defined inside interfaces.
939 
940         // Check if it is defined in the current class
941         for (MemberDefinition field = getFirstMatch(nm);
942                 field != null ; field = field.getNextMatch()) {
943             if (field.isInnerClass()) {
944                 if (field.getInnerClass().isLocal()) {
945                     continue;   // ignore this name; it is internally generated
946                 }
947                 return field;
948             }
949         }
950 
951         // Get it from the super class
952         // It is likely that 'getSuperClass()' could be made to work here
953         // but we would have to assure somehow that 'resolveTypeStructure'
954         // has been called on the current class nest.  Since we can get
955         // here from 'resolveName', which is called from 'resolveSupers',
956         // it is possible that the first attempt to resolve the superclass
957         // will originate here, instead of in the call to 'getSuperClass'
958         // in 'checkSupers'.  See 'resolveTypeStructure', in which a call
959         // to 'resolveSupers' precedes the call to 'checkSupers'.  Why is
960         // name resolution done twice, first in 'resolveName'?
961         // NOTE: 'SourceMember.resolveTypeStructure' may initiate type
962         // structure resolution for an inner class.  Normally, this
963         // occurs during the resolution of the outer class, but fields
964         // added after the resolution of their containing class will
965         // be resolved late -- see 'addMember(env,field)' below.
966         // This should only happen for synthetic members, which should
967         // never be an inner class.
968         ClassDeclaration sup = getSuperClass(env);
969         if (sup != null)
970             return sup.getClassDefinition(env).getInnerClass(env, nm);
971 
972         return null;
973     }
974 
975     /**
976      * Lookup a method.  This code implements the method lookup
977      * mechanism specified in JLS 15.11.2.
978      *
979      * This mechanism cannot be used to lookup synthetic methods.
980      */
matchMethod(Environment env, ClassDefinition accessor, Identifier methodName, Type[] argumentTypes, boolean isAnonConstCall, Identifier accessPackage)981     private MemberDefinition matchMethod(Environment env,
982                                          ClassDefinition accessor,
983                                          Identifier methodName,
984                                          Type[] argumentTypes,
985                                          boolean isAnonConstCall,
986                                          Identifier accessPackage)
987         throws AmbiguousMember, ClassNotFound {
988 
989         if (allMethods == null || !allMethods.isFrozen()) {
990             // This may be too restrictive.
991             throw new CompilerError("matchMethod called early");
992             // collectInheritedMethods(env);
993         }
994 
995         // A tentative maximally specific method.
996         MemberDefinition tentative = null;
997 
998         // A list of other methods which may be maximally specific too.
999         List<MemberDefinition> candidateList = null;
1000 
1001         // Get all the methods inherited by this class which
1002         // have the name `methodName'.
1003         Iterator<MemberDefinition> methods = allMethods.lookupName(methodName);
1004 
1005         while (methods.hasNext()) {
1006             MemberDefinition method = methods.next();
1007 
1008             // See if this method is applicable.
1009             if (!env.isApplicable(method, argumentTypes)) {
1010                 continue;
1011             }
1012 
1013             // See if this method is accessible.
1014             if (accessor != null) {
1015                 if (!accessor.canAccess(env, method)) {
1016                     continue;
1017                 }
1018             } else if (isAnonConstCall) {
1019                 if (method.isPrivate() ||
1020                     (method.isPackagePrivate() &&
1021                      accessPackage != null &&
1022                      !inSamePackage(accessPackage))) {
1023                     // For anonymous constructor accesses, we
1024                     // haven't yet built an accessing class.
1025                     // We disallow anonymous classes from seeing
1026                     // private/package-private inaccessible
1027                     // constructors in their superclass.
1028                     continue;
1029                 }
1030             } else {
1031                 // If accessor is null, we assume that the access
1032                 // is allowed.  Query: is this option used?
1033             }
1034 
1035             if (tentative == null) {
1036                 // `method' becomes our tentative maximally specific match.
1037                 tentative = method;
1038             } else {
1039                 if (env.isMoreSpecific(method, tentative)) {
1040                     // We have found a method which is a strictly better
1041                     // match than `tentative'.  Replace it.
1042                     tentative = method;
1043                 } else {
1044                     // If this method could possibly be another
1045                     // maximally specific method, add it to our
1046                     // list of other candidates.
1047                     if (!env.isMoreSpecific(tentative,method)) {
1048                         if (candidateList == null) {
1049                             candidateList = new ArrayList<>();
1050                         }
1051                         candidateList.add(method);
1052                     }
1053                 }
1054             }
1055         }
1056 
1057         if (tentative != null && candidateList != null) {
1058             // Find out if our `tentative' match is a uniquely
1059             // maximally specific.
1060             Iterator<MemberDefinition> candidates = candidateList.iterator();
1061             while (candidates.hasNext()) {
1062                 MemberDefinition method = candidates.next();
1063                 if (!env.isMoreSpecific(tentative, method)) {
1064                     throw new AmbiguousMember(tentative, method);
1065                 }
1066             }
1067         }
1068 
1069         return tentative;
1070     }
1071 
1072     /**
1073      * Lookup a method.  This code implements the method lookup
1074      * mechanism specified in JLS 15.11.2.
1075      *
1076      * This mechanism cannot be used to lookup synthetic methods.
1077      */
matchMethod(Environment env, ClassDefinition accessor, Identifier methodName, Type[] argumentTypes)1078     public MemberDefinition matchMethod(Environment env,
1079                                         ClassDefinition accessor,
1080                                         Identifier methodName,
1081                                         Type[] argumentTypes)
1082         throws AmbiguousMember, ClassNotFound {
1083 
1084         return matchMethod(env, accessor, methodName,
1085                            argumentTypes, false, null);
1086     }
1087 
1088     /**
1089      * Lookup a method.  This code implements the method lookup
1090      * mechanism specified in JLS 15.11.2.
1091      *
1092      * This mechanism cannot be used to lookup synthetic methods.
1093      */
matchMethod(Environment env, ClassDefinition accessor, Identifier methodName)1094     public MemberDefinition matchMethod(Environment env,
1095                                         ClassDefinition accessor,
1096                                         Identifier methodName)
1097         throws AmbiguousMember, ClassNotFound {
1098 
1099         return matchMethod(env, accessor, methodName,
1100                            Type.noArgs, false, null);
1101     }
1102 
1103     /**
1104      * A version of matchMethod to be used only for constructors
1105      * when we cannot pass in a sourceClass argument.  We just assert
1106      * our package name.
1107      *
1108      * This is used only for anonymous classes, where we have to look up
1109      * a (potentially) protected constructor with no valid sourceClass
1110      * parameter available.
1111      */
matchAnonConstructor(Environment env, Identifier accessPackage, Type argumentTypes[])1112     public MemberDefinition matchAnonConstructor(Environment env,
1113                                                  Identifier accessPackage,
1114                                                  Type argumentTypes[])
1115         throws AmbiguousMember, ClassNotFound {
1116 
1117         return matchMethod(env, null, idInit, argumentTypes,
1118                            true, accessPackage);
1119     }
1120 
1121     /**
1122      * Find a method, ie: exact match in this class or any of the super
1123      * classes.
1124      *
1125      * Only called by javadoc.  For now I am holding off rewriting this
1126      * code to rely on collectInheritedMethods(), as that code has
1127      * not gotten along with javadoc in the past.
1128      */
findMethod(Environment env, Identifier nm, Type t)1129     public MemberDefinition findMethod(Environment env, Identifier nm, Type t)
1130     throws ClassNotFound {
1131         // look in the current class
1132         MemberDefinition f;
1133         for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1134             // Note that non-method types return false for equalArguments().
1135             if (f.getType().equalArguments(t)) {
1136                 return f;
1137             }
1138         }
1139 
1140         // constructors are not inherited
1141         if (nm.equals(idInit)) {
1142             return null;
1143         }
1144 
1145         // look in the super class
1146         ClassDeclaration sup = getSuperClass();
1147         if (sup == null)
1148             return null;
1149 
1150         return sup.getClassDefinition(env).findMethod(env, nm, t);
1151     }
1152 
1153     // We create a stub for this.  Source classes do more work.
basicCheck(Environment env)1154     protected void basicCheck(Environment env) throws ClassNotFound {
1155         // Do the outer class first.
1156         if (outerClass != null)
1157             outerClass.basicCheck(env);
1158     }
1159 
1160     /**
1161      * Check this class.
1162      */
check(Environment env)1163     public void check(Environment env) throws ClassNotFound {
1164     }
1165 
checkLocalClass(Environment env, Context ctx, Vset vset, ClassDefinition sup, Expression args[], Type argTypes[] )1166     public Vset checkLocalClass(Environment env, Context ctx,
1167                                 Vset vset, ClassDefinition sup,
1168                                 Expression args[], Type argTypes[]
1169                                 ) throws ClassNotFound {
1170         throw new CompilerError("checkLocalClass");
1171     }
1172 
1173     //---------------------------------------------------------------
1174     // The non-synthetic methods defined in this class or in any
1175     // of its parents (class or interface).  This member is used
1176     // to cache work done in collectInheritedMethods for use by
1177     // getMethods() and matchMethod().  It should be accessed by
1178     // no other method without forethought.
1179     MethodSet allMethods = null;
1180 
1181     // One of our superclasses may contain an abstract method which
1182     // we are unable to ever implement.  This happens when there is
1183     // a package-private abstract method in our parent and we are in
1184     // a different package than our parent.  In these cases, we
1185     // keep a list of the "permanently abstract" or "unimplementable"
1186     // methods so that we can correctly detect that this class is
1187     // indeed abstract and so that we can give somewhat comprehensible
1188     // error messages.
1189     private List<MemberDefinition> permanentlyAbstractMethods = new ArrayList<>();
1190 
1191     /**
1192      * This method returns an Iterator of all abstract methods
1193      * in our superclasses which we are unable to implement.
1194      */
getPermanentlyAbstractMethods()1195     protected Iterator<MemberDefinition> getPermanentlyAbstractMethods() {
1196         // This method can only be called after collectInheritedMethods.
1197         if (allMethods == null) {
1198             throw new CompilerError("isPermanentlyAbstract() called early");
1199         }
1200 
1201         return permanentlyAbstractMethods.iterator();
1202     }
1203 
1204     /**
1205      * A flag used by turnOffInheritanceChecks() to indicate if
1206      * inheritance checks are on or off.
1207      */
1208     protected static boolean doInheritanceChecks = true;
1209 
1210     /**
1211      * This is a workaround to allow javadoc to turn off certain
1212      * inheritance/override checks which interfere with javadoc
1213      * badly.  In the future it might be good to eliminate the
1214      * shared sources of javadoc and javac to avoid the need for this
1215      * sort of workaround.
1216      */
turnOffInheritanceChecks()1217     public static void turnOffInheritanceChecks() {
1218         doInheritanceChecks = false;
1219     }
1220 
1221     /**
1222      * Add all of the methods declared in or above `parent' to
1223      * `allMethods', the set of methods in the current class.
1224      * `myMethods' is the set of all methods declared in this
1225      * class, and `mirandaMethods' is a repository for Miranda methods.
1226      * If mirandaMethods is null, no mirandaMethods will be
1227      * generated.
1228      *
1229      * For a definition of Miranda methods, see the comment above the
1230      * method addMirandaMethods() which occurs later in this file.
1231      */
collectOneClass(Environment env, ClassDeclaration parent, MethodSet myMethods, MethodSet allMethods, MethodSet mirandaMethods)1232     private void collectOneClass(Environment env,
1233                                  ClassDeclaration parent,
1234                                  MethodSet myMethods,
1235                                  MethodSet allMethods,
1236                                  MethodSet mirandaMethods) {
1237 
1238         // System.out.println("Inheriting methods from " + parent);
1239 
1240         try {
1241             ClassDefinition pClass = parent.getClassDefinition(env);
1242             Iterator<MemberDefinition> methods = pClass.getMethods(env);
1243             while (methods.hasNext()) {
1244                 MemberDefinition method =
1245                     methods.next();
1246 
1247                 // Private methods are not inherited.
1248                 //
1249                 // Constructors are not inherited.
1250                 //
1251                 // Any non-abstract methods in an interface come
1252                 // from java.lang.Object.  This means that they
1253                 // should have already been added to allMethods
1254                 // when we walked our superclass lineage.
1255                 if (method.isPrivate() ||
1256                     method.isConstructor() ||
1257                     (pClass.isInterface() && !method.isAbstract())) {
1258 
1259                     continue;
1260                 }
1261 
1262                 // Get the components of the methods' signature.
1263                 Identifier name = method.getName();
1264                 Type type = method.getType();
1265 
1266                 // Check for a method of the same signature which
1267                 // was locally declared.
1268                 MemberDefinition override =
1269                     myMethods.lookupSig(name, type);
1270 
1271                 // Is this method inaccessible due to package-private
1272                 // visibility?
1273                 if (method.isPackagePrivate() &&
1274                     !inSamePackage(method.getClassDeclaration())) {
1275 
1276                     if (override != null && this instanceof
1277                         sun.tools.javac.SourceClass) {
1278                         // We give a warning when a class shadows an
1279                         // inaccessible package-private method from
1280                         // its superclass.  This warning is meant
1281                         // to prevent people from relying on overriding
1282                         // when it does not happen.  This warning should
1283                         // probably be removed to be consistent with the
1284                         // general "no warnings" policy of this
1285                         // compiler.
1286                         //
1287                         // The `instanceof' above is a hack so that only
1288                         // SourceClass generates this warning, not a
1289                         // BinaryClass, for example.
1290                         env.error(method.getWhere(),
1291                                   "warn.no.override.access",
1292                                   override,
1293                                   override.getClassDeclaration(),
1294                                   method.getClassDeclaration());
1295                     }
1296 
1297                     // If our superclass has a package-private abstract
1298                     // method that we have no access to, then we add
1299                     // this method to our list of permanently abstract
1300                     // methods.  The idea is, since we cannot override
1301                     // the method, we can never make this class
1302                     // non-abstract.
1303                     if (method.isAbstract()) {
1304                         permanentlyAbstractMethods.add(method);
1305                     }
1306 
1307                     // `method' is inaccessible.  We do not inherit it.
1308                     continue;
1309                 }
1310 
1311                 if (override != null) {
1312                     // `method' and `override' have the same signature.
1313                     // We are required to check that `override' is a
1314                     // legal override of `method'
1315 
1316                     //System.out.println ("About to check override of " +
1317                     //              method);
1318 
1319                     override.checkOverride(env, method);
1320                 } else {
1321                     // In the absence of a definition in the class
1322                     // itself, we check to see if this definition
1323                     // can be successfully merged with any other
1324                     // inherited definitions.
1325 
1326                     // Have we added a member of the same signature
1327                     // to `allMethods' already?
1328                     MemberDefinition formerMethod =
1329                         allMethods.lookupSig(name, type);
1330 
1331                     // If the previous definition is nonexistent or
1332                     // ignorable, replace it.
1333                     if (formerMethod == null) {
1334                         //System.out.println("Added " + method + " to " +
1335                         //             this);
1336 
1337                         if (mirandaMethods != null &&
1338                             pClass.isInterface() && !isInterface()) {
1339                             // Whenever a class inherits a method
1340                             // from an interface, that method is
1341                             // one of our "miranda" methods.  Early
1342                             // VMs require that these methods be
1343                             // added as true members to the class
1344                             // to enable method lookup to work in the
1345                             // VM.
1346                             method =
1347                                 new sun.tools.javac.SourceMember(method,this,
1348                                                                  env);
1349                             mirandaMethods.add(method);
1350 
1351                             //System.out.println("Added " + method +
1352                             // " to " + this + " as a Miranda");
1353                         }
1354 
1355                         // There is no previous inherited definition.
1356                         // Add `method' to `allMethods'.
1357                         allMethods.add(method);
1358                     } else if (isInterface() &&
1359                                !formerMethod.isAbstract() &&
1360                                method.isAbstract()) {
1361                         // If we are in an interface and we have inherited
1362                         // both an abstract method and a non-abstract method
1363                         // then we know that the non-abstract method is
1364                         // a placeholder from Object put in for type checking
1365                         // and the abstract method was already checked to
1366                         // be proper by our superinterface.
1367                         allMethods.replace(method);
1368 
1369                     } else {
1370                         // Okay, `formerMethod' and `method' both have the
1371                         // same signature.  See if they are compatible.
1372 
1373                         //System.out.println ("About to check meet of " +
1374                         //              method);
1375 
1376                         if (!formerMethod.checkMeet(env,
1377                                            method,
1378                                            this.getClassDeclaration())) {
1379                                 // The methods are incompatible.  Skip to
1380                                 // next method.
1381                             continue;
1382                         }
1383 
1384                         if (formerMethod.couldOverride(env, method)) {
1385                                 // Do nothing.  The current definition
1386                                 // is specific enough.
1387 
1388                                 //System.out.println("trivial meet of " +
1389                                 //                 method);
1390                             continue;
1391                         }
1392 
1393                         if (method.couldOverride(env, formerMethod)) {
1394                                 // `method' is more specific than
1395                                 // `formerMethod'.  replace `formerMethod'.
1396 
1397                                 //System.out.println("new def of " + method);
1398                             if (mirandaMethods != null &&
1399                                 pClass.isInterface() && !isInterface()) {
1400                                 // Whenever a class inherits a method
1401                                 // from an interface, that method is
1402                                 // one of our "miranda" methods.  Early
1403                                 // VMs require that these methods be
1404                                 // added as true members to the class
1405                                 // to enable method lookup to work in the
1406                                 // VM.
1407                                 method =
1408                                     new sun.tools.javac.SourceMember(method,
1409                                                                      this,env);
1410 
1411                                 mirandaMethods.replace(method);
1412 
1413                                 //System.out.println("Added " + method +
1414                                 // " to " + this + " as a Miranda");
1415                             }
1416 
1417                             allMethods.replace(method);
1418 
1419                             continue;
1420                         }
1421 
1422                         // Neither method is more specific than the other.
1423                         // Oh well.  We need to construct a nontrivial
1424                         // meet of the two methods.
1425                         //
1426                         // This is not yet implemented, so we give
1427                         // a message with a helpful workaround.
1428                         env.error(this.where,
1429                                   "nontrivial.meet", method,
1430                                   formerMethod.getClassDefinition(),
1431                                   method.getClassDeclaration()
1432                                   );
1433                     }
1434                 }
1435             }
1436         } catch (ClassNotFound ee) {
1437             env.error(getWhere(), "class.not.found", ee.name, this);
1438         }
1439     }
1440 
1441     /**
1442      * <p>Collect all methods defined in this class or inherited from
1443      * any of our superclasses or interfaces.  Look for any
1444      * incompatible definitions.
1445      *
1446      * <p>This function is also responsible for collecting the
1447      * <em>Miranda</em> methods for a class.  For a definition of
1448      * Miranda methods, see the comment in addMirandaMethods()
1449      * below.
1450      */
collectInheritedMethods(Environment env)1451     protected void collectInheritedMethods(Environment env) {
1452         // The methods defined in this class.
1453         MethodSet myMethods;
1454         MethodSet mirandaMethods;
1455 
1456         //System.out.println("Called collectInheritedMethods() for " +
1457         //                 this);
1458 
1459         if (allMethods != null) {
1460             if (allMethods.isFrozen()) {
1461                 // We have already done the collection.  No need to
1462                 // do it again.
1463                 return;
1464             } else {
1465                 // We have run into a circular need to collect our methods.
1466                 // This should not happen at this stage.
1467                 throw new CompilerError("collectInheritedMethods()");
1468             }
1469         }
1470 
1471         myMethods = new MethodSet();
1472         allMethods = new MethodSet();
1473 
1474         // For testing, do not generate miranda methods.
1475         if (env.version12()) {
1476             mirandaMethods = null;
1477         } else {
1478             mirandaMethods = new MethodSet();
1479         }
1480 
1481         // Any methods defined in the current class get added
1482         // to both the myMethods and the allMethods MethodSets.
1483 
1484         for (MemberDefinition member = getFirstMember();
1485              member != null;
1486              member = member.nextMember) {
1487 
1488             // We only collect methods.  Initializers are not relevant.
1489             if (member.isMethod() &&
1490                 !member.isInitializer()) {
1491 
1492                 //System.out.println("Declared in " + this + ", " + member);
1493 
1494                 ////////////////////////////////////////////////////////////
1495                 // PCJ 2003-07-30 modified the following code because with
1496                 // the covariant return type feature of the 1.5 compiler,
1497                 // there might be multiple methods with the same signature
1498                 // but different return types, and MethodSet doesn't
1499                 // support that.  We use a new utility method that attempts
1500                 // to ensure that the appropriate method winds up in the
1501                 // MethodSet.  See 4892308.
1502                 ////////////////////////////////////////////////////////////
1503                 // myMethods.add(member);
1504                 // allMethods.add(member);
1505                 ////////////////////////////////////////////////////////////
1506                 methodSetAdd(env, myMethods, member);
1507                 methodSetAdd(env, allMethods, member);
1508                 ////////////////////////////////////////////////////////////
1509             }
1510         }
1511 
1512         // We're ready to start adding inherited methods.  First add
1513         // the methods from our superclass.
1514 
1515         //System.out.println("About to start superclasses for " + this);
1516 
1517         ClassDeclaration scDecl = getSuperClass(env);
1518         if (scDecl != null) {
1519             collectOneClass(env, scDecl,
1520                             myMethods, allMethods, mirandaMethods);
1521 
1522             // Make sure that we add all unimplementable methods from our
1523             // superclass to our list of unimplementable methods.
1524             ClassDefinition sc = scDecl.getClassDefinition();
1525             Iterator<MemberDefinition> supIter = sc.getPermanentlyAbstractMethods();
1526             while (supIter.hasNext()) {
1527                 permanentlyAbstractMethods.add(supIter.next());
1528             }
1529         }
1530 
1531         // Now we inherit all of the methods from our interfaces.
1532 
1533         //System.out.println("About to start interfaces for " + this);
1534 
1535         for (int i = 0; i < interfaces.length; i++) {
1536             collectOneClass(env, interfaces[i],
1537                             myMethods, allMethods, mirandaMethods);
1538         }
1539         allMethods.freeze();
1540 
1541         // Now we have collected all of our methods from our superclasses
1542         // and interfaces into our `allMethods' member.  Good.  As a last
1543         // task, we add our collected miranda methods to this class.
1544         //
1545         // If we do not add the mirandas to the class explicitly, there
1546         // will be no code generated for them.
1547         if (mirandaMethods != null && mirandaMethods.size() > 0) {
1548             addMirandaMethods(env, mirandaMethods.iterator());
1549         }
1550     }
1551 
1552     ////////////////////////////////////////////////////////////
1553     // PCJ 2003-07-30 added this utility method to insulate
1554     // MethodSet additions from the covariant return type
1555     // feature of the 1.5 compiler.  When there are multiple
1556     // methods with the same signature and different return
1557     // types to be added, we try to ensure that the one with
1558     // the most specific return type winds up in the MethodSet.
1559     // This logic was not put into MethodSet itself because it
1560     // requires access to an Environment for type relationship
1561     // checking.  No error checking is performed here, but that
1562     // should be OK because this code is only still used by
1563     // rmic.  See 4892308.
1564     ////////////////////////////////////////////////////////////
methodSetAdd(Environment env, MethodSet methodSet, MemberDefinition newMethod)1565     private static void methodSetAdd(Environment env,
1566                                      MethodSet methodSet,
1567                                      MemberDefinition newMethod)
1568     {
1569         MemberDefinition oldMethod = methodSet.lookupSig(newMethod.getName(),
1570                                                          newMethod.getType());
1571         if (oldMethod != null) {
1572             Type oldReturnType = oldMethod.getType().getReturnType();
1573             Type newReturnType = newMethod.getType().getReturnType();
1574             try {
1575                 if (env.isMoreSpecific(newReturnType, oldReturnType)) {
1576                     methodSet.replace(newMethod);
1577                 }
1578             } catch (ClassNotFound ignore) {
1579             }
1580         } else {
1581             methodSet.add(newMethod);
1582         }
1583     }
1584     ////////////////////////////////////////////////////////////
1585 
1586     /**
1587      * Get an Iterator of all methods which could be accessed in an
1588      * instance of this class.
1589      */
getMethods(Environment env)1590     public Iterator<MemberDefinition> getMethods(Environment env) {
1591         if (allMethods == null) {
1592             collectInheritedMethods(env);
1593         }
1594         return getMethods();
1595     }
1596 
1597     /**
1598      * Get an Iterator of all methods which could be accessed in an
1599      * instance of this class.  Throw a compiler error if we haven't
1600      * generated this information yet.
1601      */
getMethods()1602     public Iterator<MemberDefinition> getMethods() {
1603         if (allMethods == null) {
1604             throw new CompilerError("getMethods: too early");
1605         }
1606         return allMethods.iterator();
1607     }
1608 
1609     // In early VM's there was a bug -- the VM didn't walk the interfaces
1610     // of a class looking for a method, they only walked the superclass
1611     // chain.  This meant that abstract methods defined only in interfaces
1612     // were not being found.  To fix this bug, a counter-bug was introduced
1613     // in the compiler -- the so-called Miranda methods.  If a class
1614     // does not provide a definition for an abstract method in one of
1615     // its interfaces then the compiler inserts one in the class artificially.
1616     // That way the VM didn't have to bother looking at the interfaces.
1617     //
1618     // This is a problem.  Miranda methods are not part of the specification.
1619     // But they continue to be inserted so that old VM's can run new code.
1620     // Someday, when the old VM's are gone, perhaps classes can be compiled
1621     // without Miranda methods.  Towards this end, the compiler has a
1622     // flag, -nomiranda, which can turn off the creation of these methods.
1623     // Eventually that behavior should become the default.
1624     //
1625     // Why are they called Miranda methods?  Well the sentence "If the
1626     // class is not able to provide a method, then one will be provided
1627     // by the compiler" is very similar to the sentence "If you cannot
1628     // afford an attorney, one will be provided by the court," -- one
1629     // of the so-called "Miranda" rights in the United States.
1630 
1631     /**
1632      * Add a list of methods to this class as miranda methods.  This
1633      * gets overridden with a meaningful implementation in SourceClass.
1634      * BinaryClass should not need to do anything -- it should already
1635      * have its miranda methods and, if it doesn't, then that doesn't
1636      * affect our compilation.
1637      */
addMirandaMethods(Environment env, Iterator<MemberDefinition> mirandas)1638     protected void addMirandaMethods(Environment env,
1639                                      Iterator<MemberDefinition> mirandas) {
1640         // do nothing.
1641     }
1642 
1643     //---------------------------------------------------------------
1644 
inlineLocalClass(Environment env)1645     public void inlineLocalClass(Environment env) {
1646     }
1647 
1648     /**
1649      * We create a stub for this.  Source classes do more work.
1650      * Some calls from 'SourceClass.checkSupers' execute this method.
1651      * @see sun.tools.javac.SourceClass#resolveTypeStructure
1652      */
1653 
resolveTypeStructure(Environment env)1654     public void resolveTypeStructure(Environment env) {
1655     }
1656 
1657     /**
1658      * Look up an inner class name, from somewhere inside this class.
1659      * Since supers and outers are in scope, search them too.
1660      * <p>
1661      * If no inner class is found, env.resolveName() is then called,
1662      * to interpret the ambient package and import directives.
1663      * <p>
1664      * This routine operates on a "best-efforts" basis.  If
1665      * at some point a class is not found, the partially-resolved
1666      * identifier is returned.  Eventually, someone else has to
1667      * try to get the ClassDefinition and diagnose the ClassNotFound.
1668      * <p>
1669      * resolveName() looks at surrounding scopes, and hence
1670      * pulling in both inherited and uplevel types.  By contrast,
1671      * resolveInnerClass() is intended only for interpreting
1672      * explicitly qualified names, and so look only at inherited
1673      * types.  Also, resolveName() looks for package prefixes,
1674      * which appear similar to "very uplevel" outer classes.
1675      * <p>
1676      * A similar (but more complex) name-lookup process happens
1677      * when field and identifier expressions denoting qualified names
1678      * are type-checked.  The added complexity comes from the fact
1679      * that variables may occur in such names, and take precedence
1680      * over class and package names.
1681      * <p>
1682      * In the expression type-checker, resolveInnerClass() is paralleled
1683      * by code in FieldExpression.checkAmbigName(), which also calls
1684      * ClassDefinition.getInnerClass() to interpret names of the form
1685      * "OuterClass.Inner" (and also outerObject.Inner).  The checking
1686      * of an identifier expression that fails to be a variable is referred
1687      * directly to resolveName().
1688      */
resolveName(Environment env, Identifier name)1689     public Identifier resolveName(Environment env, Identifier name) {
1690         if (tracing) env.dtEvent("ClassDefinition.resolveName: " + name);
1691         // This logic is pretty much exactly parallel to that of
1692         // Environment.resolveName().
1693         if (name.isQualified()) {
1694             // Try to resolve the first identifier component,
1695             // because inner class names take precedence over
1696             // package prefixes.  (Cf. Environment.resolveName.)
1697             Identifier rhead = resolveName(env, name.getHead());
1698 
1699             if (rhead.hasAmbigPrefix()) {
1700                 // The first identifier component refers to an
1701                 // ambiguous class.  Limp on.  We throw away the
1702                 // rest of the classname as it is irrelevant.
1703                 // (part of solution for 4059855).
1704                 return rhead;
1705             }
1706 
1707             if (!env.classExists(rhead)) {
1708                 return env.resolvePackageQualifiedName(name);
1709             }
1710             try {
1711                 return env.getClassDefinition(rhead).
1712                     resolveInnerClass(env, name.getTail());
1713             } catch (ClassNotFound ee) {
1714                 // return partially-resolved name someone else can fail on
1715                 return Identifier.lookupInner(rhead, name.getTail());
1716             }
1717         }
1718 
1719         // This method used to fail to look for local classes, thus a
1720         // reference to a local class within, e.g., the type of a member
1721         // declaration, would fail to resolve if the immediately enclosing
1722         // context was an inner class.  The code added below is ugly, but
1723         // it works, and is lifted from existing code in 'Context.resolveName'
1724         // and 'Context.getClassCommon'. See the comments there about the design.
1725         // Fixes 4095716.
1726 
1727         int ls = -2;
1728         LocalMember lf = null;
1729         if (classContext != null) {
1730             lf = classContext.getLocalClass(name);
1731             if (lf != null) {
1732                 ls = lf.getScopeNumber();
1733             }
1734         }
1735 
1736         // Look for an unqualified name in enclosing scopes.
1737         for (ClassDefinition c = this; c != null; c = c.outerClass) {
1738             try {
1739                 MemberDefinition f = c.getInnerClass(env, name);
1740                 if (f != null &&
1741                     (lf == null || classContext.getScopeNumber(c) > ls)) {
1742                     // An uplevel member was found, and was nested more deeply than
1743                     // any enclosing local of the same name.
1744                     return f.getInnerClass().getName();
1745                 }
1746             } catch (ClassNotFound ee) {
1747                 // a missing superclass, or something catastrophic
1748             }
1749         }
1750 
1751         // No uplevel member found, so use the enclosing local if one was found.
1752         if (lf != null) {
1753            return lf.getInnerClass().getName();
1754         }
1755 
1756         // look in imports, etc.
1757         return env.resolveName(name);
1758     }
1759 
1760     /**
1761      * Interpret a qualified class name, which may have further subcomponents..
1762      * Follow inheritance links, as in:
1763      *  class C { class N { } }  class D extends C { }  ... new D.N() ...
1764      * Ignore outer scopes and packages.
1765      * @see resolveName
1766      */
resolveInnerClass(Environment env, Identifier nm)1767     public Identifier resolveInnerClass(Environment env, Identifier nm) {
1768         if (nm.isInner())  throw new CompilerError("inner");
1769         if (nm.isQualified()) {
1770             Identifier rhead = resolveInnerClass(env, nm.getHead());
1771             try {
1772                 return env.getClassDefinition(rhead).
1773                     resolveInnerClass(env, nm.getTail());
1774             } catch (ClassNotFound ee) {
1775                 // return partially-resolved name someone else can fail on
1776                 return Identifier.lookupInner(rhead, nm.getTail());
1777             }
1778         } else {
1779             try {
1780                 MemberDefinition f = getInnerClass(env, nm);
1781                 if (f != null) {
1782                     return f.getInnerClass().getName();
1783                 }
1784             } catch (ClassNotFound ee) {
1785                 // a missing superclass, or something catastrophic
1786             }
1787             // Fake a good name for a diagnostic.
1788             return Identifier.lookupInner(this.getName(), nm);
1789         }
1790     }
1791 
1792     /**
1793      * While resolving import directives, the question has arisen:
1794      * does a given inner class exist?  If the top-level class exists,
1795      * we ask it about an inner class via this method.
1796      * This method looks only at the literal name of the class,
1797      * and does not attempt to follow inheritance links.
1798      * This is necessary, since at the time imports are being
1799      * processed, inheritance links have not been resolved yet.
1800      * (Thus, an import directive must always spell a class
1801      * name exactly.)
1802      */
innerClassExists(Identifier nm)1803     public boolean innerClassExists(Identifier nm) {
1804         for (MemberDefinition field = getFirstMatch(nm.getHead()) ; field != null ; field = field.getNextMatch()) {
1805             if (field.isInnerClass()) {
1806                 if (field.getInnerClass().isLocal()) {
1807                     continue;   // ignore this name; it is internally generated
1808                 }
1809                 return !nm.isQualified() ||
1810                     field.getInnerClass().innerClassExists(nm.getTail());
1811             }
1812         }
1813         return false;
1814     }
1815 
1816    /**
1817      * Find any method with a given name.
1818      */
findAnyMethod(Environment env, Identifier nm)1819     public MemberDefinition findAnyMethod(Environment env, Identifier nm) throws ClassNotFound {
1820         MemberDefinition f;
1821         for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1822             if (f.isMethod()) {
1823                 return f;
1824             }
1825         }
1826 
1827         // look in the super class
1828         ClassDeclaration sup = getSuperClass();
1829         if (sup == null)
1830             return null;
1831         return sup.getClassDefinition(env).findAnyMethod(env, nm);
1832     }
1833 
1834     /**
1835       * Given the fact that this class has no method "nm" matching "argTypes",
1836       * find out if the mismatch can be blamed on a particular actual argument
1837       * which disagrees with all of the overloadings.
1838       * If so, return the code (i<<2)+(castOK<<1)+ambig, where
1839       * "i" is the number of the offending argument, and
1840       * "castOK" is 1 if a cast could fix the problem.
1841       * The target type for the argument is returned in margTypeResult[0].
1842       * If not all methods agree on this type, "ambig" is 1.
1843       * If there is more than one method, the choice of target type is
1844       * arbitrary.<p>
1845       * Return -1 if every argument is acceptable to at least one method.
1846       * Return -2 if there are no methods of the required arity.
1847       * The value "start" gives the index of the first argument to begin
1848       * checking.
1849       */
diagnoseMismatch(Environment env, Identifier nm, Type argTypes[], int start, Type margTypeResult[])1850     public int diagnoseMismatch(Environment env, Identifier nm, Type argTypes[],
1851                                 int start, Type margTypeResult[]) throws ClassNotFound {
1852         int haveMatch[] = new int[argTypes.length];
1853         Type margType[] = new Type[argTypes.length];
1854         if (!diagnoseMismatch(env, nm, argTypes, start, haveMatch, margType))
1855             return -2;
1856         for (int i = start; i < argTypes.length; i++) {
1857             if (haveMatch[i] < 4) {
1858                 margTypeResult[0] = margType[i];
1859                 return (i<<2) | haveMatch[i];
1860             }
1861         }
1862         return -1;
1863     }
1864 
diagnoseMismatch(Environment env, Identifier nm, Type argTypes[], int start, int haveMatch[], Type margType[])1865     private boolean diagnoseMismatch(Environment env, Identifier nm, Type argTypes[], int start,
1866                                      int haveMatch[], Type margType[]) throws ClassNotFound {
1867         // look in the current class
1868         boolean haveOne = false;
1869         MemberDefinition f;
1870         for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1871             if (!f.isMethod()) {
1872                 continue;
1873             }
1874             Type fArgTypes[] = f.getType().getArgumentTypes();
1875             if (fArgTypes.length == argTypes.length) {
1876                 haveOne = true;
1877                 for (int i = start; i < argTypes.length; i++) {
1878                     Type at = argTypes[i];
1879                     Type ft = fArgTypes[i];
1880                     if (env.implicitCast(at, ft)) {
1881                         haveMatch[i] = 4;
1882                         continue;
1883                     } else if (haveMatch[i] <= 2 && env.explicitCast(at, ft)) {
1884                         if (haveMatch[i] < 2)  margType[i] = null;
1885                         haveMatch[i] = 2;
1886                     } else if (haveMatch[i] > 0) {
1887                         continue;
1888                     }
1889                     if (margType[i] == null)
1890                         margType[i] = ft;
1891                     else if (margType[i] != ft)
1892                         haveMatch[i] |= 1;
1893                 }
1894             }
1895         }
1896 
1897         // constructors are not inherited
1898         if (nm.equals(idInit)) {
1899             return haveOne;
1900         }
1901 
1902         // look in the super class
1903         ClassDeclaration sup = getSuperClass();
1904         if (sup != null) {
1905             if (sup.getClassDefinition(env).diagnoseMismatch(env, nm, argTypes, start,
1906                                                              haveMatch, margType))
1907                 haveOne = true;
1908         }
1909         return haveOne;
1910     }
1911 
1912     /**
1913      * Add a field (no checks)
1914      */
addMember(MemberDefinition field)1915     public void addMember(MemberDefinition field) {
1916         //System.out.println("ADD = " + field);
1917         if (firstMember == null) {
1918             firstMember = lastMember = field;
1919         } else if (field.isSynthetic() && field.isFinal()
1920                                        && field.isVariable()) {
1921             // insert this at the front, because of initialization order
1922             field.nextMember = firstMember;
1923             firstMember = field;
1924             field.nextMatch = fieldHash.get(field.name);
1925         } else {
1926             lastMember.nextMember = field;
1927             lastMember = field;
1928             field.nextMatch = fieldHash.get(field.name);
1929         }
1930         fieldHash.put(field.name, field);
1931     }
1932 
1933     /**
1934      * Add a field (subclasses make checks)
1935      */
addMember(Environment env, MemberDefinition field)1936     public void addMember(Environment env, MemberDefinition field) {
1937         addMember(field);
1938         if (resolved) {
1939             // a late addition
1940             field.resolveTypeStructure(env);
1941         }
1942     }
1943 
1944     /**
1945      * Find or create an uplevel reference for the given target.
1946      */
getReference(LocalMember target)1947     public UplevelReference getReference(LocalMember target) {
1948         for (UplevelReference r = references; r != null; r = r.getNext()) {
1949             if (r.getTarget() == target) {
1950                 return r;
1951             }
1952         }
1953         return addReference(target);
1954     }
1955 
addReference(LocalMember target)1956     protected UplevelReference addReference(LocalMember target) {
1957         if (target.getClassDefinition() == this) {
1958             throw new CompilerError("addReference "+target);
1959         }
1960         referencesMustNotBeFrozen();
1961         UplevelReference r = new UplevelReference(this, target);
1962         references = r.insertInto(references);
1963         return r;
1964     }
1965 
1966     /**
1967      * Return the list of all uplevel references.
1968      */
getReferences()1969     public UplevelReference getReferences() {
1970         return references;
1971     }
1972 
1973     /**
1974      * Return the same value as getReferences.
1975      * Also, mark the set of references frozen.
1976      * After that, it is an error to add new references.
1977      */
getReferencesFrozen()1978     public UplevelReference getReferencesFrozen() {
1979         referencesFrozen = true;
1980         return references;
1981     }
1982 
1983     /**
1984      * assertion check
1985      */
referencesMustNotBeFrozen()1986     public final void referencesMustNotBeFrozen() {
1987         if (referencesFrozen) {
1988             throw new CompilerError("referencesMustNotBeFrozen "+this);
1989         }
1990     }
1991 
1992     /**
1993      * Get helper method for class literal lookup.
1994      */
getClassLiteralLookup(long fwhere)1995     public MemberDefinition getClassLiteralLookup(long fwhere) {
1996         throw new CompilerError("binary class");
1997     }
1998 
1999     /**
2000      * Add a dependency
2001      */
addDependency(ClassDeclaration c)2002     public void addDependency(ClassDeclaration c) {
2003         throw new CompilerError("addDependency");
2004     }
2005 
2006     /**
2007      * Maintain a hash table of local and anonymous classes
2008      * whose internal names are prefixed by the current class.
2009      * The key is the simple internal name, less the prefix.
2010      */
2011 
getLocalClass(String name)2012     public ClassDefinition getLocalClass(String name) {
2013         if (localClasses == null) {
2014             return null;
2015         } else {
2016             return localClasses.get(name);
2017         }
2018     }
2019 
addLocalClass(ClassDefinition c, String name)2020     public void addLocalClass(ClassDefinition c, String name) {
2021         if (localClasses == null) {
2022             localClasses = new Hashtable<>(LOCAL_CLASSES_SIZE);
2023         }
2024         localClasses.put(name, c);
2025     }
2026 
2027 
2028     /**
2029      * Print for debugging
2030      */
print(PrintStream out)2031     public void print(PrintStream out) {
2032         if (isPublic()) {
2033             out.print("public ");
2034         }
2035         if (isInterface()) {
2036             out.print("interface ");
2037         } else {
2038             out.print("class ");
2039         }
2040         out.print(getName() + " ");
2041         if (getSuperClass() != null) {
2042             out.print("extends " + getSuperClass().getName() + " ");
2043         }
2044         if (interfaces.length > 0) {
2045             out.print("implements ");
2046             for (int i = 0 ; i < interfaces.length ; i++) {
2047                 if (i > 0) {
2048                     out.print(", ");
2049                 }
2050                 out.print(interfaces[i].getName());
2051                 out.print(" ");
2052             }
2053         }
2054         out.println("{");
2055 
2056         for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {
2057             out.print("    ");
2058             f.print(out);
2059         }
2060 
2061         out.println("}");
2062     }
2063 
2064     /**
2065      * Convert to String
2066      */
toString()2067     public String toString() {
2068         return getClassDeclaration().toString();
2069     }
2070 
2071     /**
2072      * After the class has been written to disk, try to free up
2073      * some storage.
2074      */
cleanup(Environment env)2075     public void cleanup(Environment env) {
2076         if (env.dump()) {
2077             env.output("[cleanup " + getName() + "]");
2078         }
2079         for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {
2080             f.cleanup(env);
2081         }
2082         // keep "references" around, for the sake of local subclasses
2083         documentation = null;
2084     }
2085 }
2086