Search in sources :

Example 16 with TypeSystemError

use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.

the class MustCallConsistencyAnalyzer method isValidCreatesMustCallForExpression.

/**
 * Checks the validity of the given expression from an invoked method's {@link
 * org.checkerframework.checker.mustcall.qual.CreatesMustCallFor} annotation. Helper method for
 * {@link #checkCreatesMustCallForInvocation(Set, MethodInvocationNode)}.
 *
 * <p>An expression is valid if one of the following conditions is true: 1) the expression is an
 * owning pointer, 2) the expression already has a tracked Obligation (i.e. there is already a
 * resource alias in some Obligation's resource alias set that refers to the expression), or 3)
 * the method in which the invocation occurs also has an @CreatesMustCallFor annotation, with the
 * same expression.
 *
 * @param obligations the currently-tracked Obligations; this value is side-effected if there is
 *     an Obligation in it which tracks {@code expression} as one of its resource aliases
 * @param expression an element of a method's @CreatesMustCallFor annotation
 * @param path the path to the invocation of the method from whose @CreateMustCallFor annotation
 *     {@code expression} came
 * @return true iff the expression is valid, as defined above
 */
private boolean isValidCreatesMustCallForExpression(Set<Obligation> obligations, JavaExpression expression, TreePath path) {
    if (expression instanceof FieldAccess) {
        Element elt = ((FieldAccess) expression).getField();
        if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP) && typeFactory.getDeclAnnotation(elt, Owning.class) != null) {
            // The expression is an Owning field.  This satisfies case 1.
            return true;
        }
    } else if (expression instanceof LocalVariable) {
        Element elt = ((LocalVariable) expression).getElement();
        if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP) && typeFactory.getDeclAnnotation(elt, Owning.class) != null) {
            // This satisfies case 1.
            return true;
        } else {
            Obligation toRemove = null;
            Obligation toAdd = null;
            for (Obligation obligation : obligations) {
                ResourceAlias alias = obligation.getResourceAlias(expression);
                if (alias != null) {
                    // This satisfies case 2 above. Remove all its aliases, then return below.
                    if (toRemove != null) {
                        throw new TypeSystemError("tried to remove multiple sets containing a reset expression at once");
                    }
                    toRemove = obligation;
                    toAdd = new Obligation(ImmutableSet.of(alias));
                }
            }
            if (toRemove != null) {
                obligations.remove(toRemove);
                obligations.add(toAdd);
                // This satisfies case 2.
                return true;
            }
        }
    }
    // TODO: Getting this every time is inefficient if a method has many @CreatesMustCallFor
    // annotations, but that should be rare.
    MethodTree enclosingMethodTree = TreePathUtil.enclosingMethod(path);
    if (enclosingMethodTree == null) {
        return false;
    }
    ExecutableElement enclosingMethodElt = TreeUtils.elementFromDeclaration(enclosingMethodTree);
    MustCallAnnotatedTypeFactory mcAtf = typeFactory.getTypeFactoryOfSubchecker(MustCallChecker.class);
    List<String> enclosingCmcfValues = ResourceLeakVisitor.getCreatesMustCallForValues(enclosingMethodElt, mcAtf, typeFactory);
    if (enclosingCmcfValues.isEmpty()) {
        return false;
    }
    for (String enclosingCmcfValue : enclosingCmcfValues) {
        JavaExpression enclosingTarget;
        try {
            enclosingTarget = StringToJavaExpression.atMethodBody(enclosingCmcfValue, enclosingMethodTree, checker);
        } catch (JavaExpressionParseException e) {
            // Do not issue an error here, because it would be a duplicate.
            // The error will be issued by the Transfer class of the checker,
            // via the CreatesMustCallForElementSupplier interface.
            enclosingTarget = null;
        }
        if (areSame(expression, enclosingTarget)) {
            // This satisfies case 3.
            return true;
        }
    }
    return false;
}
Also used : JavaExpression(org.checkerframework.dataflow.expression.JavaExpression) StringToJavaExpression(org.checkerframework.framework.util.StringToJavaExpression) MethodTree(com.sun.source.tree.MethodTree) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) LocalVariable(org.checkerframework.dataflow.expression.LocalVariable) TypeSystemError(org.checkerframework.javacutil.TypeSystemError) MustCallAnnotatedTypeFactory(org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory) NotOwning(org.checkerframework.checker.mustcall.qual.NotOwning) Owning(org.checkerframework.checker.mustcall.qual.Owning) JavaExpressionParseException(org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException) FieldAccess(org.checkerframework.dataflow.expression.FieldAccess)

Example 17 with TypeSystemError

use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.

the class DefaultQualifierKindHierarchy method verifyHierarchy.

/**
 * Verifies that the {@link DefaultQualifierKindHierarchy} is a valid hierarchy.
 *
 * @param directSuperMap mapping from qualifier to its direct supertypes; used to verify that a
 *     polymorphic annotation does not have a {@link SubtypeOf} meta-annotation
 * @throws TypeSystemError if the hierarchy isn't valid
 */
