コード例 #1
0
  public void generatePostIncrement(
      BlockScope currentScope, CompoundAssignment postIncrement, boolean valueRequired) {
    switch (this.bits & ASTNode.RestrictiveFlagMASK) {
      case Binding.FIELD: // assigning to a field
        FieldBinding fieldBinding = (FieldBinding) this.binding;
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
        // check if postIncrement is the only usage of a private field
        reportOnlyUselesslyReadPrivateField(currentScope, fieldBinding, valueRequired);
        FieldBinding codegenField = fieldBinding.original();

        fieldStore(
            currentScope,
            codegenField,
            this.syntheticAccessors == null
                ? null
                : this.syntheticAccessors[SingleNameReference.WRITE],
            this.actualReceiverType,
            true /*implicit this*/,
            false);
        // no need for generic cast
        return;
      case Binding.LOCAL: // assigning to a local variable
        LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
        // check if postIncrement is the only usage of this local
        Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired);
        if (localBinding.resolvedPosition == -1) {
          if (valueRequired) {
            // restart code gen
            localBinding.useFlag = LocalVariableBinding.USED;
            throw new AbortMethod(null, null);
          }
        }
    }
  }
コード例 #2
0
  public void manageSyntheticAccessIfNecessary(
      BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
    if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return;

    // If inlinable field, forget the access emulation, the code gen will directly target it
    if (this.constant != Constant.NotAConstant) return;

    if ((this.bits & Binding.FIELD) != 0) {
      FieldBinding fieldBinding = (FieldBinding) this.binding;
      FieldBinding codegenField = fieldBinding.original();
      if (((this.bits & ASTNode.DepthMASK) != 0)
          && (codegenField.isPrivate() // private access
              || (codegenField.isProtected() // implicit protected access
                  && codegenField.declaringClass.getPackage()
                      != currentScope.enclosingSourceType().getPackage()))) {
        if (this.syntheticAccessors == null) this.syntheticAccessors = new MethodBinding[2];
        this.syntheticAccessors[
                isReadAccess ? SingleNameReference.READ : SingleNameReference.WRITE] =
            ((SourceTypeBinding)
                    currentScope
                        .enclosingSourceType()
                        .enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT))
                .addSyntheticMethod(codegenField, isReadAccess, false /*not super access*/);
        currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess);
        return;
      }
    }
  }
