use of com.sun.source.tree.MethodTree 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;
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class MustCallVisitor method visitReturn.
@Override
public Void visitReturn(ReturnTree node, Void p) {
// Only check return types if ownership is being transferred.
if (!checker.hasOption(MustCallChecker.NO_LIGHTWEIGHT_OWNERSHIP)) {
MethodTree enclosingMethod = TreePathUtil.enclosingMethod(this.getCurrentPath());
// precisely?
if (enclosingMethod != null) {
ExecutableElement methodElt = TreeUtils.elementFromDeclaration(enclosingMethod);
AnnotationMirror notOwningAnno = atypeFactory.getDeclAnnotation(methodElt, NotOwning.class);
if (notOwningAnno != null) {
// Checker won't check anyway.
return null;
}
}
}
return super.visitReturn(node, p);
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class LockTransfer method initialStore.
@Override
public LockStore initialStore(UnderlyingAST underlyingAST, List<LocalVariableNode> parameters) {
LockStore store = super.initialStore(underlyingAST, parameters);
Kind astKind = underlyingAST.getKind();
// Handle synchronized methods and constructors.
if (astKind == UnderlyingAST.Kind.METHOD) {
CFGMethod method = (CFGMethod) underlyingAST;
MethodTree methodTree = method.getMethod();
ExecutableElement methodElement = TreeUtils.elementFromDeclaration(methodTree);
if (methodElement.getModifiers().contains(Modifier.SYNCHRONIZED)) {
final ClassTree classTree = method.getClassTree();
TypeMirror classType = TreeUtils.typeOf(classTree);
if (methodElement.getModifiers().contains(Modifier.STATIC)) {
store.insertValue(new ClassName(classType), atypeFactory.LOCKHELD);
} else {
store.insertThisValue(atypeFactory.LOCKHELD, classType);
}
} else if (methodElement.getKind() == ElementKind.CONSTRUCTOR) {
store.setInConstructorOrInitializer();
}
} else if (astKind == Kind.ARBITRARY_CODE) {
// Handle initializers
store.setInConstructorOrInitializer();
}
return store;
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class TreeUtils method hasSyntheticArgument.
/**
* Returns true if {@code tree} has a synthetic argument.
*
* <p>For some anonymous classes with an explicit enclosing expression, javac creates a synthetic
* argument to the constructor that is the enclosing expression of the NewClassTree. Suppose a
* programmer writes:
*
* <pre>{@code class Outer {
* class Inner { }
* void method() {
* this.new Inner(){};
* }
* }}</pre>
*
* Java 9 javac creates the following synthetic tree for {@code this.new Inner(){}}:
*
* <pre>{@code new Inner(this) {
* (.Outer x0) {
* x0.super();
* }
* }}</pre>
*
* Java 11 javac creates a different tree without the synthetic argument for {@code this.new
* Inner(){}}; the first line in the below code differs:
*
* <pre>{@code this.new Inner() {
* (.Outer x0) {
* x0.super();
* }
* }}</pre>
*
* @param tree a new class tree
* @return true if {@code tree} has a synthetic argument
*/
public static boolean hasSyntheticArgument(NewClassTree tree) {
if (tree.getClassBody() == null || tree.getEnclosingExpression() != null) {
return false;
}
for (Tree member : tree.getClassBody().getMembers()) {
if (member.getKind() == Tree.Kind.METHOD && isConstructor((MethodTree) member)) {
MethodTree methodTree = (MethodTree) member;
StatementTree f = methodTree.getBody().getStatements().get(0);
return TreeUtils.getReceiverTree(((ExpressionStatementTree) f).getExpression()) != null;
}
}
return false;
}
use of com.sun.source.tree.MethodTree in project checker-framework by typetools.
the class TreePathUtil method isTreeInStaticScope.
/**
* Returns true if the leaf of the tree path is in a static scope.
*
* @param path TreePath whose leaf may or may not be in static scope
* @return true if the leaf of the tree path is in a static scope
*/
public static boolean isTreeInStaticScope(TreePath path) {
MethodTree enclosingMethod = enclosingMethod(path);
if (enclosingMethod != null) {
return enclosingMethod.getModifiers().getFlags().contains(Modifier.STATIC);
}
// no enclosing method, check for static or initializer block
BlockTree block = enclosingTopLevelBlock(path);
if (block != null) {
return block.isStatic();
}
// check if its in a variable initializer
Tree t = enclosingVariable(path);
if (t != null) {
return ((VariableTree) t).getModifiers().getFlags().contains(Modifier.STATIC);
}
ClassTree classTree = enclosingClass(path);
if (classTree != null) {
return classTree.getModifiers().getFlags().contains(Modifier.STATIC);
}
return false;
}
Aggregations