@RequiresNonNull({ "this.qualifierKinds", "this.tops", "this.bottoms" })
protected void verifyHierarchy(@UnderInitialization DefaultQualifierKindHierarchy this, Map<DefaultQualifierKind, Set<DefaultQualifierKind>> directSuperMap) {
    for (DefaultQualifierKind qualifierKind : qualifierKinds) {
        boolean isPoly = qualifierKind.isPoly();
        boolean hasSubtypeOfAnno = directSuperMap.containsKey(qualifierKind);
        if (isPoly && hasSubtypeOfAnno) {
            // Polymorphic qualifiers with upper and lower bounds are currently not supported.
            throw new TypeSystemError("AnnotatedTypeFactory: " + qualifierKind + " is polymorphic and specifies super qualifiers.%n" + "Remove the @PolymorphicQualifier or @SubtypeOf annotation from it.");
        } else if (!isPoly && !hasSubtypeOfAnno) {
            throw new TypeSystemError("AnnotatedTypeFactory: %s does not specify its super qualifiers.%n" + "Add an @SubtypeOf or @PolymorphicQualifier annotation to it,%n" + "or if it is an alias, exclude it from `createSupportedTypeQualifiers()`.", qualifierKind);
        } else if (isPoly) {
            if (qualifierKind.top == null) {
                throw new TypeSystemError("PolymorphicQualifier, %s, has to specify a type hierarchy in its" + " @PolymorphicQualifier meta-annotation, if more than one exists; top types:" + " [%s].", qualifierKind, StringsPlume.join(", ", tops));
            } else if (!tops.contains(qualifierKind.top)) {
                throw new TypeSystemError("Polymorphic qualifier %s has invalid top %s. Top qualifiers: %s", qualifierKind, qualifierKind.top, StringsPlume.join(", ", tops));
            }
        }
    }
    if (bottoms.size() != tops.size()) {
        throw new TypeSystemError("Number of tops not equal to number of bottoms: Tops: [%s] Bottoms: [%s]", StringsPlume.join(", ", tops), StringsPlume.join(", ", bottoms));
    }
}
Also used : TypeSystemError(org.checkerframework.javacutil.TypeSystemError) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 18 with TypeSystemError

use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.

the class DefaultQualifierKindHierarchy method initializePolymorphicQualifiers.

/**
 * Iterates over all the qualifier kinds and adds all polymorphic qualifier kinds to
 * polymorphicQualifiers. Also sets {@link DefaultQualifierKind#poly} and {@link
 * DefaultQualifierKind#top} for the polymorphic qualifiers, and sets {@link
 * DefaultQualifierKind#poly} for the top qualifiers.
 *
 * <p>Requires that tops has been initialized.
 */
@RequiresNonNull({ "this.nameToQualifierKind", "this.qualifierKinds", "this.tops" })
protected void initializePolymorphicQualifiers(@UnderInitialization DefaultQualifierKindHierarchy this, ) {
    for (DefaultQualifierKind qualifierKind : qualifierKinds) {
        Class<? extends Annotation> clazz = qualifierKind.getAnnotationClass();
        PolymorphicQualifier polyMetaAnno = clazz.getAnnotation(PolymorphicQualifier.class);
        if (polyMetaAnno == null) {
            continue;
        }
        qualifierKind.poly = qualifierKind;
        String topName = QualifierKindHierarchy.annotationClassName(polyMetaAnno.value());
        if (nameToQualifierKind.containsKey(topName)) {
            qualifierKind.top = nameToQualifierKind.get(topName);
        } else if (topName.equals(Annotation.class.getCanonicalName())) {
            // then there must be exactly one top.
            if (tops.size() == 1) {
                qualifierKind.top = tops.iterator().next();
            } else {
                throw new TypeSystemError("Polymorphic qualifier %s did not specify a top annotation class. Tops: [%s]", qualifierKind, StringsPlume.join(", ", tops));
            }
        } else {
            throw new TypeSystemError("Polymorphic qualifier %s's top, %s, is not a qualifier.", qualifierKind, topName);
        }
        qualifierKind.strictSuperTypes = Collections.singleton(qualifierKind.top);
        qualifierKind.top.poly = qualifierKind;
    }
}
Also used : PolymorphicQualifier(org.checkerframework.framework.qual.PolymorphicQualifier) TypeSystemError(org.checkerframework.javacutil.TypeSystemError) RequiresNonNull(org.checkerframework.checker.nullness.qual.RequiresNonNull)

Example 19 with TypeSystemError

use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.

the class AnnotatedTypeFactory method postInit.

/**
 * Actions that logically belong in the constructor, but need to run after the subclass
 * constructor has completed. In particular, parseStubFiles() may try to do type resolution with
 * this AnnotatedTypeFactory.
 */
