Source Code Cross Referenced for MethodExpression.java in  » 6.0-JDK-Modules-sun » tools » sun » tools » tree » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules sun » tools » sun.tools.tree 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1994-2003 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package sun.tools.tree;
0027:
0028:        import sun.tools.java.*;
0029:        import sun.tools.asm.Assembler;
0030:        import java.io.PrintStream;
0031:        import java.util.Hashtable;
0032:
0033:        /**
0034:         * WARNING: The contents of this source file are not part of any
0035:         * supported API.  Code that depends on them does so at its own risk:
0036:         * they are subject to change or removal without notice.
0037:         */
0038:        public class MethodExpression extends NaryExpression {
0039:            Identifier id;
0040:            ClassDefinition clazz; // The class in which the called method is defined
0041:            MemberDefinition field;
0042:            Expression implementation;
0043:
0044:            private boolean isSuper; // Set if qualified by 'super' or '<class>.super'.
0045:
0046:            /**
0047:             * constructor
0048:             */
0049:            public MethodExpression(long where, Expression right,
0050:                    Identifier id, Expression args[]) {
0051:                super (METHOD, where, Type.tError, right, args);
0052:                this .id = id;
0053:            }
0054:
0055:            public MethodExpression(long where, Expression right,
0056:                    MemberDefinition field, Expression args[]) {
0057:                super (METHOD, where, field.getType().getReturnType(), right,
0058:                        args);
0059:                this .id = field.getName();
0060:                this .field = field;
0061:                this .clazz = field.getClassDefinition();
0062:            }
0063:
0064:            // This is a hack used only within certain access methods generated by 
0065:            // 'SourceClass.getAccessMember'.  It allows an 'invokespecial' instruction
0066:            // to be forced even though 'super' does not appear within the call.
0067:            // Such access methods are needed for access to protected methods when using
0068:            // the qualified '<class>.super.<method>(...)' notation.
0069:            public MethodExpression(long where, Expression right,
0070:                    MemberDefinition field, Expression args[],
0071:                    boolean forceSuper) {
0072:                this (where, right, field, args);
0073:                this .isSuper = forceSuper;
0074:            }
0075:
0076:            public Expression getImplementation() {
0077:                if (implementation != null)
0078:                    return implementation;
0079:                return this ;
0080:            }
0081:
0082:            /**
0083:             * Check expression type
0084:             */
0085:            public Vset checkValue(Environment env, Context ctx, Vset vset,
0086:                    Hashtable exp) {
0087:                ClassDeclaration c = null;
0088:                boolean isArray = false;
0089:                boolean staticRef = false;
0090:
0091:                // Access method to use if required.
0092:                MemberDefinition implMethod = null;
0093:
0094:                ClassDefinition ctxClass = ctx.field.getClassDefinition();
0095:
0096:                // When calling a constructor, we may need to add an
0097:                // additional argument to transmit the outer instance link.
0098:                Expression args[] = this .args;
0099:                if (id.equals(idInit)) {
0100:                    ClassDefinition conCls = ctxClass;
0101:                    try {
0102:                        Expression conOuter = null;
0103:                        if (right instanceof  SuperExpression) {
0104:                            // outer.super(...)
0105:                            conCls = conCls.getSuperClass().getClassDefinition(
0106:                                    env);
0107:                            conOuter = ((SuperExpression) right).outerArg;
0108:                        } else if (right instanceof  ThisExpression) {
0109:                            // outer.this(...)
0110:                            conOuter = ((ThisExpression) right).outerArg;
0111:                        }
0112:                        args = NewInstanceExpression.insertOuterLink(env, ctx,
0113:                                where, conCls, conOuter, args);
0114:                    } catch (ClassNotFound ee) {
0115:                        // the same error is handled elsewhere
0116:                    }
0117:                }
0118:
0119:                Type argTypes[] = new Type[args.length];
0120:
0121:                // The effective accessing class, for access checking.
0122:                // This is normally the immediately enclosing class.
0123:                ClassDefinition sourceClass = ctxClass;
0124:
0125:                try {
0126:                    if (right == null) {
0127:                        staticRef = ctx.field.isStatic();
0128:                        // Find the first outer scope that mentions the method.
0129:                        ClassDefinition cdef = ctxClass;
0130:                        MemberDefinition m = null;
0131:                        for (; cdef != null; cdef = cdef.getOuterClass()) {
0132:                            m = cdef.findAnyMethod(env, id);
0133:                            if (m != null) {
0134:                                break;
0135:                            }
0136:                        }
0137:                        if (m == null) {
0138:                            // this is the scope for error diagnosis
0139:                            c = ctx.field.getClassDeclaration();
0140:                        } else {
0141:                            // found the innermost scope in which m occurs
0142:                            c = cdef.getClassDeclaration();
0143:
0144:                            // Maybe an inherited method hides an apparent method.
0145:                            // Keep looking at enclosing scopes to find out.
0146:                            if (m.getClassDefinition() != cdef) {
0147:                                ClassDefinition cdef2 = cdef;
0148:                                while ((cdef2 = cdef2.getOuterClass()) != null) {
0149:                                    MemberDefinition m2 = cdef2.findAnyMethod(
0150:                                            env, id);
0151:                                    if (m2 != null
0152:                                            && m2.getClassDefinition() == cdef2) {
0153:                                        env.error(where,
0154:                                                "inherited.hides.method", id,
0155:                                                cdef.getClassDeclaration(),
0156:                                                cdef2.getClassDeclaration());
0157:                                        break;
0158:                                    }
0159:                                }
0160:                            }
0161:                        }
0162:                    } else {
0163:                        if (id.equals(idInit)) {
0164:                            int this N = ctx.getThisNumber();
0165:                            if (!ctx.field.isConstructor()) {
0166:                                env.error(where, "invalid.constr.invoke");
0167:                                return vset.addVar(this N);
0168:                            }
0169:                            // As a consequence of the DA/DU rules in the JLS (draft of
0170:                            // forthcoming 2e), all variables are both definitely assigned
0171:                            // and definitely unassigned in unreachable code.  Normally, this
0172:                            // correctly suppresses DA/DU-related errors in such code.
0173:                            // The use of the DA status of the 'this' variable for the extra
0174:                            // check below on correct constructor usage, however, does not quite
0175:                            // fit into this DA/DU scheme.  The current representation of
0176:                            // Vsets for unreachable dead-ends, does not allow 'clearVar' 
0177:                            // to work, as the DA/DU bits (all on) are implicitly represented
0178:                            // by the fact that the Vset is a dead-end.  The DA/DU status
0179:                            // of the 'this' variable is supposed to be temporarily
0180:                            // cleared at the beginning of a constructor and during the
0181:                            // checking of constructor arguments (see below in this method).
0182:                            // Since 'clearVar' has no effect on dead-ends, we may
0183:                            // find the 'this' variable in an erroneously definitely-assigned state.
0184:                            // As a workaround, we suppress the following error message when
0185:                            // the Vset is a dead-end, i.e., when we are in unreachable code.
0186:                            // Unfortunately, the special-case treatment of reachability for
0187:                            // if-then and if-then-else allows unreachable code in some circumstances,
0188:                            // thus it is possible that no error message will be emitted at all.
0189:                            // While this behavior is strictly incorrect (thus we call this a
0190:                            // workaround), the problematic code is indeed unreachable and will
0191:                            // not be executed.  In fact, it will be entirely omitted from the
0192:                            // translated program, and can cause no harm at runtime.  A correct
0193:                            // solution would require modifying the representation of the DA/DU
0194:                            // analysis to use finite Vsets only, restricting the universe
0195:                            // of variables about which assertions are made (even in unreachable
0196:                            // code) to variables that are actually in scope. Alternatively, the
0197:                            // Vset extension and the dead-end marker (currently a reserved value
0198:                            // of the extension) could be represented orthogonally.  In either case,
0199:                            // 'clearVar' could then be made to work on (non-canonical) dead ends.
0200:                            // See file 'Vset.java'.
0201:                            if (!vset.isReallyDeadEnd() && vset.testVar(this N)) {
0202:                                env.error(where, "constr.invoke.not.first");
0203:                                return vset;
0204:                            }
0205:                            vset = vset.addVar(this N);
0206:                            if (right instanceof  SuperExpression) {
0207:                                // supers require this specific kind of checking
0208:                                vset = right.checkAmbigName(env, ctx, vset,
0209:                                        exp, this );
0210:                            } else {
0211:                                vset = right.checkValue(env, ctx, vset, exp);
0212:                            }
0213:                        } else {
0214:                            vset = right.checkAmbigName(env, ctx, vset, exp,
0215:                                    this );
0216:                            if (right.type == Type.tPackage) {
0217:                                FieldExpression.reportFailedPackagePrefix(env,
0218:                                        right);
0219:                                return vset;
0220:                            }
0221:                            if (right instanceof  TypeExpression) {
0222:                                staticRef = true;
0223:                            }
0224:                        }
0225:                        if (right.type.isType(TC_CLASS)) {
0226:                            c = env.getClassDeclaration(right.type);
0227:                        } else if (right.type.isType(TC_ARRAY)) {
0228:                            isArray = true;
0229:                            c = env.getClassDeclaration(Type.tObject);
0230:                        } else {
0231:                            if (!right.type.isType(TC_ERROR)) {
0232:                                env.error(where, "invalid.method.invoke",
0233:                                        right.type);
0234:                            }
0235:                            return vset;
0236:                        }
0237:
0238:                        // Normally, the effective accessing class is the innermost
0239:                        // class surrounding the current method call, but, for calls
0240:                        // of the form '<class>.super.<method>(...)', it is <class>.
0241:                        // This allows access to protected members of a superclass
0242:                        // from within a class nested within one of its subclasses.
0243:                        // Otherwise, for example, the call below to 'matchMethod'
0244:                        // may fail due to the rules for visibility of inaccessible
0245:                        // members.  For consistency, we treat qualified 'this' in
0246:                        // the same manner, as error diagnostics will be affected.
0247:                        // QUERY: Are there subtle unexplored language issues here?
0248:                        if (right instanceof  FieldExpression) {
0249:                            Identifier id = ((FieldExpression) right).id;
0250:                            if (id == idThis) {
0251:                                sourceClass = ((FieldExpression) right).clazz;
0252:                            } else if (id == idSuper) {
0253:                                isSuper = true;
0254:                                sourceClass = ((FieldExpression) right).clazz;
0255:                            }
0256:                        } else if (right instanceof  SuperExpression) {
0257:                            isSuper = true;
0258:                        }
0259:
0260:                        // Fix for 4158650.  When we extend a protected inner
0261:                        // class in a different package, we may not have access
0262:                        // to the type of our superclass.  Allow the call to
0263:                        // the superclass constructor from within our constructor
0264:                        // Note that this check does not apply to constructor
0265:                        // calls in new instance expressions -- those are part
0266:                        // of NewInstanceExpression#check().
0267:                        if (id != idInit) {
0268:                            // Required by JLS 6.6.1.  Fixes 4143715.
0269:                            // (See also 4094658.)
0270:                            if (!FieldExpression.isTypeAccessible(where, env,
0271:                                    right.type, sourceClass)) {
0272:                                ClassDeclaration cdecl = sourceClass
0273:                                        .getClassDeclaration();
0274:                                if (staticRef) {
0275:                                    env.error(where, "no.type.access", id,
0276:                                            right.type.toString(), cdecl);
0277:                                } else {
0278:                                    env.error(where, "cant.access.member.type",
0279:                                            id, right.type.toString(), cdecl);
0280:                                }
0281:                            }
0282:                        }
0283:                    }
0284:
0285:                    // Compose a list of argument types
0286:                    boolean hasErrors = false;
0287:
0288:                    // "this" is not defined during argument checking
0289:                    if (id.equals(idInit)) {
0290:                        vset = vset.clearVar(ctx.getThisNumber());
0291:                    }
0292:
0293:                    for (int i = 0; i < args.length; i++) {
0294:                        vset = args[i].checkValue(env, ctx, vset, exp);
0295:                        argTypes[i] = args[i].type;
0296:                        hasErrors = hasErrors || argTypes[i].isType(TC_ERROR);
0297:                    }
0298:
0299:                    // "this" is defined after the constructor invocation
0300:                    if (id.equals(idInit)) {
0301:                        vset = vset.addVar(ctx.getThisNumber());
0302:                    }
0303:
0304:                    // Check if there are any type errors in the arguments
0305:                    if (hasErrors) {
0306:                        return vset;
0307:                    }
0308:
0309:                    // Get the method field, given the argument types
0310:                    clazz = c.getClassDefinition(env);
0311:
0312:                    if (field == null) {
0313:
0314:                        field = clazz.matchMethod(env, sourceClass, id,
0315:                                argTypes);
0316:
0317:                        if (field == null) {
0318:                            if (id.equals(idInit)) {
0319:                                if (diagnoseMismatch(env, args, argTypes))
0320:                                    return vset;
0321:                                String sig = clazz.getName().getName()
0322:                                        .toString();
0323:                                sig = Type.tMethod(Type.tError, argTypes)
0324:                                        .typeString(sig, false, false);
0325:                                env.error(where, "unmatched.constr", sig, c);
0326:                                return vset;
0327:                            }
0328:                            String sig = id.toString();
0329:                            sig = Type.tMethod(Type.tError, argTypes)
0330:                                    .typeString(sig, false, false);
0331:                            if (clazz.findAnyMethod(env, id) == null) {
0332:                                if (ctx.getField(env, id) != null) {
0333:                                    env.error(where, "invalid.method", id, c);
0334:                                } else {
0335:                                    env.error(where, "undef.meth", sig, c);
0336:                                }
0337:                            } else if (diagnoseMismatch(env, args, argTypes)) {
0338:                            } else {
0339:                                env.error(where, "unmatched.meth", sig, c);
0340:                            }
0341:                            return vset;
0342:                        }
0343:
0344:                    }
0345:
0346:                    type = field.getType().getReturnType();
0347:
0348:                    // Make sure that static references are allowed
0349:                    if (staticRef && !field.isStatic()) {
0350:                        env.error(where, "no.static.meth.access", field, field
0351:                                .getClassDeclaration());
0352:                        return vset;
0353:                    }
0354:
0355:                    if (field.isProtected()
0356:                            && !(right == null)
0357:                            && !(right instanceof  SuperExpression
0358:                            // Extension of JLS 6.6.2 for qualified 'super'.
0359:                            || (right instanceof  FieldExpression && ((FieldExpression) right).id == idSuper))
0360:                            && !sourceClass.protectedAccess(env, field,
0361:                                    right.type)) {
0362:                        env.error(where, "invalid.protected.method.use", field
0363:                                .getName(), field.getClassDeclaration(),
0364:                                right.type);
0365:                        return vset;
0366:                    }
0367:
0368:                    // In <class>.super.<method>(), we cannot simply evaluate
0369:                    // <class>.super to an object reference (as we would for
0370:                    // <class>.super.<field>) and then perform an 'invokespecial'.
0371:                    // An 'invokespecial' must be performed from within (a subclass of)
0372:                    // the class in which the target method is located.
0373:                    if (right instanceof  FieldExpression
0374:                            && ((FieldExpression) right).id == idSuper) {
0375:                        if (!field.isPrivate()) {
0376:                            // The private case is handled below.
0377:                            // Use an access method unless the effective accessing class
0378:                            // (the class qualifying the 'super') is the same as the
0379:                            // immediately enclosing class, i.e., the qualification was
0380:                            // unnecessary.
0381:                            if (sourceClass != ctxClass) {
0382:                                implMethod = sourceClass.getAccessMember(env,
0383:                                        ctx, field, true);
0384:                            }
0385:                        }
0386:                    }
0387:
0388:                    // Access method for private field if not in the same class.
0389:                    if (implMethod == null && field.isPrivate()) {
0390:                        ClassDefinition cdef = field.getClassDefinition();
0391:                        if (cdef != ctxClass) {
0392:                            implMethod = cdef.getAccessMember(env, ctx, field,
0393:                                    false);
0394:                        }
0395:                    }
0396:
0397:                    // Make sure that we are not invoking an abstract method
0398:                    if (field.isAbstract() && (right != null)
0399:                            && (right.op == SUPER)) {
0400:                        env.error(where, "invoke.abstract", field, field
0401:                                .getClassDeclaration());
0402:                        return vset;
0403:                    }
0404:
0405:                    if (field.reportDeprecated(env)) {
0406:                        if (field.isConstructor()) {
0407:                            env
0408:                                    .error(where, "warn.constr.is.deprecated",
0409:                                            field);
0410:                        } else {
0411:                            env.error(where, "warn.meth.is.deprecated", field,
0412:                                    field.getClassDefinition());
0413:                        }
0414:                    }
0415:
0416:                    // Check for recursive constructor
0417:                    if (field.isConstructor() && ctx.field.equals(field)) {
0418:                        env.error(where, "recursive.constr", field);
0419:                    }
0420:
0421:                    // When a package-private class defines public or protected
0422:                    // members, those members may sometimes be accessed from
0423:                    // outside of the package in public subclasses.  In these
0424:                    // cases, we need to massage the method call to refer to
0425:                    // to an accessible subclass rather than the package-private
0426:                    // parent class.  Part of fix for 4135692.
0427:
0428:                    // Find out if the class which contains this method
0429:                    // call has access to the class which declares the
0430:                    // public or protected method referent.
0431:                    // We don't perform this translation on constructor calls.
0432:                    if (sourceClass == ctxClass) {
0433:                        ClassDefinition declarer = field.getClassDefinition();
0434:                        if (!field.isConstructor()
0435:                                && declarer.isPackagePrivate()
0436:                                && !declarer.getName().getQualifier().equals(
0437:                                        sourceClass.getName().getQualifier())) {
0438:
0439:                            //System.out.println("The access of member " +
0440:                            //		   field + " declared in class " +
0441:                            //		   declarer +
0442:                            //		   " is not allowed by the VM from class  " +
0443:                            //		   accessor +
0444:                            //		   ".  Replacing with an access of class " +
0445:                            //		   clazz);
0446:
0447:                            // We cannot make this access at the VM level.
0448:                            // Construct a member which will stand for this
0449:                            // method in clazz and set `field' to refer to it.
0450:                            field = MemberDefinition.makeProxyMember(field,
0451:                                    clazz, env);
0452:                        }
0453:                    }
0454:
0455:                    sourceClass.addDependency(field.getClassDeclaration());
0456:                    if (sourceClass != ctxClass) {
0457:                        ctxClass.addDependency(field.getClassDeclaration());
0458:                    }
0459:
0460:                } catch (ClassNotFound ee) {
0461:                    env.error(where, "class.not.found", ee.name, ctx.field);
0462:                    return vset;
0463:
0464:                } catch (AmbiguousMember ee) {
0465:                    env.error(where, "ambig.field", id, ee.field1, ee.field2);
0466:                    return vset;
0467:                }
0468:
0469:                // Make sure it is qualified
0470:                if ((right == null) && !field.isStatic()) {
0471:                    right = ctx.findOuterLink(env, where, field);
0472:                    vset = right.checkValue(env, ctx, vset, exp);
0473:                }
0474:
0475:                // Cast arguments
0476:                argTypes = field.getType().getArgumentTypes();
0477:                for (int i = 0; i < args.length; i++) {
0478:                    args[i] = convert(env, ctx, argTypes[i], args[i]);
0479:                }
0480:
0481:                if (field.isConstructor()) {
0482:                    MemberDefinition m = field;
0483:                    if (implMethod != null) {
0484:                        m = implMethod;
0485:                    }
0486:                    int nargs = args.length;
0487:                    Expression[] newargs = args;
0488:                    if (nargs > this .args.length) {
0489:                        // Argument was added above.
0490:                        // Maintain the model for hidden outer args in outer.super(...):
0491:                        Expression rightI;
0492:                        if (right instanceof  SuperExpression) {
0493:                            rightI = new SuperExpression(right.where, ctx);
0494:                            ((SuperExpression) right).outerArg = args[0];
0495:                        } else if (right instanceof  ThisExpression) {
0496:                            rightI = new ThisExpression(right.where, ctx);
0497:                        } else {
0498:                            throw new CompilerError("this.init");
0499:                        }
0500:                        if (implMethod != null) {
0501:                            // Need dummy argument for access method.
0502:                            // Dummy argument follows outer instance link.
0503:                            // Leave 'this.args' equal to 'newargs' but
0504:                            // without the outer instance link.
0505:                            newargs = new Expression[nargs + 1];
0506:                            this .args = new Expression[nargs];
0507:                            newargs[0] = args[0]; // outer instance
0508:                            this .args[0] = newargs[1] = new NullExpression(
0509:                                    where); // dummy argument
0510:                            for (int i = 1; i < nargs; i++) {
0511:                                this .args[i] = newargs[i + 1] = args[i];
0512:                            }
0513:                        } else {
0514:                            // Strip outer instance link from 'this.args'.
0515:                            // ASSERT(this.arg.length == nargs-1);
0516:                            for (int i = 1; i < nargs; i++) {
0517:                                this .args[i - 1] = args[i];
0518:                            }
0519:                        }
0520:                        implementation = new MethodExpression(where, rightI, m,
0521:                                newargs);
0522:                        implementation.type = type; // Is this needed?
0523:                    } else {
0524:                        // No argument was added.
0525:                        if (implMethod != null) {
0526:                            // Need dummy argument for access method.
0527:                            // Dummy argument is first, as there is no outer instance link.
0528:                            newargs = new Expression[nargs + 1];
0529:                            newargs[0] = new NullExpression(where);
0530:                            for (int i = 0; i < nargs; i++) {
0531:                                newargs[i + 1] = args[i];
0532:                            }
0533:                        }
0534:                        implementation = new MethodExpression(where, right, m,
0535:                                newargs);
0536:                    }
0537:                } else {
0538:                    // Have ordinary method.
0539:                    // Argument should have been added only for a constructor.
0540:                    if (args.length > this .args.length) {
0541:                        throw new CompilerError("method arg");
0542:                    }
0543:                    if (implMethod != null) {
0544:                        //System.out.println("Calling " + field + " via " + implMethod);
0545:                        Expression oldargs[] = this .args;
0546:                        if (field.isStatic()) {
0547:                            Expression call = new MethodExpression(where, null,
0548:                                    implMethod, oldargs);
0549:                            implementation = new CommaExpression(where, right,
0550:                                    call);
0551:                        } else {
0552:                            // Access method needs an explicit 'this' pointer.
0553:                            int nargs = oldargs.length;
0554:                            Expression newargs[] = new Expression[nargs + 1];
0555:                            newargs[0] = right;
0556:                            for (int i = 0; i < nargs; i++) {
0557:                                newargs[i + 1] = oldargs[i];
0558:                            }
0559:                            implementation = new MethodExpression(where, null,
0560:                                    implMethod, newargs);
0561:                        }
0562:                    }
0563:                }
0564:
0565:                // Follow super() by variable initializations
0566:                if (ctx.field.isConstructor() && field.isConstructor()
0567:                        && (right != null) && (right.op == SUPER)) {
0568:                    Expression e = makeVarInits(env, ctx);
0569:                    if (e != null) {
0570:                        if (implementation == null)
0571:                            implementation = (Expression) this .clone();
0572:                        implementation = new CommaExpression(where,
0573:                                implementation, e);
0574:                    }
0575:                }
0576:
0577:                // Throw the declared exceptions.
0578:                ClassDeclaration exceptions[] = field.getExceptions(env);
0579:                if (isArray && (field.getName() == idClone)
0580:                        && (field.getType().getArgumentTypes().length == 0)) {
0581:                    /* Arrays pretend that they have "public Object clone()" that doesn't
0582:                     * throw anything, according to the language spec.
0583:                     */
0584:                    exceptions = new ClassDeclaration[0];
0585:                    /* See if there's a bogus catch for it, to issue a warning. */
0586:                    for (Context p = ctx; p != null; p = p.prev) {
0587:                        if (p.node != null && p.node.op == TRY) {
0588:                            ((TryStatement) p.node).arrayCloneWhere = where;
0589:                        }
0590:                    }
0591:                }
0592:                for (int i = 0; i < exceptions.length; i++) {
0593:                    if (exp.get(exceptions[i]) == null) {
0594:                        exp.put(exceptions[i], this );
0595:                    }
0596:                }
0597:
0598:                // Mark all blank finals as definitely assigned following 'this(...)'.
0599:                // Correctness follows inductively from the requirement that all blank finals
0600:                // be definitely assigned at the completion of every constructor.
0601:                if (ctx.field.isConstructor() && field.isConstructor()
0602:                        && (right != null) && (right.op == THIS)) {
0603:                    ClassDefinition cls = field.getClassDefinition();
0604:                    for (MemberDefinition f = cls.getFirstMember(); f != null; f = f
0605:                            .getNextMember()) {
0606:                        if (f.isVariable() && f.isBlankFinal() && !f.isStatic()) {
0607:                            // Static variables should also be considered defined as well, but this
0608:                            // is handled in 'SourceClass.checkMembers', and we should not interfere.
0609:                            vset = vset.addVar(ctx.getFieldNumber(f));
0610:                        }
0611:                    }
0612:                }
0613:
0614:                return vset;
0615:            }
0616:
0617:            /**
0618:             * Check void expression
0619:             */
0620:            public Vset check(Environment env, Context ctx, Vset vset,
0621:                    Hashtable exp) {
0622:                return checkValue(env, ctx, vset, exp);
0623:            }
0624:
0625:            /**
0626:             * We're about to report a "unmatched method" error.
0627:             * Try to issue a better diagnostic by comparing the actual argument types
0628:             * with the method (or methods) available.
0629:             * In particular, if there is an argument which fails to match <em>any</em>
0630:             * method, we report a type mismatch error against that particular argument.
0631:             * The diagnostic will report a target type taken from one of the methods.
0632:             * <p>
0633:             * Return false if we couldn't think of anything smart to say.
0634:             */
0635:            boolean diagnoseMismatch(Environment env, Expression args[],
0636:                    Type argTypes[]) throws ClassNotFound {
0637:                Type margType[] = new Type[1];
0638:                boolean saidSomething = false;
0639:                int start = 0;
0640:                while (start < argTypes.length) {
0641:                    int code = clazz.diagnoseMismatch(env, id, argTypes, start,
0642:                            margType);
0643:                    String opName = (id.equals(idInit)) ? "constructor"
0644:                            : opNames[op];
0645:                    if (code == -2) {
0646:                        env.error(where, "wrong.number.args", opName);
0647:                        saidSomething = true;
0648:                    }
0649:                    if (code < 0)
0650:                        break;
0651:                    int i = code >> 2;
0652:                    boolean castOK = (code & 2) != 0;
0653:                    boolean ambig = (code & 1) != 0;
0654:                    Type targetType = margType[0];
0655:
0656:                    // At least one argument is offensive to all overloadings.
0657:                    // targetType is one of the argument types it does not match.
0658:                    String ttype = "" + targetType;
0659:
0660:                    // The message might be slightly misleading, if there are other
0661:                    // argument types that also would match.  Hint at this:
0662:                    //if (ambig)  ttype = "{"+ttype+";...}";
0663:
0664:                    if (castOK)
0665:                        env.error(args[i].where, "explicit.cast.needed",
0666:                                opName, argTypes[i], ttype);
0667:                    else
0668:                        env.error(args[i].where, "incompatible.type", opName,
0669:                                argTypes[i], ttype);
0670:                    saidSomething = true;
0671:                    start = i + 1; // look for other bad arguments, too
0672:                }
0673:                return saidSomething;
0674:            }
0675:
0676:            /**
0677:             * Inline
0678:             */
0679:            static final int MAXINLINECOST = Statement.MAXINLINECOST;
0680:
0681:            private Expression inlineMethod(Environment env, Context ctx,
0682:                    Statement s, boolean valNeeded) {
0683:                if (env.dump()) {
0684:                    System.out.println("INLINE METHOD " + field + " in "
0685:                            + ctx.field);
0686:                }
0687:                LocalMember v[] = LocalMember.copyArguments(ctx, field);
0688:                Statement body[] = new Statement[v.length + 2];
0689:
0690:                int n = 0;
0691:                if (field.isStatic()) {
0692:                    body[0] = new ExpressionStatement(where, right);
0693:                } else {
0694:                    if ((right != null) && (right.op == SUPER)) {
0695:                        right = new ThisExpression(right.where, ctx);
0696:                    }
0697:                    body[0] = new VarDeclarationStatement(where, v[n++], right);
0698:                }
0699:                for (int i = 0; i < args.length; i++) {
0700:                    body[i + 1] = new VarDeclarationStatement(where, v[n++],
0701:                            args[i]);
0702:                }
0703:                //System.out.print("BEFORE:"); s.print(System.out); System.out.println();
0704:                // Note: If !valNeeded, then all returns in the body of the method
0705:                // change to void returns.
0706:                body[body.length - 1] = (s != null) ? s.copyInline(ctx,
0707:                        valNeeded) : null;
0708:                //System.out.print("COPY:"); body[body.length - 1].print(System.out); System.out.println();
0709:                LocalMember.doneWithArguments(ctx, v);
0710:
0711:                // Make sure the type matches what the return statements are returning.
0712:                Type type = valNeeded ? this .type : Type.tVoid;
0713:                Expression e = new InlineMethodExpression(where, type, field,
0714:                        new CompoundStatement(where, body));
0715:                return valNeeded ? e.inlineValue(env, ctx) : e.inline(env, ctx);
0716:            }
0717:
0718:            public Expression inline(Environment env, Context ctx) {
0719:                if (implementation != null)
0720:                    return implementation.inline(env, ctx);
0721:                try {
0722:                    if (right != null) {
0723:                        right = field.isStatic() ? right.inline(env, ctx)
0724:                                : right.inlineValue(env, ctx);
0725:                    }
0726:                    for (int i = 0; i < args.length; i++) {
0727:                        args[i] = args[i].inlineValue(env, ctx);
0728:                    }
0729:
0730:                    // ctxClass is the current class trying to inline this method
0731:                    ClassDefinition ctxClass = ctx.field.getClassDefinition();
0732:
0733:                    Expression e = this ;
0734:                    if (env.opt()
0735:                            && field.isInlineable(env, clazz.isFinal())
0736:                            &&
0737:
0738:                            // Don't inline if a qualified non-static method: the call
0739:                            // itself might throw NullPointerException as a side effect
0740:                            ((right == null) || (right.op == THIS) || field
0741:                                    .isStatic())
0742:                            &&
0743:
0744:                            // We only allow the inlining if the current class can access
0745:                            // the field, the field's class, and right's declared type.
0746:                            ctxClass.permitInlinedAccess(env, field
0747:                                    .getClassDeclaration())
0748:                            && ctxClass.permitInlinedAccess(env, field)
0749:                            && (right == null || ctxClass.permitInlinedAccess(
0750:                                    env, env.getClassDeclaration(right.type)))
0751:                            &&
0752:
0753:                            ((id == null) || !id.equals(idInit))
0754:                            && (!ctx.field.isInitializer())
0755:                            && ctx.field.isMethod()
0756:                            && (ctx.getInlineMemberContext(field) == null)) {
0757:                        Statement s = (Statement) field.getValue(env);
0758:                        if ((s == null)
0759:                                || (s.costInline(MAXINLINECOST, env, ctx) < MAXINLINECOST)) {
0760:                            e = inlineMethod(env, ctx, s, false);
0761:                        }
0762:                    }
0763:                    return e;
0764:
0765:                } catch (ClassNotFound e) {
0766:                    throw new CompilerError(e);
0767:                }
0768:            }
0769:
0770:            public Expression inlineValue(Environment env, Context ctx) {
0771:                if (implementation != null)
0772:                    return implementation.inlineValue(env, ctx);
0773:                try {
0774:                    if (right != null) {
0775:                        right = field.isStatic() ? right.inline(env, ctx)
0776:                                : right.inlineValue(env, ctx);
0777:                    }
0778:                    if (field.getName().equals(idInit)) {
0779:                        ClassDefinition refc = field.getClassDefinition();
0780:                        UplevelReference r = refc.getReferencesFrozen();
0781:                        if (r != null) {
0782:                            r.willCodeArguments(env, ctx);
0783:                        }
0784:                    }
0785:                    for (int i = 0; i < args.length; i++) {
0786:                        args[i] = args[i].inlineValue(env, ctx);
0787:                    }
0788:
0789:                    // ctxClass is the current class trying to inline this method
0790:                    ClassDefinition ctxClass = ctx.field.getClassDefinition();
0791:
0792:                    if (env.opt()
0793:                            && field.isInlineable(env, clazz.isFinal())
0794:                            &&
0795:
0796:                            // Don't inline if a qualified non-static method: the call
0797:                            // itself might throw NullPointerException as a side effect
0798:                            ((right == null) || (right.op == THIS) || field
0799:                                    .isStatic())
0800:                            &&
0801:
0802:                            // We only allow the inlining if the current class can access
0803:                            // the field, the field's class, and right's declared type.
0804:                            ctxClass.permitInlinedAccess(env, field
0805:                                    .getClassDeclaration())
0806:                            && ctxClass.permitInlinedAccess(env, field)
0807:                            && (right == null || ctxClass.permitInlinedAccess(
0808:                                    env, env.getClassDeclaration(right.type)))
0809:                            &&
0810:
0811:                            (!ctx.field.isInitializer())
0812:                            && ctx.field.isMethod()
0813:                            && (ctx.getInlineMemberContext(field) == null)) {
0814:                        Statement s = (Statement) field.getValue(env);
0815:                        if ((s == null)
0816:                                || (s.costInline(MAXINLINECOST, env, ctx) < MAXINLINECOST)) {
0817:                            return inlineMethod(env, ctx, s, true);
0818:                        }
0819:                    }
0820:                    return this ;
0821:                } catch (ClassNotFound e) {
0822:                    throw new CompilerError(e);
0823:                }
0824:            }
0825:
0826:            public Expression copyInline(Context ctx) {
0827:                if (implementation != null)
0828:                    return implementation.copyInline(ctx);
0829:                return super .copyInline(ctx);
0830:            }
0831:
0832:            public int costInline(int thresh, Environment env, Context ctx) {
0833:                if (implementation != null)
0834:                    return implementation.costInline(thresh, env, ctx);
0835:
0836:                // for now, don't allow calls to super() to be inlined.  We may fix
0837:                // this later
0838:                if ((right != null) && (right.op == SUPER)) {
0839:                    return thresh;
0840:                }
0841:                return super .costInline(thresh, env, ctx);
0842:            }
0843:
0844:            /*
0845:             * Grab all instance initializer code from the class definition,
0846:             * and return as one bolus.  Note that we are assuming the
0847:             * the relevant fields have already been checked.
0848:             * (See the pre-pass in SourceClass.checkMembers which ensures this.)
0849:             */
0850:            private Expression makeVarInits(Environment env, Context ctx) {
0851:                // insert instance initializers
0852:                ClassDefinition clazz = ctx.field.getClassDefinition();
0853:                Expression e = null;
0854:                for (MemberDefinition f = clazz.getFirstMember(); f != null; f = f
0855:                        .getNextMember()) {
0856:                    if ((f.isVariable() || f.isInitializer()) && !f.isStatic()) {
0857:                        try {
0858:                            f.check(env);
0859:                        } catch (ClassNotFound ee) {
0860:                            env.error(f.getWhere(), "class.not.found", ee.name,
0861:                                    f.getClassDefinition());
0862:                        }
0863:                        Expression val = null;
0864:                        if (f.isUplevelValue()) {
0865:                            if (f != clazz.findOuterMember()) {
0866:                                // it's too early to accumulate these
0867:                                continue;
0868:                            }
0869:                            IdentifierExpression arg = new IdentifierExpression(
0870:                                    where, f.getName());
0871:                            if (!arg.bind(env, ctx)) {
0872:                                throw new CompilerError("bind " + arg.id);
0873:                            }
0874:                            val = arg;
0875:                        } else if (f.isInitializer()) {
0876:                            Statement s = (Statement) f.getValue();
0877:                            val = new InlineMethodExpression(where, Type.tVoid,
0878:                                    f, s);
0879:                        } else {
0880:                            val = (Expression) f.getValue();
0881:                        }
0882:                        // append all initializers to "e":
0883:                        // This section used to check for variables which were
0884:                        // initialized to their default values and elide such
0885:                        // initialization.  This is specifically disallowed by
0886:                        // JLS 12.5 numeral 4, which requires a textual ordering
0887:                        // on the execution of initializers.
0888:                        if ((val != null)) { //  && !val.equals(0)) {
0889:                            long p = f.getWhere();
0890:                            val = val.copyInline(ctx);
0891:                            Expression init = val;
0892:                            if (f.isVariable()) {
0893:                                Expression v = new ThisExpression(p, ctx);
0894:                                v = new FieldExpression(p, v, f);
0895:                                init = new AssignExpression(p, v, val);
0896:                            }
0897:                            e = (e == null) ? init : new CommaExpression(p, e,
0898:                                    init);
0899:                        }
0900:                    }
0901:                }
0902:                return e;
0903:            }
0904:
0905:            /**
0906:             * Code
0907:             */
0908:            public void codeValue(Environment env, Context ctx, Assembler asm) {
0909:                if (implementation != null)
0910:                    throw new CompilerError("codeValue");
0911:                int i = 0; // argument index
0912:                if (field.isStatic()) {
0913:                    if (right != null) {
0914:                        right.code(env, ctx, asm);
0915:                    }
0916:                } else if (right == null) {
0917:                    asm.add(where, opc_aload, new Integer(0));
0918:                } else if (right.op == SUPER) {
0919:                    // 'super.<method>(...)', 'super(...)', or '<expr>.super(...)'
0920:                    /*****
0921:                    isSuper = true;
0922:                     *****/
0923:                    right.codeValue(env, ctx, asm);
0924:                    if (idInit.equals(id)) {
0925:                        // 'super(...)' or '<expr>.super(...)' only
0926:                        ClassDefinition refc = field.getClassDefinition();
0927:                        UplevelReference r = refc.getReferencesFrozen();
0928:                        if (r != null) {
0929:                            // When calling a constructor for a class with
0930:                            // embedded uplevel references, add extra arguments.
0931:                            if (r.isClientOuterField()) {
0932:                                // the extra arguments are inserted after this one
0933:                                args[i++].codeValue(env, ctx, asm);
0934:                            }
0935:                            r.codeArguments(env, ctx, asm, where, field);
0936:                        }
0937:                    }
0938:                } else {
0939:                    right.codeValue(env, ctx, asm);
0940:                    /*****
0941:                    if (right.op == FIELD &&
0942:                    ((FieldExpression)right).id == idSuper) {
0943:                    // '<class>.super.<method>(...)'
0944:                    isSuper = true;
0945:                    }
0946:                     *****/
0947:                }
0948:
0949:                for (; i < args.length; i++) {
0950:                    args[i].codeValue(env, ctx, asm);
0951:                }
0952:
0953:                if (field.isStatic()) {
0954:                    asm.add(where, opc_invokestatic, field);
0955:                } else if (field.isConstructor() || field.isPrivate()
0956:                        || isSuper) {
0957:                    asm.add(where, opc_invokespecial, field);
0958:                } else if (field.getClassDefinition().isInterface()) {
0959:                    asm.add(where, opc_invokeinterface, field);
0960:                } else {
0961:                    asm.add(where, opc_invokevirtual, field);
0962:                }
0963:
0964:                if (right != null && right.op == SUPER && idInit.equals(id)) {
0965:                    // 'super(...)' or '<expr>.super(...)'
0966:                    ClassDefinition refc = ctx.field.getClassDefinition();
0967:                    UplevelReference r = refc.getReferencesFrozen();
0968:                    if (r != null) {
0969:                        // After calling a superclass constructor in a class with
0970:                        // embedded uplevel references, initialize uplevel fields.
0971:                        r.codeInitialization(env, ctx, asm, where, field);
0972:                    }
0973:                }
0974:            }
0975:
0976:            /**
0977:             * Check if the first thing is a constructor invocation
0978:             */
0979:            public Expression firstConstructor() {
0980:                return id.equals(idInit) ? this  : null;
0981:            }
0982:
0983:            /**
0984:             * Print
0985:             */
0986:            public void print(PrintStream out) {
0987:                out.print("(" + opNames[op]);
0988:                if (right != null) {
0989:                    out.print(" ");
0990:                    right.print(out);
0991:                }
0992:                out.print(" " + ((id == null) ? idInit : id));
0993:                for (int i = 0; i < args.length; i++) {
0994:                    out.print(" ");
0995:                    if (args[i] != null) {
0996:                        args[i].print(out);
0997:                    } else {
0998:                        out.print("<null>");
0999:                    }
1000:                }
1001:                out.print(")");
1002:                if (implementation != null) {
1003:                    out.print("/IMPL=");
1004:                    implementation.print(out);
1005:                }
1006:            }
1007:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.