コード例 #3
0
 /**
  * @see
  *     org.eclipse.che.ide.ext.java.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.che.ide.ext.java.jdt.internal.compiler.lookup.Scope,
  *     org.eclipse.che.ide.ext.java.jdt.internal.compiler.lookup.TypeBinding,
  *     org.eclipse.che.ide.ext.java.jdt.internal.compiler.lookup .TypeBinding)
  */
 public void computeConversion(
     Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
   if (runtimeTimeType == null || compileTimeType == null) return;
   if ((this.bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) {
     // set the generic cast after the fact, once the type expectation is fully known (no need for
     // strict cast)
     FieldBinding field = (FieldBinding) this.binding;
     FieldBinding originalBinding = field.original();
     TypeBinding originalType = originalBinding.type;
     // extra cast needed if field type is type variable
     if (originalType.leafComponentType().isTypeVariable()) {
       TypeBinding targetType =
           (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType())
               ? compileTimeType
               // unboxing: checkcast before conversion
               : runtimeTimeType;
       this.genericCast = originalType.genericCast(scope.boxing(targetType));
       if (this.genericCast instanceof ReferenceBinding) {
         ReferenceBinding referenceCast = (ReferenceBinding) this.genericCast;
         if (!referenceCast.canBeSeenBy(scope)) {
           scope
               .problemReporter()
               .invalidType(
                   this,
                   new ProblemReferenceBinding(
                       CharOperation.splitOn('.', referenceCast.shortReadableName()),
                       referenceCast,
                       ProblemReasons.NotVisible));
         }
       }
     }
   }
   super.computeConversion(scope, runtimeTimeType, compileTimeType);
 }
コード例 #4
0
 public void generateCode(BlockScope currentScope, boolean valueRequired) {
   if (this.constant != Constant.NotAConstant) {
     return;
   } else {
     switch (this.bits & ASTNode.RestrictiveFlagMASK) {
       case Binding.FIELD: // reading a field
         FieldBinding codegenField = ((FieldBinding) this.binding).original();
         Constant fieldConstant = codegenField.constant();
         if (fieldConstant != Constant.NotAConstant) {
           return;
         }
         if (codegenField.isStatic()) {
           if (!valueRequired
               // if no valueRequired, still need possible side-effects of <clinit> invocation,
               // if field belongs to different class
               && ((FieldBinding) this.binding).original().declaringClass
                   == this.actualReceiverType.erasure()
               && ((this.implicitConversion & TypeIds.UNBOXING) == 0)
               && this.genericCast == null) {
             // if no valueRequired, optimize out entire gen
             return;
           }
         } else {
           if (!valueRequired
               && (this.implicitConversion & TypeIds.UNBOXING) == 0
               && this.genericCast == null) {
             // if no valueRequired, optimize out entire gen
             return;
           }
         }
         break;
       case Binding.LOCAL: // reading a local
         LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
         if (localBinding.resolvedPosition == -1) {
           if (valueRequired) {
             // restart code gen
             localBinding.useFlag = LocalVariableBinding.USED;
             throw new AbortMethod(null, null);
           }
           return;
         }
         if (!valueRequired && (this.implicitConversion & TypeIds.UNBOXING) == 0) {
           // if no valueRequired, optimize out entire gen
           return;
         }
         break;
       default: // type
         return;
     }
   }
 }
コード例 #5
0
  public TypeBinding checkFieldAccess(BlockScope scope) {
    FieldBinding fieldBinding = (FieldBinding) this.binding;
    this.constant = fieldBinding.constant();

    this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
    this.bits |= Binding.FIELD;
    MethodScope methodScope = scope.methodScope();
    if (fieldBinding.isStatic()) {
      // check if accessing enum static field in initializer
      ReferenceBinding declaringClass = fieldBinding.declaringClass;
      if (declaringClass.isEnum()) {
        SourceTypeBinding sourceType = scope.enclosingSourceType();
        if (this.constant == Constant.NotAConstant
            && !methodScope.isStatic
            && (sourceType == declaringClass
                || sourceType.superclass == declaringClass) // enum constant body
            && methodScope.isInsideInitializerOrConstructor()) {
          scope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
        }
      }
    } else {
      if (scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess)
          != ProblemSeverities.Ignore) {
        scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
      }
      // must check for the static status....
      if (methodScope.isStatic) {
        scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
        return fieldBinding.type;
      }
    }

    if (isFieldUseDeprecated(fieldBinding, scope, this.bits))
      scope.problemReporter().deprecatedField(fieldBinding, this);

    if ((this.bits & ASTNode.IsStrictlyAssigned) == 0
        && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
        && methodScope.lastVisibleFieldID >= 0
        && fieldBinding.id >= methodScope.lastVisibleFieldID
        && (!fieldBinding.isStatic() || methodScope.isStatic)) {
      scope.problemReporter().forwardReference(this, 0, fieldBinding);
      this.bits |= ASTNode.IgnoreNoEffectAssignCheck;
    }
    return fieldBinding.type;
  }
コード例 #6
0
 public FlowInfo analyseCode(
     BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
   switch (this.bits & ASTNode.RestrictiveFlagMASK) {
     case Binding.FIELD: // reading a field
       if (valueRequired
           || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
         manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
       }
       // check if reading a final blank field
       FieldBinding fieldBinding = (FieldBinding) this.binding;
       if (fieldBinding.isBlankFinal()
           && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
         FlowInfo fieldInits =
             flowContext.getInitsForFinalBlankInitializationCheck(
                 fieldBinding.declaringClass.original(), flowInfo);
         if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
           currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
         }
       }
       if (!fieldBinding.isStatic()) {
         // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
         currentScope.resetEnclosingMethodStaticFlag();
       }
       break;
     case Binding.LOCAL: // reading a local variable
       LocalVariableBinding localBinding;
       if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
         currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
       }
       if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
         localBinding.useFlag = LocalVariableBinding.USED;
       } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
         localBinding.useFlag = LocalVariableBinding.FAKE_USED;
       }
   }
   if (valueRequired) {
     manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
   }
   return flowInfo;
 }
