jdk/src/share/classes/sun/tools/tree/FieldExpression.java
author malenkov
Tue, 29 Oct 2013 17:01:06 +0400
changeset 21278 ef8a3a2a72f2
parent 5506 202f599c92aa
child 23010 6dadb192ad81
permissions -rw-r--r--
8022746: List of spelling errors in API doc Reviewed-by: alexsch, smarks
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     2
 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.tools.tree;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import sun.tools.java.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import sun.tools.asm.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.PrintStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.util.Hashtable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 * WARNING: The contents of this source file are not part of any
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * supported API.  Code that depends on them does so at its own risk:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * they are subject to change or removal without notice.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
public
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
class FieldExpression extends UnaryExpression {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
    Identifier id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
    MemberDefinition field;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
    Expression implementation;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    // The class from which the field is select ed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    ClassDefinition clazz;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    // For an expression of the form '<class>.super', then
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    // this is <class>, else null.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    private ClassDefinition superBase;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
     * constructor
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
    public FieldExpression(long where, Expression right, Identifier id) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
        super(FIELD, where, Type.tError, right);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
        this.id = id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    public FieldExpression(long where, Expression right, MemberDefinition field) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
        super(FIELD, where, field.getType(), right);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
        this.id = field.getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
        this.field = field;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    public Expression getImplementation() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
            return implementation;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
        return this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
     * Return true if the field is being selected from
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
     * a qualified 'super'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    private boolean isQualSuper() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
        return superBase != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
     * Convert an '.' expression to a qualified identifier
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    static public Identifier toIdentifier(Expression e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
        StringBuffer buf = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
        while (e.op == FIELD) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
            FieldExpression fe = (FieldExpression)e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
            if (fe.id == idThis || fe.id == idClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
            buf.insert(0, fe.id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
            buf.insert(0, '.');
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
            e = fe.right;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        if (e.op != IDENT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        buf.insert(0, ((IdentifierExpression)e).id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        return Identifier.lookup(buf.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     * Convert a qualified name into a type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
     * Performs a careful check of each inner-class component,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
     * including the JLS 6.6.1 access checks that were omitted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * in 'FieldExpression.toType'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
     * This code is similar to 'checkCommon', which could be cleaned
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
     * up a bit long the lines we have done here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    /*-------------------------------------------------------*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    Type toQualifiedType(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        Type rty = right.toQualifiedType(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        if (rty == Type.tPackage) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
            // Is this field expression a non-inner type?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            Identifier nm = toIdentifier(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
            if ((nm != null) && env.classExists(nm)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
                Type t = Type.tClass(nm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
                if (env.resolve(where, ctxClass, t)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
                    return t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
            // Not a type.  Must be a package prefix.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
            return Type.tPackage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
        if (rty == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
            // An error was already reported, so quit.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        // Check inner-class qualification while unwinding from recursion.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
            ClassDefinition rightClass = env.getClassDefinition(rty);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
            // Local variables, which cannot be inner classes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
            // are ignored here, and thus will not hide inner
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
            // classes.  Is this correct?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            MemberDefinition field = rightClass.getInnerClass(env, id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
            if (field == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                env.error(where, "inner.class.expected", id, rightClass);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
                return Type.tError;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
            ClassDefinition innerClass = field.getInnerClass();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
            Type t = innerClass.getType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
            if (!ctxClass.canAccess(env, field)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                env.error(where, "no.type.access", id, rightClass, ctxClass);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
                return t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            if (field.isProtected()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                && !ctxClass.protectedAccess(env, field, rty)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
                env.error(where, "invalid.protected.type.use", id, ctxClass, rty);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                return t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 5506
diff changeset
   157
            // These were omitted earlier in calls to 'toType', but I can't
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
            // see any reason for that.  I think it was an oversight.  See
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            // 'checkCommon' and 'checkInnerClass'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            innerClass.noteUsedBy(ctxClass, where, env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            ctxClass.addDependency(field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            return t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        } catch (ClassNotFound e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
            env.error(where, "class.not.found", e.name, ctx.field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        // Class not found.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
    *-------------------------------------------------------*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
     * Convert an '.' expression to a type
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    // This is a rewrite to treat qualified names in a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
    // context in which a type name is expected in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    // same way that they are handled for an ambiguous
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
    // or expression-expected context in 'checkCommon'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
    // below.  The new code is cleaner and allows better
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
    // localization of errors.  Unfortunately, most
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
    // qualified names appearing in types are actually
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    // handled by 'Environment.resolve'.  There isn't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
    // much point, then, in breaking out 'toType' as a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    // special case until the other cases can be cleaned
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
    // up as well.  For the time being, we will leave this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
    // code disabled, thus reducing the testing requirements.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
    /*-------------------------------------------------------*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
    Type toType(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        Type t = toQualifiedType(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        if (t == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
            return Type.tError;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        if (t == Type.tPackage) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            FieldExpression.reportFailedPackagePrefix(env, right, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
            return Type.tError;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        return t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
    *-------------------------------------------------------*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    Type toType(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        Identifier id = toIdentifier(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        if (id == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
            env.error(where, "invalid.type.expr");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
            return Type.tError;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        Type t = Type.tClass(ctx.resolveName(env, id));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        if (env.resolve(where, ctx.field.getClassDefinition(), t)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
            return t;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        return Type.tError;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
     * Check if the present name is part of a scoping prefix.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
    public Vset checkAmbigName(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                               Vset vset, Hashtable exp,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                               UnaryExpression loc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
        if (id == idThis || id == idClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
            loc = null;         // this cannot be a type or package
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        return checkCommon(env, ctx, vset, exp, loc, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     * Check the expression
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
    public Vset checkValue(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                           Vset vset, Hashtable exp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        vset = checkCommon(env, ctx, vset, exp, null, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        if (id == idSuper && type != Type.tError) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            // "super" is not allowed in this context.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
            // It must always qualify another name.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
            env.error(where, "undef.var.super", idSuper);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
     * If 'checkAmbiguousName' returns 'Package.tPackage', then it was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     * unable to resolve any prefix of the qualified name.  This method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     * attempts to diagnose the problem.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    static void reportFailedPackagePrefix(Environment env, Expression right) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        reportFailedPackagePrefix(env, right, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    static void reportFailedPackagePrefix(Environment env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
                                          Expression right,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
                                          boolean mustBeType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        // Find the leftmost component, and put the blame on it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        Expression idp = right;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        while (idp instanceof UnaryExpression)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            idp = ((UnaryExpression)idp).right;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        IdentifierExpression ie = (IdentifierExpression)idp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        // It may be that 'ie' refers to an ambiguous class.  Check this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        // with a call to env.resolve(). Part of solution for 4059855.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            env.resolve(ie.id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        } catch (AmbiguousClass e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
            env.error(right.where, "ambig.class", e.name1, e.name2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        } catch (ClassNotFound e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        if (idp == right) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
            if (mustBeType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                env.error(ie.where, "undef.class", ie.id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
                env.error(ie.where, "undef.var.or.class", ie.id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            if (mustBeType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
                env.error(ie.where, "undef.class.or.package", ie.id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
                env.error(ie.where, "undef.var.class.or.package", ie.id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     * Rewrite accesses to private fields of another class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    private Expression
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    implementFieldAccess(Environment env, Context ctx, Expression base, boolean isLHS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        ClassDefinition abase = accessBase(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        if (abase != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            // If the field is final and its initializer is a constant expression,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
            // then just rewrite to the constant expression. This is not just an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            // optimization, but is required for correctness.  If an expression is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            // rewritten to use an access method, then its status as a constant
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            // expression is lost.  This was the cause of bug 4098737.  Note that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            // a call to 'getValue(env)' below would not be correct, as it attempts
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
            // to simplify the initial value expression, which must not occur until
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
            // after the checking phase, for example, after definite assignment checks.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            if (field.isFinal()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                Expression e = (Expression)field.getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                // Must not be LHS here.  Test as a precaution,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                // as we may not be careful to avoid this when
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
                // compiling an erroneous program.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                if ((e != null) && e.isConstant() && !isLHS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
                    return e.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
            //System.out.println("Finding access method for " + field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            MemberDefinition af = abase.getAccessMember(env, ctx, field, isQualSuper());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
            //System.out.println("Using access method " + af);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            if (!isLHS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
                //System.out.println("Reading " + field +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                //                              " via access method " + af);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                // If referencing the value of the field, then replace
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
                // with a call to the access method.  If assigning to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
                // the field, a call to the update method will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                // generated later. It is important that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                // 'implementation' not be set to non-null if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                // expression is a valid assignment target.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
                // (See 'checkLHS'.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
                if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
                    Expression args[] = { };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
                    Expression call =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
                        new MethodExpression(where, null, af, args);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                    return new CommaExpression(where, base, call);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                    Expression args[] = { base };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
                    return new MethodExpression(where, null, af, args);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     * Determine if an access method is required, and, if so, return
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
     * the class in which it should appear, else return null.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
    private ClassDefinition accessBase(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
        if (field.isPrivate()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
            ClassDefinition cdef = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
            ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
            if (cdef == ctxClass){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                // If access from same class as field, then no access
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                // method is needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            // An access method is needed in the class containing the field.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
            return cdef;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        } else if (field.isProtected()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            if (superBase == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                // If access is not via qualified super, then it is either
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
                // OK without an access method, or it is an illegal access
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
                // for which an error message should have been issued.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                // Legal accesses include unqualified 'super.foo'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
            ClassDefinition cdef = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
            ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
            if (cdef.inSamePackage(ctxClass)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
                // Access to protected member in same package always allowed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
            // Access via qualified super.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
            // An access method is needed in the qualifying class, an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
            // immediate subclass of the class containing the selected
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            // field.  NOTE: The fact that the returned class is 'superBase'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            // carries the additional bit of information (that a special
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
            // superclass access method is being created) which is provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
            // to 'getAccessMember' via its 'isSuper' argument.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            return superBase;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            // No access method needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
     * Determine if a type is accessible from a given class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
    static boolean isTypeAccessible(long where,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                                    Environment env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
                                    Type t,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                                    ClassDefinition c) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        switch (t.getTypeCode()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
          case TC_CLASS:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
                Identifier nm = t.getClassName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                // Why not just use 'Environment.getClassDeclaration' here?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
                // But 'Environment.getClassDeclation' has special treatment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                // for local classes that is probably necessary.  This code
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                // was adapted from 'Environment.resolve'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                ClassDefinition def = env.getClassDefinition(t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
                return c.canAccess(env, def.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
            } catch (ClassNotFound e) {}  // Ignore -- reported elsewhere.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
          case TC_ARRAY:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
            return isTypeAccessible(where, env, t.getElementType(), c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
          default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
     * Common code for checkValue and checkAmbigName
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
    private Vset checkCommon(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
                             Vset vset, Hashtable exp,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                             UnaryExpression loc, boolean isLHS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        // Handle class literal, e.g., 'x.class'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
        if (id == idClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
            // In 'x.class', 'x' must be a type name, possibly qualified.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
            Type t = right.toType(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
            if (!t.isType(TC_CLASS) && !t.isType(TC_ARRAY)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                if (t.isType(TC_ERROR)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                    type = Type.tClassDesc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                    return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
                String wrc = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                switch (t.getTypeCode()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
                  case TC_VOID: wrc = "Void"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
                  case TC_BOOLEAN: wrc = "Boolean"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                  case TC_BYTE: wrc = "Byte"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
                  case TC_CHAR: wrc = "Character"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
                  case TC_SHORT: wrc = "Short"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
                  case TC_INT: wrc = "Integer"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
                  case TC_FLOAT: wrc = "Float"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
                  case TC_LONG: wrc = "Long"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                  case TC_DOUBLE: wrc = "Double"; break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
                  default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                      env.error(right.where, "invalid.type.expr");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                      return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                Identifier wid = Identifier.lookup(idJavaLang+"."+wrc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                Expression wcls = new TypeExpression(where, Type.tClass(wid));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                implementation = new FieldExpression(where, wcls, idTYPE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                vset = implementation.checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
                type = implementation.type; // java.lang.Class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
            // Check for the bogus type `array of void'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
            if (t.isVoidArray()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                type = Type.tClassDesc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                env.error(right.where, "void.array");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
            // it is a class or array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            long fwhere = ctx.field.getWhere();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
            ClassDefinition fcls = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
            MemberDefinition lookup = fcls.getClassLiteralLookup(fwhere);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
            String sig = t.getTypeSignature();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
            String className;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
            if (t.isType(TC_CLASS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                // sig is like "Lfoo/bar;", name is like "foo.bar".
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                // We assume SIG_CLASS and SIG_ENDCLASS are 1 char each.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                className = sig.substring(1, sig.length()-1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                    .replace(SIGC_PACKAGE, '.');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
                // sig is like "[Lfoo/bar;" or "[I";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                // name is like "[Lfoo.bar" or (again) "[I".
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
                className = sig.replace(SIGC_PACKAGE, '.');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
            if (fcls.isInterface()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
                // The immediately-enclosing type is an interface.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                // The class literal can only appear in an initialization
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                // expression, so don't bother caching it.  (This could
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                // lose if many initializations use the same class literal,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                // but saves time and code space otherwise.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                implementation =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
                    makeClassLiteralInlineRef(env, ctx, lookup, className);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
                // Cache the call to the helper, as it may be executed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                // many times (e.g., if the class literal is inside a loop).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                ClassDefinition inClass = lookup.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
                MemberDefinition cfld =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
                    getClassLiteralCache(env, ctx, className, inClass);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                implementation =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                    makeClassLiteralCacheRef(env, ctx, lookup, cfld, className);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            vset = implementation.checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
            type = implementation.type; // java.lang.Class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
        // Arrive here if not a class literal.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        if (field != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
            // The field as been pre-set, e.g., as the result of transforming
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
            // an 'IdentifierExpression'. Most error-checking has already been
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
            // performed at this point.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
            // QUERY: Why don't we further unify checking of identifier
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
            // expressions and field expressions that denote instance and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
            // class variables?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            implementation = implementFieldAccess(env, ctx, right, isLHS);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
            return (right == null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
                vset : right.checkAmbigName(env, ctx, vset, exp, this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
        // Does the qualifier have a meaning of its own?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
        vset = right.checkAmbigName(env, ctx, vset, exp, this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
        if (right.type == Type.tPackage) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
            // Are we out of options?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
            if (loc == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                FieldExpression.reportFailedPackagePrefix(env, right);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
            // ASSERT(loc.right == this)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
            // Nope.  Is this field expression a type?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
            Identifier nm = toIdentifier(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
            if ((nm != null) && env.classExists(nm)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                loc.right = new TypeExpression(where, Type.tClass(nm));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                // Check access. (Cf. IdentifierExpression.toResolvedType.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
                env.resolve(where, ctxClass, loc.right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
            // Let the caller make sense of it, then.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            type = Type.tPackage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        // Good; we have a well-defined qualifier type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
        boolean staticRef = (right instanceof TypeExpression);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
            // Handle array 'length' field, e.g., 'x.length'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            if (!right.type.isType(TC_CLASS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
                if (right.type.isType(TC_ARRAY) && id.equals(idLength)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
                    // Verify that the type of the base expression is accessible.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
                    // Required by JLS 6.6.1.  Fixes 4094658.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
                    if (!FieldExpression.isTypeAccessible(where, env, right.type, ctxClass)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
                        ClassDeclaration cdecl = ctxClass.getClassDeclaration();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                        if (staticRef) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
                            env.error(where, "no.type.access",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
                                      id, right.type.toString(), cdecl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
                            env.error(where, "cant.access.member.type",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
                                      id, right.type.toString(), cdecl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
                    type = Type.tInt;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
                    implementation = new LengthExpression(where, right);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
                    return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
                if (!right.type.isType(TC_ERROR)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
                    env.error(where, "invalid.field.reference", id, right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
            // At this point, we know that 'right.type' is a class type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
            // Note that '<expr>.super(...)' and '<expr>.this(...)' cases never
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
            // reach here.  Instead, '<expr>' is stored as the 'outerArg' field
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            // of a 'SuperExpression' or 'ThisExpression' node.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
            // If our prefix is of the form '<class>.super', then we are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            // about to do a field selection '<class>.super.<field>'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
            // Save the qualifying class in 'superBase', which is non-null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
            // only if the current FieldExpression is a qualified 'super' form.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
            // Also, set 'sourceClass' to the "effective accessing class" relative
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            // to which access checks will be performed.  Normally, this is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
            // immediately enclosing class.  For '<class>.this' and '<class>.super',
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
            // however, we use <class>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
            ClassDefinition sourceClass = ctxClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
            if (right instanceof FieldExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
                Identifier id = ((FieldExpression)right).id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
                if (id == idThis) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
                    sourceClass = ((FieldExpression)right).clazz;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
                } else if (id == idSuper) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
                    sourceClass = ((FieldExpression)right).clazz;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
                    superBase = sourceClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
            // Handle 'class.this' and 'class.super'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
            //
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            // Suppose 'super.name' appears within a class C with immediate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            // superclass S. According to JLS 15.10.2, 'super.name' in this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            // case is equivalent to '((S)this).name'.  Analogously, we interpret
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            // 'class.super.name' as '((S)(class.this)).name', where S is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
            // immediate superclass of (enclosing) class 'class'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
            // Note that 'super' may not stand alone as an expression, but must
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            // occur as the qualifying expression of a field access or a method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
            // invocation.  This is enforced in 'SuperExpression.checkValue' and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            // 'FieldExpression.checkValue', and need not concern us here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            //ClassDefinition clazz = env.getClassDefinition(right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            clazz = env.getClassDefinition(right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
            if (id == idThis || id == idSuper) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                if (!staticRef) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                    env.error(right.where, "invalid.type.expr");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                // We used to check that 'right.type' is accessible here,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                // per JLS 6.6.1.  As a result of the fix for 4102393, however,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                // the qualifying class name must exactly match an enclosing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                // outer class, which is necessarily accessible.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
                /*** Temporary assertion check ***/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
                if (ctx.field.isSynthetic())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
                    throw new CompilerError("synthetic qualified this");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
                /*********************************/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
                // A.this means we're inside an A and we want its self ptr.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
                // C.this is always the same as this when C is innermost.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
                // Another A.this means we skip out to get a "hidden" this,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                // just as ASuper.foo skips out to get a hidden variable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
                // Last argument 'true' means we want an exact class match,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
                // not a subclass of the specified class ('clazz').
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
                implementation = ctx.findOuterLink(env, where, clazz, null, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
                vset = implementation.checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
                if (id == idSuper) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
                    type = clazz.getSuperClass().getType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
                    type = clazz.getType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
            // Field should be an instance variable or class variable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
            field = clazz.getVariable(env, id, sourceClass);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
            if (field == null && staticRef && loc != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
                // Is this field expression an inner type?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
                // Search the class and its supers (but not its outers).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
                // QUERY: We may need to get the inner class from a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
                // superclass of 'clazz'.  This call is prepared to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
                // resolve the superclass if necessary.  Can we arrange
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
                // to assure that it is always previously resolved?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
                // This is one of a small number of problematic calls that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
                // requires 'getSuperClass' to resolve superclasses on demand.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
                // See 'ClassDefinition.getInnerClass(env, nm)'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
                field = clazz.getInnerClass(env, id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
                if (field != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                    return checkInnerClass(env, ctx, vset, exp, loc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
            // If not a variable reference, diagnose error if name is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            // that of a method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
            if (field == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
                if ((field = clazz.findAnyMethod(env, id)) != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                    env.error(where, "invalid.field",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
                              id, field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                    env.error(where, "no.such.field", id, clazz);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
            // At this point, we have identified a valid field.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
            // Required by JLS 6.6.1.  Fixes 4094658.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
            if (!FieldExpression.isTypeAccessible(where, env, right.type, sourceClass)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                ClassDeclaration cdecl = sourceClass.getClassDeclaration();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
                if (staticRef) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
                    env.error(where, "no.type.access",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
                              id, right.type.toString(), cdecl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
                    env.error(where, "cant.access.member.type",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
                              id, right.type.toString(), cdecl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
            type = field.getType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
            if (!sourceClass.canAccess(env, field)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
                env.error(where, "no.field.access",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                          id, clazz, sourceClass.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
            if (staticRef && !field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                // 'Class.field' is not legal when field is not static;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                // see JLS 15.13.1.  This case was permitted by javac
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
                // prior to 1.2; static refs were silently changed to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                // be dynamic access of the form 'this.field'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                env.error(where, "no.static.field.access", id, clazz);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                // Rewrite access to use an access method if necessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                implementation = implementFieldAccess(env, ctx, right, isLHS);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
            // Check for invalid access to protected field.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
            if (field.isProtected()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                && !(right instanceof SuperExpression
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                     // Extension of JLS 6.6.2 for qualified 'super'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                     || (right instanceof FieldExpression &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                         ((FieldExpression)right).id == idSuper))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
                && !sourceClass.protectedAccess(env, field, right.type)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
                env.error(where, "invalid.protected.field.use",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
                          field.getName(), field.getClassDeclaration(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
                          right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
            if ((!field.isStatic()) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
                (right.op == THIS) && !vset.testVar(ctx.getThisNumber())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                env.error(where, "access.inst.before.super", id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
            if (field.reportDeprecated(env)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                env.error(where, "warn."+"field.is.deprecated",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
                          id, field.getClassDefinition());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
            // When a package-private class defines public or protected
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
            // members, those members may sometimes be accessed from
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            // outside of the package in public subclasses.  In these
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
            // cases, we need to massage the getField to refer to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
            // to an accessible subclass rather than the package-private
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
            // parent class.  Part of fix for 4135692.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
            // Find out if the class which contains this field
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
            // reference has access to the class which declares the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
            // public or protected field.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
            if (sourceClass == ctxClass) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                ClassDefinition declarer = field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
                if (declarer.isPackagePrivate() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
                    !declarer.getName().getQualifier()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
                    .equals(sourceClass.getName().getQualifier())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
                    //System.out.println("The access of member " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
                    //             field + " declared in class " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
                    //             declarer +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
                    //             " is not allowed by the VM from class  " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
                    //             ctxClass +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
                    //             ".  Replacing with an access of class " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                    //             clazz);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                    // We cannot make this access at the VM level.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
                    // Construct a member which will stand for this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
                    // field in ctxClass and set `field' to refer to it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
                    field =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
                        MemberDefinition.makeProxyMember(field, clazz, env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
            sourceClass.addDependency(field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
        } catch (ClassNotFound e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
            env.error(where, "class.not.found", e.name, ctx.field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
        } catch (AmbiguousMember e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
            env.error(where, "ambig.field",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
                      id, e.field1.getClassDeclaration(), e.field2.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
     * Return a <code>FieldUpdater</code> object to be used in updating the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
     * value of the location denoted by <code>this</code>, which must be an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
     * expression suitable for the left-hand side of an assignment.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
     * This is used for implementing assignments to private fields for which
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
     * an access method is required.  Returns null if no access method is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
     * needed, in which case the assignment is handled in the usual way, by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
     * direct access.  Only simple assignment expressions are handled here
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
     * Assignment operators and pre/post increment/decrement operators are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
     * are handled by 'getUpdater' below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
     * Must be called after 'checkValue', else 'right' will be invalid.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
    public FieldUpdater getAssigner(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
        if (field == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
            // Field can legitimately be null if the field name was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
            // undefined, in which case an error was reported, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
            // no value for 'field' is available.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
            //   throw new CompilerError("getAssigner");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
        ClassDefinition abase = accessBase(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
        if (abase != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
            MemberDefinition setter = abase.getUpdateMember(env, ctx, field, isQualSuper());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
            // It may not be necessary to copy 'right' here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
            Expression base = (right == null) ? null : right.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
            // Created 'FieldUpdater' has no getter method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
            return new FieldUpdater(where, field, base, null, setter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
     * Return a <code>FieldUpdater</code> object to be used in updating the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
     * value of the location denoted by <code>this</code>, which must be an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
     * expression suitable for the left-hand side of an assignment.  This is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
     * used for implementing the assignment operators and the increment and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
     * decrement operators on private fields that are accessed from another
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
     * class, e.g, uplevel from an inner class. Returns null if no access
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
     * method is needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
     * Must be called after 'checkValue', else 'right' will be invalid.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
    public FieldUpdater getUpdater(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
        if (field == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            // Field can legitimately be null if the field name was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
            // undefined, in which case an error was reported, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
            // no value for 'field' is available.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
            //   throw new CompilerError("getUpdater");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
        ClassDefinition abase = accessBase(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
        if (abase != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
            MemberDefinition getter = abase.getAccessMember(env, ctx, field, isQualSuper());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
            MemberDefinition setter = abase.getUpdateMember(env, ctx, field, isQualSuper());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
            // It may not be necessary to copy 'right' here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
            Expression base = (right == null) ? null : right.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
            return new FieldUpdater(where, field, base, getter, setter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
     * This field expression is an inner class reference.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
     * Finish checking it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
    private Vset checkInnerClass(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
                                 Vset vset, Hashtable exp,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
                                 UnaryExpression loc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
        ClassDefinition inner = field.getInnerClass();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
        type = inner.getType();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
        if (!inner.isTopLevel()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
            env.error(where, "inner.static.ref", inner.getName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
        Expression te = new TypeExpression(where, type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
        // check access
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
        ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
            if (!ctxClass.canAccess(env, field)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
                ClassDefinition clazz = env.getClassDefinition(right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
                //env.error(where, "no.type.access",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
                //          id, clazz, ctx.field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
                env.error(where, "no.type.access",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
                          id, clazz, ctxClass.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
            if (field.isProtected()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
                && !(right instanceof SuperExpression
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
                     // Extension of JLS 6.6.2 for qualified 'super'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
                     || (right instanceof FieldExpression &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
                         ((FieldExpression)right).id == idSuper))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
                && !ctxClass.protectedAccess(env, field, right.type)){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
                env.error(where, "invalid.protected.field.use",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
                          field.getName(), field.getClassDeclaration(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
                          right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
                return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
            inner.noteUsedBy(ctxClass, where, env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
        } catch (ClassNotFound e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
            env.error(where, "class.not.found", e.name, ctx.field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
        ctxClass.addDependency(field.getClassDeclaration());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
        if (loc == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
            // Complain about a free-floating type name.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
            return te.checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
        loc.right = te;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
     * Check the expression if it appears on the LHS of an assignment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
    public Vset checkLHS(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
                         Vset vset, Hashtable exp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
        boolean hadField = (field != null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
        //checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
        checkCommon(env, ctx, vset, exp, null, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
        // If 'implementation' is set to a non-null value, then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
        // field expression does not denote an assignable location,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
        // e.g., the 'length' field of an array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        if (implementation != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
            // This just reports an error and recovers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
            return super.checkLHS(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
        if (field != null && field.isFinal() && !hadField) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
            if (field.isBlankFinal()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
                if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
                    if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
                        env.error(where, "qualified.static.final.assign");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
                    // Continue with checking anyhow.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
                    // In fact, it would be easy to allow this case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
                    if ((right != null) && (right.op != THIS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
                        env.error(where, "bad.qualified.final.assign", field.getName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
                        // The actual instance could be anywhere, so don't
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
                        // continue with checking the definite assignment status.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
                        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
                vset = checkFinalAssign(env, ctx, vset, where, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
                env.error(where, "assign.to.final", id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
     * Check the expression if it appears on the LHS of an op= expression
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
    public Vset checkAssignOp(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
                              Vset vset, Hashtable exp, Expression outside) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
        //checkValue(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
        checkCommon(env, ctx, vset, exp, null, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
        // If 'implementation' is set to a non-null value, then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
        // field expression does not denote an assignable location,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
        // e.g., the 'length' field of an array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
        if (implementation != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
            return super.checkLHS(env, ctx, vset, exp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
        if (field != null && field.isFinal()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
            env.error(where, "assign.to.final", id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
     * There is a simple assignment being made to the given final field.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
     * The field was named either by a simple name or by an almost-simple
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
     * expression of the form "this.v".
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
     * Check if this is a legal assignment.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
     * Blank final variables can be set in initializers or constructor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
     * bodies.  In all cases there must be definite single assignment.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
     * (All instance and instance variable initializers and each
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
     * constructor body are treated as if concatenated for the purposes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
     * of this check.  Assignment to "this.x" is treated as a definite
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
     * assignment to the simple name "x" which names the instance variable.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
    public static Vset checkFinalAssign(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
                                        Vset vset, long where,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
                                        MemberDefinition field) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
        if (field.isBlankFinal()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
            && field.getClassDefinition() == ctx.field.getClassDefinition()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
            int number = ctx.getFieldNumber(field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
            if (number >= 0 && vset.testVarUnassigned(number)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
                // definite single assignment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
                vset = vset.addVar(number);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
                // it is a blank final in this class, but not assignable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
                Identifier id = field.getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
                env.error(where, "assign.to.blank.final", id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
            // give the generic error message
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
            Identifier id = field.getName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
            env.error(where, "assign.to.final", id);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
        return vset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
    private static MemberDefinition getClassLiteralCache(Environment env,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
                                                         Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
                                                         String className,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
                                                         ClassDefinition c) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
        // Given a class name, look for a static field to cache it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
        //      className       lname
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
        //      pkg.Foo         class$pkg$Foo
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
        //      [Lpkg.Foo;      array$Lpkg$Foo
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
        //      [[Lpkg.Foo;     array$$Lpkg$Foo
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
        //      [I              array$I
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
        //      [[I             array$$I
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
        String lname;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
        if (!className.startsWith(SIG_ARRAY)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
            lname = prefixClass + className.replace('.', '$');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
            lname = prefixArray + className.substring(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
            lname = lname.replace(SIGC_ARRAY, '$'); // [[[I => array$$$I
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
            if (className.endsWith(SIG_ENDCLASS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
                // [Lpkg.Foo; => array$Lpkg$Foo
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
                lname = lname.substring(0, lname.length() - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
                lname = lname.replace('.', '$');
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
            // else [I => array$I or some such; lname is already OK
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
        Identifier fname = Identifier.lookup(lname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
        // The class to put the cache in is now given as an argument.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
        // ClassDefinition c = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
        // while (c.isInnerClass()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
        //     c = c.getOuterClass();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
        MemberDefinition cfld;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
            cfld = c.getVariable(env, fname, c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
        } catch (ClassNotFound ee) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
        } catch (AmbiguousMember ee) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
        // Ignore inherited field.  Each top-level class
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
        // containing a given class literal must have its own copy,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
        // both for reasons of binary compatibility and to prevent
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
        // access violations should the superclass be in another
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
        // package.  Part of fix 4106051.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
        if (cfld != null && cfld.getClassDefinition() == c) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
            return cfld;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
        // Since each class now has its own copy, we might as well
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
        // tighten up the access to private (previously default).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
        // Part of fix for 4106051.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
        // ** Temporarily retract this, as it tickles 4098316.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
        return env.makeMemberDefinition(env, c.getWhere(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
                                        c, null,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
                                        M_STATIC | M_SYNTHETIC, // M_PRIVATE,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
                                        Type.tClassDesc, fname,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
                                        null, null, null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
    private Expression makeClassLiteralCacheRef(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
                                                MemberDefinition lookup,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
                                                MemberDefinition cfld,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
                                                String className) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
        Expression ccls = new TypeExpression(where,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
                                             cfld.getClassDefinition()
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
                                             .getType());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
        Expression cache = new FieldExpression(where, ccls, cfld);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
        Expression cacheOK =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
            new NotEqualExpression(where, cache.copyInline(ctx),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
                                   new NullExpression(where));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
        Expression lcls =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
            new TypeExpression(where, lookup.getClassDefinition() .getType());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
        Expression name = new StringExpression(where, className);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
        Expression namearg[] = { name };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
        Expression setCache = new MethodExpression(where, lcls,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
                                                   lookup, namearg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
        setCache = new AssignExpression(where, cache.copyInline(ctx),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
                                        setCache);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
        return new ConditionalExpression(where, cacheOK, cache, setCache);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
    private Expression makeClassLiteralInlineRef(Environment env, Context ctx,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
                                                 MemberDefinition lookup,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
                                                 String className) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
        Expression lcls =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
            new TypeExpression(where, lookup.getClassDefinition().getType());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
        Expression name = new StringExpression(where, className);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
        Expression namearg[] = { name };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
        Expression getClass = new MethodExpression(where, lcls,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
                                                   lookup, namearg);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
        return getClass;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
     * Check if constant:  Will it inline away?
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
    public boolean isConstant() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
            return implementation.isConstant();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
        if ((field != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
            && (right == null || right instanceof TypeExpression
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
                || (right.op == THIS && right.where == where))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
            return field.isConstant();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
     * Inline
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
    public Expression inline(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
            return implementation.inline(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
        // A field expression may have the side effect of causing
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
        // a NullPointerException, so evaluate it even though
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
        // the value is not needed.  Similarly, static field dereferences
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
        // may cause class initialization, so they mustn't be omitted
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
        // either.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
        //
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
        // However, NullPointerException can't happen and initialization must
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 5506
diff changeset
  1124
        // already have occurred if you are dotting into 'this'.  So
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
        // allow fields of 'this' to be eliminated as a special case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
        Expression e = inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
        if (e instanceof FieldExpression) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
            FieldExpression fe = (FieldExpression) e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
            if ((fe.right != null) && (fe.right.op==THIS))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
            // It should be possible to split this into two checks: one using
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
            // isNonNull() for non-statics and a different check for statics.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
            // That would make the inlining slightly less conservative by
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
            // allowing, for example, dotting into String constants.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
        return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
    public Expression inlineValue(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
            return implementation.inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
            if (field == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
                return this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
            if (field.isFinal()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
                Expression e = (Expression)field.getValue(env);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
                if ((e != null) && e.isConstant()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
                    // remove bogus line-number info
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
                    e = e.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
                    e.where = where;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
                    return new CommaExpression(where, right, e).inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
            if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
                if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
                    Expression e = right.inline(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
                    right = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
                    if (e != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
                        return new CommaExpression(where, e, this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
                    right = right.inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
            return this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
        } catch (ClassNotFound e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
            throw new CompilerError(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
    public Expression inlineLHS(Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
            return implementation.inlineLHS(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
        if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
            if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
                Expression e = right.inline(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
                right = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
                if (e != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
                    return new CommaExpression(where, e, this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
                right = right.inlineValue(env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
        return this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
    public Expression copyInline(Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
            return implementation.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
        return super.copyInline(ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
     * The cost of inlining this expression
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
    public int costInline(int thresh, Environment env, Context ctx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
            return implementation.costInline(thresh, env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
        if (ctx == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
            return 3 + ((right == null) ? 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
                                        : right.costInline(thresh, env, ctx));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
        // ctxClass is the current class trying to inline this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
        ClassDefinition ctxClass = ctx.field.getClassDefinition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
            // We only allow the inlining if the current class can access
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
            // the field, the field's class, and right's declared type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
            if (    ctxClass.permitInlinedAccess(env, field.getClassDeclaration())
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
                 && ctxClass.permitInlinedAccess(env, field)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
                if (right == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
                    return 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
                    ClassDeclaration rt = env.getClassDeclaration(right.type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
                    if (ctxClass.permitInlinedAccess(env, rt)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
                        return 3 + right.costInline(thresh, env, ctx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
        } catch (ClassNotFound e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
        return thresh;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
     * Code
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
    int codeLValue(Environment env, Context ctx, Assembler asm) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
        if (implementation != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
            throw new CompilerError("codeLValue");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
        if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
            if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
                right.code(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
                return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
        right.codeValue(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
        return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
    void codeLoad(Environment env, Context ctx, Assembler asm) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
        if (field == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
            throw new CompilerError("should not be null");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
        if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
            asm.add(where, opc_getstatic, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
            asm.add(where, opc_getfield, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
    void codeStore(Environment env, Context ctx, Assembler asm) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
        if (field.isStatic()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
            asm.add(where, opc_putstatic, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
            asm.add(where, opc_putfield, field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
    public void codeValue(Environment env, Context ctx, Assembler asm) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
        codeLValue(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
        codeLoad(env, ctx, asm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
     * Print
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
    public void print(PrintStream out) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
        out.print("(");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
        if (right != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1272
            right.print(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
            out.print("<empty>");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
        out.print("." + id + ")");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
        if (implementation != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
            out.print("/IMPL=");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
            implementation.print(out);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
}