/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This class is a Java class definition
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
protected long where;
protected int modifiers;
protected boolean resolved;
protected boolean error;
protected boolean nestError;
protected boolean referencesFrozen;
private int abstr;
// Table of local and anonymous classes whose internal names are constructed
// using the current class as a prefix. This is part of a fix for
// bugid 4054523 and 4030421. See also 'Environment.getClassDefinition'
// and 'BatchEnvironment.makeClassDefinition'. Allocated on demand.
// The immediately surrounding context in which the class appears.
// Set at the beginning of checking, upon entry to 'SourceClass.checkInternal'.
// Null for classes that are not local or inside a local class.
// At present, this field exists only for the benefit of 'resolveName' as part
// of the fix for 4095716.
// The saved class context is now also used in 'SourceClass.getAccessMember'.
// Provide read-only access via this method. Part of fix for 4098093.
return classContext;
}
/**
* Constructor
*/
this.declaration = declaration;
this.superClassId = superClass;
this.interfaceIds = interfaces;
}
/**
* Get the source of the class
*/
return source;
}
/**
* Check if there were any errors in this class.
*/
public final boolean getError() {
return error;
}
/**
* Mark this class to be erroneous.
*/
public final void setError() {
this.error = true;
setNestError();
}
/**
* Check if there were any errors in our class nest.
*/
public final boolean getNestError() {
// Check to see if our error value is set, or if any of our
// outer classes' error values are set. This will work in
// conjunction with setError(), which sets the error value
// of its outer class, to yield true is any of our nest
// siblings has an error. This addresses bug 4111488: either
// code should be generated for all classes in a nest, or
// none of them.
}
/**
* Mark this class, and all siblings in its class nest, to be
* erroneous.
*/
public final void setNestError() {
this.nestError = true;
if (outerClass != null) {
// If we have an outer class, set it to be erroneous as well.
// This will work in conjunction with getError(), which checks
// the error value of its outer class, to set the whole class
// nest to be erroneous. This address bug 4111488: either
// code should be generated for all classes in a nest, or
// none of them.
}
}
/**
* Get the position in the input
*/
public final long getWhere() {
return where;
}
/**
* Get the class declaration
*/
return declaration;
}
/**
* Get the class' modifiers
*/
public final int getModifiers() {
return modifiers;
}
}
}
// *** DEBUG ***
/**
* Get the class' super class
*/
/*---
if (superClass == null && superClassId != null)
throw new CompilerError("getSuperClass "+superClassId);
// There are obscure cases where null is the right answer,
// in order to enable some error reporting later on.
// For example: class T extends T.N { class N { } }
---*/
// *** DEBUG ***
// This method should not be called if the superclass has not been resolved.
return superClass;
}
/**
* Get the super class, and resolve names now if necessary.
*
* It is only possible to resolve names at this point if we are
* a source class. The provision of this method at this level
* in the class hierarchy is dubious, but see 'getInnerClass' below.
* All other calls to 'getSuperClass(env)' appear in 'SourceClass'.
* NOTE: An older definition of this method has been moved to
* 'SourceClass', where it overrides this one.
*
* @see #resolveTypeStructure
*/
return getSuperClass();
}
/**
* Get the class' interfaces
*/
return interfaces;
}
/**
* Get the class' enclosing class (or null if not inner)
*/
return outerClass;
}
/**
* Set the class' enclosing class. Must be done at most once.
*/
this.outerClass = outerClass;
}
/**
* Set the class' enclosing current instance pointer.
* Must be done at most once.
*/
this.outerMember = outerMember;
}
/**
* Tell if the class is inner.
* This predicate also returns true for top-level nested types.
* To test for a true inner class as seen by the programmer,
* use <tt>!isTopLevel()</tt>.
*/
public final boolean isInnerClass() {
return outerClass != null;
}
/**
* Tell if the class is a member of another class.
* This is false for package members and for block-local classes.
*/
public final boolean isMember() {
}
/**
* Tell if the class is "top-level", which is either a package member,
* or a static member of another top-level class.
*/
public final boolean isTopLevel() {
}
/**
* Tell if the class is local or inside a local class,
* which means it cannot be mentioned outside of its file.
*/
// The comment above is true only because M_LOCAL is set
// whenever M_ANONYMOUS is. I think it is risky to assume that
// isAnonymous(x) => isLocal(x).
public final boolean isInsideLocal() {
return isLocal() ||
}
/**
* Tell if the class is local or or anonymous class, or inside
* such a class, which means it cannot be mentioned outside of
* its file.
*/
public final boolean isInsideLocalOrAnonymous() {
return isLocal() || isAnonymous () ||
}
/**
* Return a simple identifier for this class (idNull if anonymous).
*/
return localName;
}
// This is also the name of the innerClassMember, if any:
}
/**
* Set the local name of a class. Must be a local class.
*/
if (isLocal()) {
}
}
/**
* If inner, get the field for this class in the enclosing class
*/
if (outerClass == null)
return null;
if (innerClassMember == null) {
// We must find the field in the outer class.
if (field.isInnerClass()) {
break;
}
}
if (innerClassMember == null)
throw new CompilerError("getInnerClassField");
}
return innerClassMember;
}
/**
* If inner, return an innermost uplevel self pointer, if any exists.
* Otherwise, return null.
*/
return outerMember;
}
/**
* See if this is a (nested) static class.
*/
public final boolean isStatic() {
}
/**
* Get the class' top-level enclosing class
*/
ClassDefinition p, q;
for (p = this; (q = p.outerClass) != null; p = q)
;
return p;
}
/**
* Get the class' first field or first match
*/
return firstMember;
}
}
/**
* Get the class' name
*/
return declaration.getName();
}
/**
* Get the class' type
*/
return declaration.getType();
}
/**
* Get the class' documentation
*/
return documentation;
}
/**
* Return true if the given documentation string contains a deprecation
* paragraph. This is true if the string contains the tag @deprecated
* is the first word in a line.
*/
if (documentation == null) {
return false;
}
for (int scan = 0;
// make sure there is only whitespace between this word
// and the beginning of the line
break; // OK
}
continue doScan;
}
}
// make sure the char after the word is space or end of line
continue doScan;
}
}
return true;
}
return false;
}
// find out if the class stored in c is defined in the same
// package as the current class.
}
// find out if the class stored in c is defined in the same
// package as the current class.
}
}
/**
* Checks
*/
public final boolean isInterface() {
}
public final boolean isClass() {
}
public final boolean isPublic() {
}
public final boolean isPrivate() {
}
public final boolean isProtected() {
}
public final boolean isPackagePrivate() {
}
public final boolean isFinal() {
}
public final boolean isAbstract() {
}
public final boolean isSynthetic() {
}
public final boolean isDeprecated() {
}
public final boolean isAnonymous() {
}
public final boolean isLocal() {
}
public final boolean hasConstructor() {
}
/**
* Check to see if a class must be abstract. This method replaces
* isAbstract(env)
*/
// If it is declared abstract, return true.
// (Fix for 4110534.)
if (isAbstract()) {
return true;
}
// Check to see if the class should have been declared to be
// abstract.
// We make sure that the inherited method collection has been
// performed.
// We check for any abstract methods inherited or declared
// by this class.
if (method.isAbstract()) {
return true;
}
}
// We check for hidden "permanently abstract" methods in
// our superclasses.
return getPermanentlyAbstractMethods().hasNext();
}
/**
* Check if this is a super class of another class
*/
throws ClassNotFound {
while (otherClass != null) {
return true;
}
}
return false;
}
/**
* Check if this is an enclosing class of another class
*/
if (this == otherClass) {
return true;
}
}
return false;
}
/**
* Check if this is a sub class of another class
*/
while (c != null) {
if (c.equals(otherClass)) {
return true;
}
}
return false;
}
/**
* Check if this class is implemented by another class
*/
if (getClassDeclaration().equals(c)) {
return true;
}
return true;
}
}
}
return false;
}
/**
* Check to see if a class which implements interface `this' could
* possibly implement the interface `intDef'. Note that the only
* way that this can fail is if `this' and `intDef' have methods
* which are of the same signature and different return types. This
* method is used by Environment.explicitCast() to determine if a
* cast between two interfaces is legal.
*
* This method should only be called on a class after it has been
* basicCheck()'ed.
*/
// Check to see if we could have done the necessary checks.
if (!doInheritanceChecks) {
throw new CompilerError("couldImplement: no checks");
}
// This method should only be called for interfaces.
throw new CompilerError("couldImplement: not interface");
}
// Make sure we are not called before we have collected our
// inheritance information.
if (allMethods == null) {
throw new CompilerError("couldImplement: called early");
}
// Get the other classes' methods. getMethods() in
// general can return methods which are not visible to the
// current package. We need to make sure that these do not
// prevent this class from being implemented.
while (otherMethods.hasNext()) {
// Get one of the methods from intDef...
// See if we implement a method of the same signature...
//System.out.println("Comparing\n\t" + myMethod +
// "\nand\n\t" + method);
// We do. Make sure the methods have the same return type.
return false;
}
}
}
return true;
}
/**
* Check if another class can be accessed from the 'extends' or 'implements'
* clause of this class.
*/
// Names in the 'extends' or 'implements' clause of an inner class
// are checked as if they appeared in the body of the surrounding class.
if (outerClass != null) {
}
// We are a package member.
// No locals should be in scope in the 'extends' or
// 'implements' clause of a package member.
throw new CompilerError("top local");
}
if (cdef.isInnerClass()) {
// Access to public member is always allowed.
if (f.isPublic()) {
return true;
}
// Private access is ok only from the same class nest. This can
// happen only if the class represented by 'this' encloses the inner
// class represented by 'f'.
if (f.isPrivate()) {
}
// Protected or default access -- allow access if in same package.
}
// Access to public member is always allowed.
return true;
}
// Default access -- allow access if in same package.
}
/**
* Check if another class can be accessed from within the body of this class.
*/
// if it's in scope, it's accessible
return true;
}
if (cdef.isInnerClass()) {
}
// Public access is always ok
return true;
}
// It must be in the same package
}
/**
* Check if a field can be accessed from a class
*/
throws ClassNotFound {
// Public access is always ok
if (f.isPublic()) {
return true;
}
// Protected access is ok from a subclass
return true;
}
// Private access is ok only from the same class nest
if (f.isPrivate()) {
return getTopClass().getClassDeclaration()
}
// It must be in the same package
}
/**
* Check if a class is entitled to inline access to a class from
* another class.
*/
throws ClassNotFound {
}
/**
* Check if a class is entitled to inline access to a method from
* another class.
*/
throws ClassNotFound {
}
/**
* We know the the field is marked protected (and not public) and that
* the field is visible (as per canAccess). Can we access the field as
* <accessor>.<field>, where <accessor> has the type <accessorType>?
*
* Protected fields can only be accessed when the accessorType is a
* subclass of the current class
*/
throws ClassNotFound
{
return
// static protected fields are accessible
f.isStatic()
|| // allow array.clone()
|| // <accessorType> is a subtype of the current class
|| // we are accessing the field from a friendly class (same package)
(getName().getQualifier()
}
/**
* Find or create an access method for a private member,
* or return null if this is not possible.
*/
throw new CompilerError("binary getAccessMember");
}
/**
* Find or create an update method for a private member,
* or return null if this is not possible.
*/
throw new CompilerError("binary getUpdateMember");
}
/**
* Get a field from this class. Report ambiguous fields.
* If no accessible field is found, this method may return an
* inaccessible field to allow a useful error message.
*
* getVariable now takes the source class `source' as an argument.
* This allows getVariable to check whether a field is inaccessible
* before it signals that a field is ambiguous. The compiler used to
* signal an ambiguity even when one of the fields involved was not
* accessible. (bug 4053724)
*/
throws AmbiguousMember, ClassNotFound {
}
/*
* private fields are never inherited. package-private fields are
* not inherited across package boundaries. To capture this, we
* take two booleans as parameters: showPrivate indicates whether
* we have passed a class boundary, and showPackage indicates whether
* we have crossed a package boundary.
*/
boolean showPrivate,
boolean showPackage)
throws AmbiguousMember, ClassNotFound {
// Check to see if this field is defined in the current class
if (member.isVariable()) {
// It is defined in this class.
return member;
} else {
// Even though this definition is not inherited,
// it hides all definitions in supertypes.
return null;
}
}
}
// Find the field in our superclass.
field =
false,
}
// Find the field in our superinterfaces.
// Try to look up the field in an interface. Since interfaces
// only have public fields, the values of the two boolean
// arguments are not important.
// If we have two different, accessible fields, then
// we've found an ambiguity.
}
}
}
return field;
}
/**
* Tells whether to report a deprecation error for this class.
*/
return (isDeprecated()
}
/**
* Note that this class is being used somehow by <tt>ref</tt>.
* Report deprecation errors, etc.
*/
// (Have this deal with canAccess() checks, too?)
if (reportDeprecated(env)) {
}
}
/**
* Get an inner class.
* Look in supers but not outers.
* (This is used directly to resolve expressions like "site.K", and
* inside a loop to resolve lone names like "K" or the "K" in "K.L".)
*
* Called from 'Context' and 'FieldExpression' as well as this class.
*
* @see FieldExpression.checkCommon
* @see resolveName
*/
throws ClassNotFound {
// Note: AmbiguousClass will not be thrown unless and until
// inner classes can be defined inside interfaces.
// Check if it is defined in the current class
if (field.isInnerClass()) {
continue; // ignore this name; it is internally generated
}
return field;
}
}
// Get it from the super class
// It is likely that 'getSuperClass()' could be made to work here
// but we would have to assure somehow that 'resolveTypeStructure'
// has been called on the current class nest. Since we can get
// here from 'resolveName', which is called from 'resolveSupers',
// it is possible that the first attempt to resolve the superclass
// will originate here, instead of in the call to 'getSuperClass'
// in 'checkSupers'. See 'resolveTypeStructure', in which a call
// to 'resolveSupers' precedes the call to 'checkSupers'. Why is
// name resolution done twice, first in 'resolveName'?
// NOTE: 'SourceMember.resolveTypeStructure' may initiate type
// structure resolution for an inner class. Normally, this
// occurs during the resolution of the outer class, but fields
// added after the resolution of their containing class will
// be resolved late -- see 'addMember(env,field)' below.
// This should only happen for synthetic members, which should
// never be an inner class.
return null;
}
/**
* Lookup a method. This code implements the method lookup
* mechanism specified in JLS 15.11.2.
*
* This mechanism cannot be used to lookup synthetic methods.
*/
boolean isAnonConstCall,
throws AmbiguousMember, ClassNotFound {
// This may be too restrictive.
throw new CompilerError("matchMethod called early");
// collectInheritedMethods(env);
}
// A tentative maximally specific method.
// A list of other methods which may be maximally specific too.
// Get all the methods inherited by this class which
// have the name `methodName'.
// See if this method is applicable.
continue;
}
// See if this method is accessible.
continue;
}
} else if (isAnonConstCall) {
(method.isPackagePrivate() &&
accessPackage != null &&
!inSamePackage(accessPackage))) {
// For anonymous constructor accesses, we
// haven't yet built an accessing class.
// We disallow anonymous classes from seeing
// private/package-private inaccessible
// constructors in their superclass.
continue;
}
} else {
// If accessor is null, we assume that the access
// is allowed. Query: is this option used?
}
// `method' becomes our tentative maximally specific match.
} else {
// We have found a method which is a strictly better
// match than `tentative'. Replace it.
} else {
// If this method could possibly be another
// maximally specific method, add it to our
// list of other candidates.
if (candidateList == null) {
candidateList = new ArrayList();
}
}
}
}
}
// Find out if our `tentative' match is a uniquely
// maximally specific.
while (candidates.hasNext()) {
}
}
}
return tentative;
}
/**
* Lookup a method. This code implements the method lookup
* mechanism specified in JLS 15.11.2.
*
* This mechanism cannot be used to lookup synthetic methods.
*/
throws AmbiguousMember, ClassNotFound {
argumentTypes, false, null);
}
/**
* Lookup a method. This code implements the method lookup
* mechanism specified in JLS 15.11.2.
*
* This mechanism cannot be used to lookup synthetic methods.
*/
throws AmbiguousMember, ClassNotFound {
}
/**
* A version of matchMethod to be used only for constructors
* when we cannot pass in a sourceClass argument. We just assert
* our package name.
*
* This is used only for anonymous classes, where we have to look up
* a (potentially) protected constructor with no valid sourceClass
* parameter available.
*/
throws AmbiguousMember, ClassNotFound {
true, accessPackage);
}
/**
* Find a method, ie: exact match in this class or any of the super
* classes.
*
* Only called by javadoc. For now I am holding off rewriting this
* code to rely on collectInheritedMethods(), as that code has
* not gotten along with javadoc in the past.
*/
throws ClassNotFound {
// look in the current class
// Note that non-method types return false for equalArguments().
if (f.getType().equalArguments(t)) {
return f;
}
}
// constructors are not inherited
return null;
}
// look in the super class
return null;
}
// We create a stub for this. Source classes do more work.
// Do the outer class first.
if (outerClass != null)
}
/**
* Check this class.
*/
}
) throws ClassNotFound {
throw new CompilerError("checkLocalClass");
}
//---------------------------------------------------------------
// The non-synthetic methods defined in this class or in any
// of its parents (class or interface). This member is used
// to cache work done in collectInheritedMethods for use by
// getMethods() and matchMethod(). It should be accessed by
// no other method without forethought.
// One of our superclasses may contain an abstract method which
// we are unable to ever implement. This happens when there is
// a package-private abstract method in our parent and we are in
// a different package than our parent. In these cases, we
// keep a list of the "permanently abstract" or "unimplementable"
// methods so that we can correctly detect that this class is
// indeed abstract and so that we can give somewhat comprehensible
// error messages.
/**
* This method returns an Iterator of all abstract methods
* in our superclasses which we are unable to implement.
*/
// This method can only be called after collectInheritedMethods.
if (allMethods == null) {
throw new CompilerError("isPermanentlyAbstract() called early");
}
return permanentlyAbstractMethods.iterator();
}
/**
* A flag used by turnOffInheritanceChecks() to indicate if
* inheritance checks are on or off.
*/
protected static boolean doInheritanceChecks = true;
/**
* This is a workaround to allow javadoc to turn off certain
* inheritance/override checks which interfere with javadoc
* badly. In the future it might be good to eliminate the
* shared sources of javadoc and javac to avoid the need for this
* sort of workaround.
*/
public static void turnOffInheritanceChecks() {
doInheritanceChecks = false;
}
/**
* Add all of the methods declared in or above `parent' to
* `allMethods', the set of methods in the current class.
* `myMethods' is the set of all methods declared in this
* class, and `mirandaMethods' is a repository for Miranda methods.
* If mirandaMethods is null, no mirandaMethods will be
* generated.
*
* For a definition of Miranda methods, see the comment above the
* method addMirandaMethods() which occurs later in this file.
*/
// System.out.println("Inheriting methods from " + parent);
try {
// Private methods are not inherited.
//
// Constructors are not inherited.
//
// Any non-abstract methods in an interface come
// from java.lang.Object. This means that they
// should have already been added to allMethods
// when we walked our superclass lineage.
method.isConstructor() ||
continue;
}
// Get the components of the methods' signature.
// Check for a method of the same signature which
// was locally declared.
// Is this method inaccessible due to package-private
// visibility?
if (method.isPackagePrivate() &&
// We give a warning when a class shadows an
// inaccessible package-private method from
// its superclass. This warning is meant
// to prevent people from relying on overriding
// when it does not happen. This warning should
// probably be removed to be consistent with the
// general "no warnings" policy of this
// compiler.
//
// The `instanceof' above is a hack so that only
// SourceClass generates this warning, not a
// BinaryClass, for example.
"warn.no.override.access",
}
// If our superclass has a package-private abstract
// method that we have no access to, then we add
// this method to our list of permanently abstract
// methods. The idea is, since we cannot override
// the method, we can never make this class
// non-abstract.
if (method.isAbstract()) {
}
// `method' is inaccessible. We do not inherit it.
continue;
}
// `method' and `override' have the same signature.
// We are required to check that `override' is a
// legal override of `method'
//System.out.println ("About to check override of " +
// method);
} else {
// In the absence of a definition in the class
// itself, we check to see if this definition
// can be successfully merged with any other
// inherited definitions.
// Have we added a member of the same signature
// to `allMethods' already?
// If the previous definition is nonexistent or
// ignorable, replace it.
if (formerMethod == null) {
//System.out.println("Added " + method + " to " +
// this);
if (mirandaMethods != null &&
// Whenever a class inherits a method
// from an interface, that method is
// one of our "miranda" methods. Early
// VMs require that these methods be
// added as true members to the class
// to enable method lookup to work in the
// VM.
method =
env);
//System.out.println("Added " + method +
// " to " + this + " as a Miranda");
}
// There is no previous inherited definition.
// Add `method' to `allMethods'.
} else if (isInterface() &&
!formerMethod.isAbstract() &&
method.isAbstract()) {
// If we are in an interface and we have inherited
// both an abstract method and a non-abstract method
// then we know that the non-abstract method is
// a placeholder from Object put in for type checking
// and the abstract method was already checked to
// be proper by our superinterface.
} else {
// Okay, `formerMethod' and `method' both have the
// same signature. See if they are compatible.
//System.out.println ("About to check meet of " +
// method);
this.getClassDeclaration())) {
// The methods are incompatible. Skip to
// next method.
continue;
}
// Do nothing. The current definition
// is specific enough.
//System.out.println("trivial meet of " +
// method);
continue;
}
// `method' is more specific than
// `formerMethod'. replace `formerMethod'.
//System.out.println("new def of " + method);
if (mirandaMethods != null &&
// Whenever a class inherits a method
// from an interface, that method is
// one of our "miranda" methods. Early
// VMs require that these methods be
// added as true members to the class
// to enable method lookup to work in the
// VM.
method =
this,env);
//System.out.println("Added " + method +
// " to " + this + " as a Miranda");
}
continue;
}
// Neither method is more specific than the other.
// Oh well. We need to construct a nontrivial
// meet of the two methods.
//
// This is not yet implemented, so we give
// a message with a helpful workaround.
"nontrivial.meet", method,
);
}
}
}
} catch (ClassNotFound ee) {
}
}
/**
* <p>Collect all methods defined in this class or inherited from
* any of our superclasses or interfaces. Look for any
* incompatible definitions.
*
* <p>This function is also responsible for collecting the
* <em>Miranda</em> methods for a class. For a definition of
* Miranda methods, see the comment in addMirandaMethods()
* below.
*/
// The methods defined in this class.
//System.out.println("Called collectInheritedMethods() for " +
// this);
if (allMethods != null) {
if (allMethods.isFrozen()) {
// We have already done the collection. No need to
// do it again.
return;
} else {
// We have run into a circular need to collect our methods.
// This should not happen at this stage.
throw new CompilerError("collectInheritedMethods()");
}
}
allMethods = new MethodSet();
// For testing, do not generate miranda methods.
} else {
mirandaMethods = new MethodSet();
}
// Any methods defined in the current class get added
// to both the myMethods and the allMethods MethodSets.
// We only collect methods. Initializers are not relevant.
!member.isInitializer()) {
//System.out.println("Declared in " + this + ", " + member);
////////////////////////////////////////////////////////////
// PCJ 2003-07-30 modified the following code because with
// the covariant return type feature of the 1.5 compiler,
// there might be multiple methods with the same signature
// but different return types, and MethodSet doesn't
// support that. We use a new utility method that attempts
// to ensure that the appropriate method winds up in the
// MethodSet. See 4892308.
////////////////////////////////////////////////////////////
// myMethods.add(member);
// allMethods.add(member);
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
}
}
// We're ready to start adding inherited methods. First add
// the methods from our superclass.
//System.out.println("About to start superclasses for " + this);
// Make sure that we add all unimplementable methods from our
// superclass to our list of unimplementable methods.
}
}
// Now we inherit all of the methods from our interfaces.
//System.out.println("About to start interfaces for " + this);
}
allMethods.freeze();
// Now we have collected all of our methods from our superclasses
// and interfaces into our `allMethods' member. Good. As a last
// task, we add our collected miranda methods to this class.
//
// If we do not add the mirandas to the class explicitly, there
// will be no code generated for them.
}
}
////////////////////////////////////////////////////////////
// PCJ 2003-07-30 added this utility method to insulate
// MethodSet additions from the covariant return type
// feature of the 1.5 compiler. When there are multiple
// methods with the same signature and different return
// types to be added, we try to ensure that the one with
// the most specific return type winds up in the MethodSet.
// This logic was not put into MethodSet itself because it
// requires access to an Environment for type relationship
// checking. No error checking is performed here, but that
// should be OK because this code is only still used by
// rmic. See 4892308.
////////////////////////////////////////////////////////////
{
try {
}
} catch (ClassNotFound ignore) {
}
} else {
}
}
////////////////////////////////////////////////////////////
/**
* Get an Iterator of all methods which could be accessed in an
* instance of this class.
*/
if (allMethods == null) {
}
return getMethods();
}
/**
* Get an Iterator of all methods which could be accessed in an
* instance of this class. Throw a compiler error if we haven't
* generated this information yet.
*/
if (allMethods == null) {
throw new CompilerError("getMethods: too early");
}
return allMethods.iterator();
}
// In early VM's there was a bug -- the VM didn't walk the interfaces
// of a class looking for a method, they only walked the superclass
// chain. This meant that abstract methods defined only in interfaces
// were not being found. To fix this bug, a counter-bug was introduced
// in the compiler -- the so-called Miranda methods. If a class
// does not provide a definition for an abstract method in one of
// its interfaces then the compiler inserts one in the class artificially.
// That way the VM didn't have to bother looking at the interfaces.
//
// This is a problem. Miranda methods are not part of the specification.
// But they continue to be inserted so that old VM's can run new code.
// Someday, when the old VM's are gone, perhaps classes can be compiled
// without Miranda methods. Towards this end, the compiler has a
// flag, -nomiranda, which can turn off the creation of these methods.
// Eventually that behavior should become the default.
//
// Why are they called Miranda methods? Well the sentence "If the
// class is not able to provide a method, then one will be provided
// by the compiler" is very similar to the sentence "If you cannot
// afford an attorney, one will be provided by the court," -- one
// of the so-called "Miranda" rights in the United States.
/**
* Add a list of methods to this class as miranda methods. This
* gets overridden with a meaningful implementation in SourceClass.
* BinaryClass should not need to do anything -- it should already
* have its miranda methods and, if it doesn't, then that doesn't
* affect our compilation.
*/
// do nothing.
}
//---------------------------------------------------------------
}
/**
* We create a stub for this. Source classes do more work.
* Some calls from 'SourceClass.checkSupers' execute this method.
* @see sun.tools.javac.SourceClass#resolveTypeStructure
*/
}
/**
* Look up an inner class name, from somewhere inside this class.
* Since supers and outers are in scope, search them too.
* <p>
* If no inner class is found, env.resolveName() is then called,
* to interpret the ambient package and import directives.
* <p>
* This routine operates on a "best-efforts" basis. If
* at some point a class is not found, the partially-resolved
* identifier is returned. Eventually, someone else has to
* try to get the ClassDefinition and diagnose the ClassNotFound.
* <p>
* resolveName() looks at surrounding scopes, and hence
* pulling in both inherited and uplevel types. By contrast,
* resolveInnerClass() is intended only for interpreting
* explicitly qualified names, and so look only at inherited
* types. Also, resolveName() looks for package prefixes,
* which appear similar to "very uplevel" outer classes.
* <p>
* A similar (but more complex) name-lookup process happens
* when field and identifier expressions denoting qualified names
* are type-checked. The added complexity comes from the fact
* that variables may occur in such names, and take precedence
* over class and package names.
* <p>
* In the expression type-checker, resolveInnerClass() is paralleled
* by code in FieldExpression.checkAmbigName(), which also calls
* ClassDefinition.getInnerClass() to interpret names of the form
* "OuterClass.Inner" (and also outerObject.Inner). The checking
* of an identifier expression that fails to be a variable is referred
* directly to resolveName().
*/
// This logic is pretty much exactly parallel to that of
// Environment.resolveName().
if (name.isQualified()) {
// Try to resolve the first identifier component,
// because inner class names take precedence over
// package prefixes. (Cf. Environment.resolveName.)
if (rhead.hasAmbigPrefix()) {
// The first identifier component refers to an
// ambiguous class. Limp on. We throw away the
// rest of the classname as it is irrelevant.
// (part of solution for 4059855).
return rhead;
}
}
try {
} catch (ClassNotFound ee) {
// return partially-resolved name someone else can fail on
}
}
// This method used to fail to look for local classes, thus a
// reference to a local class within, e.g., the type of a member
// declaration, would fail to resolve if the immediately enclosing
// context was an inner class. The code added below is ugly, but
// it works, and is lifted from existing code in 'Context.resolveName'
// and 'Context.getClassCommon'. See the comments there about the design.
// Fixes 4095716.
int ls = -2;
if (classContext != null) {
}
}
// Look for an unqualified name in enclosing scopes.
try {
if (f != null &&
// An uplevel member was found, and was nested more deeply than
// any enclosing local of the same name.
return f.getInnerClass().getName();
}
} catch (ClassNotFound ee) {
// a missing superclass, or something catastrophic
}
}
// No uplevel member found, so use the enclosing local if one was found.
}
// look in imports, etc.
}
/**
* Interpret a qualified class name, which may have further subcomponents..
* Follow inheritance links, as in:
* class C { class N { } } class D extends C { } ... new D.N() ...
* Ignore outer scopes and packages.
* @see resolveName
*/
if (nm.isQualified()) {
try {
} catch (ClassNotFound ee) {
// return partially-resolved name someone else can fail on
}
} else {
try {
if (f != null) {
return f.getInnerClass().getName();
}
} catch (ClassNotFound ee) {
// a missing superclass, or something catastrophic
}
// Fake a good name for a diagnostic.
}
}
/**
* While resolving import directives, the question has arisen:
* does a given inner class exist? If the top-level class exists,
* we ask it about an inner class via this method.
* This method looks only at the literal name of the class,
* and does not attempt to follow inheritance links.
* This is necessary, since at the time imports are being
* processed, inheritance links have not been resolved yet.
* (Thus, an import directive must always spell a class
* name exactly.)
*/
for (MemberDefinition field = getFirstMatch(nm.getHead()) ; field != null ; field = field.getNextMatch()) {
if (field.isInnerClass()) {
continue; // ignore this name; it is internally generated
}
return !nm.isQualified() ||
}
}
return false;
}
/**
* Find any method with a given name.
*/
if (f.isMethod()) {
return f;
}
}
// look in the super class
return null;
}
/**
* Given the fact that this class has no method "nm" matching "argTypes",
* find out if the mismatch can be blamed on a particular actual argument
* which disagrees with all of the overloadings.
* If so, return the code (i<<2)+(castOK<<1)+ambig, where
* "i" is the number of the offending argument, and
* "castOK" is 1 if a cast could fix the problem.
* The target type for the argument is returned in margTypeResult[0].
* If not all methods agree on this type, "ambig" is 1.
* If there is more than one method, the choice of target type is
* arbitrary.<p>
* Return -1 if every argument is acceptable to at least one method.
* Return -2 if there are no methods of the required arity.
* The value "start" gives the index of the first argument to begin
* checking.
*/
return -2;
if (haveMatch[i] < 4) {
return (i<<2) | haveMatch[i];
}
}
return -1;
}
// look in the current class
boolean haveOne = false;
if (!f.isMethod()) {
continue;
}
haveOne = true;
haveMatch[i] = 4;
continue;
haveMatch[i] = 2;
} else if (haveMatch[i] > 0) {
continue;
}
haveMatch[i] |= 1;
}
}
}
// constructors are not inherited
return haveOne;
}
// look in the super class
haveOne = true;
}
return haveOne;
}
/**
* Add a field (no checks)
*/
//System.out.println("ADD = " + field);
if (firstMember == null) {
&& field.isVariable()) {
// insert this at the front, because of initialization order
firstMember = field;
} else {
lastMember = field;
}
}
/**
* Add a field (subclasses make checks)
*/
if (resolved) {
// a late addition
}
}
/**
* Find or create an uplevel reference for the given target.
*/
return r;
}
}
return addReference(target);
}
if (target.getClassDefinition() == this) {
}
return r;
}
/**
* Return the list of all uplevel references.
*/
return references;
}
/**
* Return the same value as getReferences.
* Also, mark the set of references frozen.
* After that, it is an error to add new references.
*/
referencesFrozen = true;
return references;
}
/**
* assertion check
*/
public final void referencesMustNotBeFrozen() {
if (referencesFrozen) {
throw new CompilerError("referencesMustNotBeFrozen "+this);
}
}
/**
* Get helper method for class literal lookup.
*/
throw new CompilerError("binary class");
}
/**
* Add a dependency
*/
throw new CompilerError("addDependency");
}
/**
* Maintain a hash table of local and anonymous classes
* whose internal names are prefixed by the current class.
* The key is the simple internal name, less the prefix.
*/
if (localClasses == null) {
return null;
} else {
}
}
if (localClasses == null) {
}
}
/**
* Print for debugging
*/
if (isPublic()) {
}
if (isInterface()) {
} else {
}
if (getSuperClass() != null) {
}
if (i > 0) {
}
}
}
}
}
/**
* Convert to String
*/
return getClassDeclaration().toString();
}
/**
* After the class has been written to disk, try to free up
* some storage.
*/
}
}
// keep "references" around, for the sake of local subclasses
}
}