/**
     * Determines the least upper bound of a1 and a2. If a1 and a2 are both the same type of Value
     * annotation, then the LUB is the result of taking all values from both a1 and a2 and removing
     * duplicates. If a1 and a2 are not the same type of Value annotation they may still be
     * mergeable because some values can be implicitly cast as others. If a1 and a2 are both in
     * {DoubleVal, IntVal} then they will be converted upwards: IntVal → DoubleVal to arrive at
     * a common annotation type.
     *
     * @return the least upper bound of a1 and a2
     */
    @Override
    public AnnotationMirror leastUpperBound(AnnotationMirror a1, AnnotationMirror a2) {
      if (!AnnotationUtils.areSameIgnoringValues(getTopAnnotation(a1), getTopAnnotation(a2))) {
        return null;
      } else if (isSubtype(a1, a2)) {
        return a2;
      } else if (isSubtype(a2, a1)) {
        return a1;
      }
      // If both are the same type, determine the type and merge:
      else if (AnnotationUtils.areSameIgnoringValues(a1, a2)) {
        List<Object> a1Values =
            AnnotationUtils.getElementValueArray(a1, "value", Object.class, true);
        List<Object> a2Values =
            AnnotationUtils.getElementValueArray(a2, "value", Object.class, true);
        HashSet<Object> newValues = new HashSet<Object>(a1Values.size() + a2Values.size());

        newValues.addAll(a1Values);
        newValues.addAll(a2Values);

        return createAnnotation(a1.getAnnotationType().toString(), newValues);
      }
      // Annotations are in this hierarchy, but they are not the same
      else {
        // If either is UNKNOWNVAL, ARRAYLEN, STRINGVAL, or BOOLEAN then
        // the LUB is
        // UnknownVal
        if (!(AnnotationUtils.areSameByClass(a1, IntVal.class)
            || AnnotationUtils.areSameByClass(a1, DoubleVal.class)
            || AnnotationUtils.areSameByClass(a2, IntVal.class)
            || AnnotationUtils.areSameByClass(a2, DoubleVal.class))) {
          return UNKNOWNVAL;
        } else {
          // At this point one of them must be a DoubleVal and one an
          // IntVal
          AnnotationMirror doubleAnno;
          AnnotationMirror intAnno;

          if (AnnotationUtils.areSameByClass(a2, DoubleVal.class)) {
            doubleAnno = a2;
            intAnno = a1;
          } else {
            doubleAnno = a1;
            intAnno = a2;
          }
          List<Long> intVals = getIntValues(intAnno);
          List<Double> doubleVals = getDoubleValues(doubleAnno);

          for (Long n : intVals) {
            doubleVals.add(n.doubleValue());
          }

          return createDoubleValAnnotation(doubleVals);
        }
      }
    }
Exemplo n.º 2
0
 private boolean containsSameIgnoringValues(
     Set<Class<? extends Annotation>> quals, AnnotationMirror anno) {
   for (Class<? extends Annotation> q : quals) {
     if (AnnotationUtils.areSameByClass(anno, q)) {
       return true;
     }
   }
   return false;
 }
  /** @inheritDoc */
  @Override
  public Slot getSlot(final AnnotationMirror annotationMirror) {

    final int id;
    if (InferenceQualifierHierarchy.isVarAnnot(annotationMirror)) {
      if (annotationMirror.getElementValues().isEmpty()) {
        return null; // TODO: should we instead throw an exception?
      } else {
        final AnnotationValue annoValue =
            annotationMirror.getElementValues().values().iterator().next();
        id = Integer.valueOf(annoValue.toString());
      }

      return getVariable(id);

    } else {

      if (constantStore != null) {
        return constantStore.get(AnnotationUtils.annotationName(annotationMirror));

      } else {
        for (Class<? extends Annotation> realAnno : realQualifiers) {
          if (AnnotationUtils.areSameByClass(annotationMirror, realAnno)) {
            return new ConstantSlot(annotationMirror, nextId());
          }
        }
      }
    }

    if (InferenceMain.isHackMode()) {
      return new ConstantSlot(
          InferenceMain.getInstance()
              .getRealTypeFactory()
              .getQualifierHierarchy()
              .getTopAnnotations()
              .iterator()
              .next(),
          nextId());
    }
    ErrorReporter.errorAbort(
        annotationMirror + " is a type of AnnotationMirror not handled by getVariableSlot.");
    return null; // Dead
  }
    /**
     * Computes subtyping as per the subtyping in the qualifier hierarchy structure unless both
     * annotations are Value. In this case, rhs is a subtype of lhs iff lhs contains at least every
     * element of rhs
     *
     * @return true if rhs is a subtype of lhs, false otherwise
     */
    @Override
    public boolean isSubtype(AnnotationMirror rhs, AnnotationMirror lhs) {

      if (AnnotationUtils.areSameByClass(lhs, UnknownVal.class)
          || AnnotationUtils.areSameByClass(rhs, BottomVal.class)) {
        return true;
      } else if (AnnotationUtils.areSameByClass(rhs, UnknownVal.class)
          || AnnotationUtils.areSameByClass(lhs, BottomVal.class)) {
        return false;
      } else if (AnnotationUtils.areSameIgnoringValues(lhs, rhs)) {
        // Same type, so might be subtype
        List<Object> lhsValues =
            AnnotationUtils.getElementValueArray(lhs, "value", Object.class, true);
        List<Object> rhsValues =
            AnnotationUtils.getElementValueArray(rhs, "value", Object.class, true);
        return lhsValues.containsAll(rhsValues);
      } else if (AnnotationUtils.areSameByClass(lhs, DoubleVal.class)
          && AnnotationUtils.areSameByClass(rhs, IntVal.class)) {
        List<Long> rhsValues;
        rhsValues = AnnotationUtils.getElementValueArray(rhs, "value", Long.class, true);
        List<Double> lhsValues =
            AnnotationUtils.getElementValueArray(lhs, "value", Double.class, true);
        boolean same = false;
        for (Long rhsLong : rhsValues) {
          for (Double lhsDbl : lhsValues) {
            if (lhsDbl.doubleValue() == rhsLong.doubleValue()) {
              same = true;
              break;
            }
          }
          if (!same) {
            return false;
          }
        }
        return same;
      }
      return false;
    }
 /**
  * Is {@code anno} the {@link UnknownInitialization} annotation (with any type frame)? If {@code
  * useFbc} is false, then {@link Raw} is used in the comparison.
  */
 public boolean isUnclassified(AnnotationMirror anno) {
   Class<? extends Annotation> clazz = useFbc ? UnknownInitialization.class : Raw.class;
   return AnnotationUtils.areSameByClass(anno, clazz);
 }
 /**
  * Is {@code anno} the {@link UnderInitialization} annotation (with any type frame)? Always
  * returns false if {@code useFbc} is false.
  */
 public boolean isFree(AnnotationMirror anno) {
   return useFbc && AnnotationUtils.areSameByClass(anno, UnderInitialization.class);
 }
