checkBlankFinals(env, ctxInit, vsClass, true); // Check the rest of the field definitions. // (Note: Re-checking a field is a no-op.) for (MemberDefinition f = getFirstMember(); f != null; f = f.getNextMember()) { try { if (f.isConstructor()) { // When checking a constructor, an explicit call to // 'this(...)' makes all blank finals definitely assigned. // See 'MethodExpression.checkValue'. Vset vsCon = f.check(env, ctxInit, vsInst.copy()); // May issue multiple messages for the same variable!! checkBlankFinals(env, ctxInit, vsCon, false); // (drop vsCon here) } else { Vset vsFld = f.check(env, ctx, vset.copy()); // (drop vsFld here) } } catch (ClassNotFound ee) { env.error(f.getWhere(), "class.not.found", ee.name, this); } } // Must mark class as checked before visiting inner classes, // as they may in turn request checking of the current class // as an outer class. Fix for bug id 4056774. getClassDeclaration().setDefinition(this, CS_CHECKED); // Also check other classes in the same nest. // All checking of this nest must be finished before any // of its classes emit bytecode. // Otherwise, the inner classes might not have a chance to // add access or class literal fields to the outer class. for (MemberDefinition f = getFirstMember(); f != null; f = f.getNextMember()) { if (f.isInnerClass()) { SourceClass cdef = (SourceClass) f.getInnerClass(); if (!cdef.isInsideLocal()) { cdef.maybeCheck(env); } } } // Note: Since inner classes cannot set up-level variables, // the returned vset is always equal to the passed-in vset. // Still, we'll return it for the sake of regularity. return vset; } /** Make sure all my blank finals exist now. */ private void checkBlankFinals(Environment env, Context ctxInit, Vset vset, boolean isStatic) { for (int i = 0; i < ctxInit.getVarNumber(); i++) { if (!vset.testVar(i)) { MemberDefinition ff = ctxInit.getElement(i); if (ff != null && ff.isBlankFinal() && ff.isStatic() == isStatic && ff.getClassDefinition() == this) { env.error(ff.getWhere(), "final.var.not.initialized", ff.getName()); } } } } /** * Check this class has its superclass and its interfaces. Also * force it to have an <init> method (if it doesn't already have one) * and to have all the abstract methods of its parents. */ private boolean basicChecking = false; private boolean basicCheckDone = false; protected void basicCheck(Environment env) throws ClassNotFound { if (tracing) env.dtEnter("SourceClass.basicCheck: " + getName()); super.basicCheck(env); if (basicChecking || basicCheckDone) { if (tracing) env.dtExit("SourceClass.basicCheck: OK " + getName()); return; } if (tracing) env.dtEvent("SourceClass.basicCheck: CHECKING " + getName()); basicChecking = true; env = setupEnv(env); Imports imports = env.getImports(); if (imports != null) { imports.resolve(env); } resolveTypeStructure(env); // Check the existence of the superclass and all interfaces. // Also responsible for breaking inheritance cycles. This call // has been moved to 'resolveTypeStructure', just after the call // to 'resolveSupers', as inheritance cycles must be broken before // resolving types within the members. Fixes 4073739. // checkSupers(env); if (!isInterface()) { // Add implicit <init> method, if necessary. // QUERY: What keeps us from adding an implicit constructor // when the user explicitly declares one? Is it truly guaranteed // that the declaration for such an explicit constructor will have // been processed by the time we arrive here? In general, 'basicCheck' // is called very early, prior to the normal member checking phase. if (!hasConstructor()) { Node code = new CompoundStatement(getWhere(), new Statement[0]); Type t = Type.tMethod(Type.tVoid); // Default constructors inherit the access modifiers of their // class. For non-inner classes, this follows from JLS 8.6.7, // as the only possible modifier is 'public'. For the sake of // robustness in the presence of errors, we ignore any other // modifiers. For inner classes, the rule needs to be extended // in some way to account for the possibility of private and // protected classes. We make the 'obvious' extension, however, // the inner classes spec is silent on this issue, and a definitive // resolution is needed. See bugid 4087421. // WORKAROUND: A private constructor might need an access method, // but it is not possible to create one due to a restriction in // the verifier. (This is a known problem -- see 4015397.) // We therefore do not inherit the 'private' modifier from the class, // allowing the default constructor to be package private. This // workaround can be observed via reflection, but is otherwise // undetectable, as the constructor is always accessible within // the class in which its containing (private) class appears. int accessModifiers = getModifiers() & (isInnerClass() ? (M_PUBLIC | M_PROTECTED) : M_PUBLIC); env.makeMemberDefinition(env, getWhere(), this, null, accessModifiers, t, idInit, null, null, code); } } // Only do the inheritance/override checks if they are turned on. // The idea here is that they will be done in javac, but not // in javadoc. See the comment for turnOffChecks(), above. if (doInheritanceChecks) { // Verify the compatibility of all inherited method definitions // by collecting all of our inheritable methods. collectInheritedMethods(env); } basicChecking = false; basicCheckDone = true; if (tracing) env.dtExit("SourceClass.basicCheck: " + getName()); } /** * Add a group of methods to this class as miranda methods. * * For a definition of Miranda methods, see the comment above the * method addMirandaMethods() in the file * sun/tools/java/ClassDeclaration.java */ protected void addMirandaMethods(Environment env, Iterator mirandas) { while(mirandas.hasNext()) { MemberDefinition method = (MemberDefinition)mirandas.next(); addMember(method); //System.out.println("adding miranda method " + newMethod + // " to " + this); } } /** * <em>After parsing is complete</em>, resolve all names * except those inside method bodies or initializers. * In particular, this is the point at which we find out what * kinds of variables and methods there are in the classes, * and therefore what is each class's interface to the world. * <p> * Also perform certain other transformations, such as inserting * "this$C" arguments into constructors, and reorganizing structure * to flatten qualified member names. * <p> * Do not perform type-based or name-based consistency checks * or normalizations (such as default nullary constructors), * and do not attempt to compile code against this class, * until after this phase. */ private boolean resolving = false; public void resolveTypeStructure(Environment env) { if (tracing) env.dtEnter("SourceClass.resolveTypeStructure: " + getName()); // Resolve immediately enclosing type, which in turn // forces resolution of all enclosing type declarations. ClassDefinition oc = getOuterClass(); if (oc != null && oc instanceof SourceClass && !((SourceClass)oc).resolved) { // Do the outer class first, always. ((SourceClass)oc).resolveTypeStructure(env); // (Note: this.resolved is probably true at this point.) } // Punt if we've already resolved this class, or are currently // in the process of doing so. if (resolved || resolving) { if (tracing) env.dtExit("SourceClass.resolveTypeStructure: OK " + getName()); return; } // Previously, 'resolved' was set here, and served to prevent // duplicate resolutions here as well as its function in // 'ClassDefinition.addMember'. Now, 'resolving' serves the // former purpose, distinct from that of 'resolved'. resolving = true; if (tracing) env.dtEvent("SourceClass.resolveTypeStructure: RESOLVING " + getName()); env = setupEnv(env); // Resolve superclass names to class declarations // for the immediate superclass and superinterfaces. resolveSupers(env); // Check all ancestor superclasses for various // errors, verifying definition of all superclasses // and superinterfaces. Also breaks inheritance cycles. // Calls 'resolveTypeStructure' recursively for ancestors // This call used to appear in 'basicCheck', but was not // performed early enough. Most of the compiler will barf // on inheritance cycles! try { checkSupers(env); } catch (ClassNotFound ee) { // Undefined classes should be reported by 'checkSupers'. env.error(where, "class.not.found", ee.name, this); } for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) { if (f instanceof SourceMember) ((SourceMember)f).resolveTypeStructure(env); } resolving = false; // Mark class as resolved. If new members are subsequently // added to the class, they will be resolved at that time. // See 'ClassDefinition.addMember'. Previously, this variable was // set prior to the calls to 'checkSupers' and 'resolveTypeStructure' // (which may engender further calls to 'checkSupers'). This could // lead to duplicate resolution of implicit constructors, as the call to // 'basicCheck' from 'checkSupers' could add the constructor while // its class is marked resolved, and thus would resolve the constructor, // believing it to be a "late addition". It would then be resolved // redundantly during the normal traversal of the members, which // immediately follows in the code above. resolved = true; // Now we have enough information to detect method repeats. for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) { if (f.isInitializer()) continue; if (!f.isMethod()) continue; for (MemberDefinition f2 = f; (f2 = f2.getNextMatch()) != null; ) { if (!f2.isMethod()) continue; if (f.getType().equals(f2.getType())) { env.error(f.getWhere(), "meth.multidef", f); continue; } if (f.getType().equalArguments(f2.getType())) { env.error(f.getWhere(), "meth.redef.rettype", f, f2); continue; } } } if (tracing) env.dtExit("SourceClass.resolveTypeStructure: " + getName()); } protected void resolveSupers(Environment env) { if (tracing) env.dtEnter("SourceClass.resolveSupers: " + this); // Find the super class if (superClassId != null && superClass == null) { superClass = resolveSuper(env, superClassId); // Special-case java.lang.Object here (not in the parser). // In all other cases, if we have a valid 'superClassId', // we return with a valid and non-null 'superClass' value. if (superClass == getClassDeclaration() && getName().equals(idJavaLangObject)) { superClass = null; superClassId = null; } } // Find interfaces if (interfaceIds != null && interfaces == null) { interfaces = new ClassDeclaration[interfaceIds.length]; for (int i = 0 ; i < interfaces.length ; i++) { interfaces[i] = resolveSuper(env, interfaceIds[i]); for (int j = 0; j < i; j++) { if (interfaces[i] == interfaces[j]) { Identifier id = interfaceIds[i].getName(); long where = interfaceIds[j].getWhere(); env.error(where, "intf.repeated", id); } } } } if (tracing) env.dtExit("SourceClass.resolveSupers: " + this); } private ClassDeclaration resolveSuper(Environment env, IdentifierToken t) { Identifier name = t.getName(); if (tracing) env.dtEnter("SourceClass.resolveSuper: " + name); if (isInnerClass()) name = outerClass.resolveName(env, name); else name = env.resolveName(name); ClassDeclaration result = env.getClassDeclaration(name); // Result is never null, as a new 'ClassDeclaration' is // created if one with the given name does not exist. if (tracing) env.dtExit("SourceClass.resolveSuper: " + name); return result; } /** * During the type-checking of an outer method body or initializer, * this routine is called to check a local class body * in the proper context. * @param sup the named super class or interface (if anonymous) * @param args the actual arguments (if anonymous) */ public Vset checkLocalClass(Environment env, Context ctx, Vset vset, ClassDefinition sup, Expression args[], Type argTypes[] ) throws ClassNotFound { env = setupEnv(env); if ((sup != null) != isAnonymous()) { throw new CompilerError("resolveAnonymousStructure"); } if (isAnonymous()) { resolveAnonymousStructure(env, sup, args, argTypes); } // Run the checks in the lexical context from the outer class. vset = checkInternal(env, ctx, vset); // This is now done by 'checkInternal' via its call to 'checkMembers'. // getClassDeclaration().setDefinition(this, CS_CHECKED); return vset; } /** * As with checkLocalClass, run the inline phase for a local class. */ public void inlineLocalClass(Environment env) { for (MemberDefinition f = getFirstMember(); f != null; f = f.getNextMember()) { if ((f.isVariable() || f.isInitializer()) && !f.isStatic()) { continue; // inlined inside of constructors only } try { ((SourceMember)f).inline(env); } catch (ClassNotFound ee) { env.error(f.getWhere(), "class.not.found", ee.name, this); } } if (getReferencesFrozen() != null && !inlinedLocalClass) { inlinedLocalClass = true; // add more constructor arguments for uplevel references for (MemberDefinition f = getFirstMember(); f != null; f = f.getNextMember()) { if (f.isConstructor()) { //((SourceMember)f).addUplevelArguments(false); ((SourceMember)f).addUplevelArguments(); } } } } private boolean inlinedLocalClass = false; /** * Check a class which is inside a local class, but is not itself local. */ public Vset checkInsideClass(Environment env, Context ctx, Vset vset) throws ClassNotFound { if (!isInsideLocal() || isLocal()) { throw new CompilerError("checkInsideClass"); } return checkInternal(env, ctx, vset); } /** * Just before checking an anonymous class, decide its true * inheritance, and build its (sole, implicit) constructor. */ private void resolveAnonymousStructure(Environment env, ClassDefinition sup, Expression args[], Type argTypes[] ) throws ClassNotFound { if (tracing) env.dtEvent("SourceClass.resolveAnonymousStructure: " + this + ", super " + sup); // Decide now on the superclass. // This check has been removed as part of the fix for 4055017. // In the anonymous class created to hold the 'class$' method // of an interface, 'superClassId' refers to 'java.lang.Object'. /*---------------------* if (!(superClass == null && superClassId.getName() == idNull)) { throw new CompilerError("superclass "+superClass); } *---------------------*/ if (sup.isInterface()) { // allow an interface in the "super class" position int ni = (interfaces == null) ? 0 : interfaces.length; ClassDeclaration i1[] = new ClassDeclaration[1+ni]; if (ni > 0) { System.arraycopy(interfaces, 0, i1, 1, ni); if (interfaceIds != null && interfaceIds.length == ni) { IdentifierToken id1[] = new IdentifierToken[1+ni]; System.arraycopy(interfaceIds, 0, id1, 1, ni); id1[0] = new IdentifierToken(sup.getName()); } } i1[0] = sup.getClassDeclaration(); interfaces = i1; sup = toplevelEnv.getClassDefinition(idJavaLangObject); } superClass = sup.getClassDeclaration(); if (hasConstructor()) { throw new CompilerError("anonymous constructor"); } // Synthesize an appropriate constructor. Type t = Type.tMethod(Type.tVoid, argTypes); IdentifierToken names[] = new IdentifierToken[argTypes.length]; for (int i = 0; i < names.length; i++) { names[i] = new IdentifierToken(args[i].getWhere(), Identifier.lookup("$"+i)); } int outerArg = (sup.isTopLevel() || sup.isLocal()) ? 0 : 1; Expression superArgs[] = new Expression[-outerArg + args.length]; for (int i = outerArg ; i < args.length ; i++) { superArgs[-outerArg + i] = new IdentifierExpression(names[i]); } long where = getWhere(); Expression superExp; if (outerArg == 0) { superExp = new SuperExpression(where); } else { superExp = new SuperExpression(where, new IdentifierExpression(names[0])); } Expression superCall = new MethodExpression(where, superExp, idInit, superArgs); Statement body[] = { new ExpressionStatement(where, superCall) }; Node code = new CompoundStatement(where, body); int mod = M_SYNTHETIC; // ISSUE: make M_PRIVATE, with wrapper? env.makeMemberDefinition(env, where, this, null, mod, t, idInit, names, null, code); } /** * Convert class modifiers to a string for diagnostic purposes. * Accepts modifiers applicable to inner classes and that appear * in the InnerClasses attribute only, as well as those that may * appear in the class modifier proper. */ private static int classModifierBits[] = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_INTERFACE, ACC_ABSTRACT, ACC_SUPER, M_ANONYMOUS, M_LOCAL, M_STRICTFP, ACC_STRICT}; private static String classModifierNames[] = { "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL", "INTERFACE", "ABSTRACT", "SUPER", "ANONYMOUS", "LOCAL", "STRICTFP", "STRICT"};Lines 1001–1500 of 2674. Previous lines Load more
checkBlankFinals(env, ctxInit, vsClass, true); // Check the rest of the field definitions. // (Note: Re-checking a field is a no-op.) for (MemberDefinition f = getFirstMember(); f != null; f = f.getNextMember()) { try { if (f.isConstructor()) { // When checking a constructor, an explicit call to // 'this(...)' makes all blank finals definitely assigned. // See 'MethodExpression.checkValue'. Vset vsCon = f.check(env, ctxInit, vsInst.copy()); // May issue multiple messages for the same variable!! checkBlankFinals(env, ctxInit, vsCon, false); // (drop vsCon here) } else { Vset vsFld = f.check(env, ctx, vset.copy()); // (drop vsFld here) } } catch (ClassNotFound ee) { env.error(f.getWhere(), "class.not.found", ee.name, this); } } // Must mark class as checked before visiting inner classes, // as they may in turn request checking of the current class // as an outer class. Fix for bug id 4056774. getClassDeclaration().setDefinition(this, CS_CHECKED); // Also check other classes in the same nest. // All checking of this nest must be finished before any // of its classes emit bytecode. // Otherwise, the inner classes might not have a chance to // add access or class literal fields to the outer class. for (MemberDefinition f = getFirstMember(); f != null; f = f.getNextMember()) { if (f.isInnerClass()) { SourceClass cdef = (SourceClass) f.getInnerClass(); if (!cdef.isInsideLocal()) { cdef.maybeCheck(env); } } } // Note: Since inner classes cannot set up-level variables, // the returned vset is always equal to the passed-in vset. // Still, we'll return it for the sake of regularity. return vset; } /** Make sure all my blank finals exist now. */ private void checkBlankFinals(Environment env, Context ctxInit, Vset vset, boolean isStatic) { for (int i = 0; i < ctxInit.getVarNumber(); i++) { if (!vset.testVar(i)) { MemberDefinition ff = ctxInit.getElement(i); if (ff != null && ff.isBlankFinal() && ff.isStatic() == isStatic && ff.getClassDefinition() == this) { env.error(ff.getWhere(), "final.var.not.initialized", ff.getName()); } } } } /** * Check this class has its superclass and its interfaces. Also * force it to have an <init> method (if it doesn't already have one) * and to have all the abstract methods of its parents. */ private boolean basicChecking = false; private boolean basicCheckDone = false; protected void basicCheck(Environment env) throws ClassNotFound { if (tracing) env.dtEnter("SourceClass.basicCheck: " + getName()); super.basicCheck(env); if (basicChecking || basicCheckDone) { if (tracing) env.dtExit("SourceClass.basicCheck: OK " + getName()); return; } if (tracing) env.dtEvent("SourceClass.basicCheck: CHECKING " + getName()); basicChecking = true; env = setupEnv(env); Imports imports = env.getImports(); if (imports != null) { imports.resolve(env); } resolveTypeStructure(env); // Check the existence of the superclass and all interfaces. // Also responsible for breaking inheritance cycles. This call // has been moved to 'resolveTypeStructure', just after the call // to 'resolveSupers', as inheritance cycles must be broken before // resolving types within the members. Fixes 4073739. // checkSupers(env); if (!isInterface()) { // Add implicit <init> method, if necessary. // QUERY: What keeps us from adding an implicit constructor // when the user explicitly declares one? Is it truly guaranteed // that the declaration for such an explicit constructor will have // been processed by the time we arrive here? In general, 'basicCheck' // is called very early, prior to the normal member checking phase. if (!hasConstructor()) { Node code = new CompoundStatement(getWhere(), new Statement[0]); Type t = Type.tMethod(Type.tVoid); // Default constructors inherit the access modifiers of their // class. For non-inner classes, this follows from JLS 8.6.7, // as the only possible modifier is 'public'. For the sake of // robustness in the presence of errors, we ignore any other // modifiers. For inner classes, the rule needs to be extended // in some way to account for the possibility of private and // protected classes. We make the 'obvious' extension, however, // the inner classes spec is silent on this issue, and a definitive // resolution is needed. See bugid 4087421. // WORKAROUND: A private constructor might need an access method, // but it is not possible to create one due to a restriction in // the verifier. (This is a known problem -- see 4015397.) // We therefore do not inherit the 'private' modifier from the class, // allowing the default constructor to be package private. This // workaround can be observed via reflection, but is otherwise // undetectable, as the constructor is always accessible within // the class in which its containing (private) class appears. int accessModifiers = getModifiers() & (isInnerClass() ? (M_PUBLIC | M_PROTECTED) : M_PUBLIC); env.makeMemberDefinition(env, getWhere(), this, null, accessModifiers, t, idInit, null, null, code); } } // Only do the inheritance/override checks if they are turned on. // The idea here is that they will be done in javac, but not // in javadoc. See the comment for turnOffChecks(), above. if (doInheritanceChecks) { // Verify the compatibility of all inherited method definitions // by collecting all of our inheritable methods. collectInheritedMethods(env); } basicChecking = false; basicCheckDone = true; if (tracing) env.dtExit("SourceClass.basicCheck: " + getName()); } /** * Add a group of methods to this class as miranda methods. * * For a definition of Miranda methods, see the comment above the * method addMirandaMethods() in the file * sun/tools/java/ClassDeclaration.java */ protected void addMirandaMethods(Environment env, Iterator mirandas) { while(mirandas.hasNext()) { MemberDefinition method = (MemberDefinition)mirandas.next(); addMember(method); //System.out.println("adding miranda method " + newMethod + // " to " + this); } } /** * <em>After parsing is complete</em>, resolve all names * except those inside method bodies or initializers. * In particular, this is the point at which we find out what * kinds of variables and methods there are in the classes, * and therefore what is each class's interface to the world. * <p> * Also perform certain other transformations, such as inserting * "this$C" arguments into constructors, and reorganizing structure * to flatten qualified member names. * <p> * Do not perform type-based or name-based consistency checks * or normalizations (such as default nullary constructors), * and do not attempt to compile code against this class, * until after this phase. */ private boolean resolving = false; public void resolveTypeStructure(Environment env) { if (tracing) env.dtEnter("SourceClass.resolveTypeStructure: " + getName()); // Resolve immediately enclosing type, which in turn // forces resolution of all enclosing type declarations. ClassDefinition oc = getOuterClass(); if (oc != null && oc instanceof SourceClass && !((SourceClass)oc).resolved) { // Do the outer class first, always. ((SourceClass)oc).resolveTypeStructure(env); // (Note: this.resolved is probably true at this point.) } // Punt if we've already resolved this class, or are currently // in the process of doing so. if (resolved || resolving) { if (tracing) env.dtExit("SourceClass.resolveTypeStructure: OK " + getName()); return; } // Previously, 'resolved' was set here, and served to prevent // duplicate resolutions here as well as its function in // 'ClassDefinition.addMember'. Now, 'resolving' serves the // former purpose, distinct from that of 'resolved'. resolving = true; if (tracing) env.dtEvent("SourceClass.resolveTypeStructure: RESOLVING " + getName()); env = setupEnv(env); // Resolve superclass names to class declarations // for the immediate superclass and superinterfaces. resolveSupers(env); // Check all ancestor superclasses for various // errors, verifying definition of all superclasses // and superinterfaces. Also breaks inheritance cycles. // Calls 'resolveTypeStructure' recursively for ancestors // This call used to appear in 'basicCheck', but was not // performed early enough. Most of the compiler will barf // on inheritance cycles! try { checkSupers(env); } catch (ClassNotFound ee) { // Undefined classes should be reported by 'checkSupers'. env.error(where, "class.not.found", ee.name, this); } for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) { if (f instanceof SourceMember) ((SourceMember)f).resolveTypeStructure(env); } resolving = false; // Mark class as resolved. If new members are subsequently // added to the class, they will be resolved at that time. // See 'ClassDefinition.addMember'. Previously, this variable was // set prior to the calls to 'checkSupers' and 'resolveTypeStructure' // (which may engender further calls to 'checkSupers'). This could // lead to duplicate resolution of implicit constructors, as the call to // 'basicCheck' from 'checkSupers' could add the constructor while // its class is marked resolved, and thus would resolve the constructor, // believing it to be a "late addition". It would then be resolved // redundantly during the normal traversal of the members, which // immediately follows in the code above. resolved = true; // Now we have enough information to detect method repeats. for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) { if (f.isInitializer()) continue; if (!f.isMethod()) continue; for (MemberDefinition f2 = f; (f2 = f2.getNextMatch()) != null; ) { if (!f2.isMethod()) continue; if (f.getType().equals(f2.getType())) { env.error(f.getWhere(), "meth.multidef", f); continue; } if (f.getType().equalArguments(f2.getType())) { env.error(f.getWhere(), "meth.redef.rettype", f, f2); continue; } } } if (tracing) env.dtExit("SourceClass.resolveTypeStructure: " + getName()); } protected void resolveSupers(Environment env) { if (tracing) env.dtEnter("SourceClass.resolveSupers: " + this); // Find the super class if (superClassId != null && superClass == null) { superClass = resolveSuper(env, superClassId); // Special-case java.lang.Object here (not in the parser). // In all other cases, if we have a valid 'superClassId', // we return with a valid and non-null 'superClass' value. if (superClass == getClassDeclaration() && getName().equals(idJavaLangObject)) { superClass = null; superClassId = null; } } // Find interfaces if (interfaceIds != null && interfaces == null) { interfaces = new ClassDeclaration[interfaceIds.length]; for (int i = 0 ; i < interfaces.length ; i++) { interfaces[i] = resolveSuper(env, interfaceIds[i]); for (int j = 0; j < i; j++) { if (interfaces[i] == interfaces[j]) { Identifier id = interfaceIds[i].getName(); long where = interfaceIds[j].getWhere(); env.error(where, "intf.repeated", id); } } } } if (tracing) env.dtExit("SourceClass.resolveSupers: " + this); } private ClassDeclaration resolveSuper(Environment env, IdentifierToken t) { Identifier name = t.getName(); if (tracing) env.dtEnter("SourceClass.resolveSuper: " + name); if (isInnerClass()) name = outerClass.resolveName(env, name); else name = env.resolveName(name); ClassDeclaration result = env.getClassDeclaration(name); // Result is never null, as a new 'ClassDeclaration' is // created if one with the given name does not exist. if (tracing) env.dtExit("SourceClass.resolveSuper: " + name); return result; } /** * During the type-checking of an outer method body or initializer, * this routine is called to check a local class body * in the proper context. * @param sup the named super class or interface (if anonymous) * @param args the actual arguments (if anonymous) */ public Vset checkLocalClass(Environment env, Context ctx, Vset vset, ClassDefinition sup, Expression args[], Type argTypes[] ) throws ClassNotFound { env = setupEnv(env); if ((sup != null) != isAnonymous()) { throw new CompilerError("resolveAnonymousStructure"); } if (isAnonymous()) { resolveAnonymousStructure(env, sup, args, argTypes); } // Run the checks in the lexical context from the outer class. vset = checkInternal(env, ctx, vset); // This is now done by 'checkInternal' via its call to 'checkMembers'. // getClassDeclaration().setDefinition(this, CS_CHECKED); return vset; } /** * As with checkLocalClass, run the inline phase for a local class. */ public void inlineLocalClass(Environment env) { for (MemberDefinition f = getFirstMember(); f != null; f = f.getNextMember()) { if ((f.isVariable() || f.isInitializer()) && !f.isStatic()) { continue; // inlined inside of constructors only } try { ((SourceMember)f).inline(env); } catch (ClassNotFound ee) { env.error(f.getWhere(), "class.not.found", ee.name, this); } } if (getReferencesFrozen() != null && !inlinedLocalClass) { inlinedLocalClass = true; // add more constructor arguments for uplevel references for (MemberDefinition f = getFirstMember(); f != null; f = f.getNextMember()) { if (f.isConstructor()) { //((SourceMember)f).addUplevelArguments(false); ((SourceMember)f).addUplevelArguments(); } } } } private boolean inlinedLocalClass = false; /** * Check a class which is inside a local class, but is not itself local. */ public Vset checkInsideClass(Environment env, Context ctx, Vset vset) throws ClassNotFound { if (!isInsideLocal() || isLocal()) { throw new CompilerError("checkInsideClass"); } return checkInternal(env, ctx, vset); } /** * Just before checking an anonymous class, decide its true * inheritance, and build its (sole, implicit) constructor. */ private void resolveAnonymousStructure(Environment env, ClassDefinition sup, Expression args[], Type argTypes[] ) throws ClassNotFound { if (tracing) env.dtEvent("SourceClass.resolveAnonymousStructure: " + this + ", super " + sup); // Decide now on the superclass. // This check has been removed as part of the fix for 4055017. // In the anonymous class created to hold the 'class$' method // of an interface, 'superClassId' refers to 'java.lang.Object'. /*---------------------* if (!(superClass == null && superClassId.getName() == idNull)) { throw new CompilerError("superclass "+superClass); } *---------------------*/ if (sup.isInterface()) { // allow an interface in the "super class" position int ni = (interfaces == null) ? 0 : interfaces.length; ClassDeclaration i1[] = new ClassDeclaration[1+ni]; if (ni > 0) { System.arraycopy(interfaces, 0, i1, 1, ni); if (interfaceIds != null && interfaceIds.length == ni) { IdentifierToken id1[] = new IdentifierToken[1+ni]; System.arraycopy(interfaceIds, 0, id1, 1, ni); id1[0] = new IdentifierToken(sup.getName()); } } i1[0] = sup.getClassDeclaration(); interfaces = i1; sup = toplevelEnv.getClassDefinition(idJavaLangObject); } superClass = sup.getClassDeclaration(); if (hasConstructor()) { throw new CompilerError("anonymous constructor"); } // Synthesize an appropriate constructor. Type t = Type.tMethod(Type.tVoid, argTypes); IdentifierToken names[] = new IdentifierToken[argTypes.length]; for (int i = 0; i < names.length; i++) { names[i] = new IdentifierToken(args[i].getWhere(), Identifier.lookup("$"+i)); } int outerArg = (sup.isTopLevel() || sup.isLocal()) ? 0 : 1; Expression superArgs[] = new Expression[-outerArg + args.length]; for (int i = outerArg ; i < args.length ; i++) { superArgs[-outerArg + i] = new IdentifierExpression(names[i]); } long where = getWhere(); Expression superExp; if (outerArg == 0) { superExp = new SuperExpression(where); } else { superExp = new SuperExpression(where, new IdentifierExpression(names[0])); } Expression superCall = new MethodExpression(where, superExp, idInit, superArgs); Statement body[] = { new ExpressionStatement(where, superCall) }; Node code = new CompoundStatement(where, body); int mod = M_SYNTHETIC; // ISSUE: make M_PRIVATE, with wrapper? env.makeMemberDefinition(env, where, this, null, mod, t, idInit, names, null, code); } /** * Convert class modifiers to a string for diagnostic purposes. * Accepts modifiers applicable to inner classes and that appear * in the InnerClasses attribute only, as well as those that may * appear in the class modifier proper. */ private static int classModifierBits[] = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_INTERFACE, ACC_ABSTRACT, ACC_SUPER, M_ANONYMOUS, M_LOCAL, M_STRICTFP, ACC_STRICT}; private static String classModifierNames[] = { "PUBLIC", "PRIVATE", "PROTECTED", "STATIC", "FINAL", "INTERFACE", "ABSTRACT", "SUPER", "ANONYMOUS", "LOCAL", "STRICTFP", "STRICT"};