diff --git a/checker/jtreg/nullness/EISOPissue548/ConservativeClassLiteral.java b/checker/jtreg/nullness/EISOPissue548/ConservativeClassLiteral.java new file mode 100644 index 00000000000..246648a4e53 --- /dev/null +++ b/checker/jtreg/nullness/EISOPissue548/ConservativeClassLiteral.java @@ -0,0 +1,15 @@ +/* + * @test + * @summary Test class literals in CFGs and their type with conservative nullness. + * + * @compile MyEnum.java + * @compile -processor org.checkerframework.checker.nullness.NullnessChecker -AuseConservativeDefaultsForUncheckedCode=bytecode,-source ConservativeClassLiteral.java + */ + +import java.util.EnumSet; + +class ConservativeClassLiteral { + EnumSet none() { + return EnumSet.noneOf(MyEnum.class); + } +} diff --git a/checker/jtreg/nullness/EISOPissue548/MyEnum.java b/checker/jtreg/nullness/EISOPissue548/MyEnum.java new file mode 100644 index 00000000000..c4b60a93a39 --- /dev/null +++ b/checker/jtreg/nullness/EISOPissue548/MyEnum.java @@ -0,0 +1,3 @@ +enum MyEnum { + VALUE; +} diff --git a/checker/src/main/java/org/checkerframework/checker/initialization/InitializationParentAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/initialization/InitializationParentAnnotatedTypeFactory.java index 6fb6ae3d6ec..d5357bbbd06 100644 --- a/checker/src/main/java/org/checkerframework/checker/initialization/InitializationParentAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/initialization/InitializationParentAnnotatedTypeFactory.java @@ -794,7 +794,7 @@ public Void visitNewArray(NewArrayTree tree, AnnotatedTypeMirror type) { @Override public Void visitMemberSelect( MemberSelectTree tree, AnnotatedTypeMirror annotatedTypeMirror) { - if (TreeUtils.isArrayLengthAccess(tree)) { + if (TreeUtils.isArrayLengthAccess(tree) || TreeUtils.isClassLiteral(tree)) { annotatedTypeMirror.replaceAnnotation(INITIALIZED); } return super.visitMemberSelect(tree, annotatedTypeMirror); diff --git a/checker/src/main/java/org/checkerframework/checker/nullness/NullnessNoInitAnnotatedTypeFactory.java b/checker/src/main/java/org/checkerframework/checker/nullness/NullnessNoInitAnnotatedTypeFactory.java index ea521789880..24950471210 100644 --- a/checker/src/main/java/org/checkerframework/checker/nullness/NullnessNoInitAnnotatedTypeFactory.java +++ b/checker/src/main/java/org/checkerframework/checker/nullness/NullnessNoInitAnnotatedTypeFactory.java @@ -669,9 +669,10 @@ public Void visitMemberSelect(MemberSelectTree tree, AnnotatedTypeMirror type) { Element elt = TreeUtils.elementFromUse(tree); assert elt != null; - // Make primitive variable @NonNull in case the Initialization Checker + // Make primitive variable and class literal @NonNull in case the Initialization Checker // considers it uninitialized. - if (TypesUtils.isPrimitive(type.getUnderlyingType())) { + if (TypesUtils.isPrimitive(type.getUnderlyingType()) + || TreeUtils.isClassLiteral(tree)) { type.replaceAnnotation(NONNULL); } diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/builder/CFGTranslationPhaseOne.java b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/builder/CFGTranslationPhaseOne.java index 8f92a87c8ca..548a3ee97cf 100644 --- a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/builder/CFGTranslationPhaseOne.java +++ b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/builder/CFGTranslationPhaseOne.java @@ -77,6 +77,7 @@ import org.checkerframework.dataflow.cfg.node.CatchMarkerNode; import org.checkerframework.dataflow.cfg.node.CharacterLiteralNode; import org.checkerframework.dataflow.cfg.node.ClassDeclarationNode; +import org.checkerframework.dataflow.cfg.node.ClassLiteralNode; import org.checkerframework.dataflow.cfg.node.ClassNameNode; import org.checkerframework.dataflow.cfg.node.ConditionalAndNode; import org.checkerframework.dataflow.cfg.node.ConditionalNotNode; @@ -3671,6 +3672,11 @@ public Node visitMemberSelect(MemberSelectTree tree, Void p) { Node result = new PackageNameNode(tree, (PackageNameNode) expr); extendWithNode(result); return result; + } else if (element.getKind() == ElementKind.FIELD + && element.toString().equals("class")) { + Node result = new ClassLiteralNode(tree, expr); + extendWithNode((ClassLiteralNode) result); + return result; } else { throw new BugInCF("Unexpected element kind: " + element.getKind()); } diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/AbstractNodeVisitor.java b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/AbstractNodeVisitor.java index 4f04678f1a4..9377d90a9f9 100644 --- a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/AbstractNodeVisitor.java +++ b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/AbstractNodeVisitor.java @@ -358,6 +358,11 @@ public R visitPrimitiveType(PrimitiveTypeNode n, P p) { return visitNode(n, p); } + @Override + public R visitClassLiteral(ClassLiteralNode n, P p) { + return visitNode(n, p); + } + @Override public R visitClassName(ClassNameNode n, P p) { return visitNode(n, p); diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/ClassLiteralNode.java b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/ClassLiteralNode.java new file mode 100644 index 00000000000..dd7ef501962 --- /dev/null +++ b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/ClassLiteralNode.java @@ -0,0 +1,60 @@ +package org.checkerframework.dataflow.cfg.node; + +import com.sun.source.tree.MemberSelectTree; +import com.sun.source.tree.Tree; + +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.javacutil.TreeUtils; + +import java.util.Collection; +import java.util.Collections; + +/** A node for a class literal. For example: {@code String.class}. */ +public class ClassLiteralNode extends Node { + /** The tree for the class literal. */ + protected final MemberSelectTree tree; + + /** The class name of class literal */ + protected final Node className; + + /** + * Create a new ClassLiteralNode. + * + * @param tree the class literal + * @param className the class name for the class literal + */ + public ClassLiteralNode(MemberSelectTree tree, Node className) { + super(TreeUtils.typeOf(tree)); + this.tree = tree; + this.className = className; + } + + @Override + public @Nullable Tree getTree() { + return tree; + } + + /** + * Get the class name of the class literal. + * + * @return the class name of the class literal + */ + public Node getClassName() { + return className; + } + + @Override + public R accept(NodeVisitor visitor, P p) { + return visitor.visitClassLiteral(this, p); + } + + @Override + public String toString() { + return tree.toString(); + } + + @Override + public Collection getOperands() { + return Collections.emptyList(); + } +} diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/NodeVisitor.java b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/NodeVisitor.java index 20211a9619b..8e78a73b268 100644 --- a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/NodeVisitor.java +++ b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/NodeVisitor.java @@ -10,152 +10,636 @@ */ public interface NodeVisitor { // Literals + /** + * Visits a short literal node. + * + * @param n the {@link ShortLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitShortLiteral(ShortLiteralNode n, P p); + /** + * Visits an integer literal node. + * + * @param n the {@link IntegerLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitIntegerLiteral(IntegerLiteralNode n, P p); + /** + * Visits a long literal node. + * + * @param n the {@link LongLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitLongLiteral(LongLiteralNode n, P p); + /** + * Visits a float literal node. + * + * @param n the {@link FloatLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitFloatLiteral(FloatLiteralNode n, P p); + /** + * Visits a double literal node. + * + * @param n the {@link DoubleLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitDoubleLiteral(DoubleLiteralNode n, P p); + /** + * Visits a boolean literal node. + * + * @param n the {@link BooleanLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitBooleanLiteral(BooleanLiteralNode n, P p); + /** + * Visits a character literal node. + * + * @param n the {@link CharacterLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitCharacterLiteral(CharacterLiteralNode n, P p); + /** + * Visits a string literal node. + * + * @param n the {@link StringLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitStringLiteral(StringLiteralNode n, P p); + /** + * Visits a null literal node. + * + * @param n the {@link NullLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNullLiteral(NullLiteralNode n, P p); // Unary operations + /** + * Visits a unary minus node. + * + * @param n the {@link NumericalMinusNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNumericalMinus(NumericalMinusNode n, P p); + /** + * Visits a unary plus node. + * + * @param n the {@link NumericalPlusNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNumericalPlus(NumericalPlusNode n, P p); + /** + * Visits a bitwise complement node. + * + * @param n the {@link BitwiseComplementNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitBitwiseComplement(BitwiseComplementNode n, P p); + /** + * Visits a NullChk node. + * + * @param n the {@link NullChkNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNullChk(NullChkNode n, P p); // Binary operations + /** + * Visits a string concatenation node. + * + * @param n the {@link StringConcatenateNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitStringConcatenate(StringConcatenateNode n, P p); + /** + * Visits a numerical addition node. + * + * @param n the {@link NumericalAdditionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNumericalAddition(NumericalAdditionNode n, P p); + /** + * Visits a numerical subtraction node. + * + * @param n the {@link NumericalSubtractionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNumericalSubtraction(NumericalSubtractionNode n, P p); + /** + * Visits a numerical multiplication node. + * + * @param n the {@link NumericalMultiplicationNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNumericalMultiplication(NumericalMultiplicationNode n, P p); + /** + * Visits a integer division node. + * + * @param n the {@link IntegerDivisionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitIntegerDivision(IntegerDivisionNode n, P p); + /** + * Visits a floating division node. + * + * @param n the {@link FloatingDivisionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitFloatingDivision(FloatingDivisionNode n, P p); + /** + * Visits a integer remainder node. + * + * @param n the {@link IntegerRemainderNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitIntegerRemainder(IntegerRemainderNode n, P p); + /** + * Visits a floating remainder node. + * + * @param n the {@link FloatingRemainderNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitFloatingRemainder(FloatingRemainderNode n, P p); + /** + * Visits a left shift node. + * + * @param n the {@link LeftShiftNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitLeftShift(LeftShiftNode n, P p); + /** + * Visits a signed right shift node. + * + * @param n the {@link SignedRightShiftNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitSignedRightShift(SignedRightShiftNode n, P p); + /** + * Visits an unsigned right shift node. + * + * @param n the {@link UnsignedRightShiftNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitUnsignedRightShift(UnsignedRightShiftNode n, P p); + /** + * Visits a bitwise and node. + * + * @param n the {@link BitwiseAndNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitBitwiseAnd(BitwiseAndNode n, P p); + /** + * Visits a bitwise or node. + * + * @param n the {@link BitwiseOrNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitBitwiseOr(BitwiseOrNode n, P p); + /** + * Visits a bitwise xor node. + * + * @param n the {@link BitwiseXorNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitBitwiseXor(BitwiseXorNode n, P p); // Comparison operations + /** + * Visits a less than node. + * + * @param n the {@link LessThanNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitLessThan(LessThanNode n, P p); + /** + * Visits a less than or equal node. + * + * @param n the {@link LessThanOrEqualNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitLessThanOrEqual(LessThanOrEqualNode n, P p); + /** + * Visits a greater than node. + * + * @param n the {@link GreaterThanNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitGreaterThan(GreaterThanNode n, P p); + /** + * Visits a greater than or equal node. + * + * @param n the {@link GreaterThanOrEqualNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitGreaterThanOrEqual(GreaterThanOrEqualNode n, P p); + /** + * Visits an equal to node. + * + * @param n the {@link EqualToNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitEqualTo(EqualToNode n, P p); + /** + * Visits a not equal node. + * + * @param n the {@link NotEqualNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNotEqual(NotEqualNode n, P p); // Conditional operations + /** + * Visits a conditional and node. + * + * @param n the {@link ConditionalAndNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitConditionalAnd(ConditionalAndNode n, P p); + /** + * Visits a conditional or node. + * + * @param n the {@link ConditionalOrNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitConditionalOr(ConditionalOrNode n, P p); + /** + * Visits a conditional not node. + * + * @param n the {@link ConditionalNotNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitConditionalNot(ConditionalNotNode n, P p); + /** + * Visits a ternary expression node. + * + * @param n the {@link TernaryExpressionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitTernaryExpression(TernaryExpressionNode n, P p); + /** + * Visits a switch expression node. + * + * @param n the {@link SwitchExpressionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitSwitchExpressionNode(SwitchExpressionNode n, P p); + /** + * Visits a switch expression node. + * + * @param n the {@link SwitchExpressionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitAssignment(AssignmentNode n, P p); + /** + * Visits a local variable node. + * + * @param n the {@link LocalVariableNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitLocalVariable(LocalVariableNode n, P p); + /** + * Visits a variable declaration node. + * + * @param n the {@link VariableDeclarationNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitVariableDeclaration(VariableDeclarationNode n, P p); + /** + * Visits a field access node. + * + * @param n the {@link FieldAccessNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitFieldAccess(FieldAccessNode n, P p); + /** + * Visits a method access node. + * + * @param n the {@link MethodAccessNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitMethodAccess(MethodAccessNode n, P p); + /** + * Visits an array access node. + * + * @param n the {@link ArrayAccessNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitArrayAccess(ArrayAccessNode n, P p); + /** + * Visits an implicit this node. + * + * @param n the {@link ImplicitThisNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitImplicitThis(ImplicitThisNode n, P p); + /** + * Visits an explicit this node. + * + * @param n the {@link ExplicitThisNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitExplicitThis(ExplicitThisNode n, P p); + /** + * Visits a super node. + * + * @param n the {@link SuperNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitSuper(SuperNode n, P p); + /** + * Visits a return node. + * + * @param n the {@link ReturnNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitReturn(ReturnNode n, P p); + /** + * Visits a lambda result expression node. + * + * @param n the {@link LambdaResultExpressionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitLambdaResultExpression(LambdaResultExpressionNode n, P p); + /** + * Visits a string conversion node. + * + * @param n the {@link StringConversionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitStringConversion(StringConversionNode n, P p); + /** + * Visits a widening conversion node. + * + * @param n the {@link WideningConversionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitWideningConversion(WideningConversionNode n, P p); + /** + * Visits a narrowing conversion node. + * + * @param n the {@link NarrowingConversionNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitNarrowingConversion(NarrowingConversionNode n, P p); + /** + * Visits an instance of node. + * + * @param n the {@link InstanceOfNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitInstanceOf(InstanceOfNode n, P p); + /** + * Visits a type cast node. + * + * @param n the {@link TypeCastNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitTypeCast(TypeCastNode n, P p); // Blocks - + /** + * Visits a synchronized node. + * + * @param n the {@link SynchronizedNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitSynchronized(SynchronizedNode n, P p); // Statements + /** + * Visits an assertion error node. + * + * @param n the {@link AssertionErrorNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitAssertionError(AssertionErrorNode n, P p); + /** + * Visits a throw node. + * + * @param n the {@link ThrowNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitThrow(ThrowNode n, P p); // Cases + /** + * Visits a case node. + * + * @param n the {@link CaseNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitCase(CaseNode n, P p); // Method and constructor invocations + /** + * Visits a method invocation node. + * + * @param n the {@link MethodInvocationNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitMethodInvocation(MethodInvocationNode n, P p); + /** + * Visits a object creation node. + * + * @param n the {@link ObjectCreationNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitObjectCreation(ObjectCreationNode n, P p); + /** + * Visits a Member Reference node. + * + * @param n the {@link FunctionalInterfaceNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitMemberReference(FunctionalInterfaceNode n, P p); + /** + * Visits an array creation node. + * + * @param n the {@link ArrayCreationNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitArrayCreation(ArrayCreationNode n, P p); // Type, package and class names + /** + * Visits an array type node. + * + * @param n the {@link ArrayTypeNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitArrayType(ArrayTypeNode n, P p); + /** + * Visits a primitive type node. + * + * @param n the {@link PrimitiveTypeNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitPrimitiveType(PrimitiveTypeNode n, P p); + /** + * Visits a class literal node. + * + * @param n the {@link ClassLiteralNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ + R visitClassLiteral(ClassLiteralNode n, P p); + + /** + * Visits a class name node. + * + * @param n the {@link ClassNameNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitClassName(ClassNameNode n, P p); + /** + * Visits a package name node. + * + * @param n the {@link PackageNameNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitPackageName(PackageNameNode n, P p); // Parameterized types + /** + * Visits a parameterized type node. + * + * @param n the {@link ParameterizedTypeNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitParameterizedType(ParameterizedTypeNode n, P p); // Marker nodes + /** + * Visits a marker node. + * + * @param n the {@link MarkerNode} to be visited + * @param p the argument for the operation implemented by this visitor + * @return the return value of the operation implemented by this visitor + */ R visitMarker(MarkerNode n, P p); /** diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/PrimitiveTypeNode.java b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/PrimitiveTypeNode.java index a69081a99ab..e8107a8704e 100644 --- a/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/PrimitiveTypeNode.java +++ b/dataflow/src/main/java/org/checkerframework/dataflow/cfg/node/PrimitiveTypeNode.java @@ -18,12 +18,18 @@ *

type .class */ public class PrimitiveTypeNode extends Node { - + /** The PrimitiveTypeTree that represents the type. */ protected final PrimitiveTypeTree tree; /** For Types.isSameType. */ protected final Types types; + /** + * Create a new PrimitiveTypeNode. + * + * @param tree the tree that represents the type + * @param types the types utility + */ public PrimitiveTypeNode(PrimitiveTypeTree tree, Types types) { super(TreeUtils.typeOf(tree)); this.tree = tree; diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/expression/ClassName.java b/dataflow/src/main/java/org/checkerframework/dataflow/expression/ClassName.java index 708bdaa6ee4..2e4ee4e13cd 100644 --- a/dataflow/src/main/java/org/checkerframework/dataflow/expression/ClassName.java +++ b/dataflow/src/main/java/org/checkerframework/dataflow/expression/ClassName.java @@ -19,7 +19,7 @@ public class ClassName extends JavaExpression { /** * Creates a new ClassName object for the given type. * - * @param type the type for the new ClassName. If it will represent a class literal, the type is + * @param type the type for the new ClassName. If it represents a class literal, the type is * declared primitive, void, or array of one of them. If it represents part of a static * field access or static method invocation, the type is declared, type variable, or array * (including array of primitive). diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/expression/JavaExpression.java b/dataflow/src/main/java/org/checkerframework/dataflow/expression/JavaExpression.java index d55fd6eefb2..bd15ec22d89 100644 --- a/dataflow/src/main/java/org/checkerframework/dataflow/expression/JavaExpression.java +++ b/dataflow/src/main/java/org/checkerframework/dataflow/expression/JavaExpression.java @@ -22,6 +22,7 @@ import org.checkerframework.dataflow.cfg.node.ArrayAccessNode; import org.checkerframework.dataflow.cfg.node.ArrayCreationNode; import org.checkerframework.dataflow.cfg.node.BinaryOperationNode; +import org.checkerframework.dataflow.cfg.node.ClassLiteralNode; import org.checkerframework.dataflow.cfg.node.ClassNameNode; import org.checkerframework.dataflow.cfg.node.FieldAccessNode; import org.checkerframework.dataflow.cfg.node.LocalVariableNode; @@ -243,7 +244,7 @@ public static JavaExpression fromNodeFieldAccess(FieldAccessNode node) { // access. return new ThisReference(receiverNode.getType()); } else if (fieldName.equals("class")) { - // The CFG represents "className.class" as a FieldAccessNode; bit it is a class literal. + // The CFG represents "className.class" as a FieldAccessNode; but it is a class literal. return new ClassName(receiverNode.getType()); } JavaExpression receiver; @@ -280,6 +281,9 @@ public static JavaExpression fromNode(Node receiverNode) { JavaExpression result = null; if (receiverNode instanceof FieldAccessNode) { result = fromNodeFieldAccess((FieldAccessNode) receiverNode); + } else if (receiverNode instanceof ClassLiteralNode) { + ClassLiteralNode cl = (ClassLiteralNode) receiverNode; + result = new ClassName(cl.getClassName().getType()); } else if (receiverNode instanceof ThisNode) { result = new ThisReference(receiverNode.getType()); } else if (receiverNode instanceof SuperNode) { @@ -559,7 +563,7 @@ private static JavaExpression fromMemberSelect(MemberSelectTree memberSelectTree return new ClassName(expressionType); } if (TreeUtils.isExplicitThisDereference(memberSelectTree)) { - // the identifier is "class" + // the identifier is "this" return new ThisReference(expressionType); } diff --git a/dataflow/src/main/java/org/checkerframework/dataflow/expression/JavaExpressionVisitor.java b/dataflow/src/main/java/org/checkerframework/dataflow/expression/JavaExpressionVisitor.java index 024ec632ce1..69612800962 100644 --- a/dataflow/src/main/java/org/checkerframework/dataflow/expression/JavaExpressionVisitor.java +++ b/dataflow/src/main/java/org/checkerframework/dataflow/expression/JavaExpressionVisitor.java @@ -9,7 +9,7 @@ public abstract class JavaExpressionVisitor { /** - * Visits the given {@code javaExpr}. + * Visits the given {@link JavaExpression}. * * @param javaExpr the expression to visit * @param p the parameter to pass to the visit method diff --git a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java index 6fbd74259f5..eb57f65d855 100644 --- a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java +++ b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java @@ -1453,7 +1453,7 @@ public static boolean isClassLiteral(Tree tree) { * obj . f * * - * This method currently also returns true for class literals and qualified this. + * This method currently also returns true for qualified this. * * @param tree a tree that might be a field access * @return true iff if tree is a field access expression (implicit or explicit) @@ -1470,16 +1470,19 @@ public static boolean isFieldAccess(Tree tree) { * obj . f * * - * This method currently also returns a non-null value for class literals and qualified this. + * This method currently also returns a non-null value for qualified this. * * @param tree a tree that might be a field access * @return the element if tree is a field access expression (implicit or explicit); null * otherwise */ - // TODO: fix value for class literals and qualified this, which are not field accesses. + // TODO: fix value for qualified this, which is not field accesses. public static @Nullable VariableElement asFieldAccess(Tree tree) { + if (isClassLiteral(tree)) { + return null; + } if (tree.getKind() == Tree.Kind.MEMBER_SELECT) { - // explicit member access (or a class literal or a qualified this) + // explicit member access (or a qualified this) MemberSelectTree memberSelect = (MemberSelectTree) tree; assert isUseOfElement(memberSelect) : "@AssumeAssertion(nullness): tree kind"; Element el = TreeUtils.elementFromUse(memberSelect); @@ -1503,7 +1506,7 @@ public static boolean isFieldAccess(Tree tree) { /** * Compute the name of the field that the field access {@code tree} accesses. Requires {@code * tree} to be a field access, as determined by {@code isFieldAccess} (which currently also - * returns true for class literals and qualified this). + * returns true for qualified this). * * @param tree a field access tree * @return the name of the field accessed by {@code tree}