Exemplo n.º 7
0
  /*
   * Provided that m is of a type that implements interface java.util.Map:
   * -Given a call m.containsKey(k), ensures that k is @KeyFor("m") in the thenStore of the transfer result.
   * -Given a call m.put(k, ...), ensures that k is @KeyFor("m") in the thenStore and elseStore of the transfer result.
   */
  @Override
  public TransferResult<CFValue, CFStore> visitMethodInvocation(
      MethodInvocationNode node, TransferInput<CFValue, CFStore> in) {

    TransferResult<CFValue, CFStore> result = super.visitMethodInvocation(node, in);

    String methodName = node.getTarget().getMethod().toString();

    // First verify if the method name is containsKey or put. This is an inexpensive check.

    boolean containsKey = methodName.startsWith("containsKey(");
    boolean put = methodName.startsWith("put(");

    if (containsKey || put) {
      // Now verify that the receiver of the method invocation is of a type
      // that extends that java.util.Map interface. This is a more expensive check.

      javax.lang.model.util.Types types = analysis.getTypes();

      TypeMirror mapInterfaceTypeMirror =
          types.erasure(
              TypesUtils.typeFromClass(types, analysis.getEnv().getElementUtils(), Map.class));

      TypeMirror receiverType = types.erasure(node.getTarget().getReceiver().getType());

      if (types.isSubtype(receiverType, mapInterfaceTypeMirror)) {

        FlowExpressionContext flowExprContext =
            FlowExpressionParseUtil.buildFlowExprContextForUse(node, checker);

        String mapName = flowExprContext.receiver.toString();
        Receiver keyReceiver = flowExprContext.arguments.get(0);

        KeyForAnnotatedTypeFactory atypeFactory =
            (KeyForAnnotatedTypeFactory) analysis.getTypeFactory();

        LinkedHashSet<String> keyForMaps = new LinkedHashSet<>();
        keyForMaps.add(mapName);

        final CFValue previousKeyValue = in.getValueOfSubNode(node.getArgument(0));
        if (previousKeyValue != null) {
          final AnnotationMirror prevAm =
              previousKeyValue.getType().getAnnotationInHierarchy(KEYFOR);
          if (prevAm != null && AnnotationUtils.areSameByClass(prevAm, KeyFor.class)) {
            keyForMaps.addAll(getKeys(prevAm));
          }
        }

        AnnotationMirror am = atypeFactory.createKeyForAnnotationMirrorWithValue(keyForMaps);

        if (containsKey) {
          ConditionalTransferResult<CFValue, CFStore> conditionalResult =
              (ConditionalTransferResult<CFValue, CFStore>) result;
          conditionalResult.getThenStore().insertValue(keyReceiver, am);
        } else if (put) {
          result.getThenStore().insertValue(keyReceiver, am);
          result.getElseStore().insertValue(keyReceiver, am);
        }
      }
    }

    return result;
  }