use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AliasingTransfer method visitMethodInvocation.
/**
* Case 3: Given a method invocation expression, if the parent of the expression is not a
* statement, check if there are any arguments of the method call annotated as
* {@literal @}LeakedToResult and remove it from the store, since it might be leaked.
*/
@Override
public TransferResult<CFValue, CFStore> visitMethodInvocation(MethodInvocationNode n, TransferInput<CFValue, CFStore> in) {
Tree parent = n.getTreePath().getParentPath().getLeaf();
boolean parentIsStatement = parent.getKind() == Kind.EXPRESSION_STATEMENT;
if (!parentIsStatement) {
ExecutableElement methodElement = TreeUtils.elementFromUse(n.getTree());
List<Node> args = n.getArguments();
List<? extends VariableElement> params = methodElement.getParameters();
assert (args.size() == params.size()) : "Number of arguments in " + "the method call " + n.toString() + " is different from the" + " number of parameters for the method declaration: " + methodElement.getSimpleName().toString();
CFStore store = in.getRegularStore();
for (int i = 0; i < args.size(); i++) {
Node arg = args.get(i);
VariableElement param = params.get(i);
if (factory.getAnnotatedType(param).hasAnnotation(LeakedToResult.class)) {
// If argument can leak to result, and parent is not a
// single statement, remove that node from store.
store.clearValue(FlowExpressions.internalReprOf(factory, arg));
}
}
// Now, doing the same as above for the receiver parameter
Node receiver = n.getTarget().getReceiver();
AnnotatedExecutableType annotatedType = factory.getAnnotatedType(methodElement);
AnnotatedDeclaredType receiverType = annotatedType.getReceiverType();
if (receiverType != null && receiverType.hasAnnotation(LeakedToResult.class)) {
store.clearValue(FlowExpressions.internalReprOf(factory, receiver));
}
}
// pseudo-assignments.
return super.visitMethodInvocation(n, in);
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AliasingVisitor method visitMethodInvocation.
/**
* Checks that if a method call is being invoked inside a constructor with result type
* {@literal @}Unique, it must not leak the "this" reference. There are 3 ways to make sure that
* this is not happening:
*
* <ol>
* <li>{@code this} is not an argument of the method call.
* <li>{@code this} is an argument of the method call, but the respective parameter is
* annotated as {@literal @}NonLeaked.
* <li>{@code this} is an argument of the method call, but the respective parameter is
* annotated as {@literal @}LeakedToResult AND the result of the method call is not being
* stored (the method call is a statement).
* </ol>
*
* The private method {@code isUniqueCheck} handles cases 2 and 3.
*/
@Override
public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
// @Unique. We also want to avoid visiting the <init> method.
if (isInUniqueConstructor(node)) {
if (TreeUtils.isSuperCall(node)) {
// Check if a call to super() might create an alias: that
// happens when the parent's respective constructor is not @Unique.
AnnotatedTypeMirror superResult = atypeFactory.getAnnotatedType(node);
if (!superResult.hasAnnotation(Unique.class)) {
checker.report(Result.failure("unique.leaked"), node);
}
} else {
// TODO: Currently the type of "this" doesn't always return
// the type of the constructor result, therefore we need
// this "else" block. Once constructors are implemented
// correctly we could remove that code below, since the type
// of "this" in a @Unique constructor will be @Unique.
Tree parent = getCurrentPath().getParentPath().getLeaf();
boolean parentIsStatement = parent.getKind() == Kind.EXPRESSION_STATEMENT;
ExecutableElement methodElement = TreeUtils.elementFromUse(node);
List<? extends VariableElement> params = methodElement.getParameters();
List<? extends ExpressionTree> args = node.getArguments();
assert (args.size() == params.size()) : "Number of arguments in" + " the method call " + node.toString() + " is different from the " + "number of parameters for the method declaration: " + methodElement.getSimpleName().toString();
for (int i = 0; i < args.size(); i++) {
// For every argument we check if it is a reference to "this".
if (TreeUtils.isExplicitThisDereference(args.get(i))) {
// If it is a reference to "this", there is still hope that
// it is not being leaked (2. and 3. from the javadoc).
VariableElement param = params.get(i);
boolean hasNonLeaked = atypeFactory.getAnnotatedType(param).hasAnnotation(NonLeaked.class);
boolean hasLeakedToResult = atypeFactory.getAnnotatedType(param).hasAnnotation(LeakedToResult.class);
isUniqueCheck(node, parentIsStatement, hasNonLeaked, hasLeakedToResult);
} else {
// Not possible to leak reference here (case 1. from the javadoc).
}
}
// Now, doing the same as above for the receiver parameter
AnnotatedExecutableType annotatedType = atypeFactory.getAnnotatedType(methodElement);
AnnotatedDeclaredType receiverType = annotatedType.getReceiverType();
if (receiverType != null) {
boolean hasNonLeaked = receiverType.hasAnnotation(NonLeaked.class);
boolean hasLeakedToResult = receiverType.hasAnnotation(LeakedToResult.class);
isUniqueCheck(node, parentIsStatement, hasNonLeaked, hasLeakedToResult);
}
}
}
return super.visitMethodInvocation(node, p);
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class AliasingVisitor method visitVariable.
@Override
public Void visitVariable(VariableTree node, Void p) {
// Component types are not allowed to have the @Unique annotation.
AnnotatedTypeMirror varType = atypeFactory.getAnnotatedType(node);
VariableElement elt = TreeUtils.elementFromDeclaration(node);
if (elt.getKind().isField() && varType.hasExplicitAnnotation(Unique.class)) {
checker.report(Result.failure("unique.location.forbidden"), node);
} else if (node.getType().getKind() == Kind.ARRAY_TYPE) {
AnnotatedArrayType arrayType = (AnnotatedArrayType) varType;
if (arrayType.getComponentType().hasAnnotation(Unique.class)) {
checker.report(Result.failure("unique.location.forbidden"), node);
}
} else if (node.getType().getKind() == Kind.PARAMETERIZED_TYPE) {
AnnotatedDeclaredType declaredType = (AnnotatedDeclaredType) varType;
for (AnnotatedTypeMirror atm : declaredType.getTypeArguments()) {
if (atm.hasAnnotation(Unique.class)) {
checker.report(Result.failure("unique.location.forbidden"), node);
}
}
}
return super.visitVariable(node, p);
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class BaseTypeVisitor method visitClass.
/**
* Type-check classTree and skips classes specified by the skipDef option. Subclasses should
* override {@link #processClassTree(ClassTree)} instead of this method.
*
* @param classTree class to check
* @param p null
* @return null
*/
@Override
public final Void visitClass(ClassTree classTree, Void p) {
if (checker.shouldSkipDefs(classTree)) {
// class entirely.
return null;
}
atypeFactory.preProcessClassTree(classTree);
AnnotatedDeclaredType preACT = visitorState.getClassType();
ClassTree preCT = visitorState.getClassTree();
AnnotatedDeclaredType preAMT = visitorState.getMethodReceiver();
MethodTree preMT = visitorState.getMethodTree();
Pair<Tree, AnnotatedTypeMirror> preAssCtxt = visitorState.getAssignmentContext();
visitorState.setClassType(atypeFactory.getAnnotatedType(classTree));
visitorState.setClassTree(classTree);
visitorState.setMethodReceiver(null);
visitorState.setMethodTree(null);
visitorState.setAssignmentContext(null);
try {
processClassTree(classTree);
atypeFactory.postProcessClassTree(classTree);
} finally {
this.visitorState.setClassType(preACT);
this.visitorState.setClassTree(preCT);
this.visitorState.setMethodReceiver(preAMT);
this.visitorState.setMethodTree(preMT);
this.visitorState.setAssignmentContext(preAssCtxt);
}
return null;
}
use of org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType in project checker-framework by typetools.
the class BaseTypeVisitor method checkConstructorInvocation.
protected boolean checkConstructorInvocation(AnnotatedDeclaredType invocation, AnnotatedExecutableType constructor, NewClassTree newClassTree) {
AnnotatedDeclaredType returnType = (AnnotatedDeclaredType) constructor.getReturnType();
// to the declared type and then do a subtyping check.
if (invocation.getUnderlyingType().asElement().getKind().isInterface() && TypesUtils.isObject(returnType.getUnderlyingType())) {
final AnnotatedDeclaredType retAsDt = invocation.deepCopy();
retAsDt.replaceAnnotations(returnType.getAnnotations());
returnType = retAsDt;
} else if (newClassTree.getClassBody() != null) {
// An anonymous class invokes the constructor of its super class, so the underlying
// types of invocation and returnType are not the same. Call asSuper so they are the
// same and the is subtype tests below work correctly
invocation = AnnotatedTypes.asSuper(atypeFactory, invocation, returnType);
}
// constructor invocation (invocation).
if (!(atypeFactory.getTypeHierarchy().isSubtype(invocation, returnType) || atypeFactory.getTypeHierarchy().isSubtype(returnType, invocation))) {
checker.report(Result.failure("constructor.invocation.invalid", constructor.toString(), invocation, returnType), newClassTree);
return false;
}
return true;
// TODO: what properties should hold for constructor receivers for
// inner type instantiations?
}
Aggregations