public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
    if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) {
      // need assertion flag: $assertionsDisabled on outer most source clas
      // (in case of static member of interface, will use the outermost static member - bug 22334)
      SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
      while (outerMostClass.isLocalType()) {
        ReferenceBinding enclosing = outerMostClass.enclosingType();
        if (enclosing == null || enclosing.isInterface()) break;
        outerMostClass = (SourceTypeBinding) enclosing;
      }
      this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope);

      // find <clinit> and enable assertion support
      TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
      AbstractMethodDeclaration[] methods = typeDeclaration.methods;
      for (int i = 0, max = methods.length; i < max; i++) {
        AbstractMethodDeclaration method = methods[i];
        if (method.isClinit()) {
          ((Clinit) method)
              .setAssertionSupport(
                  this.assertionSyntheticFieldBinding,
                  currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5);
          break;
        }
      }
    }
  }
  public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {

    // {ObjectTeams: role class literal?
    if (this.roleClassLiteralAccess != null)
      return this.roleClassLiteralAccess.analyseCode(currentScope, flowContext, flowInfo);
    // SH}
    // if reachable, request the addition of a synthetic field for caching the class descriptor
    SourceTypeBinding sourceType = currentScope.outerMostClassScope().enclosingSourceType();
    // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=22334
    if (!sourceType.isInterface()
        && !this.targetType.isBaseType()
        && currentScope.compilerOptions().targetJDK < ClassFileConstants.JDK1_5) {
      this.syntheticField =
          sourceType.addSyntheticFieldForClassLiteral(this.targetType, currentScope);
    }
    return flowInfo;
  }
  public TypeBinding resolveType(BlockScope scope) {

    this.constant = Constant.NotAConstant;
    if ((this.targetType = this.type.resolveType(scope, true /* check bounds*/)) == null)
      return null;

    /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=320463
      https://bugs.eclipse.org/bugs/show_bug.cgi?id=312076
      JLS3 15.8.2 forbids the type named in the class literal expression from being a parameterized type.
      And the grammar in 18.1 disallows (where X and Y are some concrete types) constructs of the form
      Outer<X>.class, Outer<X>.Inner.class, Outer.Inner<X>.class, Outer<X>.Inner<Y>.class etc.
      Corollary wise, we should resolve the type of the class literal expression to be a raw type as
      class literals exist only for the raw underlying type.
    */
    LookupEnvironment environment = scope.environment();
    this.targetType =
        environment.convertToRawType(
            this.targetType, true /* force conversion of enclosing types*/);

    if (this.targetType.isArrayType()) {
      ArrayBinding arrayBinding = (ArrayBinding) this.targetType;
      TypeBinding leafComponentType = arrayBinding.leafComponentType;
      if (leafComponentType == TypeBinding.VOID) {
        scope.problemReporter().cannotAllocateVoidArray(this);
        return null;
      } else if (leafComponentType.isTypeVariable()) {
        scope
            .problemReporter()
            .illegalClassLiteralForTypeVariable((TypeVariableBinding) leafComponentType, this);
      }
    } else if (this.targetType.isTypeVariable()) {
      scope
          .problemReporter()
          .illegalClassLiteralForTypeVariable((TypeVariableBinding) this.targetType, this);
    }
    // {ObjectTeams: do we need a RoleClassLiteralAccess?
    if (this.targetType instanceof ReferenceBinding) {
      ReferenceBinding targetRef = (ReferenceBinding) this.targetType;
      if (targetRef.isRole()) {
        if (this.verbatim) {
          this.targetType =
              RoleTypeCreator.maybeWrapUnqualifiedRoleType(scope, this.targetType, this);
        } else {
          SourceTypeBinding site = scope.enclosingSourceType();
          if (scope.methodScope().isStatic // role class literal needs team instance
              && !site.isRole() // static role method are OK.
              && !RoleTypeBinding.isRoleWithExplicitAnchor(this.targetType)) // t.R.class?
          {
            scope.problemReporter().roleClassLiteralLacksTeamInstance(this, targetRef);
            return null;
          }
          ReferenceBinding teamBinding;
          if (RoleTypeBinding.isRoleWithExplicitAnchor(targetRef))
            teamBinding = targetRef.enclosingType();
          else teamBinding = TeamModel.findEnclosingTeamContainingRole(site, targetRef);
          if (teamBinding == null)
            scope.problemReporter().externalizedRoleClassLiteral(this, targetRef);
          else {
            TypeBinding methodType =
                RoleClassLiteralAccess.ensureGetClassMethod(
                    teamBinding.getTeamModel(),
                    targetRef.roleModel); // not affected by visibility check (for resilience)
            this.roleClassLiteralAccess = new RoleClassLiteralAccess(this, methodType);
            this.resolvedType = this.roleClassLiteralAccess.resolveType(scope);
          }
          return this.resolvedType;
        }
      }
    }
    // SH}
    ReferenceBinding classType = scope.getJavaLangClass();
    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=328689
    if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
      // Integer.class --> Class<Integer>, perform boxing of base types (int.class -->
      // Class<Integer>)
      TypeBinding boxedType = null;
      if (this.targetType.id == T_void) {
        boxedType = environment.getResolvedType(JAVA_LANG_VOID, scope);
      } else {
        boxedType = scope.boxing(this.targetType);
      }
      if (environment.usesNullTypeAnnotations())
        boxedType =
            environment.createAnnotatedType(
                boxedType, new AnnotationBinding[] {environment.getNonNullAnnotation()});
      this.resolvedType =
          environment.createParameterizedType(
              classType, new TypeBinding[] {boxedType}, null /*not a member*/);
    } else {
      this.resolvedType = classType;
    }
    return this.resolvedType;
  }