protected void postInit() {
    this.qualHierarchy = createQualifierHierarchy();
    if (qualHierarchy == null) {
        throw new TypeSystemError("AnnotatedTypeFactory with null qualifier hierarchy not supported.");
    } else if (!qualHierarchy.isValid()) {
        throw new TypeSystemError("AnnotatedTypeFactory: invalid qualifier hierarchy: %s %s ", qualHierarchy.getClass(), qualHierarchy);
    }
    this.typeHierarchy = createTypeHierarchy();
    this.typeVarSubstitutor = createTypeVariableSubstitutor();
    this.typeArgumentInference = createTypeArgumentInference();
    this.qualifierUpperBounds = createQualifierUpperBounds();
    // TODO: is this the best location for declaring this alias?
    addAliasedDeclAnnotation(org.jmlspecs.annotation.Pure.class, org.checkerframework.dataflow.qual.Pure.class, AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.Pure.class));
    // Accommodate the inability to write @InheritedAnnotation on these annotations.
    addInheritedAnnotation(AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.Pure.class));
    addInheritedAnnotation(AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.SideEffectFree.class));
    addInheritedAnnotation(AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.Deterministic.class));
    addInheritedAnnotation(AnnotationBuilder.fromClass(elements, org.checkerframework.dataflow.qual.TerminatesExecution.class));
    initializeReflectionResolution();
    if (this.getClass() == AnnotatedTypeFactory.class) {
        this.parseAnnotationFiles();
    }
    TypeMirror iterableTypeMirror = ElementUtils.getTypeElement(processingEnv, Iterable.class).asType();
    this.iterableDeclType = (AnnotatedDeclaredType) AnnotatedTypeMirror.createType(iterableTypeMirror, this, true);
}
Also used : SideEffectFree(org.checkerframework.dataflow.qual.SideEffectFree) TypeMirror(javax.lang.model.type.TypeMirror) TypeSystemError(org.checkerframework.javacutil.TypeSystemError)

Example 20 with TypeSystemError

use of org.checkerframework.javacutil.TypeSystemError in project checker-framework by typetools.

the class AnnotatedTypeFactory method checkSupportedQuals.

/**
 * @throws BugInCF If supportedQuals is empty or if any of the support qualifiers has a @Target
 *     meta-annotation that contain something besides TYPE_USE or TYPE_PARAMETER. (@Target({}) is
 *     allowed.)
 */
private void checkSupportedQuals() {
    if (supportedQuals.isEmpty()) {
        throw new TypeSystemError("Found no supported qualifiers.");
    }
    for (Class<? extends Annotation> annotationClass : supportedQuals) {
        // Check @Target values
        ElementType[] targetValues = annotationClass.getAnnotation(Target.class).value();
        List<ElementType> badTargetValues = new ArrayList<>();
        for (ElementType element : targetValues) {
            if (!(element == ElementType.TYPE_USE || element == ElementType.TYPE_PARAMETER)) {
                // if there's an ElementType with an enumerated value of something other
                // than TYPE_USE or TYPE_PARAMETER then it isn't a valid qualifier
                badTargetValues.add(element);
            }
        }
        if (!badTargetValues.isEmpty()) {
            String msg = "The @Target meta-annotation on type qualifier " + annotationClass.toString() + " must not contain " + StringsPlume.conjunction("or", badTargetValues) + ".";
            throw new TypeSystemError(msg);
        }
    }
}
Also used : ElementType(java.lang.annotation.ElementType) Target(java.lang.annotation.Target) ArrayList(java.util.ArrayList) TypeSystemError(org.checkerframework.javacutil.TypeSystemError)

Aggregations

TypeSystemError (org.checkerframework.javacutil.TypeSystemError)23 AnnotationMirror (javax.lang.model.element.AnnotationMirror)6 ExecutableElement (javax.lang.model.element.ExecutableElement)4 Range (org.checkerframework.common.value.util.Range)4 Element (javax.lang.model.element.Element)3 VariableElement (javax.lang.model.element.VariableElement)3 RequiresNonNull (org.checkerframework.checker.nullness.qual.RequiresNonNull)3 ArrayLenRange (org.checkerframework.common.value.qual.ArrayLenRange)3 MethodTree (com.sun.source.tree.MethodTree)2 ArrayList (java.util.ArrayList)2 TypeElement (javax.lang.model.element.TypeElement)2 MustCallAnnotatedTypeFactory (org.checkerframework.checker.mustcall.MustCallAnnotatedTypeFactory)2 MethodInvocationNode (org.checkerframework.dataflow.cfg.node.MethodInvocationNode)2 ObjectCreationNode (org.checkerframework.dataflow.cfg.node.ObjectCreationNode)2 AnnotatedTypeMirror (org.checkerframework.framework.type.AnnotatedTypeMirror)2 AnnotationBuilder (org.checkerframework.javacutil.AnnotationBuilder)2 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)1 ExpressionTree (com.sun.source.tree.ExpressionTree)1 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)1 MemberReferenceTree (com.sun.source.tree.MemberReferenceTree)1