コード例 #7
0
  public FlowInfo analyseAssignment(
      BlockScope currentScope,
      FlowContext flowContext,
      FlowInfo flowInfo,
      Assignment assignment,
      boolean isCompound) {
    boolean isReachable = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0;
    // compound assignment extra work
    if (isCompound) { // check the variable part is initialized if blank final
      switch (this.bits & ASTNode.RestrictiveFlagMASK) {
        case Binding.FIELD: // reading a field
          FieldBinding fieldBinding = (FieldBinding) this.binding;
          if (fieldBinding.isBlankFinal()
              && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
            FlowInfo fieldInits =
                flowContext.getInitsForFinalBlankInitializationCheck(
                    fieldBinding.declaringClass.original(), flowInfo);
            if (!fieldInits.isDefinitelyAssigned(fieldBinding)) {
              currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
            }
          }
          if (!fieldBinding.isStatic()) {
            // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
            currentScope.resetEnclosingMethodStaticFlag();
          }
          manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
          break;
        case Binding.LOCAL: // reading a local variable
          // check if assigning a final blank field
          LocalVariableBinding localBinding;
          if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
            currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
            // we could improve error msg here telling "cannot use compound assignment on final
            // local variable"
          }
          if (localBinding.useFlag != LocalVariableBinding.USED) {
            // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682
            // access from compound assignment does not prevent "unused" warning, unless unboxing is
            // involved:
            if (isReachable && (this.implicitConversion & TypeIds.UNBOXING) != 0) {
              localBinding.useFlag = LocalVariableBinding.USED;
            } else {
              // use values < 0 to count the number of compound uses:
              if (localBinding.useFlag <= LocalVariableBinding.UNUSED) localBinding.useFlag--;
            }
          }
      }
    }
    if (assignment.expression != null) {
      flowInfo =
          assignment
              .expression
              .analyseCode(currentScope, flowContext, flowInfo)
              .unconditionalInits();
    }
    switch (this.bits & ASTNode.RestrictiveFlagMASK) {
      case Binding.FIELD: // assigning to a field
        manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);

        // check if assigning a final field
        FieldBinding fieldBinding = (FieldBinding) this.binding;
        if (fieldBinding.isFinal()) {
          // inside a context where allowed
          if (!isCompound
              && fieldBinding.isBlankFinal()
              && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
            if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
              currentScope
                  .problemReporter()
                  .duplicateInitializationOfBlankFinalField(fieldBinding, this);
            } else {
              flowContext.recordSettingFinal(fieldBinding, this, flowInfo);
            }
            flowInfo.markAsDefinitelyAssigned(fieldBinding);
          } else {
            currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
          }
        }
        if (!fieldBinding.isStatic()) {
          // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
          currentScope.resetEnclosingMethodStaticFlag();
        }
        break;
      case Binding.LOCAL: // assigning to a local variable
        LocalVariableBinding localBinding = (LocalVariableBinding) this.binding;
        if (!flowInfo.isDefinitelyAssigned(localBinding)) { // for local variable debug attributes
          this.bits |= ASTNode.FirstAssignmentToLocal;
        } else {
          this.bits &= ~ASTNode.FirstAssignmentToLocal;
        }
        if (localBinding.isFinal()) {
          if ((this.bits & ASTNode.DepthMASK) == 0) {
            // tolerate assignment to final local in unreachable code (45674)
            if ((isReachable && isCompound) || !localBinding.isBlankFinal()) {
              currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this);
            } else if (flowInfo.isPotentiallyAssigned(localBinding)) {
              currentScope
                  .problemReporter()
                  .duplicateInitializationOfFinalLocal(localBinding, this);
            } else {
              flowContext.recordSettingFinal(localBinding, this, flowInfo);
            }
          } else {
            currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
          }
        } else /* avoid double diagnostic */ if ((localBinding.tagBits & TagBits.IsArgument) != 0) {
          currentScope.problemReporter().parameterAssignment(localBinding, this);
        }
        flowInfo.markAsDefinitelyAssigned(localBinding);
    }
    manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
    return flowInfo;
  }