1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2003 IBM Corporation and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v1.0
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v10.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.compiler.ast;
 
  13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
 
  14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
 
  15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
 
  16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
 
  17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
 
  18 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
 
  19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
 
  20 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
 
  21 import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
 
  22 import net.sourceforge.phpdt.internal.compiler.lookup.ProblemFieldBinding;
 
  23 import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReferenceBinding;
 
  24 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
 
  25 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
 
  26 import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
 
  28 public class SingleNameReference extends NameReference implements OperatorIds {
 
  31         public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write
 
  34         public static final int READ = 0;
 
  36         public static final int WRITE = 1;
 
  38         public SingleNameReference(char[] source, long pos) {
 
  41                 sourceStart = (int) (pos >>> 32);
 
  42                 sourceEnd = (int) pos;
 
  45         public FlowInfo analyseAssignment(BlockScope currentScope,
 
  46                         FlowContext flowContext, FlowInfo flowInfo, Assignment assignment,
 
  49                 // compound assignment extra work
 
  50                 if (isCompound) { // check the variable part is initialized if blank
 
  52                         switch (bits & RestrictiveFlagMASK) {
 
  53                         case FIELD: // reading a field
 
  54                                 FieldBinding fieldBinding;
 
  55                                 if ((fieldBinding = (FieldBinding) binding).isBlankFinal()
 
  57                                                                 .allowBlankFinalFieldAssignment(fieldBinding)) {
 
  58                                         if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
 
  59                                                 currentScope.problemReporter()
 
  60                                                                 .uninitializedBlankFinalField(fieldBinding,
 
  64                                 manageSyntheticReadAccessIfNecessary(currentScope);
 
  66                         // case LOCAL : // reading a local variable
 
  67                         // // check if assigning a final blank field
 
  68                         // LocalVariableBinding localBinding;
 
  69                         // if (!flowInfo.isDefinitelyAssigned(localBinding =
 
  70                         // (LocalVariableBinding) binding)) {
 
  71                         // currentScope.problemReporter().uninitializedLocalVariable(localBinding,
 
  73                         // // we could improve error msg here telling "cannot use compound
 
  74                         // assignment on final local variable"
 
  76                         // if (flowInfo.isReachable()) {
 
  77                         // localBinding.useFlag = LocalVariableBinding.USED;
 
  78                         // } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
 
  79                         // localBinding.useFlag = LocalVariableBinding.FAKE_USED;
 
  83                 if (assignment.expression != null) {
 
  84                         flowInfo = assignment.expression.analyseCode(currentScope,
 
  85                                         flowContext, flowInfo).unconditionalInits();
 
  87                 switch (bits & RestrictiveFlagMASK) {
 
  88                 case FIELD: // assigning to a field
 
  89                         manageSyntheticWriteAccessIfNecessary(currentScope);
 
  91                         // check if assigning a final field
 
  92                         FieldBinding fieldBinding;
 
  93                         if ((fieldBinding = (FieldBinding) binding).isFinal()) {
 
  94                                 // inside a context where allowed
 
  96                                                 && fieldBinding.isBlankFinal()
 
  98                                                                 .allowBlankFinalFieldAssignment(fieldBinding)) {
 
  99                                         if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
 
 100                                                 currentScope.problemReporter()
 
 101                                                                 .duplicateInitializationOfBlankFinalField(
 
 104                                                 flowContext.recordSettingFinal(fieldBinding, this);
 
 106                                         flowInfo.markAsDefinitelyAssigned(fieldBinding);
 
 108                                         currentScope.problemReporter().cannotAssignToFinalField(
 
 113                 case LOCAL: // assigning to a local variable
 
 114                         LocalVariableBinding localBinding = (LocalVariableBinding) binding;
 
 115                         if (!flowInfo.isDefinitelyAssigned(localBinding)) {// for local
 
 119                                 bits |= FirstAssignmentToLocalMASK;
 
 121                                 bits &= ~FirstAssignmentToLocalMASK;
 
 123                         if (localBinding.isFinal()) {
 
 124                                 if ((bits & DepthMASK) == 0) {
 
 125                                         if (isCompound || !localBinding.isBlankFinal()) {
 
 126                                                 currentScope.problemReporter()
 
 127                                                                 .cannotAssignToFinalLocal(localBinding, this);
 
 128                                         } else if (flowInfo.isPotentiallyAssigned(localBinding)) {
 
 129                                                 currentScope.problemReporter()
 
 130                                                                 .duplicateInitializationOfFinalLocal(
 
 133                                                 flowContext.recordSettingFinal(localBinding, this);
 
 136                                         currentScope.problemReporter()
 
 137                                                         .cannotAssignToFinalOuterLocal(localBinding, this);
 
 140                         flowInfo.markAsDefinitelyAssigned(localBinding);
 
 142                 manageEnclosingInstanceAccessIfNecessary(currentScope);
 
 146         public FlowInfo analyseCode(BlockScope currentScope,
 
 147                         FlowContext flowContext, FlowInfo flowInfo) {
 
 148                 return analyseCode(currentScope, flowContext, flowInfo, true);
 
 151         public FlowInfo analyseCode(BlockScope currentScope,
 
 152                         FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
 
 154                 switch (bits & RestrictiveFlagMASK) {
 
 155                 case FIELD: // reading a field
 
 157                                 manageSyntheticReadAccessIfNecessary(currentScope);
 
 159                         // check if reading a final blank field
 
 160                         FieldBinding fieldBinding;
 
 161                         if ((fieldBinding = (FieldBinding) binding).isBlankFinal()
 
 163                                                         .allowBlankFinalFieldAssignment(fieldBinding)) {
 
 164                                 if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
 
 165                                         currentScope.problemReporter()
 
 166                                                         .uninitializedBlankFinalField(fieldBinding, this);
 
 170                 // case LOCAL : // reading a local variable
 
 171                 // LocalVariableBinding localBinding;
 
 172                 // if (!flowInfo.isDefinitelyAssigned(localBinding =
 
 173                 // (LocalVariableBinding) binding)) {
 
 174                 // currentScope.problemReporter().uninitializedLocalVariable(localBinding,
 
 177                 // if (flowInfo.isReachable()) {
 
 178                 // localBinding.useFlag = LocalVariableBinding.USED;
 
 179                 // } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
 
 180                 // localBinding.useFlag = LocalVariableBinding.FAKE_USED;
 
 184                         manageEnclosingInstanceAccessIfNecessary(currentScope);
 
 189         public TypeBinding checkFieldAccess(BlockScope scope) {
 
 191                 FieldBinding fieldBinding = (FieldBinding) binding;
 
 193                 bits &= ~RestrictiveFlagMASK; // clear bits
 
 195                 if (!((FieldBinding) binding).isStatic()) {
 
 196                         // must check for the static status....
 
 197                         if (scope.methodScope().isStatic) {
 
 198                                 scope.problemReporter().staticFieldAccessToNonStaticVariable(
 
 200                                 constant = NotAConstant;
 
 201                                 return fieldBinding.type;
 
 204                 constant = FieldReference.getConstantFor(fieldBinding, this, true,
 
 207                 if (isFieldUseDeprecated(fieldBinding, scope))
 
 208                         scope.problemReporter().deprecatedField(fieldBinding, this);
 
 210                 MethodScope ms = scope.methodScope();
 
 211                 if ((this.bits & IsStrictlyAssignedMASK) == 0
 
 212                                 && ms.enclosingSourceType() == fieldBinding.declaringClass
 
 213                                 && ms.fieldDeclarationIndex != MethodScope.NotInFieldDecl
 
 214                                 && fieldBinding.id >= ms.fieldDeclarationIndex) {
 
 215                         // if the field is static and ms is not .... then it is valid
 
 216                         if (!fieldBinding.isStatic() || ms.isStatic)
 
 217                                 scope.problemReporter().forwardReference(this, 0,
 
 218                                                 scope.enclosingSourceType());
 
 220                 // ====================================================
 
 222                 return fieldBinding.type;
 
 226         // public void generateAssignment(BlockScope currentScope, CodeStream
 
 227         // codeStream, Assignment assignment, boolean valueRequired) {
 
 229         // // optimizing assignment like: i = i + 1 or i = 1 + i
 
 230         // if (assignment.expression.isCompactableOperation()) {
 
 231         // BinaryExpression operation = (BinaryExpression) assignment.expression;
 
 232         // SingleNameReference variableReference;
 
 233         // if ((operation.left instanceof SingleNameReference) &&
 
 234         // ((variableReference = (SingleNameReference) operation.left).binding ==
 
 236         // // i = i + value, then use the variable on the right hand side, since it
 
 237         // has the correct implicit conversion
 
 238         // variableReference.generateCompoundAssignment(currentScope, codeStream,
 
 239         // syntheticAccessors == null ? null : syntheticAccessors[WRITE],
 
 240         // operation.right, (operation.bits & OperatorMASK) >> OperatorSHIFT,
 
 241         // operation.left.implicitConversion /*should be equivalent to no
 
 242         // conversion*/, valueRequired);
 
 245         // int operator = (operation.bits & OperatorMASK) >> OperatorSHIFT;
 
 246         // if ((operation.right instanceof SingleNameReference)
 
 247         // && ((operator == PLUS) || (operator == MULTIPLY)) // only commutative
 
 249         // && ((variableReference = (SingleNameReference) operation.right).binding
 
 251         // && (operation.left.constant != NotAConstant) // exclude non constant
 
 252         // expressions, since could have side-effect
 
 253         // && ((operation.left.implicitConversion >> 4) != T_String) // exclude
 
 254         // string concatenation which would occur backwards
 
 255         // && ((operation.right.implicitConversion >> 4) != T_String)) { // exclude
 
 256         // string concatenation which would occur backwards
 
 257         // // i = value + i, then use the variable on the right hand side, since it
 
 258         // has the correct implicit conversion
 
 259         // variableReference.generateCompoundAssignment(currentScope, codeStream,
 
 260         // syntheticAccessors == null ? null : syntheticAccessors[WRITE],
 
 261         // operation.left, operator, operation.right.implicitConversion /*should be
 
 262         // equivalent to no conversion*/, valueRequired);
 
 266         // switch (bits & RestrictiveFlagMASK) {
 
 267         // case FIELD : // assigning to a field
 
 268         // FieldBinding fieldBinding;
 
 269         // if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { //
 
 271         // if ((bits & DepthMASK) != 0) {
 
 272         // ReferenceBinding targetType =
 
 273         // currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >>
 
 275         // Object[] emulationPath = currentScope.getEmulationPath(targetType, true
 
 276         // /*only exact match*/, false/*consider enclosing arg*/);
 
 277         // codeStream.generateOuterAccess(emulationPath, this, targetType,
 
 280         // this.generateReceiver(codeStream);
 
 283         // assignment.expression.generateCode(currentScope, codeStream, true);
 
 284         // fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null :
 
 285         // syntheticAccessors[WRITE], valueRequired);
 
 286         // if (valueRequired) {
 
 287         // codeStream.generateImplicitConversion(assignment.implicitConversion);
 
 290         // case LOCAL : // assigning to a local variable
 
 291         // LocalVariableBinding localBinding = (LocalVariableBinding)
 
 292         // this.codegenBinding;
 
 293         // if (localBinding.resolvedPosition != -1) {
 
 294         // assignment.expression.generateCode(currentScope, codeStream, true);
 
 296         // if (assignment.expression.constant != NotAConstant) {
 
 297         // // assigning an unused local to a constant value = no actual assignment
 
 299         // if (valueRequired) {
 
 300         // codeStream.generateConstant(assignment.expression.constant,
 
 301         // assignment.implicitConversion);
 
 304         // assignment.expression.generateCode(currentScope, codeStream, true);
 
 305         // /* Even though the value may not be required, we force it to be produced,
 
 306         // and discard it later
 
 307         // on if it was actually not necessary, so as to provide the same behavior
 
 308         // as JDK1.2beta3. */
 
 309         // if (valueRequired) {
 
 310         // codeStream.generateImplicitConversion(assignment.implicitConversion); //
 
 311         // implicit conversion
 
 313         // if ((localBinding.type == LongBinding) || (localBinding.type ==
 
 315         // codeStream.pop2();
 
 323         // // 26903, need extra cast to store null in array local var
 
 324         // if (localBinding.type.isArrayType()
 
 325         // && (assignment.expression.resolvedType == NullBinding // arrayLoc = null
 
 326         // || ((assignment.expression instanceof CastExpression) // arrayLoc =
 
 329         // (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType
 
 330         // == NullBinding)))){
 
 331         // codeStream.checkcast(localBinding.type);
 
 334         // // normal local assignment (since cannot store in outer local which are
 
 336         // codeStream.store(localBinding, valueRequired);
 
 337         // if ((bits & FirstAssignmentToLocalMASK) != 0) { // for local variable
 
 339         // localBinding.recordInitializationStartPC(codeStream.position);
 
 341         // // implicit conversion
 
 342         // if (valueRequired) {
 
 343         // codeStream.generateImplicitConversion(assignment.implicitConversion);
 
 347         // public void generateCode(BlockScope currentScope, CodeStream codeStream,
 
 348         // boolean valueRequired) {
 
 349         // int pc = codeStream.position;
 
 350         // if (constant != NotAConstant) {
 
 351         // if (valueRequired) {
 
 352         // codeStream.generateConstant(constant, implicitConversion);
 
 355         // switch (bits & RestrictiveFlagMASK) {
 
 356         // case FIELD : // reading a field
 
 357         // FieldBinding fieldBinding;
 
 358         // if (valueRequired) {
 
 359         // if ((fieldBinding = (FieldBinding) this.codegenBinding).constant ==
 
 360         // NotAConstant) { // directly use inlined value for constant fields
 
 362         // if (!(isStatic = fieldBinding.isStatic())) {
 
 363         // if ((bits & DepthMASK) != 0) {
 
 364         // ReferenceBinding targetType =
 
 365         // currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >>
 
 367         // Object[] emulationPath = currentScope.getEmulationPath(targetType, true
 
 368         // /*only exact match*/, false/*consider enclosing arg*/);
 
 369         // codeStream.generateOuterAccess(emulationPath, this, targetType,
 
 372         // generateReceiver(codeStream);
 
 375         // // managing private access
 
 376         // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
 
 378         // codeStream.getstatic(fieldBinding);
 
 380         // codeStream.getfield(fieldBinding);
 
 383         // codeStream.invokestatic(syntheticAccessors[READ]);
 
 385         // codeStream.generateImplicitConversion(implicitConversion);
 
 386         // } else { // directly use the inlined value
 
 387         // codeStream.generateConstant(fieldBinding.constant, implicitConversion);
 
 391         // case LOCAL : // reading a local
 
 392         // LocalVariableBinding localBinding = (LocalVariableBinding)
 
 393         // this.codegenBinding;
 
 394         // if (valueRequired) {
 
 396         // if ((bits & DepthMASK) != 0) {
 
 397         // // outer local can be reached either through a synthetic arg or a
 
 399         // VariableBinding[] path = currentScope.getEmulationPath(localBinding);
 
 400         // codeStream.generateOuterAccess(path, this, localBinding, currentScope);
 
 402         // // regular local variable read
 
 403         // codeStream.load(localBinding);
 
 405         // codeStream.generateImplicitConversion(implicitConversion);
 
 409         // codeStream.recordPositionsFrom(pc, this.sourceStart);
 
 412         // * Regular API for compound assignment, relies on the fact that there is
 
 413         // only one reference to the
 
 414         // * variable, which carries both synthetic read/write accessors.
 
 415         // * The APIs with an extra argument is used whenever there are two
 
 416         // references to the same variable which
 
 417         // * are optimized in one access: e.g "a = a + 1" optimized into "a++".
 
 419         // public void generateCompoundAssignment(BlockScope currentScope,
 
 420         // CodeStream codeStream, Expression expression, int operator, int
 
 421         // assignmentImplicitConversion, boolean valueRequired) {
 
 423         // this.generateCompoundAssignment(
 
 426         // syntheticAccessors == null ? null : syntheticAccessors[WRITE],
 
 429         // assignmentImplicitConversion,
 
 433         // * The APIs with an extra argument is used whenever there are two
 
 434         // references to the same variable which
 
 435         // * are optimized in one access: e.g "a = a + 1" optimized into "a++".
 
 437         // public void generateCompoundAssignment(BlockScope currentScope,
 
 438         // CodeStream codeStream, MethodBinding writeAccessor, Expression
 
 439         // expression, int operator, int assignmentImplicitConversion, boolean
 
 441         // switch (bits & RestrictiveFlagMASK) {
 
 442         // case FIELD : // assigning to a field
 
 443         // FieldBinding fieldBinding;
 
 444         // if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
 
 445         // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
 
 446         // codeStream.getstatic(fieldBinding);
 
 448         // codeStream.invokestatic(syntheticAccessors[READ]);
 
 451         // if ((bits & DepthMASK) != 0) {
 
 452         // ReferenceBinding targetType =
 
 453         // currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >>
 
 455         // Object[] emulationPath = currentScope.getEmulationPath(targetType, true
 
 456         // /*only exact match*/, false/*consider enclosing arg*/);
 
 457         // codeStream.generateOuterAccess(emulationPath, this, targetType,
 
 460         // codeStream.aload_0();
 
 463         // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
 
 464         // codeStream.getfield(fieldBinding);
 
 466         // codeStream.invokestatic(syntheticAccessors[READ]);
 
 470         // case LOCAL : // assigning to a local variable (cannot assign to outer
 
 472         // LocalVariableBinding localBinding = (LocalVariableBinding)
 
 473         // this.codegenBinding;
 
 474         // Constant assignConstant;
 
 476         // // using incr bytecode if possible
 
 477         // switch (localBinding.type.id) {
 
 479         // codeStream.generateStringAppend(currentScope, this, expression);
 
 480         // if (valueRequired) {
 
 483         // codeStream.store(localBinding, false);
 
 486         // if (((assignConstant = expression.constant) != NotAConstant)
 
 487         // && (assignConstant.typeID() != T_float) // only for integral types
 
 488         // && (assignConstant.typeID() != T_double)
 
 489         // && ((increment = assignConstant.intValue()) == (short) increment)) { //
 
 491         // switch (operator) {
 
 493         // codeStream.iinc(localBinding.resolvedPosition, increment);
 
 494         // if (valueRequired) {
 
 495         // codeStream.load(localBinding);
 
 499         // codeStream.iinc(localBinding.resolvedPosition, -increment);
 
 500         // if (valueRequired) {
 
 501         // codeStream.load(localBinding);
 
 507         // codeStream.load(localBinding);
 
 510         // // perform the actual compound operation
 
 511         // int operationTypeID;
 
 512         // if ((operationTypeID = implicitConversion >> 4) == T_String ||
 
 513         // operationTypeID == T_Object) {
 
 514         // // we enter here if the single name reference is a field of type
 
 515         // java.lang.String or if the type of the
 
 516         // // operation is java.lang.Object
 
 517         // // For example: o = o + ""; // where the compiled type of o is
 
 519         // codeStream.generateStringAppend(currentScope, null, expression);
 
 521         // // promote the array reference to the suitable operation type
 
 522         // codeStream.generateImplicitConversion(implicitConversion);
 
 523         // // generate the increment value (will by itself be promoted to the
 
 525         // if (expression == IntLiteral.One){ // prefix operation
 
 526         // codeStream.generateConstant(expression.constant, implicitConversion);
 
 528         // expression.generateCode(currentScope, codeStream, true);
 
 530         // // perform the operation
 
 531         // codeStream.sendOperator(operator, operationTypeID);
 
 532         // // cast the value back to the array reference type
 
 533         // codeStream.generateImplicitConversion(assignmentImplicitConversion);
 
 535         // // store the result back into the variable
 
 536         // switch (bits & RestrictiveFlagMASK) {
 
 537         // case FIELD : // assigning to a field
 
 538         // fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor,
 
 541         // case LOCAL : // assigning to a local variable
 
 542         // LocalVariableBinding localBinding = (LocalVariableBinding)
 
 543         // this.codegenBinding;
 
 544         // if (valueRequired) {
 
 545         // if ((localBinding.type == LongBinding) || (localBinding.type ==
 
 547         // codeStream.dup2();
 
 552         // codeStream.store(localBinding, false);
 
 555         // public void generatePostIncrement(BlockScope currentScope, CodeStream
 
 556         // codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
 
 557         // switch (bits & RestrictiveFlagMASK) {
 
 558         // case FIELD : // assigning to a field
 
 559         // FieldBinding fieldBinding;
 
 560         // if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
 
 561         // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
 
 562         // codeStream.getstatic(fieldBinding);
 
 564         // codeStream.invokestatic(syntheticAccessors[READ]);
 
 567         // if ((bits & DepthMASK) != 0) {
 
 568         // ReferenceBinding targetType =
 
 569         // currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >>
 
 571         // Object[] emulationPath = currentScope.getEmulationPath(targetType, true
 
 572         // /*only exact match*/, false/*consider enclosing arg*/);
 
 573         // codeStream.generateOuterAccess(emulationPath, this, targetType,
 
 576         // codeStream.aload_0();
 
 579         // if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
 
 580         // codeStream.getfield(fieldBinding);
 
 582         // codeStream.invokestatic(syntheticAccessors[READ]);
 
 585         // if (valueRequired) {
 
 586         // if (fieldBinding.isStatic()) {
 
 587         // if ((fieldBinding.type == LongBinding) || (fieldBinding.type ==
 
 589         // codeStream.dup2();
 
 593         // } else { // Stack: [owner][old field value] ---> [old field
 
 594         // value][owner][old field value]
 
 595         // if ((fieldBinding.type == LongBinding) || (fieldBinding.type ==
 
 597         // codeStream.dup2_x1();
 
 599         // codeStream.dup_x1();
 
 603         // codeStream.generateConstant(postIncrement.expression.constant,
 
 604         // implicitConversion);
 
 605         // codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
 
 606         // codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 
 607         // fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null :
 
 608         // syntheticAccessors[WRITE], false);
 
 610         // case LOCAL : // assigning to a local variable
 
 611         // LocalVariableBinding localBinding = (LocalVariableBinding)
 
 612         // this.codegenBinding;
 
 613         // // using incr bytecode if possible
 
 614         // if (localBinding.type == IntBinding) {
 
 615         // if (valueRequired) {
 
 616         // codeStream.load(localBinding);
 
 618         // if (postIncrement.operator == PLUS) {
 
 619         // codeStream.iinc(localBinding.resolvedPosition, 1);
 
 621         // codeStream.iinc(localBinding.resolvedPosition, -1);
 
 624         // codeStream.load(localBinding);
 
 625         // if (valueRequired){
 
 626         // if ((localBinding.type == LongBinding) || (localBinding.type ==
 
 628         // codeStream.dup2();
 
 633         // codeStream.generateConstant(postIncrement.expression.constant,
 
 634         // implicitConversion);
 
 635         // codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
 
 636         // codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 
 638         // codeStream.store(localBinding, false);
 
 642         // public void generateReceiver(CodeStream codeStream) {
 
 643         // codeStream.aload_0();
 
 645         public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
 
 647                 // If inlinable field, forget the access emulation, the code gen will
 
 648                 // directly target it
 
 649                 if (((bits & DepthMASK) == 0) || (constant != NotAConstant))
 
 652                 if ((bits & RestrictiveFlagMASK) == LOCAL) {
 
 653                         currentScope.emulateOuterAccess((LocalVariableBinding) binding);
 
 657         public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope) {
 
 659                 // If inlinable field, forget the access emulation, the code gen will
 
 660                 // directly target it
 
 661                 if (constant != NotAConstant)
 
 664                 if ((bits & FIELD) != 0) {
 
 665                         FieldBinding fieldBinding = (FieldBinding) binding;
 
 666                         if (((bits & DepthMASK) != 0) && (fieldBinding.isPrivate() // private
 
 668                                         || (fieldBinding.isProtected() // implicit protected access
 
 669                                         && fieldBinding.declaringClass.getPackage() != currentScope
 
 670                                                         .enclosingSourceType().getPackage()))) {
 
 671                                 if (syntheticAccessors == null)
 
 672                                         syntheticAccessors = new MethodBinding[2];
 
 673                                 syntheticAccessors[READ] = ((SourceTypeBinding) currentScope
 
 674                                                 .enclosingSourceType().enclosingTypeAt(
 
 675                                                                 (bits & DepthMASK) >> DepthSHIFT))
 
 676                                                 .addSyntheticMethod(fieldBinding, true);
 
 677                                 currentScope.problemReporter().needToEmulateFieldReadAccess(
 
 681                         // if the binding declaring class is not visible, need special
 
 683                         // for runtime compatibility on 1.2 VMs : change the declaring class
 
 685                         // NOTE: from target 1.2 on, field's declaring class is touched if
 
 686                         // any different from receiver type
 
 687                         // and not from Object or implicit static field access.
 
 688                         // if (fieldBinding.declaringClass != this.actualReceiverType
 
 689                         // && !this.actualReceiverType.isArrayType()
 
 690                         // && fieldBinding.declaringClass != null
 
 691                         // && fieldBinding.constant == NotAConstant
 
 692                         // && ((currentScope.environment().options.targetJDK >=
 
 693                         // CompilerOptions.JDK1_2
 
 694                         // && !fieldBinding.isStatic()
 
 695                         // && fieldBinding.declaringClass.id != T_Object) // no change for
 
 696                         // Object fields (if there was any)
 
 697                         // || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
 
 698                         // this.codegenBinding =
 
 699                         // currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding,
 
 700                         // (ReferenceBinding)this.actualReceiverType);
 
 705         public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope) {
 
 707                 if ((bits & FIELD) != 0) {
 
 708                         FieldBinding fieldBinding = (FieldBinding) binding;
 
 709                         if (((bits & DepthMASK) != 0) && (fieldBinding.isPrivate() // private
 
 711                                         || (fieldBinding.isProtected() // implicit protected access
 
 712                                         && fieldBinding.declaringClass.getPackage() != currentScope
 
 713                                                         .enclosingSourceType().getPackage()))) {
 
 714                                 if (syntheticAccessors == null)
 
 715                                         syntheticAccessors = new MethodBinding[2];
 
 716                                 syntheticAccessors[WRITE] = ((SourceTypeBinding) currentScope
 
 717                                                 .enclosingSourceType().enclosingTypeAt(
 
 718                                                                 (bits & DepthMASK) >> DepthSHIFT))
 
 719                                                 .addSyntheticMethod(fieldBinding, false);
 
 720                                 currentScope.problemReporter().needToEmulateFieldWriteAccess(
 
 724                         // if the binding declaring class is not visible, need special
 
 726                         // for runtime compatibility on 1.2 VMs : change the declaring class
 
 728                         // NOTE: from target 1.2 on, field's declaring class is touched if
 
 729                         // any different from receiver type
 
 730                         // and not from Object or implicit static field access.
 
 731                         // if (fieldBinding.declaringClass != this.actualReceiverType
 
 732                         // && !this.actualReceiverType.isArrayType()
 
 733                         // && fieldBinding.declaringClass != null
 
 734                         // && fieldBinding.constant == NotAConstant
 
 735                         // && ((currentScope.environment().options.targetJDK >=
 
 736                         // CompilerOptions.JDK1_2
 
 737                         // && !fieldBinding.isStatic()
 
 738                         // && fieldBinding.declaringClass.id != T_Object) // no change for
 
 739                         // Object fields (if there was any)
 
 740                         // || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
 
 741                         // this.codegenBinding =
 
 742                         // currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding,
 
 743                         // (ReferenceBinding)this.actualReceiverType);
 
 748         public TypeBinding reportError(BlockScope scope) {
 
 749                 // =====error cases=======
 
 750                 constant = Constant.NotAConstant;
 
 751                 if (binding instanceof ProblemFieldBinding) {
 
 752                         scope.problemReporter().invalidField(this, (FieldBinding) binding);
 
 753                 } else if (binding instanceof ProblemReferenceBinding) {
 
 754                         scope.problemReporter().invalidType(this, (TypeBinding) binding);
 
 756                         scope.problemReporter().unresolvableReference(this, binding);
 
 761         public TypeBinding resolveType(BlockScope scope) {
 
 762                 // for code gen, harm the restrictiveFlag
 
 764                 this.actualReceiverType = this.receiverType = scope
 
 765                                 .enclosingSourceType();
 
 767                 if ((this.codegenBinding = this.binding = scope.getBinding(token, bits
 
 768                                 & RestrictiveFlagMASK, this)).isValidBinding()) {
 
 769                         switch (bits & RestrictiveFlagMASK) {
 
 770                         case VARIABLE: // =========only variable============
 
 771                         case VARIABLE | TYPE: // ====both variable and type============
 
 772                                 if (binding instanceof VariableBinding) {
 
 773                                         VariableBinding variable = (VariableBinding) binding;
 
 774                                         if (binding instanceof LocalVariableBinding) {
 
 775                                                 bits &= ~RestrictiveFlagMASK; // clear bits
 
 777                                                 if ((this.bits & IsStrictlyAssignedMASK) == 0) {
 
 778                                                         constant = variable.constant;
 
 780                                                         constant = NotAConstant;
 
 782                                                 if ((!variable.isFinal()) && ((bits & DepthMASK) != 0)) {
 
 783                                                         scope.problemReporter()
 
 784                                                                         .cannotReferToNonFinalOuterLocal(
 
 785                                                                                         (LocalVariableBinding) variable,
 
 788                                                 return this.resolvedType = variable.type;
 
 791                                         return this.resolvedType = checkFieldAccess(scope);
 
 794                                 // thus it was a type
 
 795                                 bits &= ~RestrictiveFlagMASK; // clear bits
 
 797                         case TYPE: // ========only type==============
 
 798                                 constant = Constant.NotAConstant;
 
 800                                 if (isTypeUseDeprecated((TypeBinding) binding, scope))
 
 801                                         scope.problemReporter().deprecatedType(
 
 802                                                         (TypeBinding) binding, this);
 
 803                                 return this.resolvedType = (TypeBinding) binding;
 
 808                 return this.resolvedType = this.reportError(scope);
 
 811         public StringBuffer printExpression(int indent, StringBuffer output) {
 
 813                 return output.append(token);
 
 816         public String toStringExpression() {
 
 818                 return new String(token);
 
 821         public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
 
 822                 visitor.visit(this, scope);
 
 823                 visitor.endVisit(this, scope);
 
 826         public String unboundReferenceErrorName() {
 
 828                 return new String(token);