From 88a007244f51ed66a62d442e28de483e13a68576 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Wed, 28 Mar 2018 11:42:55 -0700 Subject: Update to version 2.4.0 of Checker Framework dataflow and javacutil Change-Id: I29e007625d0a25279d8b2967f89b1014b4825bd6 --- third_party/checker_framework_dataflow/BUILD | 17 +- .../dataflow-2.4.0-sources.jar | Bin 0 -> 162105 bytes .../checker_framework_dataflow/dataflow-2.4.0.jar | Bin 0 -> 308674 bytes .../dataflow/analysis/AbstractValue.java | 25 - .../dataflow/analysis/Analysis.java | 767 ---- .../dataflow/analysis/AnalysisResult.java | 220 - .../analysis/ConditionalTransferResult.java | 126 - .../dataflow/analysis/FlowExpressions.java | 1143 ----- .../dataflow/analysis/RegularTransferResult.java | 116 - .../checkerframework/dataflow/analysis/Store.java | 91 - .../dataflow/analysis/TransferFunction.java | 41 - .../dataflow/analysis/TransferInput.java | 250 -- .../dataflow/analysis/TransferResult.java | 104 - .../checkerframework/dataflow/cfg/CFGBuilder.java | 4491 -------------------- .../dataflow/cfg/CFGVisualizer.java | 167 - .../dataflow/cfg/ControlFlowGraph.java | 246 -- .../dataflow/cfg/DOTCFGVisualizer.java | 511 --- .../dataflow/cfg/JavaSource2CFGDOT.java | 269 -- .../dataflow/cfg/UnderlyingAST.java | 125 - .../checkerframework/dataflow/cfg/block/Block.java | 31 - .../dataflow/cfg/block/BlockImpl.java | 57 - .../dataflow/cfg/block/ConditionalBlock.java | 30 - .../dataflow/cfg/block/ConditionalBlockImpl.java | 81 - .../dataflow/cfg/block/ExceptionBlock.java | 27 - .../dataflow/cfg/block/ExceptionBlockImpl.java | 66 - .../dataflow/cfg/block/RegularBlock.java | 27 - .../dataflow/cfg/block/RegularBlockImpl.java | 59 - .../dataflow/cfg/block/SingleSuccessorBlock.java | 24 - .../cfg/block/SingleSuccessorBlockImpl.java | 45 - .../dataflow/cfg/block/SpecialBlock.java | 31 - .../dataflow/cfg/block/SpecialBlockImpl.java | 22 - .../dataflow/cfg/node/AbstractNodeVisitor.java | 374 -- .../dataflow/cfg/node/ArrayAccessNode.java | 81 - .../dataflow/cfg/node/ArrayCreationNode.java | 136 - .../dataflow/cfg/node/ArrayTypeNode.java | 60 - .../dataflow/cfg/node/AssertionErrorNode.java | 80 - .../dataflow/cfg/node/AssignmentContext.java | 126 - .../dataflow/cfg/node/AssignmentNode.java | 93 - .../dataflow/cfg/node/BinaryOperationNode.java | 52 - .../dataflow/cfg/node/BitwiseAndNode.java | 48 - .../dataflow/cfg/node/BitwiseComplementNode.java | 47 - .../dataflow/cfg/node/BitwiseOrNode.java | 48 - .../dataflow/cfg/node/BitwiseXorNode.java | 48 - .../dataflow/cfg/node/BooleanLiteralNode.java | 49 - .../dataflow/cfg/node/CaseNode.java | 81 - .../dataflow/cfg/node/CharacterLiteralNode.java | 51 - .../dataflow/cfg/node/ClassNameNode.java | 120 - .../dataflow/cfg/node/ConditionalAndNode.java | 48 - .../dataflow/cfg/node/ConditionalNotNode.java | 47 - .../dataflow/cfg/node/ConditionalOrNode.java | 47 - .../dataflow/cfg/node/DoubleLiteralNode.java | 50 - .../dataflow/cfg/node/EqualToNode.java | 47 - .../dataflow/cfg/node/ExplicitThisLiteralNode.java | 41 - .../dataflow/cfg/node/FieldAccessNode.java | 106 - .../dataflow/cfg/node/FloatLiteralNode.java | 50 - .../dataflow/cfg/node/FloatingDivisionNode.java | 48 - .../dataflow/cfg/node/FloatingRemainderNode.java | 48 - .../dataflow/cfg/node/FunctionalInterfaceNode.java | 90 - .../dataflow/cfg/node/GreaterThanNode.java | 48 - .../dataflow/cfg/node/GreaterThanOrEqualNode.java | 48 - .../dataflow/cfg/node/ImplicitThisLiteralNode.java | 31 - .../dataflow/cfg/node/InstanceOfNode.java | 87 - .../dataflow/cfg/node/IntegerDivisionNode.java | 48 - .../dataflow/cfg/node/IntegerLiteralNode.java | 51 - .../dataflow/cfg/node/IntegerRemainderNode.java | 48 - .../dataflow/cfg/node/LeftShiftNode.java | 48 - .../dataflow/cfg/node/LessThanNode.java | 51 - .../dataflow/cfg/node/LessThanOrEqualNode.java | 48 - .../dataflow/cfg/node/LocalVariableNode.java | 101 - .../dataflow/cfg/node/LongLiteralNode.java | 50 - .../dataflow/cfg/node/MarkerNode.java | 82 - .../dataflow/cfg/node/MethodAccessNode.java | 78 - .../dataflow/cfg/node/MethodInvocationNode.java | 126 - .../dataflow/cfg/node/NarrowingConversionNode.java | 76 - .../checkerframework/dataflow/cfg/node/Node.java | 144 - .../dataflow/cfg/node/NodeVisitor.java | 160 - .../dataflow/cfg/node/NotEqualNode.java | 48 - .../dataflow/cfg/node/NullChkNode.java | 69 - .../dataflow/cfg/node/NullLiteralNode.java | 49 - .../dataflow/cfg/node/NumericalAdditionNode.java | 47 - .../dataflow/cfg/node/NumericalMinusNode.java | 47 - .../cfg/node/NumericalMultiplicationNode.java | 48 - .../dataflow/cfg/node/NumericalPlusNode.java | 47 - .../cfg/node/NumericalSubtractionNode.java | 48 - .../dataflow/cfg/node/ObjectCreationNode.java | 101 - .../dataflow/cfg/node/PackageNameNode.java | 101 - .../dataflow/cfg/node/ParameterizedTypeNode.java | 67 - .../dataflow/cfg/node/PrimitiveTypeNode.java | 60 - .../dataflow/cfg/node/ReturnNode.java | 100 - .../dataflow/cfg/node/ShortLiteralNode.java | 54 - .../dataflow/cfg/node/SignedRightShiftNode.java | 48 - .../cfg/node/StringConcatenateAssignmentNode.java | 57 - .../dataflow/cfg/node/StringConcatenateNode.java | 48 - .../dataflow/cfg/node/StringConversionNode.java | 76 - .../dataflow/cfg/node/StringLiteralNode.java | 53 - .../dataflow/cfg/node/SuperNode.java | 66 - .../dataflow/cfg/node/SynchronizedNode.java | 89 - .../dataflow/cfg/node/TernaryExpressionNode.java | 94 - .../dataflow/cfg/node/ThisLiteralNode.java | 45 - .../dataflow/cfg/node/ThrowNode.java | 69 - .../dataflow/cfg/node/TypeCastNode.java | 72 - .../dataflow/cfg/node/UnaryOperationNode.java | 45 - .../dataflow/cfg/node/UnsignedRightShiftNode.java | 48 - .../dataflow/cfg/node/ValueLiteralNode.java | 72 - .../dataflow/cfg/node/VariableDeclarationNode.java | 71 - .../dataflow/cfg/node/WideningConversionNode.java | 76 - .../playground/ConstantPropagationPlayground.java | 27 - .../dataflow/constantpropagation/Constant.java | 102 - .../ConstantPropagationStore.java | 163 - .../ConstantPropagationTransfer.java | 85 - .../dataflow/qual/Deterministic.java | 87 - .../org/checkerframework/dataflow/qual/Pure.java | 30 - .../dataflow/qual/SideEffectFree.java | 54 - .../dataflow/qual/TerminatesExecution.java | 34 - .../dataflow/util/HashCodeUtils.java | 102 - .../dataflow/util/MostlySingleton.java | 151 - .../checkerframework/dataflow/util/NodeUtils.java | 56 - .../dataflow/util/PurityChecker.java | 491 --- .../dataflow/util/PurityUtils.java | 91 - 119 files changed, 5 insertions(+), 16033 deletions(-) create mode 100644 third_party/checker_framework_dataflow/dataflow-2.4.0-sources.jar create mode 100644 third_party/checker_framework_dataflow/dataflow-2.4.0.jar delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/AbstractValue.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/Analysis.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/AnalysisResult.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/ConditionalTransferResult.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/FlowExpressions.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/RegularTransferResult.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/Store.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferFunction.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferInput.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferResult.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/CFGBuilder.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/CFGVisualizer.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/ControlFlowGraph.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/DOTCFGVisualizer.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/JavaSource2CFGDOT.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/UnderlyingAST.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/Block.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/BlockImpl.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ConditionalBlock.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ConditionalBlockImpl.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ExceptionBlock.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ExceptionBlockImpl.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/RegularBlock.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/RegularBlockImpl.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SingleSuccessorBlock.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SingleSuccessorBlockImpl.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SpecialBlock.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SpecialBlockImpl.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AbstractNodeVisitor.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayAccessNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayCreationNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayTypeNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssertionErrorNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssignmentContext.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssignmentNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BinaryOperationNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseAndNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseComplementNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseOrNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseXorNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BooleanLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/CaseNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/CharacterLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ClassNameNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalAndNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalNotNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalOrNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/DoubleLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/EqualToNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ExplicitThisLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FieldAccessNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatingDivisionNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatingRemainderNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FunctionalInterfaceNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/GreaterThanNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/GreaterThanOrEqualNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ImplicitThisLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/InstanceOfNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerDivisionNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerRemainderNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LeftShiftNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LessThanNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LessThanOrEqualNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LocalVariableNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LongLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MarkerNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MethodAccessNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MethodInvocationNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NarrowingConversionNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/Node.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NodeVisitor.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NotEqualNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NullChkNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NullLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalAdditionNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalMinusNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalMultiplicationNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalPlusNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalSubtractionNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ObjectCreationNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/PackageNameNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ParameterizedTypeNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/PrimitiveTypeNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ReturnNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ShortLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SignedRightShiftNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConcatenateAssignmentNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConcatenateNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConversionNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SuperNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SynchronizedNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/TernaryExpressionNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ThisLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ThrowNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/TypeCastNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/UnaryOperationNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/UnsignedRightShiftNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ValueLiteralNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/VariableDeclarationNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/WideningConversionNode.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/playground/ConstantPropagationPlayground.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/Constant.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/ConstantPropagationStore.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/ConstantPropagationTransfer.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/Deterministic.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/Pure.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/SideEffectFree.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/TerminatesExecution.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/HashCodeUtils.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/MostlySingleton.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/NodeUtils.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java delete mode 100644 third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityUtils.java (limited to 'third_party/checker_framework_dataflow') diff --git a/third_party/checker_framework_dataflow/BUILD b/third_party/checker_framework_dataflow/BUILD index b174255011..8361cdc1bb 100644 --- a/third_party/checker_framework_dataflow/BUILD +++ b/third_party/checker_framework_dataflow/BUILD @@ -7,20 +7,13 @@ filegroup( srcs = glob(["**"]), ) -java_library( +java_import( name = "checker_framework_dataflow", - srcs = glob(["java/**"]), - javacopts = ["-Xep:MissingCasesInEnumSwitch:OFF"], - deps = [ - "//third_party/checker_framework_javacutil", - "@local_jdk//:langtools-neverlink", - ], + jars = ["dataflow-2.4.0.jar"], + srcjar = "dataflow-2.4.0-sources.jar", ) -load("//tools/build_rules:java_rules_skylark.bzl", "bootstrap_java_library") - -bootstrap_java_library( +filegroup( name = "bootstrap", - srcs = glob(["java/**"]), - deps = ["//third_party/checker_framework_javacutil:bootstrap"], + srcs = ["dataflow-2.4.0.jar"], ) diff --git a/third_party/checker_framework_dataflow/dataflow-2.4.0-sources.jar b/third_party/checker_framework_dataflow/dataflow-2.4.0-sources.jar new file mode 100644 index 0000000000..d95f203b8e Binary files /dev/null and b/third_party/checker_framework_dataflow/dataflow-2.4.0-sources.jar differ diff --git a/third_party/checker_framework_dataflow/dataflow-2.4.0.jar b/third_party/checker_framework_dataflow/dataflow-2.4.0.jar new file mode 100644 index 0000000000..2ee9edecdd Binary files /dev/null and b/third_party/checker_framework_dataflow/dataflow-2.4.0.jar differ diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/AbstractValue.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/AbstractValue.java deleted file mode 100644 index 25b78075da..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/AbstractValue.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -/** - * An abstract value used in the org.checkerframework.dataflow analysis. - * - * @author Stefan Heule - */ -public interface AbstractValue> { - - /** - * Compute the least upper bound of two stores. - * - *

Important: This method must fulfill the following contract: - * - *

- */ - V leastUpperBound(V other); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/Analysis.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/Analysis.java deleted file mode 100644 index 2e81b4af4a..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/Analysis.java +++ /dev/null @@ -1,767 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.LambdaExpressionTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.VariableTree; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.PriorityQueue; -import java.util.Set; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Types; -import org.checkerframework.dataflow.cfg.ControlFlowGraph; -import org.checkerframework.dataflow.cfg.UnderlyingAST; -import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGLambda; -import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod; -import org.checkerframework.dataflow.cfg.UnderlyingAST.Kind; -import org.checkerframework.dataflow.cfg.block.Block; -import org.checkerframework.dataflow.cfg.block.ConditionalBlock; -import org.checkerframework.dataflow.cfg.block.ExceptionBlock; -import org.checkerframework.dataflow.cfg.block.RegularBlock; -import org.checkerframework.dataflow.cfg.block.SpecialBlock; -import org.checkerframework.dataflow.cfg.node.AssignmentNode; -import org.checkerframework.dataflow.cfg.node.LocalVariableNode; -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.dataflow.cfg.node.ReturnNode; -import org.checkerframework.javacutil.ElementUtils; -import org.checkerframework.javacutil.Pair; - -/** - * An implementation of an iterative algorithm to solve a org.checkerframework.dataflow problem, - * given a control flow graph and a transfer function. - * - * @author Stefan Heule - * @param the abstract value type to be tracked by the analysis - * @param the store type used in the analysis - * @param the transfer function type that is used to approximated runtime behavior - */ -public class Analysis< - A extends AbstractValue, S extends Store, T extends TransferFunction> { - - /** Is the analysis currently running? */ - protected boolean isRunning = false; - - /** The transfer function for regular nodes. */ - protected T transferFunction; - - /** The control flow graph to perform the analysis on. */ - protected ControlFlowGraph cfg; - - /** The associated processing environment */ - protected final ProcessingEnvironment env; - - /** Instance of the types utility. */ - protected final Types types; - - /** Then stores before every basic block (assumed to be 'no information' if not present). */ - protected IdentityHashMap thenStores; - - /** Else stores before every basic block (assumed to be 'no information' if not present). */ - protected IdentityHashMap elseStores; - - /** - * Number of times every block has been analyzed since the last time widening was applied. Null, - * if maxCountBeforeWidening is -1 which implies widening isn't used for this analysis. - */ - protected IdentityHashMap blockCount; - - /** - * Number of times a block can be analyzed before widening. -1 implies that widening shouldn't - * be used. - */ - protected final int maxCountBeforeWidening; - - /** - * The transfer inputs before every basic block (assumed to be 'no information' if not present). - */ - protected IdentityHashMap> inputs; - - /** The stores after every return statement. */ - protected IdentityHashMap> storesAtReturnStatements; - - /** The worklist used for the fix-point iteration. */ - protected Worklist worklist; - - /** Abstract values of nodes. */ - protected IdentityHashMap nodeValues; - - /** Map from (effectively final) local variable elements to their abstract value. */ - public HashMap finalLocalValues; - - /** - * The node that is currently handled in the analysis (if it is running). The following - * invariant holds: - * - *
-     *   !isRunning ⇒ (currentNode == null)
-     * 
- */ - protected Node currentNode; - - /** - * The tree that is currently being looked at. The transfer function can set this tree to make - * sure that calls to {@code getValue} will not return information for this given tree. - */ - protected Tree currentTree; - - /** The current transfer input when the analysis is running. */ - protected TransferInput currentInput; - - public Tree getCurrentTree() { - return currentTree; - } - - public void setCurrentTree(Tree currentTree) { - this.currentTree = currentTree; - } - - /** - * Construct an object that can perform a org.checkerframework.dataflow analysis over a control - * flow graph. The transfer function is set later using {@code setTransferFunction}. - */ - public Analysis(ProcessingEnvironment env) { - this(env, null, -1); - } - - /** - * Construct an object that can perform a org.checkerframework.dataflow analysis over a control - * flow graph, given a transfer function. - */ - public Analysis(ProcessingEnvironment env, T transfer) { - this(env, transfer, -1); - } - - /** - * Construct an object that can perform a org.checkerframework.dataflow analysis over a control - * flow graph, given a transfer function. - */ - public Analysis(ProcessingEnvironment env, T transfer, int maxCountBeforeWidening) { - this.env = env; - types = env.getTypeUtils(); - this.transferFunction = transfer; - this.maxCountBeforeWidening = maxCountBeforeWidening; - this.transferFunction = transfer; - } - - public void setTransferFunction(T transfer) { - this.transferFunction = transfer; - } - - public T getTransferFunction() { - return transferFunction; - } - - public Types getTypes() { - return types; - } - - public ProcessingEnvironment getEnv() { - return env; - } - - /** - * Perform the actual analysis. Should only be called once after the object has been created. - */ - public void performAnalysis(ControlFlowGraph cfg) { - assert isRunning == false; - isRunning = true; - - init(cfg); - - while (!worklist.isEmpty()) { - Block b = worklist.poll(); - - switch (b.getType()) { - case REGULAR_BLOCK: - { - RegularBlock rb = (RegularBlock) b; - - // apply transfer function to contents - TransferInput inputBefore = getInputBefore(rb); - currentInput = inputBefore.copy(); - TransferResult transferResult = null; - Node lastNode = null; - boolean addToWorklistAgain = false; - for (Node n : rb.getContents()) { - transferResult = callTransferFunction(n, currentInput); - addToWorklistAgain |= updateNodeValues(n, transferResult); - currentInput = new TransferInput<>(n, this, transferResult); - lastNode = n; - } - // loop will run at least one, making transferResult non-null - - // propagate store to successors - Block succ = rb.getSuccessor(); - assert succ != null - : "regular basic block without non-exceptional successor unexpected"; - propagateStoresTo( - succ, lastNode, currentInput, rb.getFlowRule(), addToWorklistAgain); - break; - } - - case EXCEPTION_BLOCK: - { - ExceptionBlock eb = (ExceptionBlock) b; - - // apply transfer function to content - TransferInput inputBefore = getInputBefore(eb); - currentInput = inputBefore.copy(); - Node node = eb.getNode(); - TransferResult transferResult = - callTransferFunction(node, currentInput); - boolean addToWorklistAgain = updateNodeValues(node, transferResult); - - // propagate store to successor - Block succ = eb.getSuccessor(); - if (succ != null) { - currentInput = new TransferInput<>(node, this, transferResult); - // TODO? Variable wasn't used. - // Store.FlowRule storeFlow = eb.getFlowRule(); - propagateStoresTo( - succ, node, currentInput, eb.getFlowRule(), addToWorklistAgain); - } - - // propagate store to exceptional successors - for (Entry> e : - eb.getExceptionalSuccessors().entrySet()) { - TypeMirror cause = e.getKey(); - S exceptionalStore = transferResult.getExceptionalStore(cause); - if (exceptionalStore != null) { - for (Block exceptionSucc : e.getValue()) { - addStoreBefore( - exceptionSucc, - node, - exceptionalStore, - Store.Kind.BOTH, - addToWorklistAgain); - } - } else { - for (Block exceptionSucc : e.getValue()) { - addStoreBefore( - exceptionSucc, - node, - inputBefore.copy().getRegularStore(), - Store.Kind.BOTH, - addToWorklistAgain); - } - } - } - break; - } - - case CONDITIONAL_BLOCK: - { - ConditionalBlock cb = (ConditionalBlock) b; - - // get store before - TransferInput inputBefore = getInputBefore(cb); - TransferInput input = inputBefore.copy(); - - // propagate store to successor - Block thenSucc = cb.getThenSuccessor(); - Block elseSucc = cb.getElseSuccessor(); - - propagateStoresTo(thenSucc, null, input, cb.getThenFlowRule(), false); - propagateStoresTo(elseSucc, null, input, cb.getElseFlowRule(), false); - break; - } - - case SPECIAL_BLOCK: - { - // special basic blocks are empty and cannot throw exceptions, - // thus there is no need to perform any analysis. - SpecialBlock sb = (SpecialBlock) b; - Block succ = sb.getSuccessor(); - if (succ != null) { - propagateStoresTo( - succ, null, getInputBefore(b), sb.getFlowRule(), false); - } - break; - } - - default: - assert false; - break; - } - } - - assert isRunning == true; - isRunning = false; - } - - /** - * Propagate the stores in currentInput to the successor block, succ, according to the flowRule. - */ - protected void propagateStoresTo( - Block succ, - Node node, - TransferInput currentInput, - Store.FlowRule flowRule, - boolean addToWorklistAgain) { - switch (flowRule) { - case EACH_TO_EACH: - if (currentInput.containsTwoStores()) { - addStoreBefore( - succ, - node, - currentInput.getThenStore(), - Store.Kind.THEN, - addToWorklistAgain); - addStoreBefore( - succ, - node, - currentInput.getElseStore(), - Store.Kind.ELSE, - addToWorklistAgain); - } else { - addStoreBefore( - succ, - node, - currentInput.getRegularStore(), - Store.Kind.BOTH, - addToWorklistAgain); - } - break; - case THEN_TO_BOTH: - addStoreBefore( - succ, - node, - currentInput.getThenStore(), - Store.Kind.BOTH, - addToWorklistAgain); - break; - case ELSE_TO_BOTH: - addStoreBefore( - succ, - node, - currentInput.getElseStore(), - Store.Kind.BOTH, - addToWorklistAgain); - break; - case THEN_TO_THEN: - addStoreBefore( - succ, - node, - currentInput.getThenStore(), - Store.Kind.THEN, - addToWorklistAgain); - break; - case ELSE_TO_ELSE: - addStoreBefore( - succ, - node, - currentInput.getElseStore(), - Store.Kind.ELSE, - addToWorklistAgain); - break; - } - } - - /** - * Updates the value of node {@code node} to the value of the {@code transferResult}. Returns - * true if the node's value changed, or a store was updated. - */ - protected boolean updateNodeValues(Node node, TransferResult transferResult) { - A newVal = transferResult.getResultValue(); - boolean nodeValueChanged = false; - - if (newVal != null) { - A oldVal = nodeValues.get(node); - nodeValues.put(node, newVal); - nodeValueChanged = !Objects.equals(oldVal, newVal); - } - - return nodeValueChanged || transferResult.storeChanged(); - } - - /** - * Call the transfer function for node {@code node}, and set that node as current node first. - */ - protected TransferResult callTransferFunction(Node node, TransferInput store) { - - if (node.isLValue()) { - // TODO: should the default behavior be to return either a regular - // transfer result or a conditional transfer result (depending on - // store.hasTwoStores()), or is the following correct? - return new RegularTransferResult(null, store.getRegularStore()); - } - store.node = node; - currentNode = node; - TransferResult transferResult = node.accept(transferFunction, store); - currentNode = null; - if (node instanceof ReturnNode) { - // save a copy of the store to later check if some property held at - // a given return statement - storesAtReturnStatements.put((ReturnNode) node, transferResult); - } - if (node instanceof AssignmentNode) { - // store the flow-refined value for effectively final local variables - AssignmentNode assignment = (AssignmentNode) node; - Node lhst = assignment.getTarget(); - if (lhst instanceof LocalVariableNode) { - LocalVariableNode lhs = (LocalVariableNode) lhst; - Element elem = lhs.getElement(); - if (ElementUtils.isEffectivelyFinal(elem)) { - finalLocalValues.put(elem, transferResult.getResultValue()); - } - } - } - return transferResult; - } - - /** Initialize the analysis with a new control flow graph. */ - protected void init(ControlFlowGraph cfg) { - this.cfg = cfg; - thenStores = new IdentityHashMap<>(); - elseStores = new IdentityHashMap<>(); - blockCount = maxCountBeforeWidening == -1 ? null : new IdentityHashMap(); - inputs = new IdentityHashMap<>(); - storesAtReturnStatements = new IdentityHashMap<>(); - worklist = new Worklist(cfg); - nodeValues = new IdentityHashMap<>(); - finalLocalValues = new HashMap<>(); - worklist.add(cfg.getEntryBlock()); - - List parameters = null; - UnderlyingAST underlyingAST = cfg.getUnderlyingAST(); - if (underlyingAST.getKind() == Kind.METHOD) { - MethodTree tree = ((CFGMethod) underlyingAST).getMethod(); - parameters = new ArrayList<>(); - for (VariableTree p : tree.getParameters()) { - LocalVariableNode var = new LocalVariableNode(p); - parameters.add(var); - // TODO: document that LocalVariableNode has no block that it - // belongs to - } - } else if (underlyingAST.getKind() == Kind.LAMBDA) { - LambdaExpressionTree lambda = ((CFGLambda) underlyingAST).getLambdaTree(); - parameters = new ArrayList<>(); - for (VariableTree p : lambda.getParameters()) { - LocalVariableNode var = new LocalVariableNode(p); - parameters.add(var); - // TODO: document that LocalVariableNode has no block that it - // belongs to - } - - } else { - // nothing to do - } - S initialStore = transferFunction.initialStore(underlyingAST, parameters); - Block entry = cfg.getEntryBlock(); - thenStores.put(entry, initialStore); - elseStores.put(entry, initialStore); - inputs.put(entry, new TransferInput<>(null, this, initialStore)); - } - - /** - * Add a basic block to the worklist. If {@code b} is already present, the method does nothing. - */ - protected void addToWorklist(Block b) { - // TODO: use a more efficient way to check if b is already present - if (!worklist.contains(b)) { - worklist.add(b); - } - } - - /** - * Add a store before the basic block {@code b} by merging with the existing stores for that - * location. - */ - protected void addStoreBefore( - Block b, Node node, S s, Store.Kind kind, boolean addBlockToWorklist) { - S thenStore = getStoreBefore(b, Store.Kind.THEN); - S elseStore = getStoreBefore(b, Store.Kind.ELSE); - boolean shouldWiden = false; - if (blockCount != null) { - Integer count = blockCount.get(b); - if (count == null) { - count = 0; - } - shouldWiden = count >= maxCountBeforeWidening; - if (shouldWiden) { - blockCount.put(b, 0); - } else { - blockCount.put(b, count + 1); - } - } - - switch (kind) { - case THEN: - { - // Update the then store - S newThenStore = mergeStores(s, thenStore, shouldWiden); - if (!newThenStore.equals(thenStore)) { - thenStores.put(b, newThenStore); - if (elseStore != null) { - inputs.put(b, new TransferInput<>(node, this, newThenStore, elseStore)); - addBlockToWorklist = true; - } - } - break; - } - case ELSE: - { - // Update the else store - S newElseStore = mergeStores(s, elseStore, shouldWiden); - if (!newElseStore.equals(elseStore)) { - elseStores.put(b, newElseStore); - if (thenStore != null) { - inputs.put(b, new TransferInput<>(node, this, thenStore, newElseStore)); - addBlockToWorklist = true; - } - } - break; - } - case BOTH: - if (thenStore == elseStore) { - // Currently there is only one regular store - S newStore = mergeStores(s, thenStore, shouldWiden); - if (!newStore.equals(thenStore)) { - thenStores.put(b, newStore); - elseStores.put(b, newStore); - inputs.put(b, new TransferInput<>(node, this, newStore)); - addBlockToWorklist = true; - } - } else { - boolean storeChanged = false; - - S newThenStore = mergeStores(s, thenStore, shouldWiden); - if (!newThenStore.equals(thenStore)) { - thenStores.put(b, newThenStore); - storeChanged = true; - } - - S newElseStore = mergeStores(s, elseStore, shouldWiden); - if (!newElseStore.equals(elseStore)) { - elseStores.put(b, newElseStore); - storeChanged = true; - } - - if (storeChanged) { - inputs.put(b, new TransferInput<>(node, this, newThenStore, newElseStore)); - addBlockToWorklist = true; - } - } - } - - if (addBlockToWorklist) { - addToWorklist(b); - } - } - - private S mergeStores(S newStore, S previousStore, boolean shouldWiden) { - if (previousStore == null) { - return newStore; - } else if (shouldWiden) { - return newStore.widenedUpperBound(previousStore); - } else { - return newStore.leastUpperBound(previousStore); - } - } - - /** - * A worklist is a priority queue of blocks in which the order is given by depth-first ordering - * to place non-loop predecessors ahead of successors. - */ - protected static class Worklist { - - /** Map all blocks in the CFG to their depth-first order. */ - protected IdentityHashMap depthFirstOrder; - - /** Comparator to allow priority queue to order blocks by their depth-first order. */ - public class DFOComparator implements Comparator { - @Override - public int compare(Block b1, Block b2) { - return depthFirstOrder.get(b1) - depthFirstOrder.get(b2); - } - } - - /** The backing priority queue. */ - protected PriorityQueue queue; - - public Worklist(ControlFlowGraph cfg) { - depthFirstOrder = new IdentityHashMap<>(); - int count = 1; - for (Block b : cfg.getDepthFirstOrderedBlocks()) { - depthFirstOrder.put(b, count++); - } - - queue = new PriorityQueue(11, new DFOComparator()); - } - - public boolean isEmpty() { - return queue.isEmpty(); - } - - public boolean contains(Block block) { - return queue.contains(block); - } - - public void add(Block block) { - queue.add(block); - } - - public Block poll() { - return queue.poll(); - } - - @Override - public String toString() { - return "Worklist(" + queue + ")"; - } - } - - /** - * Read the {@link TransferInput} for a particular basic block (or {@code null} if none exists - * yet). - */ - public /*@Nullable*/ TransferInput getInput(Block b) { - return getInputBefore(b); - } - - /** - * @return the transfer input corresponding to the location right before the basic block {@code - * b}. - */ - protected /*@Nullable*/ TransferInput getInputBefore(Block b) { - return inputs.get(b); - } - - /** @return the store corresponding to the location right before the basic block {@code b}. */ - protected /*@Nullable*/ S getStoreBefore(Block b, Store.Kind kind) { - switch (kind) { - case THEN: - return readFromStore(thenStores, b); - case ELSE: - return readFromStore(elseStores, b); - default: - assert false; - return null; - } - } - - /** - * Read the {@link Store} for a particular basic block from a map of stores (or {@code null} if - * none exists yet). - */ - protected static /*@Nullable*/ S readFromStore(Map stores, Block b) { - return stores.get(b); - } - - /** Is the analysis currently running? */ - public boolean isRunning() { - return isRunning; - } - - /** - * @return the abstract value for {@link Node} {@code n}, or {@code null} if no information is - * available. Note that if the analysis has not finished yet, this value might not represent - * the final value for this node. - */ - public /*@Nullable*/ A getValue(Node n) { - if (isRunning) { - // we do not yet have a org.checkerframework.dataflow fact about the current node - if (currentNode == null - || currentNode == n - || (currentTree != null && currentTree == n.getTree())) { - return null; - } - // check that 'n' is a subnode of 'node'. Check immediate operands - // first for efficiency. - assert !n.isLValue() : "Did not expect an lvalue, but got " + n; - if (!(currentNode != n - && (currentNode.getOperands().contains(n) - || currentNode.getTransitiveOperands().contains(n)))) { - return null; - } - return nodeValues.get(n); - } - return nodeValues.get(n); - } - - /** - * @return the abstract value for {@link Tree} {@code t}, or {@code null} if no information is - * available. Note that if the analysis has not finished yet, this value might not represent - * the final value for this node. - */ - public /*@Nullable*/ A getValue(Tree t) { - // we do not yet have a org.checkerframework.dataflow fact about the current node - if (t == currentTree) { - return null; - } - Node nodeCorrespondingToTree = getNodeForTree(t); - if (nodeCorrespondingToTree == null || nodeCorrespondingToTree.isLValue()) { - return null; - } - return getValue(nodeCorrespondingToTree); - } - - /** Get the {@link Node} for a given {@link Tree}. */ - public Node getNodeForTree(Tree t) { - return cfg.getNodeCorrespondingToTree(t); - } - - /** - * Get the {@link MethodTree} of the current CFG if the argument {@link Tree} maps to a {@link - * Node} in the CFG or null otherwise. - */ - public /*@Nullable*/ MethodTree getContainingMethod(Tree t) { - return cfg.getContainingMethod(t); - } - - /** - * Get the {@link ClassTree} of the current CFG if the argument {@link Tree} maps to a {@link - * Node} in the CFG or null otherwise. - */ - public /*@Nullable*/ ClassTree getContainingClass(Tree t) { - return cfg.getContainingClass(t); - } - - public List>> getReturnStatementStores() { - List>> result = new ArrayList<>(); - for (ReturnNode returnNode : cfg.getReturnNodes()) { - TransferResult store = storesAtReturnStatements.get(returnNode); - result.add(Pair.of(returnNode, store)); - } - return result; - } - - public AnalysisResult getResult() { - assert !isRunning; - IdentityHashMap treeLookup = cfg.getTreeLookup(); - return new AnalysisResult<>(nodeValues, inputs, treeLookup, finalLocalValues); - } - - /** - * @return the regular exit store, or {@code null}, if there is no such store (because the - * method cannot exit through the regular exit block). - */ - public /*@Nullable*/ S getRegularExitStore() { - SpecialBlock regularExitBlock = cfg.getRegularExitBlock(); - if (inputs.containsKey(regularExitBlock)) { - S regularExitStore = inputs.get(regularExitBlock).getRegularStore(); - return regularExitStore; - } else { - return null; - } - } - - public S getExceptionalExitStore() { - S exceptionalExitStore = inputs.get(cfg.getExceptionalExitBlock()).getRegularStore(); - return exceptionalExitStore; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/AnalysisResult.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/AnalysisResult.java deleted file mode 100644 index 48f376dbea..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/AnalysisResult.java +++ /dev/null @@ -1,220 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.Tree; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Map.Entry; -import javax.lang.model.element.Element; -import org.checkerframework.dataflow.cfg.block.Block; -import org.checkerframework.dataflow.cfg.block.ExceptionBlock; -import org.checkerframework.dataflow.cfg.block.RegularBlock; -import org.checkerframework.dataflow.cfg.node.Node; - -/** - * An {@link AnalysisResult} represents the result of a org.checkerframework.dataflow analysis by - * providing the abstract values given a node or a tree. Note that it does not keep track of custom - * results computed by some analysis. - * - * @author Stefan Heule - * @param
type of the abstract value that is tracked - */ -public class AnalysisResult, S extends Store> { - - /** Abstract values of nodes. */ - protected final IdentityHashMap nodeValues; - - /** Map from AST {@link Tree}s to {@link Node}s. */ - protected final IdentityHashMap treeLookup; - - /** Map from (effectively final) local variable elements to their abstract value. */ - protected final HashMap finalLocalValues; - - /** The stores before every method call. */ - protected final IdentityHashMap> stores; - - /** Initialize with a given node-value mapping. */ - public AnalysisResult( - Map nodeValues, - IdentityHashMap> stores, - IdentityHashMap treeLookup, - HashMap finalLocalValues) { - this.nodeValues = new IdentityHashMap<>(nodeValues); - this.treeLookup = new IdentityHashMap<>(treeLookup); - this.stores = stores; - this.finalLocalValues = finalLocalValues; - } - - /** Initialize empty result. */ - public AnalysisResult() { - nodeValues = new IdentityHashMap<>(); - treeLookup = new IdentityHashMap<>(); - stores = new IdentityHashMap<>(); - finalLocalValues = new HashMap<>(); - } - - /** Combine with another analysis result. */ - public void combine(AnalysisResult other) { - for (Entry e : other.nodeValues.entrySet()) { - nodeValues.put(e.getKey(), e.getValue()); - } - for (Entry e : other.treeLookup.entrySet()) { - treeLookup.put(e.getKey(), e.getValue()); - } - for (Entry> e : other.stores.entrySet()) { - stores.put(e.getKey(), e.getValue()); - } - for (Entry e : other.finalLocalValues.entrySet()) { - finalLocalValues.put(e.getKey(), e.getValue()); - } - } - - /** @return the value of effectively final local variables */ - public HashMap getFinalLocalValues() { - return finalLocalValues; - } - - /** - * @return the abstract value for {@link Node} {@code n}, or {@code null} if no information is - * available. - */ - public /*@Nullable*/ A getValue(Node n) { - return nodeValues.get(n); - } - - /** - * @return the abstract value for {@link Tree} {@code t}, or {@code null} if no information is - * available. - */ - public /*@Nullable*/ A getValue(Tree t) { - A val = getValue(treeLookup.get(t)); - return val; - } - - /** @return the {@link Node} for a given {@link Tree}. */ - public /*@Nullable*/ Node getNodeForTree(Tree tree) { - return treeLookup.get(tree); - } - - /** @return the store immediately before a given {@link Tree}. */ - public S getStoreBefore(Tree tree) { - Node node = getNodeForTree(tree); - if (node == null) { - return null; - } - return getStoreBefore(node); - } - - /** @return the store immediately before a given {@link Node}. */ - public S getStoreBefore(Node node) { - return runAnalysisFor(node, true); - } - - /** @return the store immediately after a given {@link Tree}. */ - public S getStoreAfter(Tree tree) { - Node node = getNodeForTree(tree); - if (node == null) { - return null; - } - return getStoreAfter(node); - } - - /** @return the store immediately after a given {@link Node}. */ - public S getStoreAfter(Node node) { - return runAnalysisFor(node, false); - } - - /** - * Runs the analysis again within the block of {@code node} and returns the store at the - * location of {@code node}. If {@code before} is true, then the store immediately before the - * {@link Node} {@code node} is returned. Otherwise, the store after {@code node} is returned. - * - *

For the meaning of storeChanged, see {@link - * org.checkerframework.dataflow.analysis.TransferResult#storeChanged}. - * - *

Exceptions: If the corresponding {@link - * org.checkerframework.dataflow.cfg.node.Node} throws an exception, then it is assumed that no - * special handling is necessary and the store before the corresponding {@link - * org.checkerframework.dataflow.cfg.node.Node} will be passed along any exceptional edge. - * - *

Aliasing: {@code thenStore} and {@code elseStore} are not allowed to be used - * anywhere outside of this class (including use through aliases). Complete control over the - * objects is transfered to this class. - */ - public ConditionalTransferResult(A value, S thenStore, S elseStore, boolean storeChanged) { - super(value); - this.thenStore = thenStore; - this.elseStore = elseStore; - this.storeChanged = storeChanged; - } - - public ConditionalTransferResult(A value, S thenStore, S elseStore) { - this(value, thenStore, elseStore, false); - } - - /** - * Create a {@code ConditionalTransferResult} with {@code thenStore} as the resulting store if - * the corresponding {@link org.checkerframework.dataflow.cfg.node.Node} evaluates to {@code - * true} and {@code elseStore} otherwise. - * - *

Exceptions: If the corresponding {@link - * org.checkerframework.dataflow.cfg.node.Node} throws an exception, then the corresponding - * store in {@code exceptionalStores} is used. If no exception is found in {@code - * exceptionalStores}, then it is assumed that no special handling is necessary and the store - * before the corresponding {@link org.checkerframework.dataflow.cfg.node.Node} will be passed - * along any exceptional edge. - * - *

Aliasing: {@code thenStore}, {@code elseStore}, and any store in {@code - * exceptionalStores} are not allowed to be used anywhere outside of this class (including use - * through aliases). Complete control over the objects is transfered to this class. - */ - public ConditionalTransferResult( - A value, - S thenStore, - S elseStore, - Map exceptionalStores, - boolean storeChanged) { - super(value); - this.exceptionalStores = exceptionalStores; - this.thenStore = thenStore; - this.elseStore = elseStore; - this.storeChanged = storeChanged; - } - - public ConditionalTransferResult( - A value, S thenStore, S elseStore, Map exceptionalStores) { - this(value, thenStore, elseStore, exceptionalStores, false); - } - - @Override - public S getRegularStore() { - return thenStore.leastUpperBound(elseStore); - } - - @Override - public S getThenStore() { - return thenStore; - } - - @Override - public S getElseStore() { - return elseStore; - } - - @Override - public boolean containsTwoStores() { - return true; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append("RegularTransferResult("); - result.append(System.getProperty("line.separator")); - result.append("resultValue = " + resultValue); - result.append(System.getProperty("line.separator")); - result.append("thenStore = " + thenStore); - result.append("elseStore = " + elseStore); - result.append(System.getProperty("line.separator")); - result.append(")"); - return result.toString(); - } - - /** @see org.checkerframework.dataflow.analysis.TransferResult#storeChanged() */ - @Override - public boolean storeChanged() { - return storeChanged; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/FlowExpressions.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/FlowExpressions.java deleted file mode 100644 index 85ad7b4b00..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/FlowExpressions.java +++ /dev/null @@ -1,1143 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -import com.sun.source.tree.ArrayAccessTree; -import com.sun.source.tree.ExpressionTree; -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.MemberSelectTree; -import com.sun.source.tree.MethodInvocationTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.VariableTree; -import com.sun.source.util.TreePath; -import com.sun.tools.javac.code.Symbol.VarSymbol; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.cfg.node.ArrayAccessNode; -import org.checkerframework.dataflow.cfg.node.ArrayCreationNode; -import org.checkerframework.dataflow.cfg.node.ClassNameNode; -import org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode; -import org.checkerframework.dataflow.cfg.node.FieldAccessNode; -import org.checkerframework.dataflow.cfg.node.LocalVariableNode; -import org.checkerframework.dataflow.cfg.node.MethodInvocationNode; -import org.checkerframework.dataflow.cfg.node.NarrowingConversionNode; -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.dataflow.cfg.node.StringConversionNode; -import org.checkerframework.dataflow.cfg.node.SuperNode; -import org.checkerframework.dataflow.cfg.node.ThisLiteralNode; -import org.checkerframework.dataflow.cfg.node.ValueLiteralNode; -import org.checkerframework.dataflow.cfg.node.WideningConversionNode; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.dataflow.util.PurityUtils; -import org.checkerframework.javacutil.AnnotationProvider; -import org.checkerframework.javacutil.ElementUtils; -import org.checkerframework.javacutil.ErrorReporter; -import org.checkerframework.javacutil.InternalUtils; -import org.checkerframework.javacutil.TreeUtils; -import org.checkerframework.javacutil.TypeAnnotationUtils; -import org.checkerframework.javacutil.TypesUtils; - -/** - * Collection of classes and helper functions to represent Java expressions about which the - * org.checkerframework.dataflow analysis can possibly infer facts. Expressions include: - * - *

- * - * @author Stefan Heule - */ -public class FlowExpressions { - - /** - * @return the internal representation (as {@link FieldAccess}) of a {@link FieldAccessNode}. - * Can contain {@link Unknown} as receiver. - */ - public static FieldAccess internalReprOfFieldAccess( - AnnotationProvider provider, FieldAccessNode node) { - Receiver receiver; - Node receiverNode = node.getReceiver(); - if (node.isStatic()) { - receiver = new ClassName(receiverNode.getType()); - } else { - receiver = internalReprOf(provider, receiverNode); - } - return new FieldAccess(receiver, node); - } - - /** - * @return the internal representation (as {@link FieldAccess}) of a {@link FieldAccessNode}. - * Can contain {@link Unknown} as receiver. - */ - public static ArrayAccess internalReprOfArrayAccess( - AnnotationProvider provider, ArrayAccessNode node) { - Receiver receiver = internalReprOf(provider, node.getArray()); - Receiver index = internalReprOf(provider, node.getIndex()); - return new ArrayAccess(node.getType(), receiver, index); - } - - /** - * We ignore operations such as widening and narrowing when computing the internal - * representation. - * - * @return the internal representation (as {@link Receiver}) of any {@link Node}. Might contain - * {@link Unknown}. - */ - public static Receiver internalReprOf(AnnotationProvider provider, Node receiverNode) { - return internalReprOf(provider, receiverNode, false); - } - - /** - * We ignore operations such as widening and narrowing when computing the internal - * representation. - * - * @return the internal representation (as {@link Receiver}) of any {@link Node}. Might contain - * {@link Unknown}. - */ - public static Receiver internalReprOf( - AnnotationProvider provider, Node receiverNode, boolean allowNonDeterministic) { - Receiver receiver = null; - if (receiverNode instanceof FieldAccessNode) { - FieldAccessNode fan = (FieldAccessNode) receiverNode; - - if (fan.getFieldName().equals("this")) { - // For some reason, "className.this" is considered a field access. - // We right this wrong here. - receiver = new ThisReference(fan.getReceiver().getType()); - } else if (fan.getFieldName().equals("class")) { - // "className.class" is considered a field access. This makes sense, - // since .class is similar to a field access which is the equivalent - // of a call to getClass(). However for the purposes of dataflow - // analysis, and value stores, this is the equivalent of a ClassNameNode. - receiver = new ClassName(fan.getReceiver().getType()); - } else { - receiver = internalReprOfFieldAccess(provider, fan); - } - } else if (receiverNode instanceof ExplicitThisLiteralNode) { - receiver = new ThisReference(receiverNode.getType()); - } else if (receiverNode instanceof ThisLiteralNode) { - receiver = new ThisReference(receiverNode.getType()); - } else if (receiverNode instanceof SuperNode) { - receiver = new ThisReference(receiverNode.getType()); - } else if (receiverNode instanceof LocalVariableNode) { - LocalVariableNode lv = (LocalVariableNode) receiverNode; - receiver = new LocalVariable(lv); - } else if (receiverNode instanceof ArrayAccessNode) { - ArrayAccessNode a = (ArrayAccessNode) receiverNode; - receiver = internalReprOfArrayAccess(provider, a); - } else if (receiverNode instanceof StringConversionNode) { - // ignore string conversion - return internalReprOf(provider, ((StringConversionNode) receiverNode).getOperand()); - } else if (receiverNode instanceof WideningConversionNode) { - // ignore widening - return internalReprOf(provider, ((WideningConversionNode) receiverNode).getOperand()); - } else if (receiverNode instanceof NarrowingConversionNode) { - // ignore narrowing - return internalReprOf(provider, ((NarrowingConversionNode) receiverNode).getOperand()); - } else if (receiverNode instanceof ClassNameNode) { - ClassNameNode cn = (ClassNameNode) receiverNode; - receiver = new ClassName(cn.getType()); - } else if (receiverNode instanceof ValueLiteralNode) { - ValueLiteralNode vn = (ValueLiteralNode) receiverNode; - receiver = new ValueLiteral(vn.getType(), vn); - } else if (receiverNode instanceof ArrayCreationNode) { - ArrayCreationNode an = (ArrayCreationNode) receiverNode; - receiver = new ArrayCreation(an.getType(), an.getDimensions(), an.getInitializers()); - } else if (receiverNode instanceof MethodInvocationNode) { - MethodInvocationNode mn = (MethodInvocationNode) receiverNode; - ExecutableElement invokedMethod = TreeUtils.elementFromUse(mn.getTree()); - - // check if this represents a boxing operation of a constant, in which - // case we treat the method call as deterministic, because there is no way - // to behave differently in two executions where two constants are being used. - boolean considerDeterministic = false; - if (invokedMethod.toString().equals("valueOf(long)") - && mn.getTarget().getReceiver().toString().equals("Long")) { - Node arg = mn.getArgument(0); - if (arg instanceof ValueLiteralNode) { - considerDeterministic = true; - } - } - - if (PurityUtils.isDeterministic(provider, invokedMethod) - || allowNonDeterministic - || considerDeterministic) { - List parameters = new ArrayList<>(); - for (Node p : mn.getArguments()) { - parameters.add(internalReprOf(provider, p)); - } - Receiver methodReceiver; - if (ElementUtils.isStatic(invokedMethod)) { - methodReceiver = new ClassName(mn.getTarget().getReceiver().getType()); - } else { - methodReceiver = internalReprOf(provider, mn.getTarget().getReceiver()); - } - receiver = new MethodCall(mn.getType(), invokedMethod, methodReceiver, parameters); - } - } - - if (receiver == null) { - receiver = new Unknown(receiverNode.getType()); - } - return receiver; - } - - /** - * @return the internal representation (as {@link Receiver}) of any {@link ExpressionTree}. - * Might contain {@link Unknown}. - */ - public static Receiver internalReprOf( - AnnotationProvider provider, ExpressionTree receiverTree) { - return internalReprOf(provider, receiverTree, true); - } - /** - * We ignore operations such as widening and narrowing when computing the internal - * representation. - * - * @return the internal representation (as {@link Receiver}) of any {@link ExpressionTree}. - * Might contain {@link Unknown}. - */ - public static Receiver internalReprOf( - AnnotationProvider provider, - ExpressionTree receiverTree, - boolean allowNonDeterministic) { - Receiver receiver; - switch (receiverTree.getKind()) { - case ARRAY_ACCESS: - ArrayAccessTree a = (ArrayAccessTree) receiverTree; - Receiver arrayAccessExpression = internalReprOf(provider, a.getExpression()); - Receiver index = internalReprOf(provider, a.getIndex()); - receiver = new ArrayAccess(InternalUtils.typeOf(a), arrayAccessExpression, index); - break; - case BOOLEAN_LITERAL: - case CHAR_LITERAL: - case DOUBLE_LITERAL: - case FLOAT_LITERAL: - case INT_LITERAL: - case LONG_LITERAL: - case NULL_LITERAL: - case STRING_LITERAL: - LiteralTree vn = (LiteralTree) receiverTree; - receiver = new ValueLiteral(InternalUtils.typeOf(receiverTree), vn.getValue()); - break; - case NEW_ARRAY: - receiver = - new ArrayCreation( - InternalUtils.typeOf(receiverTree), - Collections.emptyList(), - Collections.emptyList()); - break; - case METHOD_INVOCATION: - MethodInvocationTree mn = (MethodInvocationTree) receiverTree; - ExecutableElement invokedMethod = TreeUtils.elementFromUse(mn); - if (PurityUtils.isDeterministic(provider, invokedMethod) || allowNonDeterministic) { - List parameters = new ArrayList<>(); - for (ExpressionTree p : mn.getArguments()) { - parameters.add(internalReprOf(provider, p)); - } - Receiver methodReceiver; - if (ElementUtils.isStatic(invokedMethod)) { - methodReceiver = new ClassName(InternalUtils.typeOf(mn.getMethodSelect())); - } else { - methodReceiver = internalReprOf(provider, mn.getMethodSelect()); - } - TypeMirror type = InternalUtils.typeOf(mn); - receiver = new MethodCall(type, invokedMethod, methodReceiver, parameters); - } else { - receiver = null; - } - break; - case MEMBER_SELECT: - receiver = internalRepOfMemberSelect(provider, (MemberSelectTree) receiverTree); - break; - case IDENTIFIER: - IdentifierTree identifierTree = (IdentifierTree) receiverTree; - TypeMirror typeOfId = InternalUtils.typeOf(identifierTree); - if (identifierTree.getName().contentEquals("this") - || identifierTree.getName().contentEquals("super")) { - receiver = new ThisReference(typeOfId); - break; - } - Element ele = TreeUtils.elementFromUse(identifierTree); - switch (ele.getKind()) { - case LOCAL_VARIABLE: - case RESOURCE_VARIABLE: - case EXCEPTION_PARAMETER: - case PARAMETER: - receiver = new LocalVariable(ele); - break; - case FIELD: - // Implicit access expression, such as "this" or a class name - Receiver fieldAccessExpression; - TypeMirror enclosingType = ElementUtils.enclosingClass(ele).asType(); - if (ElementUtils.isStatic(ele)) { - fieldAccessExpression = new ClassName(enclosingType); - } else { - fieldAccessExpression = new ThisReference(enclosingType); - } - receiver = - new FieldAccess( - fieldAccessExpression, typeOfId, (VariableElement) ele); - break; - case CLASS: - case ENUM: - case ANNOTATION_TYPE: - case INTERFACE: - receiver = new ClassName(ele.asType()); - break; - default: - receiver = null; - } - break; - default: - receiver = null; - } - - if (receiver == null) { - receiver = new Unknown(InternalUtils.typeOf(receiverTree)); - } - return receiver; - } - - /** - * Returns the implicit receiver of ele. - * - *

Returns either a new ClassName or a new ThisReference depending on whether ele is static - * or not. The passed element must be a field, method, or class. - * - * @param ele field, method, or class - * @return either a new ClassName or a new ThisReference depending on whether ele is static or - * not - */ - public static Receiver internalRepOfImplicitReceiver(Element ele) { - TypeMirror enclosingType = ElementUtils.enclosingClass(ele).asType(); - if (ElementUtils.isStatic(ele)) { - return new ClassName(enclosingType); - } else { - return new ThisReference(enclosingType); - } - } - - /** - * Returns either a new ClassName or ThisReference Receiver object for the enclosingType - * - *

The Tree should be an expression or a statement that does not have a receiver or an - * implicit receiver. For example, a local variable declaration. - * - * @param path TreePath to tree - * @param enclosingType type of the enclosing type - * @return a new ClassName or ThisReference that is a Receiver object for the enclosingType - */ - public static Receiver internalRepOfPseudoReceiver(TreePath path, TypeMirror enclosingType) { - if (TreeUtils.isTreeInStaticScope(path)) { - return new ClassName(enclosingType); - } else { - return new ThisReference(enclosingType); - } - } - - private static Receiver internalRepOfMemberSelect( - AnnotationProvider provider, MemberSelectTree memberSelectTree) { - TypeMirror expressionType = InternalUtils.typeOf(memberSelectTree.getExpression()); - if (TreeUtils.isClassLiteral(memberSelectTree)) { - return new ClassName(expressionType); - } - Element ele = TreeUtils.elementFromUse(memberSelectTree); - switch (ele.getKind()) { - case METHOD: - case CONSTRUCTOR: - return internalReprOf(provider, memberSelectTree.getExpression()); - case CLASS: // o instanceof MyClass.InnerClass - case ENUM: - case INTERFACE: // o instanceof MyClass.InnerInterface - case ANNOTATION_TYPE: - return new ClassName(expressionType); - case ENUM_CONSTANT: - case FIELD: - Receiver r = internalReprOf(provider, memberSelectTree.getExpression()); - return new FieldAccess(r, ElementUtils.getType(ele), (VariableElement) ele); - default: - ErrorReporter.errorAbort( - "Unexpected element kind: %s element: %s", ele.getKind(), ele); - return null; - } - } - - /** - * Returns Receiver objects for the formal parameters of the method in which path is enclosed. - * - * @param annotationProvider annotationProvider - * @param path TreePath that is enclosed by the method - * @return list of Receiver objects for the formal parameters of the method in which path is - * enclosed - */ - public static List getParametersOfEnclosingMethod( - AnnotationProvider annotationProvider, TreePath path) { - MethodTree methodTree = TreeUtils.enclosingMethod(path); - if (methodTree == null) { - return null; - } - List internalArguments = new ArrayList<>(); - for (VariableTree arg : methodTree.getParameters()) { - internalArguments.add(internalReprOf(annotationProvider, new LocalVariableNode(arg))); - } - return internalArguments; - } - - public abstract static class Receiver { - protected final TypeMirror type; - - public Receiver(TypeMirror type) { - assert type != null; - this.type = type; - } - - public TypeMirror getType() { - return type; - } - - public abstract boolean containsOfClass(Class clazz); - - public boolean containsUnknown() { - return containsOfClass(Unknown.class); - } - - /** - * Returns true if and only if the value this expression stands for cannot be changed by a - * method call. This is the case for local variables, the self reference as well as final - * field accesses for whose receiver {@link #isUnmodifiableByOtherCode} is true. - */ - public abstract boolean isUnmodifiableByOtherCode(); - - /** @return true if and only if the two receiver are syntactically identical */ - public boolean syntacticEquals(Receiver other) { - return other == this; - } - - /** - * @return true if and only if this receiver contains a receiver that is syntactically equal - * to {@code other}. - */ - public boolean containsSyntacticEqualReceiver(Receiver other) { - return syntacticEquals(other); - } - - /** - * Returns true if and only if {@code other} appears anywhere in this receiver or an - * expression appears in this receiver such that {@code other} might alias this expression, - * and that expression is modifiable. - * - *

Exceptions: If the corresponding {@link - * org.checkerframework.dataflow.cfg.node.Node} throws an exception, then it is assumed that no - * special handling is necessary and the store before the corresponding {@link - * org.checkerframework.dataflow.cfg.node.Node} will be passed along any exceptional edge. - * - *

Aliasing: {@code resultStore} is not allowed to be used anywhere outside of this - * class (including use through aliases). Complete control over the object is transfered to this - * class. - */ - public RegularTransferResult(A value, S resultStore, boolean storeChanged) { - super(value); - this.store = resultStore; - this.storeChanged = storeChanged; - } - - public RegularTransferResult(A value, S resultStore) { - this(value, resultStore, false); - } - - /** - * Create a {@code TransferResult} with {@code resultStore} as the resulting store. If the - * corresponding {@link org.checkerframework.dataflow.cfg.node.Node} is a boolean node, then - * {@code resultStore} is used for both the 'then' and 'else' edge. - * - *

For the meaning of storeChanged, see {@link - * org.checkerframework.dataflow.analysis.TransferResult#storeChanged}. - * - *

Exceptions: If the corresponding {@link - * org.checkerframework.dataflow.cfg.node.Node} throws an exception, then the corresponding - * store in {@code exceptionalStores} is used. If no exception is found in {@code - * exceptionalStores}, then it is assumed that no special handling is necessary and the store - * before the corresponding {@link org.checkerframework.dataflow.cfg.node.Node} will be passed - * along any exceptional edge. - * - *

Aliasing: {@code resultStore} and any store in {@code exceptionalStores} are not - * allowed to be used anywhere outside of this class (including use through aliases). Complete - * control over the objects is transfered to this class. - */ - public RegularTransferResult( - A value, S resultStore, Map exceptionalStores, boolean storeChanged) { - super(value); - this.store = resultStore; - this.storeChanged = storeChanged; - this.exceptionalStores = exceptionalStores; - } - - public RegularTransferResult(A value, S resultStore, Map exceptionalStores) { - this(value, resultStore, exceptionalStores, false); - } - - @Override - public S getRegularStore() { - return store; - } - - @Override - public S getThenStore() { - return store; - } - - @Override - public S getElseStore() { - // copy the store such that it is the same as the result of getThenStore - // (that is, identical according to equals), but two different objects. - return store.copy(); - } - - @Override - public boolean containsTwoStores() { - return false; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append("RegularTransferResult("); - result.append(System.getProperty("line.separator")); - result.append("resultValue = " + resultValue); - result.append(System.getProperty("line.separator")); - result.append("store = " + store); - result.append(System.getProperty("line.separator")); - result.append(")"); - return result.toString(); - } - - /** @see org.checkerframework.dataflow.analysis.TransferResult#storeChanged() */ - @Override - public boolean storeChanged() { - return storeChanged; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/Store.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/Store.java deleted file mode 100644 index 5d714da889..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/Store.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -import org.checkerframework.dataflow.cfg.CFGVisualizer; - -/** - * A store is used to keep track of the information that the org.checkerframework.dataflow analysis - * has accumulated at any given point in time. - * - * @author Stefan Heule - * @param the type of the store returned by {@code copy} and that is used in {@code - * leastUpperBound}. Usually it is the implementing class itself, e.g. in {@code T extends - * Store}. - */ -public interface Store> { - - // We maintain a then store and an else store before each basic block. - // When they are identical (by reference equality), they can be treated - // as a regular unconditional store. - // Once we have some information for both the then and else store, we - // create a TransferInput for the block and allow it to be analyzed. - public static enum Kind { - THEN, - ELSE, - BOTH - } - - /** A flow rule describes how stores flow along one edge between basic blocks. */ - public static enum FlowRule { - EACH_TO_EACH, // The normal case, then store flows to the then store - // and else store flows to the else store. - THEN_TO_BOTH, // Then store flows to both then and else of successor. - ELSE_TO_BOTH, // Else store flows to both then and else of successor. - THEN_TO_THEN, // Then store flows to the then of successor. Else store is ignored. - ELSE_TO_ELSE, // Else store flows to the else of successor. Then store is ignored. - } - - /** @return an exact copy of this store. */ - S copy(); - - /** - * Compute the least upper bound of two stores. - * - *

Important: This method must fulfill the following contract: - * - *

- */ - S leastUpperBound(S other); - - /** - * Compute an upper bound of two stores that is wider than the least upper bound of the two - * stores. Used to jump to a higher abstraction to allow faster termination of the fixed point - * computations in {@link Analysis}. {@code previous} must be the previous store. - * - *

A particular analysis might not require widening and should implement this method by - * calling leastUpperBound. - * - *

Important: This method must fulfill the following contract: - * - *

    - *
  • Does not change {@code this}. - *
  • Does not change {@code previous}. - *
  • Returns a fresh object which is not aliased yet. - *
  • Returns an object of the same (dynamic) type as {@code this}, even if the signature is - * more permissive. - *
  • Is commutative. - *
- * - * @param previous must be the previous store - */ - S widenedUpperBound(S previous); - - /** - * Can the objects {@code a} and {@code b} be aliases? Returns a conservative answer (i.e., - * returns {@code true} if not enough information is available to determine aliasing). - */ - boolean canAlias(FlowExpressions.Receiver a, FlowExpressions.Receiver b); - - /** - * Delegate visualization responsibility to a visualizer. - * - * @param viz the visualizer to visualize this store - */ - void visualize(CFGVisualizer viz); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferFunction.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferFunction.java deleted file mode 100644 index a10a766b33..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferFunction.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import java.util.List; -import org.checkerframework.dataflow.cfg.UnderlyingAST; -import org.checkerframework.dataflow.cfg.node.LocalVariableNode; -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.dataflow.cfg.node.NodeVisitor; - -/** - * Interface of a transfer function for the abstract interpretation used for the flow analysis. - * - *

A transfer function consists of the following components: - * - *

    - *
  • A method {@code initialStore} that determines which initial store should be used in the - * org.checkerframework.dataflow analysis. - *
  • A function for every {@link Node} type that determines the behavior of the - * org.checkerframework.dataflow analysis in that case. This method takes a {@link Node} and - * an incoming store, and produces a {@link RegularTransferResult}. - *
- * - *

Important: The individual transfer functions ( {@code visit*}) are allowed to use - * (and modify) the stores contained in the argument passed; the ownership is transfered from the - * caller to that function. - * - * @author Stefan Heule - * @param the {@link Store} used to keep track of intermediate results - */ -public interface TransferFunction, S extends Store> - extends NodeVisitor, TransferInput> { - - /** - * @return the initial store to be used by the org.checkerframework.dataflow analysis. {@code - * parameters} is only set if the underlying AST is a method. - */ - S initialStore(UnderlyingAST underlyingAST, /*@Nullable*/ List parameters); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferInput.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferInput.java deleted file mode 100644 index f827ad302d..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferInput.java +++ /dev/null @@ -1,250 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * {@code TransferInput} is used as the input type of the individual transfer functions of a {@link - * TransferFunction}. It also contains a reference to the node for which the transfer function will - * be applied. - * - *

A {@code TransferInput} contains one or two stores. If two stores are present, one belongs to - * 'then', and the other to 'else'. - * - * @author Stefan Heule - * @param the {@link Store} used to keep track of intermediate results - */ -public class TransferInput, S extends Store> { - - /** The corresponding node. */ - protected Node node; - - /** - * The regular result store (or {@code null} if none is present). The following invariant is - * maintained: - * - *

{@code
-     * store == null ⇔ thenStore != null && elseStore != null
-     * }
- */ - protected final /*@Nullable*/ S store; - - /** - * The 'then' result store (or {@code null} if none is present). The following invariant is - * maintained: - * - *
{@code
-     * store == null ⇔ thenStore != null && elseStore != null
-     * }
- */ - protected final /*@Nullable*/ S thenStore; - - /** - * The 'else' result store (or {@code null} if none is present). The following invariant is - * maintained: - * - *
{@code
-     * store == null ⇔ thenStore != null && elseStore != null
-     * }
- */ - protected final /*@Nullable*/ S elseStore; - - /** The corresponding analysis class to get intermediate flow results. */ - protected final Analysis analysis; - - /** - * Create a {@link TransferInput}, given a {@link TransferResult} and a node-value mapping. - * - *

Aliasing: The stores returned by any methods of {@code to} will be stored - * internally and are not allowed to be used elsewhere. Full control of them is transfered to - * this object. - * - *

The node-value mapping {@code nodeValues} is provided by the analysis and is only read - * from within this {@link TransferInput}. - */ - public TransferInput(Node n, Analysis analysis, TransferResult to) { - node = n; - this.analysis = analysis; - if (to.containsTwoStores()) { - thenStore = to.getThenStore(); - elseStore = to.getElseStore(); - store = null; - } else { - store = to.getRegularStore(); - thenStore = elseStore = null; - } - } - - /** - * Create a {@link TransferInput}, given a store and a node-value mapping. - * - *

Aliasing: The store {@code s} will be stored internally and is not allowed to be - * used elsewhere. Full control over {@code s} is transfered to this object. - * - *

The node-value mapping {@code nodeValues} is provided by the analysis and is only read - * from within this {@link TransferInput}. - */ - public TransferInput(Node n, Analysis analysis, S s) { - node = n; - this.analysis = analysis; - store = s; - thenStore = elseStore = null; - } - - /** - * Create a {@link TransferInput}, given two stores and a node-value mapping. - * - *

Aliasing: The two stores {@code s1} and {@code s2} will be stored internally and - * are not allowed to be used elsewhere. Full control of them is transfered to this object. - */ - public TransferInput(Node n, Analysis analysis, S s1, S s2) { - node = n; - this.analysis = analysis; - thenStore = s1; - elseStore = s2; - store = null; - } - - /** Copy constructor. */ - protected TransferInput(TransferInput from) { - this.node = from.node; - this.analysis = from.analysis; - if (from.store == null) { - thenStore = from.thenStore.copy(); - elseStore = from.elseStore.copy(); - store = null; - } else { - store = from.store.copy(); - thenStore = elseStore = null; - } - } - - /** @return the {@link Node} for this {@link TransferInput}. */ - public Node getNode() { - return node; - } - - /** - * @return the abstract value of {@link Node} {@code n}, which is required to be a 'sub-node' - * (that is, a direct or indirect child) of the node this transfer input is associated with. - * Furthermore, {@code n} cannot be a l-value node. Returns {@code null} if no value if - * available. - */ - public /*@Nullable*/ A getValueOfSubNode(Node n) { - return analysis.getValue(n); - } - - /** - * @return the regular result store produced if no exception is thrown by the {@link Node} - * corresponding to this transfer function result - */ - public S getRegularStore() { - if (store == null) { - return thenStore.leastUpperBound(elseStore); - } else { - return store; - } - } - - /** - * @return the result store produced if the {@link Node} this result belongs to evaluates to - * {@code true}. - */ - public S getThenStore() { - if (store == null) { - return thenStore; - } - return store; - } - - /** - * @return the result store produced if the {@link Node} this result belongs to evaluates to - * {@code false}. - */ - public S getElseStore() { - if (store == null) { - return elseStore; - } - // copy the store such that it is the same as the result of getThenStore - // (that is, identical according to equals), but two different objects. - return store.copy(); - } - - /** - * @return {@code true} if and only if this transfer input contains two stores that are - * potentially not equal. Note that the result {@code true} does not imply that {@code - * getRegularStore} cannot be called (or vice versa for {@code false}). Rather, it indicates - * that {@code getThenStore} or {@code getElseStore} can be used to give more precise - * results. Otherwise, if the result is {@code false}, then all three methods {@code - * getRegularStore}, {@code getThenStore}, and {@code getElseStore} return equivalent - * stores. - */ - public boolean containsTwoStores() { - return (thenStore != null && elseStore != null); - } - - /** @return an exact copy of this store. */ - public TransferInput copy() { - return new TransferInput<>(this); - } - - /** - * Compute the least upper bound of two stores. - * - *

Important: This method must fulfill the same contract as {@code leastUpperBound} - * of {@link Store}. - */ - public TransferInput leastUpperBound(TransferInput other) { - if (store == null) { - S newThenStore = thenStore.leastUpperBound(other.getThenStore()); - S newElseStore = elseStore.leastUpperBound(other.getElseStore()); - return new TransferInput<>(node, analysis, newThenStore, newElseStore); - } else { - if (other.store == null) { - // make sure we do not lose precision and keep two stores if at - // least one of the two TransferInput's has two stores. - return other.leastUpperBound(this); - } - return new TransferInput<>( - node, analysis, store.leastUpperBound(other.getRegularStore())); - } - } - - @Override - public boolean equals(Object o) { - if (o != null && o instanceof TransferInput) { - @SuppressWarnings("unchecked") - TransferInput other = (TransferInput) o; - if (containsTwoStores()) { - if (other.containsTwoStores()) { - return getThenStore().equals(other.getThenStore()) - && getElseStore().equals(other.getElseStore()); - } - } else { - if (!other.containsTwoStores()) { - return getRegularStore().equals(other.getRegularStore()); - } - } - } - return false; - } - - @Override - public int hashCode() { - return HashCodeUtils.hash( - this.analysis, this.node, this.store, this.thenStore, this.elseStore); - } - - @Override - public String toString() { - if (store == null) { - return "[then=" + thenStore + ", else=" + elseStore + "]"; - } else { - return "[" + store + "]"; - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferResult.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferResult.java deleted file mode 100644 index 7c178a13fc..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/TransferResult.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import java.util.Map; -import javax.lang.model.type.TypeMirror; - -/** - * {@code TransferResult} is used as the result type of the individual transfer functions of a - * {@link TransferFunction}. It always belongs to the result of the individual transfer function for - * a particular {@link org.checkerframework.dataflow.cfg.node.Node}, even though that {@code - * org.checkerframework.dataflow.cfg.node.Node} is not explicitly store in {@code TransferResult}. - * - *

A {@code TransferResult} contains one or two stores (for 'then' and 'else'), and zero or more - * stores with a cause ({@link TypeMirror}). - * - * @author Stefan Heule - * @param the {@link Store} used to keep track of intermediate results - */ -public abstract class TransferResult, S extends Store> { - - /** - * The stores in case the basic block throws an exception (or {@code null} if the corresponding - * {@link org.checkerframework.dataflow.cfg.node.Node} does not throw any exceptions). Does not - * necessarily contain a store for every exception, in which case the in-store will be used. - */ - protected /*@Nullable*/ Map exceptionalStores; - - /** - * The abstract value of the {@link org.checkerframework.dataflow.cfg.node.Node} associated with - * this {@link TransferResult}, or {@code null} if no value has been produced. - */ - protected /*@Nullable*/ A resultValue; - - public TransferResult(/*@Nullable*/ A resultValue) { - this.resultValue = resultValue; - } - - /** @return the abstract value produced by the transfer function */ - public A getResultValue() { - return resultValue; - } - - public void setResultValue(A resultValue) { - this.resultValue = resultValue; - } - - /** - * @return the regular result store produced if no exception is thrown by the {@link - * org.checkerframework.dataflow.cfg.node.Node} corresponding to this transfer function - * result. - */ - public abstract S getRegularStore(); - - /** - * @return the result store produced if the {@link org.checkerframework.dataflow.cfg.node.Node} - * this result belongs to evaluates to {@code true}. - */ - public abstract S getThenStore(); - - /** - * @return the result store produced if the {@link org.checkerframework.dataflow.cfg.node.Node} - * this result belongs to evaluates to {@code false}. - */ - public abstract S getElseStore(); - - /** - * @return the store that flows along the outgoing exceptional edge labeled with {@code - * exception} (or {@code null} if no special handling is required for exceptional edges). - */ - public /*@Nullable*/ S getExceptionalStore(TypeMirror exception) { - if (exceptionalStores == null) { - return null; - } - return exceptionalStores.get(exception); - } - - /** - * @return a Map of {@link TypeMirror} to {@link Store} - * @see TransferResult#getExceptionalStore(TypeMirror) - */ - public Map getExceptionalStores() { - return exceptionalStores; - } - - /** - * @return {@code true} if and only if this transfer result contains two stores that are - * potentially not equal. Note that the result {@code true} does not imply that {@code - * getRegularStore} cannot be called (or vice versa for {@code false}). Rather, it indicates - * that {@code getThenStore} or {@code getElseStore} can be used to give more precise - * results. Otherwise, if the result is {@code false}, then all three methods {@code - * getRegularStore}, {@code getThenStore}, and {@code getElseStore} return equivalent - * stores. - */ - public abstract boolean containsTwoStores(); - - /** - * @return {@code true} if and only if the transfer function returning this transfer result - * changed the regularStore, elseStore, or thenStore. - */ - public abstract boolean storeChanged(); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/CFGBuilder.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/CFGBuilder.java deleted file mode 100644 index 55daff24ff..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/CFGBuilder.java +++ /dev/null @@ -1,4491 +0,0 @@ -package org.checkerframework.dataflow.cfg; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.AnnotatedTypeTree; -import com.sun.source.tree.AnnotationTree; -import com.sun.source.tree.ArrayAccessTree; -import com.sun.source.tree.ArrayTypeTree; -import com.sun.source.tree.AssertTree; -import com.sun.source.tree.AssignmentTree; -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.BlockTree; -import com.sun.source.tree.BreakTree; -import com.sun.source.tree.CaseTree; -import com.sun.source.tree.CatchTree; -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.CompoundAssignmentTree; -import com.sun.source.tree.ConditionalExpressionTree; -import com.sun.source.tree.ContinueTree; -import com.sun.source.tree.DoWhileLoopTree; -import com.sun.source.tree.EmptyStatementTree; -import com.sun.source.tree.EnhancedForLoopTree; -import com.sun.source.tree.ErroneousTree; -import com.sun.source.tree.ExpressionStatementTree; -import com.sun.source.tree.ExpressionTree; -import com.sun.source.tree.ForLoopTree; -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.IfTree; -import com.sun.source.tree.ImportTree; -import com.sun.source.tree.InstanceOfTree; -import com.sun.source.tree.LabeledStatementTree; -import com.sun.source.tree.LambdaExpressionTree; -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.MemberReferenceTree; -import com.sun.source.tree.MemberSelectTree; -import com.sun.source.tree.MethodInvocationTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.ModifiersTree; -import com.sun.source.tree.NewArrayTree; -import com.sun.source.tree.NewClassTree; -import com.sun.source.tree.ParameterizedTypeTree; -import com.sun.source.tree.ParenthesizedTree; -import com.sun.source.tree.PrimitiveTypeTree; -import com.sun.source.tree.ReturnTree; -import com.sun.source.tree.StatementTree; -import com.sun.source.tree.SwitchTree; -import com.sun.source.tree.SynchronizedTree; -import com.sun.source.tree.ThrowTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.Tree.Kind; -import com.sun.source.tree.TryTree; -import com.sun.source.tree.TypeCastTree; -import com.sun.source.tree.TypeParameterTree; -import com.sun.source.tree.UnaryTree; -import com.sun.source.tree.UnionTypeTree; -import com.sun.source.tree.VariableTree; -import com.sun.source.tree.WhileLoopTree; -import com.sun.source.tree.WildcardTree; -import com.sun.source.util.TreePath; -import com.sun.source.util.TreePathScanner; -import com.sun.source.util.Trees; -import com.sun.tools.javac.code.Symbol.MethodSymbol; -import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.processing.JavacProcessingEnvironment; -import com.sun.tools.javac.util.Context; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Name; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.PrimitiveType; -import javax.lang.model.type.ReferenceType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.TypeVariable; -import javax.lang.model.type.UnionType; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -import org.checkerframework.dataflow.analysis.Store; -import org.checkerframework.dataflow.cfg.CFGBuilder.ExtendedNode.ExtendedNodeType; -import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod; -import org.checkerframework.dataflow.cfg.block.Block; -import org.checkerframework.dataflow.cfg.block.Block.BlockType; -import org.checkerframework.dataflow.cfg.block.BlockImpl; -import org.checkerframework.dataflow.cfg.block.ConditionalBlockImpl; -import org.checkerframework.dataflow.cfg.block.ExceptionBlockImpl; -import org.checkerframework.dataflow.cfg.block.RegularBlockImpl; -import org.checkerframework.dataflow.cfg.block.SingleSuccessorBlockImpl; -import org.checkerframework.dataflow.cfg.block.SpecialBlock.SpecialBlockType; -import org.checkerframework.dataflow.cfg.block.SpecialBlockImpl; -import org.checkerframework.dataflow.cfg.node.ArrayAccessNode; -import org.checkerframework.dataflow.cfg.node.ArrayCreationNode; -import org.checkerframework.dataflow.cfg.node.ArrayTypeNode; -import org.checkerframework.dataflow.cfg.node.AssertionErrorNode; -import org.checkerframework.dataflow.cfg.node.AssignmentNode; -import org.checkerframework.dataflow.cfg.node.BitwiseAndNode; -import org.checkerframework.dataflow.cfg.node.BitwiseComplementNode; -import org.checkerframework.dataflow.cfg.node.BitwiseOrNode; -import org.checkerframework.dataflow.cfg.node.BitwiseXorNode; -import org.checkerframework.dataflow.cfg.node.BooleanLiteralNode; -import org.checkerframework.dataflow.cfg.node.CaseNode; -import org.checkerframework.dataflow.cfg.node.CharacterLiteralNode; -import org.checkerframework.dataflow.cfg.node.ClassNameNode; -import org.checkerframework.dataflow.cfg.node.ConditionalAndNode; -import org.checkerframework.dataflow.cfg.node.ConditionalNotNode; -import org.checkerframework.dataflow.cfg.node.ConditionalOrNode; -import org.checkerframework.dataflow.cfg.node.DoubleLiteralNode; -import org.checkerframework.dataflow.cfg.node.EqualToNode; -import org.checkerframework.dataflow.cfg.node.ExplicitThisLiteralNode; -import org.checkerframework.dataflow.cfg.node.FieldAccessNode; -import org.checkerframework.dataflow.cfg.node.FloatLiteralNode; -import org.checkerframework.dataflow.cfg.node.FloatingDivisionNode; -import org.checkerframework.dataflow.cfg.node.FloatingRemainderNode; -import org.checkerframework.dataflow.cfg.node.FunctionalInterfaceNode; -import org.checkerframework.dataflow.cfg.node.GreaterThanNode; -import org.checkerframework.dataflow.cfg.node.GreaterThanOrEqualNode; -import org.checkerframework.dataflow.cfg.node.ImplicitThisLiteralNode; -import org.checkerframework.dataflow.cfg.node.InstanceOfNode; -import org.checkerframework.dataflow.cfg.node.IntegerDivisionNode; -import org.checkerframework.dataflow.cfg.node.IntegerLiteralNode; -import org.checkerframework.dataflow.cfg.node.IntegerRemainderNode; -import org.checkerframework.dataflow.cfg.node.LeftShiftNode; -import org.checkerframework.dataflow.cfg.node.LessThanNode; -import org.checkerframework.dataflow.cfg.node.LessThanOrEqualNode; -import org.checkerframework.dataflow.cfg.node.LocalVariableNode; -import org.checkerframework.dataflow.cfg.node.LongLiteralNode; -import org.checkerframework.dataflow.cfg.node.MarkerNode; -import org.checkerframework.dataflow.cfg.node.MethodAccessNode; -import org.checkerframework.dataflow.cfg.node.MethodInvocationNode; -import org.checkerframework.dataflow.cfg.node.NarrowingConversionNode; -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.dataflow.cfg.node.NotEqualNode; -import org.checkerframework.dataflow.cfg.node.NullChkNode; -import org.checkerframework.dataflow.cfg.node.NullLiteralNode; -import org.checkerframework.dataflow.cfg.node.NumericalAdditionNode; -import org.checkerframework.dataflow.cfg.node.NumericalMinusNode; -import org.checkerframework.dataflow.cfg.node.NumericalMultiplicationNode; -import org.checkerframework.dataflow.cfg.node.NumericalPlusNode; -import org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode; -import org.checkerframework.dataflow.cfg.node.ObjectCreationNode; -import org.checkerframework.dataflow.cfg.node.PackageNameNode; -import org.checkerframework.dataflow.cfg.node.ParameterizedTypeNode; -import org.checkerframework.dataflow.cfg.node.PrimitiveTypeNode; -import org.checkerframework.dataflow.cfg.node.ReturnNode; -import org.checkerframework.dataflow.cfg.node.SignedRightShiftNode; -import org.checkerframework.dataflow.cfg.node.StringConcatenateAssignmentNode; -import org.checkerframework.dataflow.cfg.node.StringConcatenateNode; -import org.checkerframework.dataflow.cfg.node.StringConversionNode; -import org.checkerframework.dataflow.cfg.node.StringLiteralNode; -import org.checkerframework.dataflow.cfg.node.SuperNode; -import org.checkerframework.dataflow.cfg.node.SynchronizedNode; -import org.checkerframework.dataflow.cfg.node.TernaryExpressionNode; -import org.checkerframework.dataflow.cfg.node.ThisLiteralNode; -import org.checkerframework.dataflow.cfg.node.ThrowNode; -import org.checkerframework.dataflow.cfg.node.TypeCastNode; -import org.checkerframework.dataflow.cfg.node.UnsignedRightShiftNode; -import org.checkerframework.dataflow.cfg.node.ValueLiteralNode; -import org.checkerframework.dataflow.cfg.node.VariableDeclarationNode; -import org.checkerframework.dataflow.cfg.node.WideningConversionNode; -import org.checkerframework.dataflow.qual.TerminatesExecution; -import org.checkerframework.dataflow.util.MostlySingleton; -import org.checkerframework.javacutil.AnnotationProvider; -import org.checkerframework.javacutil.BasicAnnotationProvider; -import org.checkerframework.javacutil.ElementUtils; -import org.checkerframework.javacutil.InternalUtils; -import org.checkerframework.javacutil.Pair; -import org.checkerframework.javacutil.TreeUtils; -import org.checkerframework.javacutil.TypesUtils; -import org.checkerframework.javacutil.trees.TreeBuilder; - -/** - * Builds the control flow graph of some Java code (either a method, or an arbitrary statement). - * - *

The translation of the AST to the CFG is split into three phases: - * - *

    - *
  1. Phase one. In the first phase, the AST is translated into a sequence of {@link - * org.checkerframework.dataflow.cfg.CFGBuilder.ExtendedNode}s. An extended node can either be - * a {@link Node}, or one of several meta elements such as a conditional or unconditional jump - * or a node with additional information about exceptions. Some of the extended nodes contain - * labels (e.g., for the jump target), and phase one additionally creates a mapping from - * labels to extended nodes. Finally, the list of leaders is computed: A leader is an extended - * node which will give rise to a basic block in phase two. - *
  2. Phase two. In this phase, the sequence of extended nodes is translated to a graph - * of control flow blocks that contain nodes. The meta elements from phase one are translated - * into the correct edges. - *
  3. Phase three. The control flow graph generated in phase two can contain degenerate - * basic blocks such as empty regular basic blocks or conditional basic blocks that have the - * same block as both 'then' and 'else' successor. This phase removes these cases while - * preserving the control flow structure. - *
- * - * @author Stefan Heule - */ -public class CFGBuilder { - - /** Can assertions be assumed to be disabled? */ - protected final boolean assumeAssertionsDisabled; - - /** Can assertions be assumed to be enabled? */ - protected final boolean assumeAssertionsEnabled; - - public CFGBuilder(boolean assumeAssertionsEnabled, boolean assumeAssertionsDisabled) { - assert !(assumeAssertionsDisabled && assumeAssertionsEnabled); - this.assumeAssertionsEnabled = assumeAssertionsEnabled; - this.assumeAssertionsDisabled = assumeAssertionsDisabled; - } - - /** - * Class declarations that have been encountered when building the control-flow graph for a - * method. - */ - protected final List declaredClasses = new LinkedList<>(); - - public List getDeclaredClasses() { - return declaredClasses; - } - - /** - * Lambdas encountered when building the control-flow graph for a method, variable initializer, - * or initializer. - */ - protected final List declaredLambdas = new LinkedList<>(); - - public List getDeclaredLambdas() { - return declaredLambdas; - } - - /** Build the control flow graph of some code. */ - public static ControlFlowGraph build( - CompilationUnitTree root, - ProcessingEnvironment env, - UnderlyingAST underlyingAST, - boolean assumeAssertionsEnabled, - boolean assumeAssertionsDisabled) { - return new CFGBuilder(assumeAssertionsEnabled, assumeAssertionsDisabled) - .run(root, env, underlyingAST); - } - - /** - * Build the control flow graph of some code (method, initializer block, ...). bodyPath is the - * TreePath to the body of that code. - */ - public static ControlFlowGraph build( - TreePath bodyPath, - ProcessingEnvironment env, - UnderlyingAST underlyingAST, - boolean assumeAssertionsEnabled, - boolean assumeAssertionsDisabled) { - return new CFGBuilder(assumeAssertionsEnabled, assumeAssertionsDisabled) - .run(bodyPath, env, underlyingAST); - } - - /** Build the control flow graph of a method. */ - public static ControlFlowGraph build( - CompilationUnitTree root, - ProcessingEnvironment env, - MethodTree tree, - ClassTree classTree, - boolean assumeAssertionsEnabled, - boolean assumeAssertionsDisabled) { - return new CFGBuilder(assumeAssertionsEnabled, assumeAssertionsDisabled) - .run(root, env, tree, classTree); - } - - /** Build the control flow graph of some code. */ - public static ControlFlowGraph build( - CompilationUnitTree root, ProcessingEnvironment env, UnderlyingAST underlyingAST) { - return new CFGBuilder(false, false).run(root, env, underlyingAST); - } - - /** Build the control flow graph of a method. */ - public static ControlFlowGraph build( - CompilationUnitTree root, - ProcessingEnvironment env, - MethodTree tree, - ClassTree classTree) { - return new CFGBuilder(false, false).run(root, env, tree, classTree); - } - - /** Build the control flow graph of some code. */ - public ControlFlowGraph run( - CompilationUnitTree root, ProcessingEnvironment env, UnderlyingAST underlyingAST) { - declaredClasses.clear(); - declaredLambdas.clear(); - - TreeBuilder builder = new TreeBuilder(env); - AnnotationProvider annotationProvider = new BasicAnnotationProvider(); - PhaseOneResult phase1result = - new CFGTranslationPhaseOne() - .process( - root, - env, - underlyingAST, - exceptionalExitLabel, - builder, - annotationProvider); - ControlFlowGraph phase2result = new CFGTranslationPhaseTwo().process(phase1result); - ControlFlowGraph phase3result = CFGTranslationPhaseThree.process(phase2result); - return phase3result; - } - - /** - * Build the control flow graph of some code (method, initializer block, ...). bodyPath is the - * TreePath to the body of that code. - */ - public ControlFlowGraph run( - TreePath bodyPath, ProcessingEnvironment env, UnderlyingAST underlyingAST) { - declaredClasses.clear(); - TreeBuilder builder = new TreeBuilder(env); - AnnotationProvider annotationProvider = new BasicAnnotationProvider(); - PhaseOneResult phase1result = - new CFGTranslationPhaseOne() - .process( - bodyPath, - env, - underlyingAST, - exceptionalExitLabel, - builder, - annotationProvider); - ControlFlowGraph phase2result = new CFGTranslationPhaseTwo().process(phase1result); - ControlFlowGraph phase3result = CFGTranslationPhaseThree.process(phase2result); - return phase3result; - } - - /** Build the control flow graph of a method. */ - public ControlFlowGraph run( - CompilationUnitTree root, - ProcessingEnvironment env, - MethodTree tree, - ClassTree classTree) { - UnderlyingAST underlyingAST = new CFGMethod(tree, classTree); - return run(root, env, underlyingAST); - } - - /* --------------------------------------------------------- */ - /* Extended Node Types and Labels */ - /* --------------------------------------------------------- */ - - /** Special label to identify the exceptional exit. */ - protected final Label exceptionalExitLabel = new Label(); - - /** Special label to identify the regular exit. */ - protected final Label regularExitLabel = new Label(); - - /** - * An extended node can be one of several things (depending on its {@code type}): - * - *
    - *
  • NODE. An extended node of this type is just a wrapper for a {@link Node} (that - * cannot throw exceptions). - *
  • EXCEPTION_NODE. A wrapper for a {@link Node} which can throw exceptions. It - * contains a label for every possible exception type the node might throw. - *
  • UNCONDITIONAL_JUMP. An unconditional jump to a label. - *
  • TWO_TARGET_CONDITIONAL_JUMP. A conditional jump with two targets for both the - * 'then' and 'else' branch. - *
- */ - protected abstract static class ExtendedNode { - - /** The basic block this extended node belongs to (as determined in phase two). */ - protected BlockImpl block; - - /** Type of this node. */ - protected ExtendedNodeType type; - - /** Does this node terminate the execution? (e.g., "System.exit()") */ - protected boolean terminatesExecution = false; - - public ExtendedNode(ExtendedNodeType type) { - this.type = type; - } - - /** Extended node types (description see above). */ - public enum ExtendedNodeType { - NODE, - EXCEPTION_NODE, - UNCONDITIONAL_JUMP, - CONDITIONAL_JUMP - } - - public ExtendedNodeType getType() { - return type; - } - - public boolean getTerminatesExecution() { - return terminatesExecution; - } - - public void setTerminatesExecution(boolean terminatesExecution) { - this.terminatesExecution = terminatesExecution; - } - - /** - * @return the node contained in this extended node (only applicable if the type is {@code - * NODE} or {@code EXCEPTION_NODE}). - */ - public Node getNode() { - assert false; - return null; - } - - /** - * @return the label associated with this extended node (only applicable if type is {@link - * ExtendedNodeType#CONDITIONAL_JUMP} or {@link ExtendedNodeType#UNCONDITIONAL_JUMP}). - */ - public Label getLabel() { - assert false; - return null; - } - - public BlockImpl getBlock() { - return block; - } - - public void setBlock(BlockImpl b) { - this.block = b; - } - - @Override - public String toString() { - return "ExtendedNode(" + type + ")"; - } - } - - /** An extended node of type {@code NODE}. */ - protected static class NodeHolder extends ExtendedNode { - - protected Node node; - - public NodeHolder(Node node) { - super(ExtendedNodeType.NODE); - this.node = node; - } - - @Override - public Node getNode() { - return node; - } - - @Override - public String toString() { - return "NodeHolder(" + node + ")"; - } - } - - /** An extended node of type {@code EXCEPTION_NODE}. */ - protected static class NodeWithExceptionsHolder extends ExtendedNode { - - protected Node node; - /** - * Map from exception type to labels of successors that may be reached as a result of that - * exception. - */ - protected Map> exceptions; - - public NodeWithExceptionsHolder(Node node, Map> exceptions) { - super(ExtendedNodeType.EXCEPTION_NODE); - this.node = node; - this.exceptions = exceptions; - } - - public Map> getExceptions() { - return exceptions; - } - - @Override - public Node getNode() { - return node; - } - - @Override - public String toString() { - return "NodeWithExceptionsHolder(" + node + ")"; - } - } - - /** - * An extended node of type {@link ExtendedNodeType#CONDITIONAL_JUMP}. - * - *

Important: In the list of extended nodes, there should not be any labels that - * point to a conditional jump. Furthermore, the node directly ahead of any conditional jump has - * to be a {@link NodeWithExceptionsHolder} or {@link NodeHolder}, and the node held by that - * extended node is required to be of boolean type. - */ - protected static class ConditionalJump extends ExtendedNode { - - protected Label trueSucc; - protected Label falseSucc; - - protected Store.FlowRule trueFlowRule; - protected Store.FlowRule falseFlowRule; - - public ConditionalJump(Label trueSucc, Label falseSucc) { - super(ExtendedNodeType.CONDITIONAL_JUMP); - this.trueSucc = trueSucc; - this.falseSucc = falseSucc; - } - - public Label getThenLabel() { - return trueSucc; - } - - public Label getElseLabel() { - return falseSucc; - } - - public Store.FlowRule getTrueFlowRule() { - return trueFlowRule; - } - - public Store.FlowRule getFalseFlowRule() { - return falseFlowRule; - } - - public void setTrueFlowRule(Store.FlowRule rule) { - trueFlowRule = rule; - } - - public void setFalseFlowRule(Store.FlowRule rule) { - falseFlowRule = rule; - } - - @Override - public String toString() { - return "TwoTargetConditionalJump(" + getThenLabel() + "," + getElseLabel() + ")"; - } - } - - /** An extended node of type {@link ExtendedNodeType#UNCONDITIONAL_JUMP}. */ - protected static class UnconditionalJump extends ExtendedNode { - - protected Label jumpTarget; - - public UnconditionalJump(Label jumpTarget) { - super(ExtendedNodeType.UNCONDITIONAL_JUMP); - this.jumpTarget = jumpTarget; - } - - @Override - public Label getLabel() { - return jumpTarget; - } - - @Override - public String toString() { - return "JumpMarker(" + getLabel() + ")"; - } - } - - /** - * A label is used to refer to other extended nodes using a mapping from labels to extended - * nodes. Labels get their names either from labeled statements in the source code or from - * internally generated unique names. - */ - protected static class Label { - private static int uid = 0; - - protected String name; - - public Label(String name) { - this.name = name; - } - - public Label() { - this.name = uniqueName(); - } - - @Override - public String toString() { - return name; - } - - /** - * Return a new unique label name that cannot be confused with a Java source code label. - * - * @return a new unique label name - */ - private static String uniqueName() { - return "%L" + uid++; - } - } - - /** - * A TryFrame takes a thrown exception type and maps it to a set of possible control-flow - * successors. - */ - protected static interface TryFrame { - /** - * Given a type of thrown exception, add the set of possible control flow successor {@link - * Label}s to the argument set. Return true if the exception is known to be caught by one of - * those labels and false if it may propagate still further. - */ - public boolean possibleLabels(TypeMirror thrown, Set

    - *
  1. Empty regular basic blocks: These blocks will be removed and their predecessors linked - * directly to the successor. - *
  2. Conditional basic blocks that have the same basic block as the 'then' and 'else' - * successor: The conditional basic block will be removed in this case. - *
  3. Two consecutive, non-empty, regular basic blocks where the second block has exactly one - * predecessor (namely the other of the two blocks): In this case, the two blocks are - * merged. - *
  4. Some basic blocks might not be reachable from the entryBlock. These basic blocks are - * removed, and the list of predecessors (in the doubly-linked structure of basic blocks) - * are adapted correctly. - *
- * - * Eliminating the second type of degenerate cases might introduce cases of the third problem. - * These are also removed. - */ - public static class CFGTranslationPhaseThree { - - /** - * A simple wrapper object that holds a basic block and allows to set one of its successors. - */ - protected interface PredecessorHolder { - void setSuccessor(BlockImpl b); - - BlockImpl getBlock(); - } - - /** - * Perform phase three on the control flow graph {@code cfg}. - * - * @param cfg the control flow graph. Ownership is transfered to this method and the caller - * is not allowed to read or modify {@code cfg} after the call to {@code process} any - * more. - * @return the resulting control flow graph - */ - public static ControlFlowGraph process(ControlFlowGraph cfg) { - Set worklist = cfg.getAllBlocks(); - Set dontVisit = new HashSet<>(); - - // note: this method has to be careful when relinking basic blocks - // to not forget to adjust the predecessors, too - - // fix predecessor lists by removing any unreachable predecessors - for (Block c : worklist) { - BlockImpl cur = (BlockImpl) c; - for (BlockImpl pred : new HashSet<>(cur.getPredecessors())) { - if (!worklist.contains(pred)) { - cur.removePredecessor(pred); - } - } - } - - // remove empty blocks - for (Block cur : worklist) { - if (dontVisit.contains(cur)) { - continue; - } - - if (cur.getType() == BlockType.REGULAR_BLOCK) { - RegularBlockImpl b = (RegularBlockImpl) cur; - if (b.isEmpty()) { - Set empty = new HashSet<>(); - Set predecessors = new HashSet<>(); - BlockImpl succ = computeNeighborhoodOfEmptyBlock(b, empty, predecessors); - for (RegularBlockImpl e : empty) { - succ.removePredecessor(e); - dontVisit.add(e); - } - for (PredecessorHolder p : predecessors) { - BlockImpl block = p.getBlock(); - dontVisit.add(block); - succ.removePredecessor(block); - p.setSuccessor(succ); - } - } - } - } - - // remove useless conditional blocks - worklist = cfg.getAllBlocks(); - for (Block c : worklist) { - BlockImpl cur = (BlockImpl) c; - - if (cur.getType() == BlockType.CONDITIONAL_BLOCK) { - ConditionalBlockImpl cb = (ConditionalBlockImpl) cur; - assert cb.getPredecessors().size() == 1; - if (cb.getThenSuccessor() == cb.getElseSuccessor()) { - BlockImpl pred = cb.getPredecessors().iterator().next(); - PredecessorHolder predecessorHolder = getPredecessorHolder(pred, cb); - BlockImpl succ = (BlockImpl) cb.getThenSuccessor(); - succ.removePredecessor(cb); - predecessorHolder.setSuccessor(succ); - } - } - } - - // merge consecutive basic blocks if possible - worklist = cfg.getAllBlocks(); - for (Block cur : worklist) { - if (cur.getType() == BlockType.REGULAR_BLOCK) { - RegularBlockImpl b = (RegularBlockImpl) cur; - Block succ = b.getRegularSuccessor(); - if (succ.getType() == BlockType.REGULAR_BLOCK) { - RegularBlockImpl rs = (RegularBlockImpl) succ; - if (rs.getPredecessors().size() == 1) { - b.setSuccessor(rs.getRegularSuccessor()); - b.addNodes(rs.getContents()); - rs.getRegularSuccessor().removePredecessor(rs); - } - } - } - } - - return cfg; - } - - /** - * Compute the set of empty regular basic blocks {@code empty}, starting at {@code start} - * and going both forward and backwards. Furthermore, compute the predecessors of these - * empty blocks ({@code predecessors} ), and their single successor (return value). - * - * @param start the starting point of the search (an empty, regular basic block) - * @param empty an empty set to be filled by this method with all empty basic blocks found - * (including {@code start}). - * @param predecessors an empty set to be filled by this method with all predecessors - * @return the single successor of the set of the empty basic blocks - */ - protected static BlockImpl computeNeighborhoodOfEmptyBlock( - RegularBlockImpl start, - Set empty, - Set predecessors) { - - // get empty neighborhood that come before 'start' - computeNeighborhoodOfEmptyBlockBackwards(start, empty, predecessors); - - // go forward - BlockImpl succ = (BlockImpl) start.getSuccessor(); - while (succ.getType() == BlockType.REGULAR_BLOCK) { - RegularBlockImpl cur = (RegularBlockImpl) succ; - if (cur.isEmpty()) { - computeNeighborhoodOfEmptyBlockBackwards(cur, empty, predecessors); - assert empty.contains(cur) : "cur ought to be in empty"; - succ = (BlockImpl) cur.getSuccessor(); - if (succ == cur) { - // An infinite loop, making exit block unreachable - break; - } - } else { - break; - } - } - return succ; - } - - /** - * Compute the set of empty regular basic blocks {@code empty}, starting at {@code start} - * and looking only backwards in the control flow graph. Furthermore, compute the - * predecessors of these empty blocks ( {@code predecessors}). - * - * @param start the starting point of the search (an empty, regular basic block) - * @param empty a set to be filled by this method with all empty basic blocks found - * (including {@code start}). - * @param predecessors a set to be filled by this method with all predecessors - */ - protected static void computeNeighborhoodOfEmptyBlockBackwards( - RegularBlockImpl start, - Set empty, - Set predecessors) { - - RegularBlockImpl cur = start; - empty.add(cur); - for (final BlockImpl pred : cur.getPredecessors()) { - switch (pred.getType()) { - case SPECIAL_BLOCK: - // add pred correctly to predecessor list - predecessors.add(getPredecessorHolder(pred, cur)); - break; - case CONDITIONAL_BLOCK: - // add pred correctly to predecessor list - predecessors.add(getPredecessorHolder(pred, cur)); - break; - case EXCEPTION_BLOCK: - // add pred correctly to predecessor list - predecessors.add(getPredecessorHolder(pred, cur)); - break; - case REGULAR_BLOCK: - RegularBlockImpl r = (RegularBlockImpl) pred; - if (r.isEmpty()) { - // recursively look backwards - if (!empty.contains(r)) { - computeNeighborhoodOfEmptyBlockBackwards(r, empty, predecessors); - } - } else { - // add pred correctly to predecessor list - predecessors.add(getPredecessorHolder(pred, cur)); - } - break; - } - } - } - - /** - * Return a predecessor holder that can be used to set the successor of {@code pred} in the - * place where previously the edge pointed to {@code cur}. Additionally, the predecessor - * holder also takes care of unlinking (i.e., removing the {@code pred} from {@code cur's} - * predecessors). - */ - protected static PredecessorHolder getPredecessorHolder( - final BlockImpl pred, final BlockImpl cur) { - switch (pred.getType()) { - case SPECIAL_BLOCK: - SingleSuccessorBlockImpl s = (SingleSuccessorBlockImpl) pred; - return singleSuccessorHolder(s, cur); - case CONDITIONAL_BLOCK: - // add pred correctly to predecessor list - final ConditionalBlockImpl c = (ConditionalBlockImpl) pred; - if (c.getThenSuccessor() == cur) { - return new PredecessorHolder() { - @Override - public void setSuccessor(BlockImpl b) { - c.setThenSuccessor(b); - cur.removePredecessor(pred); - } - - @Override - public BlockImpl getBlock() { - return c; - } - }; - } else { - assert c.getElseSuccessor() == cur; - return new PredecessorHolder() { - @Override - public void setSuccessor(BlockImpl b) { - c.setElseSuccessor(b); - cur.removePredecessor(pred); - } - - @Override - public BlockImpl getBlock() { - return c; - } - }; - } - case EXCEPTION_BLOCK: - // add pred correctly to predecessor list - final ExceptionBlockImpl e = (ExceptionBlockImpl) pred; - if (e.getSuccessor() == cur) { - return singleSuccessorHolder(e, cur); - } else { - Set>> entrySet = - e.getExceptionalSuccessors().entrySet(); - for (final Entry> entry : entrySet) { - if (entry.getValue().contains(cur)) { - return new PredecessorHolder() { - @Override - public void setSuccessor(BlockImpl b) { - e.addExceptionalSuccessor(b, entry.getKey()); - cur.removePredecessor(pred); - } - - @Override - public BlockImpl getBlock() { - return e; - } - }; - } - } - } - assert false; - break; - case REGULAR_BLOCK: - RegularBlockImpl r = (RegularBlockImpl) pred; - return singleSuccessorHolder(r, cur); - } - return null; - } - - /** - * @return a {@link PredecessorHolder} that sets the successor of a single successor block - * {@code s}. - */ - protected static PredecessorHolder singleSuccessorHolder( - final SingleSuccessorBlockImpl s, final BlockImpl old) { - return new PredecessorHolder() { - @Override - public void setSuccessor(BlockImpl b) { - s.setSuccessor(b); - old.removePredecessor(s); - } - - @Override - public BlockImpl getBlock() { - return s; - } - }; - } - } - - /* --------------------------------------------------------- */ - /* Phase Two */ - /* --------------------------------------------------------- */ - - /** Tuple class with up to three members. */ - protected static class Tuple { - public A a; - public B b; - public C c; - - public Tuple(A a, B b) { - this.a = a; - this.b = b; - } - - public Tuple(A a, B b, C c) { - this.a = a; - this.b = b; - this.c = c; - } - } - - /** Class that performs phase two of the translation process. */ - public class CFGTranslationPhaseTwo { - - public CFGTranslationPhaseTwo() {} - - /** - * Perform phase two of the translation. - * - * @param in the result of phase one - * @return a control flow graph that might still contain degenerate basic block (such as - * empty regular basic blocks or conditional blocks with the same block as 'then' and - * 'else' sucessor) - */ - public ControlFlowGraph process(PhaseOneResult in) { - - Map bindings = in.bindings; - ArrayList nodeList = in.nodeList; - Set leaders = in.leaders; - - assert in.nodeList.size() > 0; - - // exit blocks - SpecialBlockImpl regularExitBlock = new SpecialBlockImpl(SpecialBlockType.EXIT); - SpecialBlockImpl exceptionalExitBlock = - new SpecialBlockImpl(SpecialBlockType.EXCEPTIONAL_EXIT); - - // record missing edges that will be added later - Set> missingEdges = - new MostlySingleton<>(); - - // missing exceptional edges - Set> missingExceptionalEdges = - new HashSet<>(); - - // create start block - SpecialBlockImpl startBlock = new SpecialBlockImpl(SpecialBlockType.ENTRY); - missingEdges.add(new Tuple<>(startBlock, 0)); - - // loop through all 'leaders' (while dynamically detecting the - // leaders) - RegularBlockImpl block = new RegularBlockImpl(); - int i = 0; - for (ExtendedNode node : nodeList) { - switch (node.getType()) { - case NODE: - if (leaders.contains(i)) { - RegularBlockImpl b = new RegularBlockImpl(); - block.setSuccessor(b); - block = b; - } - block.addNode(node.getNode()); - node.setBlock(block); - - // does this node end the execution (modeled as an edge to - // the exceptional exit block) - boolean terminatesExecution = node.getTerminatesExecution(); - if (terminatesExecution) { - block.setSuccessor(exceptionalExitBlock); - block = new RegularBlockImpl(); - } - break; - case CONDITIONAL_JUMP: - { - ConditionalJump cj = (ConditionalJump) node; - // Exception nodes may fall through to conditional jumps, - // so we set the block which is required for the insertion - // of missing edges. - node.setBlock(block); - assert block != null; - final ConditionalBlockImpl cb = new ConditionalBlockImpl(); - if (cj.getTrueFlowRule() != null) { - cb.setThenFlowRule(cj.getTrueFlowRule()); - } - if (cj.getFalseFlowRule() != null) { - cb.setElseFlowRule(cj.getFalseFlowRule()); - } - block.setSuccessor(cb); - block = new RegularBlockImpl(); - // use two anonymous SingleSuccessorBlockImpl that set the - // 'then' and 'else' successor of the conditional block - final Label thenLabel = cj.getThenLabel(); - final Label elseLabel = cj.getElseLabel(); - missingEdges.add( - new Tuple<>( - new SingleSuccessorBlockImpl() { - @Override - public void setSuccessor(BlockImpl successor) { - cb.setThenSuccessor(successor); - } - }, - bindings.get(thenLabel))); - missingEdges.add( - new Tuple<>( - new SingleSuccessorBlockImpl() { - @Override - public void setSuccessor(BlockImpl successor) { - cb.setElseSuccessor(successor); - } - }, - bindings.get(elseLabel))); - break; - } - case UNCONDITIONAL_JUMP: - if (leaders.contains(i)) { - RegularBlockImpl b = new RegularBlockImpl(); - block.setSuccessor(b); - block = b; - } - node.setBlock(block); - if (node.getLabel() == regularExitLabel) { - block.setSuccessor(regularExitBlock); - } else if (node.getLabel() == exceptionalExitLabel) { - block.setSuccessor(exceptionalExitBlock); - } else { - missingEdges.add(new Tuple<>(block, bindings.get(node.getLabel()))); - } - block = new RegularBlockImpl(); - break; - case EXCEPTION_NODE: - NodeWithExceptionsHolder en = (NodeWithExceptionsHolder) node; - // create new exception block and link with previous block - ExceptionBlockImpl e = new ExceptionBlockImpl(); - Node nn = en.getNode(); - e.setNode(nn); - node.setBlock(e); - block.setSuccessor(e); - block = new RegularBlockImpl(); - - // ensure linking between e and next block (normal edge) - // Note: do not link to the next block for throw statements - // (these throw exceptions for sure) - if (!node.getTerminatesExecution()) { - missingEdges.add(new Tuple<>(e, i + 1)); - } - - // exceptional edges - for (Entry> entry : en.getExceptions().entrySet()) { - TypeMirror cause = entry.getKey(); - for (Label label : entry.getValue()) { - Integer target = bindings.get(label); - missingExceptionalEdges.add( - new Tuple( - e, target, cause)); - } - } - break; - } - i++; - } - - // add missing edges - for (Tuple p : missingEdges) { - Integer index = p.b; - ExtendedNode extendedNode = nodeList.get(index); - BlockImpl target = extendedNode.getBlock(); - SingleSuccessorBlockImpl source = p.a; - source.setSuccessor(target); - } - - // add missing exceptional edges - for (Tuple p : missingExceptionalEdges) { - Integer index = p.b; - TypeMirror cause = (TypeMirror) p.c; - ExceptionBlockImpl source = p.a; - if (index == null) { - // edge to exceptional exit - source.addExceptionalSuccessor(exceptionalExitBlock, cause); - } else { - // edge to specific target - ExtendedNode extendedNode = nodeList.get(index); - BlockImpl target = extendedNode.getBlock(); - source.addExceptionalSuccessor(target, cause); - } - } - - return new ControlFlowGraph( - startBlock, - regularExitBlock, - exceptionalExitBlock, - in.underlyingAST, - in.treeLookupMap, - in.convertedTreeLookupMap, - in.returnNodes); - } - } - - /* --------------------------------------------------------- */ - /* Phase One */ - /* --------------------------------------------------------- */ - - /** - * A wrapper object to pass around the result of phase one. For a documentation of the fields - * see {@link CFGTranslationPhaseOne}. - */ - protected static class PhaseOneResult { - - private final IdentityHashMap treeLookupMap; - private final IdentityHashMap convertedTreeLookupMap; - private final UnderlyingAST underlyingAST; - private final Map bindings; - private final ArrayList nodeList; - private final Set leaders; - private final List returnNodes; - - public PhaseOneResult( - UnderlyingAST underlyingAST, - IdentityHashMap treeLookupMap, - IdentityHashMap convertedTreeLookupMap, - ArrayList nodeList, - Map bindings, - Set leaders, - List returnNodes) { - this.underlyingAST = underlyingAST; - this.treeLookupMap = treeLookupMap; - this.convertedTreeLookupMap = convertedTreeLookupMap; - this.nodeList = nodeList; - this.bindings = bindings; - this.leaders = leaders; - this.returnNodes = returnNodes; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (ExtendedNode n : nodeList) { - sb.append(nodeToString(n)); - sb.append("\n"); - } - return sb.toString(); - } - - protected String nodeToString(ExtendedNode n) { - if (n.getType() == ExtendedNodeType.CONDITIONAL_JUMP) { - ConditionalJump t = (ConditionalJump) n; - return "TwoTargetConditionalJump(" - + resolveLabel(t.getThenLabel()) - + "," - + resolveLabel(t.getElseLabel()) - + ")"; - } else if (n.getType() == ExtendedNodeType.UNCONDITIONAL_JUMP) { - return "UnconditionalJump(" + resolveLabel(n.getLabel()) + ")"; - } else { - return n.toString(); - } - } - - private String resolveLabel(Label label) { - Integer index = bindings.get(label); - if (index == null) { - return "null"; - } - return nodeToString(nodeList.get(index)); - } - } - - /** - * Class that performs phase one of the translation process. It generates the following - * information: - * - *
    - *
  • A sequence of extended nodes. - *
  • A set of bindings from {@link Label}s to positions in the node sequence. - *
  • A set of leader nodes that give rise to basic blocks in phase two. - *
  • A lookup map that gives the mapping from AST tree nodes to {@link Node}s. - *
- * - *

The return type of this scanner is {@link Node}. For expressions, the corresponding node - * is returned to allow linking between different nodes. - * - *

However, for statements there is usually no single {@link Node} that is created, and thus - * no node is returned (rather, null is returned). - * - *

Every {@code visit*} method is assumed to add at least one extended node to the list of - * nodes (which might only be a jump). - */ - public class CFGTranslationPhaseOne extends TreePathScanner { - - public CFGTranslationPhaseOne() {} - - /** Annotation processing environment and its associated type and tree utilities. */ - protected ProcessingEnvironment env; - - protected Elements elements; - protected Types types; - protected Trees trees; - protected TreeBuilder treeBuilder; - protected AnnotationProvider annotationProvider; - - /** - * Current {@link Label} to which a break statement with no label should jump, or null if - * there is no valid destination. - */ - protected /*@Nullable*/ Label breakTargetL; - - /** - * Map from AST label Names to CFG {@link Label}s for breaks. Each labeled statement creates - * two CFG {@link Label}s, one for break and one for continue. - */ - protected Map breakLabels; - - /** - * Current {@link Label} to which a continue statement with no label should jump, or null if - * there is no valid destination. - */ - protected /*@Nullable*/ Label continueTargetL; - - /** - * Map from AST label Names to CFG {@link Label}s for continues. Each labeled statement - * creates two CFG {@link Label}s, one for break and one for continue. - */ - protected Map continueLabels; - - /** - * Maps from AST {@link Tree}s to {@link Node}s. Every Tree that produces a value will have - * at least one corresponding Node. Trees that undergo conversions, such as boxing or - * unboxing, can map to two distinct Nodes. The Node for the pre-conversion value is stored - * in the treeLookupMap, while the Node for the post-conversion value is stored in the - * convertedTreeLookupMap. - */ - protected IdentityHashMap treeLookupMap; - - /** Map from AST {@link Tree}s to post-conversion {@link Node}s. */ - protected IdentityHashMap convertedTreeLookupMap; - - /** The list of extended nodes. */ - protected ArrayList nodeList; - - /** The bindings of labels to positions (i.e., indices) in the {@code nodeList}. */ - protected Map bindings; - - /** The set of leaders (represented as indices into {@code nodeList}). */ - protected Set leaders; - - /** - * All return nodes (if any) encountered. Only includes return statements that actually - * return something - */ - private List returnNodes; - - /** Nested scopes of try-catch blocks in force at the current program point. */ - private TryStack tryStack; - - /** - * Performs the actual work of phase one. - * - * @param bodyPath path to the body of the underlying AST's method - * @param env annotation processing environment containing type utilities - * @param underlyingAST the AST for which the CFG is to be built - * @param exceptionalExitLabel the label for exceptional exits from the CFG - * @param treeBuilder builder for new AST nodes - * @param annotationProvider extracts annotations from AST nodes - * @return the result of phase one - */ - public PhaseOneResult process( - TreePath bodyPath, - ProcessingEnvironment env, - UnderlyingAST underlyingAST, - Label exceptionalExitLabel, - TreeBuilder treeBuilder, - AnnotationProvider annotationProvider) { - this.env = env; - this.tryStack = new TryStack(exceptionalExitLabel); - this.treeBuilder = treeBuilder; - this.annotationProvider = annotationProvider; - elements = env.getElementUtils(); - types = env.getTypeUtils(); - - // initialize lists and maps - treeLookupMap = new IdentityHashMap<>(); - convertedTreeLookupMap = new IdentityHashMap<>(); - nodeList = new ArrayList<>(); - bindings = new HashMap<>(); - leaders = new HashSet<>(); - breakLabels = new HashMap<>(); - continueLabels = new HashMap<>(); - returnNodes = new ArrayList<>(); - - // traverse AST of the method body - scan(bodyPath, null); - - // add marker to indicate that the next block will be the exit block - // Note: if there is a return statement earlier in the method (which - // is always the case for non-void methods), then this is not - // strictly necessary. However, it is also not a problem, as it will - // just generate a degenerated control graph case that will be - // removed in a later phase. - nodeList.add(new UnconditionalJump(regularExitLabel)); - - return new PhaseOneResult( - underlyingAST, - treeLookupMap, - convertedTreeLookupMap, - nodeList, - bindings, - leaders, - returnNodes); - } - - public PhaseOneResult process( - CompilationUnitTree root, - ProcessingEnvironment env, - UnderlyingAST underlyingAST, - Label exceptionalExitLabel, - TreeBuilder treeBuilder, - AnnotationProvider annotationProvider) { - trees = Trees.instance(env); - TreePath bodyPath = trees.getPath(root, underlyingAST.getCode()); - return process( - bodyPath, - env, - underlyingAST, - exceptionalExitLabel, - treeBuilder, - annotationProvider); - } - - /** - * Perform any actions required when CFG translation creates a new Tree that is not part of - * the original AST. - * - * @param tree the newly created Tree - */ - public void handleArtificialTree(Tree tree) {} - - /* --------------------------------------------------------- */ - /* Nodes and Labels Management */ - /* --------------------------------------------------------- */ - - /** - * Add a node to the lookup map if it not already present. - * - * @param node the node to add to the lookup map - */ - protected void addToLookupMap(Node node) { - Tree tree = node.getTree(); - if (tree == null) { - return; - } - if (!treeLookupMap.containsKey(tree)) { - treeLookupMap.put(tree, node); - } - - Tree enclosingParens = parenMapping.get(tree); - while (enclosingParens != null) { - treeLookupMap.put(enclosingParens, node); - enclosingParens = parenMapping.get(enclosingParens); - } - } - - /** - * Add a node in the post-conversion lookup map. The node should refer to a Tree and that - * Tree should already be in the pre-conversion lookup map. This method is used to update - * the Tree-Node mapping with conversion nodes. - * - * @param node the node to add to the lookup map - */ - protected void addToConvertedLookupMap(Node node) { - Tree tree = node.getTree(); - addToConvertedLookupMap(tree, node); - } - - /** - * Add a node in the post-conversion lookup map. The tree argument should already be in the - * pre-conversion lookup map. This method is used to update the Tree-Node mapping with - * conversion nodes. - * - * @param tree the tree used as a key in the map - * @param node the node to add to the lookup map - */ - protected void addToConvertedLookupMap(Tree tree, Node node) { - assert tree != null; - assert treeLookupMap.containsKey(tree); - convertedTreeLookupMap.put(tree, node); - } - - /** - * Extend the list of extended nodes with a node. - * - * @param node the node to add - * @return the same node (for convenience) - */ - protected T extendWithNode(T node) { - addToLookupMap(node); - extendWithExtendedNode(new NodeHolder(node)); - return node; - } - - /** - * Extend the list of extended nodes with a node, where {@code node} might throw the - * exception {@code cause}. - * - * @param node the node to add - * @param cause an exception that the node might throw - * @return the node holder - */ - protected NodeWithExceptionsHolder extendWithNodeWithException( - Node node, TypeMirror cause) { - addToLookupMap(node); - return extendWithNodeWithExceptions(node, Collections.singleton(cause)); - } - - /** - * Extend the list of extended nodes with a node, where {@code node} might throw any of the - * exception in {@code causes}. - * - * @param node the node to add - * @param causes set of exceptions that the node might throw - * @return the node holder - */ - protected NodeWithExceptionsHolder extendWithNodeWithExceptions( - Node node, Set causes) { - addToLookupMap(node); - Map> exceptions = new HashMap<>(); - for (TypeMirror cause : causes) { - exceptions.put(cause, tryStack.possibleLabels(cause)); - } - NodeWithExceptionsHolder exNode = new NodeWithExceptionsHolder(node, exceptions); - extendWithExtendedNode(exNode); - return exNode; - } - - /** - * Insert {@code node} after {@code pred} in the list of extended nodes, or append to the - * list if {@code pred} is not present. - * - * @param node the node to add - * @param pred the desired predecessor of node - * @return the node holder - */ - protected T insertNodeAfter(T node, Node pred) { - addToLookupMap(node); - insertExtendedNodeAfter(new NodeHolder(node), pred); - return node; - } - - /** - * Insert a {@code node} that might throw the exception {@code cause} after {@code pred} in - * the list of extended nodes, or append to the list if {@code pred} is not present. - * - * @param node the node to add - * @param causes set of exceptions that the node might throw - * @param pred the desired predecessor of node - * @return the node holder - */ - protected NodeWithExceptionsHolder insertNodeWithExceptionsAfter( - Node node, Set causes, Node pred) { - addToLookupMap(node); - Map> exceptions = new HashMap<>(); - for (TypeMirror cause : causes) { - exceptions.put(cause, tryStack.possibleLabels(cause)); - } - NodeWithExceptionsHolder exNode = new NodeWithExceptionsHolder(node, exceptions); - insertExtendedNodeAfter(exNode, pred); - return exNode; - } - - /** - * Extend the list of extended nodes with an extended node. - * - * @param n the extended node - */ - protected void extendWithExtendedNode(ExtendedNode n) { - nodeList.add(n); - } - - /** - * Insert {@code n} after the node {@code pred} in the list of extended nodes, or append - * {@code n} if {@code pred} is not present. - * - * @param n the extended node - * @param pred the desired predecessor - */ - protected void insertExtendedNodeAfter(ExtendedNode n, Node pred) { - int index = -1; - for (int i = 0; i < nodeList.size(); i++) { - ExtendedNode inList = nodeList.get(i); - if (inList instanceof NodeHolder || inList instanceof NodeWithExceptionsHolder) { - if (inList.getNode() == pred) { - index = i; - break; - } - } - } - if (index != -1) { - nodeList.add(index + 1, n); - // update bindings - for (Entry e : bindings.entrySet()) { - if (e.getValue() >= index + 1) { - bindings.put(e.getKey(), e.getValue() + 1); - } - } - // update leaders - Set newLeaders = new HashSet<>(); - for (Integer l : leaders) { - if (l >= index + 1) { - newLeaders.add(l + 1); - } else { - newLeaders.add(l); - } - } - leaders = newLeaders; - } else { - nodeList.add(n); - } - } - - /** - * Add the label {@code l} to the extended node that will be placed next in the sequence. - */ - protected void addLabelForNextNode(Label l) { - leaders.add(nodeList.size()); - bindings.put(l, nodeList.size()); - } - - /* --------------------------------------------------------- */ - /* Utility Methods */ - /* --------------------------------------------------------- */ - - protected long uid = 0; - - protected String uniqueName(String prefix) { - return prefix + "#num" + uid++; - } - - /** - * If the input node is an unboxed primitive type, insert a call to the appropriate valueOf - * method, otherwise leave it alone. - * - * @param node in input node - * @return a Node representing the boxed version of the input, which may simply be the input - * node - */ - protected Node box(Node node) { - // For boxing conversion, see JLS 5.1.7 - if (TypesUtils.isPrimitive(node.getType())) { - PrimitiveType primitive = types.getPrimitiveType(node.getType().getKind()); - TypeMirror boxedType = types.getDeclaredType(types.boxedClass(primitive)); - - TypeElement boxedElement = (TypeElement) ((DeclaredType) boxedType).asElement(); - IdentifierTree classTree = treeBuilder.buildClassUse(boxedElement); - handleArtificialTree(classTree); - ClassNameNode className = new ClassNameNode(classTree); - className.setInSource(false); - insertNodeAfter(className, node); - - MemberSelectTree valueOfSelect = treeBuilder.buildValueOfMethodAccess(classTree); - handleArtificialTree(valueOfSelect); - MethodAccessNode valueOfAccess = new MethodAccessNode(valueOfSelect, className); - valueOfAccess.setInSource(false); - insertNodeAfter(valueOfAccess, className); - - MethodInvocationTree valueOfCall = - treeBuilder.buildMethodInvocation( - valueOfSelect, (ExpressionTree) node.getTree()); - handleArtificialTree(valueOfCall); - Node boxed = - new MethodInvocationNode( - valueOfCall, - valueOfAccess, - Collections.singletonList(node), - getCurrentPath()); - boxed.setInSource(false); - // Add Throwable to account for unchecked exceptions - TypeElement throwableElement = elements.getTypeElement("java.lang.Throwable"); - addToConvertedLookupMap(node.getTree(), boxed); - insertNodeWithExceptionsAfter( - boxed, Collections.singleton(throwableElement.asType()), valueOfAccess); - return boxed; - } else { - return node; - } - } - - /** - * If the input node is a boxed type, unbox it, otherwise leave it alone. - * - * @param node in input node - * @return a Node representing the unboxed version of the input, which may simply be the - * input node - */ - protected Node unbox(Node node) { - if (TypesUtils.isBoxedPrimitive(node.getType())) { - - MemberSelectTree primValueSelect = - treeBuilder.buildPrimValueMethodAccess(node.getTree()); - handleArtificialTree(primValueSelect); - MethodAccessNode primValueAccess = new MethodAccessNode(primValueSelect, node); - primValueAccess.setInSource(false); - // Method access may throw NullPointerException - TypeElement npeElement = elements.getTypeElement("java.lang.NullPointerException"); - insertNodeWithExceptionsAfter( - primValueAccess, Collections.singleton(npeElement.asType()), node); - - MethodInvocationTree primValueCall = - treeBuilder.buildMethodInvocation(primValueSelect); - handleArtificialTree(primValueCall); - Node unboxed = - new MethodInvocationNode( - primValueCall, - primValueAccess, - Collections.emptyList(), - getCurrentPath()); - unboxed.setInSource(false); - - // Add Throwable to account for unchecked exceptions - TypeElement throwableElement = elements.getTypeElement("java.lang.Throwable"); - addToConvertedLookupMap(node.getTree(), unboxed); - insertNodeWithExceptionsAfter( - unboxed, Collections.singleton(throwableElement.asType()), primValueAccess); - return unboxed; - } else { - return node; - } - } - - private TreeInfo getTreeInfo(Tree tree) { - final TypeMirror type = InternalUtils.typeOf(tree); - final boolean boxed = TypesUtils.isBoxedPrimitive(type); - final TypeMirror unboxedType = boxed ? types.unboxedType(type) : type; - - final boolean bool = TypesUtils.isBooleanType(type); - final boolean numeric = TypesUtils.isNumeric(unboxedType); - - return new TreeInfo() { - @Override - public boolean isNumeric() { - return numeric; - } - - @Override - public boolean isBoxed() { - return boxed; - } - - @Override - public boolean isBoolean() { - return bool; - } - - @Override - public TypeMirror unboxedType() { - return unboxedType; - } - }; - } - - /** @return the unboxed tree if necessary, as described in JLS 5.1.8 */ - private Node unboxAsNeeded(Node node, boolean boxed) { - return boxed ? unbox(node) : node; - } - - /** - * Convert the input node to String type, if it isn't already. - * - * @param node an input node - * @return a Node with the value promoted to String, which may be the input node - */ - protected Node stringConversion(Node node) { - // For string conversion, see JLS 5.1.11 - TypeElement stringElement = elements.getTypeElement("java.lang.String"); - if (!TypesUtils.isString(node.getType())) { - Node converted = - new StringConversionNode(node.getTree(), node, stringElement.asType()); - addToConvertedLookupMap(converted); - insertNodeAfter(converted, node); - return converted; - } else { - return node; - } - } - - /** - * Perform unary numeric promotion on the input node. - * - * @param node a node producing a value of numeric primitive or boxed type - * @return a Node with the value promoted to the int, long float or double, which may be the - * input node - */ - protected Node unaryNumericPromotion(Node node) { - // For unary numeric promotion, see JLS 5.6.1 - node = unbox(node); - - switch (node.getType().getKind()) { - case BYTE: - case CHAR: - case SHORT: - { - TypeMirror intType = types.getPrimitiveType(TypeKind.INT); - Node widened = new WideningConversionNode(node.getTree(), node, intType); - addToConvertedLookupMap(widened); - insertNodeAfter(widened, node); - return widened; - } - default: - // Nothing to do. - break; - } - - return node; - } - - /** - * Returns true if the argument type is a numeric primitive or a boxed numeric primitive and - * false otherwise. - */ - protected boolean isNumericOrBoxed(TypeMirror type) { - if (TypesUtils.isBoxedPrimitive(type)) { - type = types.unboxedType(type); - } - return TypesUtils.isNumeric(type); - } - - /** - * Compute the type to which two numeric types must be promoted before performing a binary - * numeric operation on them. The input types must both be numeric and the output type is - * primitive. - * - * @param left the type of the left operand - * @param right the type of the right operand - * @return a TypeMirror representing the binary numeric promoted type - */ - protected TypeMirror binaryPromotedType(TypeMirror left, TypeMirror right) { - if (TypesUtils.isBoxedPrimitive(left)) { - left = types.unboxedType(left); - } - if (TypesUtils.isBoxedPrimitive(right)) { - right = types.unboxedType(right); - } - TypeKind promotedTypeKind = TypesUtils.widenedNumericType(left, right); - return types.getPrimitiveType(promotedTypeKind); - } - - /** - * Perform binary numeric promotion on the input node to make it match the expression type. - * - * @param node a node producing a value of numeric primitive or boxed type - * @param exprType the type to promote the value to - * @return a Node with the value promoted to the exprType, which may be the input node - */ - protected Node binaryNumericPromotion(Node node, TypeMirror exprType) { - // For binary numeric promotion, see JLS 5.6.2 - node = unbox(node); - - if (!types.isSameType(node.getType(), exprType)) { - Node widened = new WideningConversionNode(node.getTree(), node, exprType); - addToConvertedLookupMap(widened); - insertNodeAfter(widened, node); - return widened; - } else { - return node; - } - } - - /** - * Perform widening primitive conversion on the input node to make it match the destination - * type. - * - * @param node a node producing a value of numeric primitive type - * @param destType the type to widen the value to - * @return a Node with the value widened to the exprType, which may be the input node - */ - protected Node widen(Node node, TypeMirror destType) { - // For widening conversion, see JLS 5.1.2 - assert TypesUtils.isPrimitive(node.getType()) && TypesUtils.isPrimitive(destType) - : "widening must be applied to primitive types"; - if (types.isSubtype(node.getType(), destType) - && !types.isSameType(node.getType(), destType)) { - Node widened = new WideningConversionNode(node.getTree(), node, destType); - addToConvertedLookupMap(widened); - insertNodeAfter(widened, node); - return widened; - } else { - return node; - } - } - - /** - * Perform narrowing conversion on the input node to make it match the destination type. - * - * @param node a node producing a value of numeric primitive type - * @param destType the type to narrow the value to - * @return a Node with the value narrowed to the exprType, which may be the input node - */ - protected Node narrow(Node node, TypeMirror destType) { - // For narrowing conversion, see JLS 5.1.3 - assert TypesUtils.isPrimitive(node.getType()) && TypesUtils.isPrimitive(destType) - : "narrowing must be applied to primitive types"; - if (types.isSubtype(destType, node.getType()) - && !types.isSameType(destType, node.getType())) { - Node narrowed = new NarrowingConversionNode(node.getTree(), node, destType); - addToConvertedLookupMap(narrowed); - insertNodeAfter(narrowed, node); - return narrowed; - } else { - return node; - } - } - - /** - * Perform narrowing conversion and optionally boxing conversion on the input node to make - * it match the destination type. - * - * @param node a node producing a value of numeric primitive type - * @param destType the type to narrow the value to (possibly boxed) - * @return a Node with the value narrowed and boxed to the destType, which may be the input - * node - */ - protected Node narrowAndBox(Node node, TypeMirror destType) { - if (TypesUtils.isBoxedPrimitive(destType)) { - return box(narrow(node, types.unboxedType(destType))); - } else { - return narrow(node, destType); - } - } - - /** - * Return whether a conversion from the type of the node to varType requires narrowing. - * - * @param varType the type of a variable (or general LHS) to be converted to - * @param node a node whose value is being converted - * @return whether this conversion requires narrowing to succeed - */ - protected boolean conversionRequiresNarrowing(TypeMirror varType, Node node) { - // Narrowing is restricted to cases where the left hand side - // is byte, char, short or Byte, Char, Short and the right - // hand side is a constant. - TypeMirror unboxedVarType = - TypesUtils.isBoxedPrimitive(varType) ? types.unboxedType(varType) : varType; - TypeKind unboxedVarKind = unboxedVarType.getKind(); - boolean isLeftNarrowableTo = - unboxedVarKind == TypeKind.BYTE - || unboxedVarKind == TypeKind.SHORT - || unboxedVarKind == TypeKind.CHAR; - boolean isRightConstant = node instanceof ValueLiteralNode; - return isLeftNarrowableTo && isRightConstant; - } - - /** - * Assignment conversion and method invocation conversion are almost identical, except that - * assignment conversion allows narrowing. We factor out the common logic here. - * - * @param node a Node producing a value - * @param varType the type of a variable - * @param contextAllowsNarrowing whether to allow narrowing (for assignment conversion) or - * not (for method invocation conversion) - * @return a Node with the value converted to the type of the variable, which may be the - * input node itself - */ - protected Node commonConvert( - Node node, TypeMirror varType, boolean contextAllowsNarrowing) { - // For assignment conversion, see JLS 5.2 - // For method invocation conversion, see JLS 5.3 - - // Check for identical types or "identity conversion" - TypeMirror nodeType = node.getType(); - boolean isSameType = types.isSameType(nodeType, varType); - if (isSameType) { - return node; - } - - boolean isRightNumeric = TypesUtils.isNumeric(nodeType); - boolean isRightPrimitive = TypesUtils.isPrimitive(nodeType); - boolean isRightBoxed = TypesUtils.isBoxedPrimitive(nodeType); - boolean isRightReference = nodeType instanceof ReferenceType; - boolean isLeftNumeric = TypesUtils.isNumeric(varType); - boolean isLeftPrimitive = TypesUtils.isPrimitive(varType); - // boolean isLeftBoxed = TypesUtils.isBoxedPrimitive(varType); - boolean isLeftReference = varType instanceof ReferenceType; - boolean isSubtype = types.isSubtype(nodeType, varType); - - if (isRightNumeric && isLeftNumeric && isSubtype) { - node = widen(node, varType); - nodeType = node.getType(); - } else if (isRightReference && isLeftReference && isSubtype) { - // widening reference conversion is a no-op, but if it - // applies, then later conversions do not. - } else if (isRightPrimitive && isLeftReference) { - if (contextAllowsNarrowing && conversionRequiresNarrowing(varType, node)) { - node = narrowAndBox(node, varType); - nodeType = node.getType(); - } else { - node = box(node); - nodeType = node.getType(); - } - } else if (isRightBoxed && isLeftPrimitive) { - node = unbox(node); - nodeType = node.getType(); - - if (types.isSubtype(nodeType, varType) && !types.isSameType(nodeType, varType)) { - node = widen(node, varType); - nodeType = node.getType(); - } - } else if (isRightPrimitive && isLeftPrimitive) { - if (contextAllowsNarrowing && conversionRequiresNarrowing(varType, node)) { - node = narrow(node, varType); - nodeType = node.getType(); - } - } - - // TODO: if checkers need to know about null references of - // a particular type, add logic for them here. - - return node; - } - - /** - * Perform assignment conversion so that it can be assigned to a variable of the given type. - * - * @param node a Node producing a value - * @param varType the type of a variable - * @return a Node with the value converted to the type of the variable, which may be the - * input node itself - */ - protected Node assignConvert(Node node, TypeMirror varType) { - return commonConvert(node, varType, true); - } - - /** - * Perform method invocation conversion so that the node can be passed as a formal parameter - * of the given type. - * - * @param node a Node producing a value - * @param formalType the type of a formal parameter - * @return a Node with the value converted to the type of the formal, which may be the input - * node itself - */ - protected Node methodInvocationConvert(Node node, TypeMirror formalType) { - return commonConvert(node, formalType, false); - } - - /** - * Given a method element and as list of argument expressions, return a list of {@link - * Node}s representing the arguments converted for a call of the method. This method applies - * to both method invocations and constructor calls. - * - * @param method an ExecutableElement representing a method to be called - * @param actualExprs a List of argument expressions to a call - * @return a List of {@link Node}s representing arguments after conversions required by a - * call to this method - */ - protected List convertCallArguments( - ExecutableElement method, List actualExprs) { - // NOTE: It is important to convert one method argument before - // generating CFG nodes for the next argument, since label binding - // expects nodes to be generated in execution order. Therefore, - // this method first determines which conversions need to be applied - // and then iterates over the actual arguments. - List formals = method.getParameters(); - - ArrayList convertedNodes = new ArrayList(); - - int numFormals = formals.size(); - int numActuals = actualExprs.size(); - if (method.isVarArgs()) { - // Create a new array argument if the actuals outnumber - // the formals, or if the last actual is not assignable - // to the last formal. - int lastArgIndex = numFormals - 1; - TypeMirror lastParamType = formals.get(lastArgIndex).asType(); - List dimensions = new ArrayList<>(); - List initializers = new ArrayList<>(); - - if (numActuals == numFormals - 1) { - // Apply method invocation conversion to all actual - // arguments, then create and append an empty array - for (int i = 0; i < numActuals; i++) { - Node actualVal = scan(actualExprs.get(i), null); - convertedNodes.add( - methodInvocationConvert(actualVal, formals.get(i).asType())); - } - - Node lastArgument = - new ArrayCreationNode(null, lastParamType, dimensions, initializers); - extendWithNode(lastArgument); - - convertedNodes.add(lastArgument); - } else { - TypeMirror actualType = InternalUtils.typeOf(actualExprs.get(lastArgIndex)); - if (numActuals == numFormals && types.isAssignable(actualType, lastParamType)) { - // Normal call with no array creation, apply method - // invocation conversion to all arguments. - for (int i = 0; i < numActuals; i++) { - Node actualVal = scan(actualExprs.get(i), null); - convertedNodes.add( - methodInvocationConvert(actualVal, formals.get(i).asType())); - } - } else { - assert lastParamType instanceof ArrayType - : "variable argument formal must be an array"; - // Apply method invocation conversion to lastArgIndex - // arguments and use the remaining ones to initialize - // an array. - for (int i = 0; i < lastArgIndex; i++) { - Node actualVal = scan(actualExprs.get(i), null); - convertedNodes.add( - methodInvocationConvert(actualVal, formals.get(i).asType())); - } - - TypeMirror elemType = ((ArrayType) lastParamType).getComponentType(); - for (int i = lastArgIndex; i < numActuals; i++) { - Node actualVal = scan(actualExprs.get(i), null); - initializers.add(assignConvert(actualVal, elemType)); - } - - Node lastArgument = - new ArrayCreationNode( - null, lastParamType, dimensions, initializers); - extendWithNode(lastArgument); - convertedNodes.add(lastArgument); - } - } - } else { - for (int i = 0; i < numActuals; i++) { - Node actualVal = scan(actualExprs.get(i), null); - convertedNodes.add(methodInvocationConvert(actualVal, formals.get(i).asType())); - } - } - - return convertedNodes; - } - - /** - * Convert an operand of a conditional expression to the type of the whole expression. - * - * @param node a node occurring as the second or third operand of a conditional expression - * @param destType the type to promote the value to - * @return a Node with the value promoted to the destType, which may be the input node - */ - protected Node conditionalExprPromotion(Node node, TypeMirror destType) { - // For rules on converting operands of conditional expressions, - // JLS 15.25 - TypeMirror nodeType = node.getType(); - - // If the operand is already the same type as the whole - // expression, then do nothing. - if (types.isSameType(nodeType, destType)) { - return node; - } - - // If the operand is a primitive and the whole expression is - // boxed, then apply boxing. - if (TypesUtils.isPrimitive(nodeType) && TypesUtils.isBoxedPrimitive(destType)) { - return box(node); - } - - // If the operand is byte or Byte and the whole expression is - // short, then convert to short. - boolean isBoxedPrimitive = TypesUtils.isBoxedPrimitive(nodeType); - TypeMirror unboxedNodeType = isBoxedPrimitive ? types.unboxedType(nodeType) : nodeType; - TypeMirror unboxedDestType = - TypesUtils.isBoxedPrimitive(destType) ? types.unboxedType(destType) : destType; - if (TypesUtils.isNumeric(unboxedNodeType) && TypesUtils.isNumeric(unboxedDestType)) { - if (unboxedNodeType.getKind() == TypeKind.BYTE - && destType.getKind() == TypeKind.SHORT) { - if (isBoxedPrimitive) { - node = unbox(node); - } - return widen(node, destType); - } - - // If the operand is Byte, Short or Character and the whole expression - // is the unboxed version of it, then apply unboxing. - TypeKind destKind = destType.getKind(); - if (destKind == TypeKind.BYTE - || destKind == TypeKind.CHAR - || destKind == TypeKind.SHORT) { - if (isBoxedPrimitive) { - return unbox(node); - } else if (nodeType.getKind() == TypeKind.INT) { - return narrow(node, destType); - } - } - - return binaryNumericPromotion(node, destType); - } - - // For the final case in JLS 15.25, apply boxing but not lub. - if (TypesUtils.isPrimitive(nodeType) - && (destType.getKind() == TypeKind.DECLARED - || destType.getKind() == TypeKind.UNION - || destType.getKind() == TypeKind.INTERSECTION)) { - return box(node); - } - - return node; - } - - /** - * Returns the label {@link Name} of the leaf in the argument path, or null if the leaf is - * not a labeled statement. - */ - protected /*@Nullable*/ Name getLabel(TreePath path) { - if (path.getParentPath() != null) { - Tree parent = path.getParentPath().getLeaf(); - if (parent.getKind() == Tree.Kind.LABELED_STATEMENT) { - return ((LabeledStatementTree) parent).getLabel(); - } - } - return null; - } - - /* --------------------------------------------------------- */ - /* Visitor Methods */ - /* --------------------------------------------------------- */ - - @Override - public Node visitAnnotatedType(AnnotatedTypeTree tree, Void p) { - return scan(tree.getUnderlyingType(), p); - } - - @Override - public Node visitAnnotation(AnnotationTree tree, Void p) { - assert false : "AnnotationTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public MethodInvocationNode visitMethodInvocation(MethodInvocationTree tree, Void p) { - - // see JLS 15.12.4 - - // First, compute the receiver, if any (15.12.4.1) - // Second, evaluate the actual arguments, left to right and - // possibly some arguments are stored into an array for variable - // arguments calls (15.12.4.2) - // Third, test the receiver, if any, for nullness (15.12.4.4) - // Fourth, convert the arguments to the type of the formal - // parameters (15.12.4.5) - // Fifth, if the method is synchronized, lock the receiving - // object or class (15.12.4.5) - ExecutableElement method = TreeUtils.elementFromUse(tree); - if (method == null) { - // The method wasn't found, e.g. because of a compilation error. - return null; - } - - // TODO? Variable wasn't used. - // boolean isBooleanMethod = TypesUtils.isBooleanType(method.getReturnType()); - - ExpressionTree methodSelect = tree.getMethodSelect(); - assert TreeUtils.isMethodAccess(methodSelect) - : "Expected a method access, but got: " + methodSelect; - - List actualExprs = tree.getArguments(); - - // Look up method to invoke and possibly throw NullPointerException - Node receiver = getReceiver(methodSelect, TreeUtils.enclosingClass(getCurrentPath())); - - MethodAccessNode target = new MethodAccessNode(methodSelect, receiver); - - ExecutableElement element = TreeUtils.elementFromUse(tree); - if (ElementUtils.isStatic(element) || receiver instanceof ThisLiteralNode) { - // No NullPointerException can be thrown, use normal node - extendWithNode(target); - } else { - TypeElement npeElement = elements.getTypeElement("java.lang.NullPointerException"); - extendWithNodeWithException(target, npeElement.asType()); - } - - List arguments = new ArrayList<>(); - - // Don't convert arguments for enum super calls. The AST contains - // no actual arguments, while the method element expects two arguments, - // leading to an exception in convertCallArguments. Since no actual - // arguments are present in the AST that is being checked, it shouldn't - // cause any harm to omit the conversions. - // See also BaseTypeVisitor.visitMethodInvocation and - // QualifierPolymorphism.annotate - if (!TreeUtils.isEnumSuper(tree)) { - arguments = convertCallArguments(method, actualExprs); - } - - // TODO: lock the receiver for synchronized methods - - MethodInvocationNode node = - new MethodInvocationNode(tree, target, arguments, getCurrentPath()); - - Set thrownSet = new HashSet<>(); - // Add exceptions explicitly mentioned in the throws clause. - List thrownTypes = element.getThrownTypes(); - thrownSet.addAll(thrownTypes); - // Add Throwable to account for unchecked exceptions - TypeElement throwableElement = elements.getTypeElement("java.lang.Throwable"); - thrownSet.add(throwableElement.asType()); - - ExtendedNode extendedNode = extendWithNodeWithExceptions(node, thrownSet); - - /* Check for the TerminatesExecution annotation. */ - Element methodElement = InternalUtils.symbol(tree); - boolean terminatesExecution = - annotationProvider.getDeclAnnotation(methodElement, TerminatesExecution.class) - != null; - if (terminatesExecution) { - extendedNode.setTerminatesExecution(true); - } - - return node; - } - - @Override - public Node visitAssert(AssertTree tree, Void p) { - - // see JLS 14.10 - - // If assertions are enabled, then we can just translate the - // assertion. - if (assumeAssertionsEnabled || assumeAssertionsEnabledFor(tree)) { - translateAssertWithAssertionsEnabled(tree); - return null; - } - - // If assertions are disabled, then nothing is executed. - if (assumeAssertionsDisabled) { - return null; - } - - // Otherwise, we don't know if assertions are enabled, so we use a - // variable "ea" and case-split on it. One branch does execute the - // assertion, while the other assumes assertions are disabled. - VariableTree ea = getAssertionsEnabledVariable(); - - // all necessary labels - Label assertionEnabled = new Label(); - Label assertionDisabled = new Label(); - - extendWithNode(new LocalVariableNode(ea)); - extendWithExtendedNode(new ConditionalJump(assertionEnabled, assertionDisabled)); - - // 'then' branch (i.e. check the assertion) - addLabelForNextNode(assertionEnabled); - - translateAssertWithAssertionsEnabled(tree); - - // 'else' branch - addLabelForNextNode(assertionDisabled); - - return null; - } - - /** - * Should assertions be assumed to be executed for a given {@link AssertTree}? False by - * default. - */ - protected boolean assumeAssertionsEnabledFor(AssertTree tree) { - return false; - } - - /** The {@link VariableTree} that indicates whether assertions are enabled or not. */ - protected VariableTree ea = null; - - /** - * Get a synthetic {@link VariableTree} that indicates whether assertions are enabled or - * not. - */ - protected VariableTree getAssertionsEnabledVariable() { - if (ea == null) { - String name = uniqueName("assertionsEnabled"); - MethodTree enclosingMethod = TreeUtils.enclosingMethod(getCurrentPath()); - Element owner; - if (enclosingMethod != null) { - owner = TreeUtils.elementFromDeclaration(enclosingMethod); - } else { - ClassTree enclosingClass = TreeUtils.enclosingClass(getCurrentPath()); - owner = TreeUtils.elementFromDeclaration(enclosingClass); - } - ExpressionTree initializer = null; - ea = - treeBuilder.buildVariableDecl( - types.getPrimitiveType(TypeKind.BOOLEAN), name, owner, initializer); - } - return ea; - } - - /** - * Translates an assertion statement to the correct CFG nodes. The translation assumes that - * assertions are enabled. - */ - protected void translateAssertWithAssertionsEnabled(AssertTree tree) { - - // all necessary labels - Label assertEnd = new Label(); - Label elseEntry = new Label(); - - // basic block for the condition - Node condition = unbox(scan(tree.getCondition(), null)); - ConditionalJump cjump = new ConditionalJump(assertEnd, elseEntry); - extendWithExtendedNode(cjump); - - // else branch - Node detail = null; - addLabelForNextNode(elseEntry); - if (tree.getDetail() != null) { - detail = scan(tree.getDetail(), null); - } - TypeElement assertException = elements.getTypeElement("java.lang.AssertionError"); - AssertionErrorNode assertNode = - new AssertionErrorNode(tree, condition, detail, assertException.asType()); - extendWithNode(assertNode); - NodeWithExceptionsHolder exNode = - extendWithNodeWithException( - new ThrowNode(null, assertNode, env.getTypeUtils()), - assertException.asType()); - exNode.setTerminatesExecution(true); - - // then branch (nothing happens) - addLabelForNextNode(assertEnd); - } - - @Override - public Node visitAssignment(AssignmentTree tree, Void p) { - - // see JLS 15.26.1 - - AssignmentNode assignmentNode; - ExpressionTree variable = tree.getVariable(); - TypeMirror varType = InternalUtils.typeOf(variable); - - // case 1: field access - if (TreeUtils.isFieldAccess(variable)) { - // visit receiver - Node receiver = getReceiver(variable, TreeUtils.enclosingClass(getCurrentPath())); - - // visit expression - Node expression = scan(tree.getExpression(), p); - expression = assignConvert(expression, varType); - - // visit field access (throws null-pointer exception) - FieldAccessNode target = new FieldAccessNode(variable, receiver); - target.setLValue(); - - Element element = TreeUtils.elementFromUse(variable); - if (ElementUtils.isStatic(element) || receiver instanceof ThisLiteralNode) { - // No NullPointerException can be thrown, use normal node - extendWithNode(target); - } else { - TypeElement npeElement = - elements.getTypeElement("java.lang.NullPointerException"); - extendWithNodeWithException(target, npeElement.asType()); - } - - // add assignment node - assignmentNode = new AssignmentNode(tree, target, expression); - extendWithNode(assignmentNode); - } - - // case 2: other cases - else { - Node target = scan(variable, p); - target.setLValue(); - - assignmentNode = translateAssignment(tree, target, tree.getExpression()); - } - - return assignmentNode; - } - - /** Translate an assignment. */ - protected AssignmentNode translateAssignment(Tree tree, Node target, ExpressionTree rhs) { - Node expression = scan(rhs, null); - return translateAssignment(tree, target, expression); - } - - /** Translate an assignment where the RHS has already been scanned. */ - protected AssignmentNode translateAssignment(Tree tree, Node target, Node expression) { - assert tree instanceof AssignmentTree || tree instanceof VariableTree; - target.setLValue(); - expression = assignConvert(expression, target.getType()); - AssignmentNode assignmentNode = new AssignmentNode(tree, target, expression); - extendWithNode(assignmentNode); - return assignmentNode; - } - - /** - * Note 1: Requires {@code tree} to be a field or method access tree. - * - *

Note 2: Visits the receiver and adds all necessary blocks to the CFG. - * - * @param tree the field access tree containing the receiver - * @param classTree the ClassTree enclosing the field access - * @return the receiver of the field access - */ - private Node getReceiver(ExpressionTree tree, ClassTree classTree) { - assert TreeUtils.isFieldAccess(tree) || TreeUtils.isMethodAccess(tree); - if (tree.getKind().equals(Tree.Kind.MEMBER_SELECT)) { - MemberSelectTree mtree = (MemberSelectTree) tree; - return scan(mtree.getExpression(), null); - } else { - Element ele = TreeUtils.elementFromUse(tree); - TypeElement declaringClass = ElementUtils.enclosingClass(ele); - TypeMirror type = ElementUtils.getType(declaringClass); - if (ElementUtils.isStatic(ele)) { - Node node = new ClassNameNode(type, declaringClass); - extendWithNode(node); - return node; - } else { - Node node = new ImplicitThisLiteralNode(type); - extendWithNode(node); - return node; - } - } - } - - /** - * Map an operation with assignment to the corresponding operation without assignment. - * - * @param kind a Tree.Kind representing an operation with assignment - * @return the Tree.Kind for the same operation without assignment - */ - protected Tree.Kind withoutAssignment(Tree.Kind kind) { - switch (kind) { - case DIVIDE_ASSIGNMENT: - return Tree.Kind.DIVIDE; - case MULTIPLY_ASSIGNMENT: - return Tree.Kind.MULTIPLY; - case REMAINDER_ASSIGNMENT: - return Tree.Kind.REMAINDER; - case MINUS_ASSIGNMENT: - return Tree.Kind.MINUS; - case PLUS_ASSIGNMENT: - return Tree.Kind.PLUS; - case LEFT_SHIFT_ASSIGNMENT: - return Tree.Kind.LEFT_SHIFT; - case RIGHT_SHIFT_ASSIGNMENT: - return Tree.Kind.RIGHT_SHIFT; - case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: - return Tree.Kind.UNSIGNED_RIGHT_SHIFT; - case AND_ASSIGNMENT: - return Tree.Kind.AND; - case OR_ASSIGNMENT: - return Tree.Kind.OR; - case XOR_ASSIGNMENT: - return Tree.Kind.XOR; - default: - return Tree.Kind.ERRONEOUS; - } - } - - @Override - public Node visitCompoundAssignment(CompoundAssignmentTree tree, Void p) { - // According the JLS 15.26.2, E1 op= E2 is equivalent to - // E1 = (T) ((E1) op (E2)), where T is the type of E1, - // except that E1 is evaluated only once. - // - - Tree.Kind kind = tree.getKind(); - switch (kind) { - case DIVIDE_ASSIGNMENT: - case MULTIPLY_ASSIGNMENT: - case REMAINDER_ASSIGNMENT: - { - // see JLS 15.17 and 15.26.2 - Node targetLHS = scan(tree.getVariable(), p); - Node value = scan(tree.getExpression(), p); - - TypeMirror exprType = InternalUtils.typeOf(tree); - TypeMirror leftType = InternalUtils.typeOf(tree.getVariable()); - TypeMirror rightType = InternalUtils.typeOf(tree.getExpression()); - TypeMirror promotedType = binaryPromotedType(leftType, rightType); - Node targetRHS = binaryNumericPromotion(targetLHS, promotedType); - value = binaryNumericPromotion(value, promotedType); - - BinaryTree operTree = - treeBuilder.buildBinary( - promotedType, - withoutAssignment(kind), - tree.getVariable(), - tree.getExpression()); - handleArtificialTree(operTree); - Node operNode; - if (kind == Tree.Kind.MULTIPLY_ASSIGNMENT) { - operNode = new NumericalMultiplicationNode(operTree, targetRHS, value); - } else if (kind == Tree.Kind.DIVIDE_ASSIGNMENT) { - if (TypesUtils.isIntegral(exprType)) { - operNode = new IntegerDivisionNode(operTree, targetRHS, value); - } else { - operNode = new FloatingDivisionNode(operTree, targetRHS, value); - } - } else { - assert kind == Kind.REMAINDER_ASSIGNMENT; - if (TypesUtils.isIntegral(exprType)) { - operNode = new IntegerRemainderNode(operTree, targetRHS, value); - } else { - operNode = new FloatingRemainderNode(operTree, targetRHS, value); - } - } - extendWithNode(operNode); - - TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree); - handleArtificialTree(castTree); - TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType); - castNode.setInSource(false); - extendWithNode(castNode); - - AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode); - extendWithNode(assignNode); - return assignNode; - } - - case MINUS_ASSIGNMENT: - case PLUS_ASSIGNMENT: - { - // see JLS 15.18 and 15.26.2 - - Node targetLHS = scan(tree.getVariable(), p); - Node value = scan(tree.getExpression(), p); - - TypeMirror leftType = InternalUtils.typeOf(tree.getVariable()); - TypeMirror rightType = InternalUtils.typeOf(tree.getExpression()); - - if (TypesUtils.isString(leftType) || TypesUtils.isString(rightType)) { - assert (kind == Tree.Kind.PLUS_ASSIGNMENT); - Node targetRHS = stringConversion(targetLHS); - value = stringConversion(value); - Node r = new StringConcatenateAssignmentNode(tree, targetRHS, value); - extendWithNode(r); - return r; - } else { - TypeMirror promotedType = binaryPromotedType(leftType, rightType); - Node targetRHS = binaryNumericPromotion(targetLHS, promotedType); - value = binaryNumericPromotion(value, promotedType); - - BinaryTree operTree = - treeBuilder.buildBinary( - promotedType, - withoutAssignment(kind), - tree.getVariable(), - tree.getExpression()); - handleArtificialTree(operTree); - Node operNode; - if (kind == Tree.Kind.PLUS_ASSIGNMENT) { - operNode = new NumericalAdditionNode(operTree, targetRHS, value); - } else { - assert kind == Kind.MINUS_ASSIGNMENT; - operNode = new NumericalSubtractionNode(operTree, targetRHS, value); - } - extendWithNode(operNode); - - TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree); - handleArtificialTree(castTree); - TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType); - castNode.setInSource(false); - extendWithNode(castNode); - - // Map the compound assignment tree to an assignment node, which - // will have the correct type. - AssignmentNode assignNode = - new AssignmentNode(tree, targetLHS, castNode); - extendWithNode(assignNode); - return assignNode; - } - } - - case LEFT_SHIFT_ASSIGNMENT: - case RIGHT_SHIFT_ASSIGNMENT: - case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: - { - // see JLS 15.19 and 15.26.2 - Node targetLHS = scan(tree.getVariable(), p); - Node value = scan(tree.getExpression(), p); - - TypeMirror leftType = InternalUtils.typeOf(tree.getVariable()); - - Node targetRHS = unaryNumericPromotion(targetLHS); - value = unaryNumericPromotion(value); - - BinaryTree operTree = - treeBuilder.buildBinary( - leftType, - withoutAssignment(kind), - tree.getVariable(), - tree.getExpression()); - handleArtificialTree(operTree); - Node operNode; - if (kind == Tree.Kind.LEFT_SHIFT_ASSIGNMENT) { - operNode = new LeftShiftNode(operTree, targetRHS, value); - } else if (kind == Tree.Kind.RIGHT_SHIFT_ASSIGNMENT) { - operNode = new SignedRightShiftNode(operTree, targetRHS, value); - } else { - assert kind == Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT; - operNode = new UnsignedRightShiftNode(operTree, targetRHS, value); - } - extendWithNode(operNode); - - TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree); - handleArtificialTree(castTree); - TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType); - castNode.setInSource(false); - extendWithNode(castNode); - - AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode); - extendWithNode(assignNode); - return assignNode; - } - - case AND_ASSIGNMENT: - case OR_ASSIGNMENT: - case XOR_ASSIGNMENT: - // see JLS 15.22 - Node targetLHS = scan(tree.getVariable(), p); - Node value = scan(tree.getExpression(), p); - - TypeMirror leftType = InternalUtils.typeOf(tree.getVariable()); - TypeMirror rightType = InternalUtils.typeOf(tree.getExpression()); - - Node targetRHS = null; - if (isNumericOrBoxed(leftType) && isNumericOrBoxed(rightType)) { - TypeMirror promotedType = binaryPromotedType(leftType, rightType); - targetRHS = binaryNumericPromotion(targetLHS, promotedType); - value = binaryNumericPromotion(value, promotedType); - } else if (TypesUtils.isBooleanType(leftType) - && TypesUtils.isBooleanType(rightType)) { - targetRHS = unbox(targetLHS); - value = unbox(value); - } else { - assert false - : "Both argument to logical operation must be numeric or boolean"; - } - - BinaryTree operTree = - treeBuilder.buildBinary( - leftType, - withoutAssignment(kind), - tree.getVariable(), - tree.getExpression()); - handleArtificialTree(operTree); - Node operNode; - if (kind == Tree.Kind.AND_ASSIGNMENT) { - operNode = new BitwiseAndNode(operTree, targetRHS, value); - } else if (kind == Tree.Kind.OR_ASSIGNMENT) { - operNode = new BitwiseOrNode(operTree, targetRHS, value); - } else { - assert kind == Kind.XOR_ASSIGNMENT; - operNode = new BitwiseXorNode(operTree, targetRHS, value); - } - extendWithNode(operNode); - - TypeCastTree castTree = treeBuilder.buildTypeCast(leftType, operTree); - handleArtificialTree(castTree); - TypeCastNode castNode = new TypeCastNode(castTree, operNode, leftType); - castNode.setInSource(false); - extendWithNode(castNode); - - AssignmentNode assignNode = new AssignmentNode(tree, targetLHS, castNode); - extendWithNode(assignNode); - return assignNode; - default: - assert false : "unexpected compound assignment type"; - break; - } - assert false : "unexpected compound assignment type"; - return null; - } - - @Override - public Node visitBinary(BinaryTree tree, Void p) { - // Note that for binary operations it is important to perform any required - // promotion on the left operand before generating any Nodes for the right - // operand, because labels must be inserted AFTER ALL preceding Nodes and - // BEFORE ALL following Nodes. - Node r = null; - Tree leftTree = tree.getLeftOperand(); - Tree rightTree = tree.getRightOperand(); - - Tree.Kind kind = tree.getKind(); - switch (kind) { - case DIVIDE: - case MULTIPLY: - case REMAINDER: - { - // see JLS 15.17 - - TypeMirror exprType = InternalUtils.typeOf(tree); - TypeMirror leftType = InternalUtils.typeOf(leftTree); - TypeMirror rightType = InternalUtils.typeOf(rightTree); - TypeMirror promotedType = binaryPromotedType(leftType, rightType); - - Node left = binaryNumericPromotion(scan(leftTree, p), promotedType); - Node right = binaryNumericPromotion(scan(rightTree, p), promotedType); - - if (kind == Tree.Kind.MULTIPLY) { - r = new NumericalMultiplicationNode(tree, left, right); - } else if (kind == Tree.Kind.DIVIDE) { - if (TypesUtils.isIntegral(exprType)) { - r = new IntegerDivisionNode(tree, left, right); - } else { - r = new FloatingDivisionNode(tree, left, right); - } - } else { - assert kind == Kind.REMAINDER; - if (TypesUtils.isIntegral(exprType)) { - r = new IntegerRemainderNode(tree, left, right); - } else { - r = new FloatingRemainderNode(tree, left, right); - } - } - break; - } - - case MINUS: - case PLUS: - { - // see JLS 15.18 - - // TypeMirror exprType = InternalUtils.typeOf(tree); - TypeMirror leftType = InternalUtils.typeOf(leftTree); - TypeMirror rightType = InternalUtils.typeOf(rightTree); - - if (TypesUtils.isString(leftType) || TypesUtils.isString(rightType)) { - assert (kind == Tree.Kind.PLUS); - Node left = stringConversion(scan(leftTree, p)); - Node right = stringConversion(scan(rightTree, p)); - r = new StringConcatenateNode(tree, left, right); - } else { - TypeMirror promotedType = binaryPromotedType(leftType, rightType); - Node left = binaryNumericPromotion(scan(leftTree, p), promotedType); - Node right = binaryNumericPromotion(scan(rightTree, p), promotedType); - - // TODO: Decide whether to deal with floating-point value - // set conversion. - if (kind == Tree.Kind.PLUS) { - r = new NumericalAdditionNode(tree, left, right); - } else { - assert kind == Kind.MINUS; - r = new NumericalSubtractionNode(tree, left, right); - } - } - break; - } - - case LEFT_SHIFT: - case RIGHT_SHIFT: - case UNSIGNED_RIGHT_SHIFT: - { - // see JLS 15.19 - - Node left = unaryNumericPromotion(scan(leftTree, p)); - Node right = unaryNumericPromotion(scan(rightTree, p)); - - if (kind == Tree.Kind.LEFT_SHIFT) { - r = new LeftShiftNode(tree, left, right); - } else if (kind == Tree.Kind.RIGHT_SHIFT) { - r = new SignedRightShiftNode(tree, left, right); - } else { - assert kind == Kind.UNSIGNED_RIGHT_SHIFT; - r = new UnsignedRightShiftNode(tree, left, right); - } - break; - } - - case GREATER_THAN: - case GREATER_THAN_EQUAL: - case LESS_THAN: - case LESS_THAN_EQUAL: - { - // see JLS 15.20.1 - TypeMirror leftType = InternalUtils.typeOf(leftTree); - if (TypesUtils.isBoxedPrimitive(leftType)) { - leftType = types.unboxedType(leftType); - } - - TypeMirror rightType = InternalUtils.typeOf(rightTree); - if (TypesUtils.isBoxedPrimitive(rightType)) { - rightType = types.unboxedType(rightType); - } - - TypeMirror promotedType = binaryPromotedType(leftType, rightType); - Node left = binaryNumericPromotion(scan(leftTree, p), promotedType); - Node right = binaryNumericPromotion(scan(rightTree, p), promotedType); - - Node node; - if (kind == Tree.Kind.GREATER_THAN) { - node = new GreaterThanNode(tree, left, right); - } else if (kind == Tree.Kind.GREATER_THAN_EQUAL) { - node = new GreaterThanOrEqualNode(tree, left, right); - } else if (kind == Tree.Kind.LESS_THAN) { - node = new LessThanNode(tree, left, right); - } else { - assert kind == Tree.Kind.LESS_THAN_EQUAL; - node = new LessThanOrEqualNode(tree, left, right); - } - - extendWithNode(node); - - return node; - } - - case EQUAL_TO: - case NOT_EQUAL_TO: - { - // see JLS 15.21 - TreeInfo leftInfo = getTreeInfo(leftTree); - TreeInfo rightInfo = getTreeInfo(rightTree); - Node left = scan(leftTree, p); - Node right = scan(rightTree, p); - - if (leftInfo.isNumeric() - && rightInfo.isNumeric() - && !(leftInfo.isBoxed() && rightInfo.isBoxed())) { - // JLS 15.21.1 numerical equality - TypeMirror promotedType = - binaryPromotedType( - leftInfo.unboxedType(), rightInfo.unboxedType()); - left = binaryNumericPromotion(left, promotedType); - right = binaryNumericPromotion(right, promotedType); - } else if (leftInfo.isBoolean() - && rightInfo.isBoolean() - && !(leftInfo.isBoxed() && rightInfo.isBoxed())) { - // JSL 15.21.2 boolean equality - left = unboxAsNeeded(left, leftInfo.isBoxed()); - right = unboxAsNeeded(right, rightInfo.isBoxed()); - } - - Node node; - if (kind == Tree.Kind.EQUAL_TO) { - node = new EqualToNode(tree, left, right); - } else { - assert kind == Kind.NOT_EQUAL_TO; - node = new NotEqualNode(tree, left, right); - } - extendWithNode(node); - - return node; - } - - case AND: - case OR: - case XOR: - { - // see JLS 15.22 - TypeMirror leftType = InternalUtils.typeOf(leftTree); - TypeMirror rightType = InternalUtils.typeOf(rightTree); - boolean isBooleanOp = - TypesUtils.isBooleanType(leftType) - && TypesUtils.isBooleanType(rightType); - - Node left; - Node right; - - if (isBooleanOp) { - left = unbox(scan(leftTree, p)); - right = unbox(scan(rightTree, p)); - } else if (isNumericOrBoxed(leftType) && isNumericOrBoxed(rightType)) { - TypeMirror promotedType = binaryPromotedType(leftType, rightType); - left = binaryNumericPromotion(scan(leftTree, p), promotedType); - right = binaryNumericPromotion(scan(rightTree, p), promotedType); - } else { - left = unbox(scan(leftTree, p)); - right = unbox(scan(rightTree, p)); - } - - Node node; - if (kind == Tree.Kind.AND) { - node = new BitwiseAndNode(tree, left, right); - } else if (kind == Tree.Kind.OR) { - node = new BitwiseOrNode(tree, left, right); - } else { - assert kind == Kind.XOR; - node = new BitwiseXorNode(tree, left, right); - } - - extendWithNode(node); - - return node; - } - - case CONDITIONAL_AND: - case CONDITIONAL_OR: - { - // see JLS 15.23 and 15.24 - - // all necessary labels - Label rightStartL = new Label(); - Label shortCircuitL = new Label(); - - // left-hand side - Node left = scan(leftTree, p); - - ConditionalJump cjump; - if (kind == Tree.Kind.CONDITIONAL_AND) { - cjump = new ConditionalJump(rightStartL, shortCircuitL); - cjump.setFalseFlowRule(Store.FlowRule.ELSE_TO_ELSE); - } else { - cjump = new ConditionalJump(shortCircuitL, rightStartL); - cjump.setTrueFlowRule(Store.FlowRule.THEN_TO_THEN); - } - extendWithExtendedNode(cjump); - - // right-hand side - addLabelForNextNode(rightStartL); - Node right = scan(rightTree, p); - - // conditional expression itself - addLabelForNextNode(shortCircuitL); - Node node; - if (kind == Tree.Kind.CONDITIONAL_AND) { - node = new ConditionalAndNode(tree, left, right); - } else { - node = new ConditionalOrNode(tree, left, right); - } - extendWithNode(node); - return node; - } - default: - assert false : "unexpected binary tree: " + kind; - break; - } - assert r != null : "unexpected binary tree"; - return extendWithNode(r); - } - - @Override - public Node visitBlock(BlockTree tree, Void p) { - for (StatementTree n : tree.getStatements()) { - scan(n, null); - } - return null; - } - - @Override - public Node visitBreak(BreakTree tree, Void p) { - Name label = tree.getLabel(); - if (label == null) { - assert breakTargetL != null : "no target for break statement"; - - extendWithExtendedNode(new UnconditionalJump(breakTargetL)); - } else { - assert breakLabels.containsKey(label); - - extendWithExtendedNode(new UnconditionalJump(breakLabels.get(label))); - } - - return null; - } - - @Override - public Node visitSwitch(SwitchTree tree, Void p) { - SwitchBuilder builder = new SwitchBuilder(tree, p); - builder.build(); - return null; - } - - private class SwitchBuilder { - private final SwitchTree switchTree; - private final Label[] caseBodyLabels; - private final Void p; - private Node switchExpr; - - private SwitchBuilder(SwitchTree tree, Void p) { - this.switchTree = tree; - this.caseBodyLabels = new Label[switchTree.getCases().size() + 1]; - this.p = p; - } - - public void build() { - Label oldBreakTargetL = breakTargetL; - breakTargetL = new Label(); - int cases = caseBodyLabels.length - 1; - for (int i = 0; i < cases; ++i) { - caseBodyLabels[i] = new Label(); - } - caseBodyLabels[cases] = breakTargetL; - - switchExpr = unbox(scan(switchTree.getExpression(), p)); - extendWithNode( - new MarkerNode( - switchTree, "start of switch statement", env.getTypeUtils())); - - Integer defaultIndex = null; - for (int i = 0; i < cases; ++i) { - CaseTree caseTree = switchTree.getCases().get(i); - if (caseTree.getExpression() == null) { - defaultIndex = i; - } else { - buildCase(caseTree, i); - } - } - if (defaultIndex != null) { - // the checks of all cases must happen before the default case, - // therefore we build the default case last. - // fallthrough is still handled correctly with the caseBodyLabels. - buildCase(switchTree.getCases().get(defaultIndex), defaultIndex); - } - - addLabelForNextNode(breakTargetL); - breakTargetL = oldBreakTargetL; - } - - private void buildCase(CaseTree tree, int index) { - final Label thisBodyL = caseBodyLabels[index]; - final Label nextBodyL = caseBodyLabels[index + 1]; - final Label nextCaseL = new Label(); - - ExpressionTree exprTree = tree.getExpression(); - if (exprTree != null) { - Node expr = scan(exprTree, p); - CaseNode test = new CaseNode(tree, switchExpr, expr, env.getTypeUtils()); - extendWithNode(test); - extendWithExtendedNode(new ConditionalJump(thisBodyL, nextCaseL)); - } - addLabelForNextNode(thisBodyL); - for (StatementTree stmt : tree.getStatements()) { - scan(stmt, p); - } - extendWithExtendedNode(new UnconditionalJump(nextBodyL)); - addLabelForNextNode(nextCaseL); - } - } - - @Override - public Node visitCase(CaseTree tree, Void p) { - throw new AssertionError("case visitor is implemented in SwitchBuilder"); - } - - @Override - public Node visitCatch(CatchTree tree, Void p) { - scan(tree.getParameter(), p); - scan(tree.getBlock(), p); - return null; - } - - @Override - public Node visitClass(ClassTree tree, Void p) { - declaredClasses.add(tree); - return null; - } - - @Override - public Node visitConditionalExpression(ConditionalExpressionTree tree, Void p) { - // see JLS 15.25 - TypeMirror exprType = InternalUtils.typeOf(tree); - - Label trueStart = new Label(); - Label falseStart = new Label(); - Label merge = new Label(); - - Node condition = unbox(scan(tree.getCondition(), p)); - ConditionalJump cjump = new ConditionalJump(trueStart, falseStart); - extendWithExtendedNode(cjump); - - addLabelForNextNode(trueStart); - Node trueExpr = scan(tree.getTrueExpression(), p); - trueExpr = conditionalExprPromotion(trueExpr, exprType); - extendWithExtendedNode(new UnconditionalJump(merge)); - - addLabelForNextNode(falseStart); - Node falseExpr = scan(tree.getFalseExpression(), p); - falseExpr = conditionalExprPromotion(falseExpr, exprType); - - addLabelForNextNode(merge); - Node node = new TernaryExpressionNode(tree, condition, trueExpr, falseExpr); - extendWithNode(node); - - return node; - } - - @Override - public Node visitContinue(ContinueTree tree, Void p) { - Name label = tree.getLabel(); - if (label == null) { - assert continueTargetL != null : "no target for continue statement"; - - extendWithExtendedNode(new UnconditionalJump(continueTargetL)); - } else { - assert continueLabels.containsKey(label); - - extendWithExtendedNode(new UnconditionalJump(continueLabels.get(label))); - } - - return null; - } - - @Override - public Node visitDoWhileLoop(DoWhileLoopTree tree, Void p) { - Name parentLabel = getLabel(getCurrentPath()); - - Label loopEntry = new Label(); - Label loopExit = new Label(); - - // If the loop is a labeled statement, then its continue - // target is identical for continues with no label and - // continues with the loop's label. - Label conditionStart; - if (parentLabel != null) { - conditionStart = continueLabels.get(parentLabel); - } else { - conditionStart = new Label(); - } - - Label oldBreakTargetL = breakTargetL; - breakTargetL = loopExit; - - Label oldContinueTargetL = continueTargetL; - continueTargetL = conditionStart; - - // Loop body - addLabelForNextNode(loopEntry); - if (tree.getStatement() != null) { - scan(tree.getStatement(), p); - } - - // Condition - addLabelForNextNode(conditionStart); - if (tree.getCondition() != null) { - unbox(scan(tree.getCondition(), p)); - ConditionalJump cjump = new ConditionalJump(loopEntry, loopExit); - extendWithExtendedNode(cjump); - } - - // Loop exit - addLabelForNextNode(loopExit); - - breakTargetL = oldBreakTargetL; - continueTargetL = oldContinueTargetL; - - return null; - } - - @Override - public Node visitErroneous(ErroneousTree tree, Void p) { - assert false : "ErroneousTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public Node visitExpressionStatement(ExpressionStatementTree tree, Void p) { - return scan(tree.getExpression(), p); - } - - @Override - public Node visitEnhancedForLoop(EnhancedForLoopTree tree, Void p) { - // see JLS 14.14.2 - Name parentLabel = getLabel(getCurrentPath()); - - Label conditionStart = new Label(); - Label loopEntry = new Label(); - Label loopExit = new Label(); - - // If the loop is a labeled statement, then its continue - // target is identical for continues with no label and - // continues with the loop's label. - Label updateStart; - if (parentLabel != null) { - updateStart = continueLabels.get(parentLabel); - } else { - updateStart = new Label(); - } - - Label oldBreakTargetL = breakTargetL; - breakTargetL = loopExit; - - Label oldContinueTargetL = continueTargetL; - continueTargetL = updateStart; - - // Distinguish loops over Iterables from loops over arrays. - - TypeElement iterableElement = elements.getTypeElement("java.lang.Iterable"); - TypeMirror iterableType = types.erasure(iterableElement.asType()); - - VariableTree variable = tree.getVariable(); - VariableElement variableElement = TreeUtils.elementFromDeclaration(variable); - ExpressionTree expression = tree.getExpression(); - StatementTree statement = tree.getStatement(); - - TypeMirror exprType = InternalUtils.typeOf(expression); - - if (types.isSubtype(exprType, iterableType)) { - // Take the upper bound of a type variable or wildcard - exprType = TypesUtils.upperBound(exprType); - - assert (exprType instanceof DeclaredType) : "an Iterable must be a DeclaredType"; - DeclaredType declaredExprType = (DeclaredType) exprType; - declaredExprType.getTypeArguments(); - - MemberSelectTree iteratorSelect = treeBuilder.buildIteratorMethodAccess(expression); - handleArtificialTree(iteratorSelect); - - MethodInvocationTree iteratorCall = - treeBuilder.buildMethodInvocation(iteratorSelect); - handleArtificialTree(iteratorCall); - - VariableTree iteratorVariable = - createEnhancedForLoopIteratorVariable(iteratorCall, variableElement); - handleArtificialTree(iteratorVariable); - - VariableDeclarationNode iteratorVariableDecl = - new VariableDeclarationNode(iteratorVariable); - iteratorVariableDecl.setInSource(false); - - extendWithNode(iteratorVariableDecl); - - Node expressionNode = scan(expression, p); - - MethodAccessNode iteratorAccessNode = - new MethodAccessNode(iteratorSelect, expressionNode); - iteratorAccessNode.setInSource(false); - extendWithNode(iteratorAccessNode); - MethodInvocationNode iteratorCallNode = - new MethodInvocationNode( - iteratorCall, - iteratorAccessNode, - Collections.emptyList(), - getCurrentPath()); - iteratorCallNode.setInSource(false); - extendWithNode(iteratorCallNode); - - translateAssignment( - iteratorVariable, - new LocalVariableNode(iteratorVariable), - iteratorCallNode); - - // Test the loop ending condition - addLabelForNextNode(conditionStart); - IdentifierTree iteratorUse1 = treeBuilder.buildVariableUse(iteratorVariable); - handleArtificialTree(iteratorUse1); - - LocalVariableNode iteratorReceiverNode = new LocalVariableNode(iteratorUse1); - iteratorReceiverNode.setInSource(false); - extendWithNode(iteratorReceiverNode); - - MemberSelectTree hasNextSelect = treeBuilder.buildHasNextMethodAccess(iteratorUse1); - handleArtificialTree(hasNextSelect); - - MethodAccessNode hasNextAccessNode = - new MethodAccessNode(hasNextSelect, iteratorReceiverNode); - hasNextAccessNode.setInSource(false); - extendWithNode(hasNextAccessNode); - - MethodInvocationTree hasNextCall = treeBuilder.buildMethodInvocation(hasNextSelect); - handleArtificialTree(hasNextCall); - - MethodInvocationNode hasNextCallNode = - new MethodInvocationNode( - hasNextCall, - hasNextAccessNode, - Collections.emptyList(), - getCurrentPath()); - hasNextCallNode.setInSource(false); - extendWithNode(hasNextCallNode); - extendWithExtendedNode(new ConditionalJump(loopEntry, loopExit)); - - // Loop body, starting with declaration of the loop iteration variable - addLabelForNextNode(loopEntry); - extendWithNode(new VariableDeclarationNode(variable)); - - IdentifierTree iteratorUse2 = treeBuilder.buildVariableUse(iteratorVariable); - handleArtificialTree(iteratorUse2); - - LocalVariableNode iteratorReceiverNode2 = new LocalVariableNode(iteratorUse2); - iteratorReceiverNode2.setInSource(false); - extendWithNode(iteratorReceiverNode2); - - MemberSelectTree nextSelect = treeBuilder.buildNextMethodAccess(iteratorUse2); - handleArtificialTree(nextSelect); - - MethodAccessNode nextAccessNode = - new MethodAccessNode(nextSelect, iteratorReceiverNode2); - nextAccessNode.setInSource(false); - extendWithNode(nextAccessNode); - - MethodInvocationTree nextCall = treeBuilder.buildMethodInvocation(nextSelect); - handleArtificialTree(nextCall); - - MethodInvocationNode nextCallNode = - new MethodInvocationNode( - nextCall, - nextAccessNode, - Collections.emptyList(), - getCurrentPath()); - nextCallNode.setInSource(false); - extendWithNode(nextCallNode); - - translateAssignment(variable, new LocalVariableNode(variable), nextCall); - - if (statement != null) { - scan(statement, p); - } - - // Loop back edge - addLabelForNextNode(updateStart); - extendWithExtendedNode(new UnconditionalJump(conditionStart)); - - } else { - // TODO: Shift any labels after the initialization of the - // temporary array variable. - - VariableTree arrayVariable = - createEnhancedForLoopArrayVariable(expression, variableElement); - handleArtificialTree(arrayVariable); - - VariableDeclarationNode arrayVariableNode = - new VariableDeclarationNode(arrayVariable); - arrayVariableNode.setInSource(false); - extendWithNode(arrayVariableNode); - Node expressionNode = scan(expression, p); - - translateAssignment( - arrayVariable, new LocalVariableNode(arrayVariable), expressionNode); - - // Declare and initialize the loop index variable - TypeMirror intType = types.getPrimitiveType(TypeKind.INT); - - LiteralTree zero = treeBuilder.buildLiteral(Integer.valueOf(0)); - handleArtificialTree(zero); - - VariableTree indexVariable = - treeBuilder.buildVariableDecl( - intType, - uniqueName("index"), - variableElement.getEnclosingElement(), - zero); - handleArtificialTree(indexVariable); - VariableDeclarationNode indexVariableNode = - new VariableDeclarationNode(indexVariable); - indexVariableNode.setInSource(false); - extendWithNode(indexVariableNode); - IntegerLiteralNode zeroNode = extendWithNode(new IntegerLiteralNode(zero)); - - translateAssignment(indexVariable, new LocalVariableNode(indexVariable), zeroNode); - - // Compare index to array length - addLabelForNextNode(conditionStart); - IdentifierTree indexUse1 = treeBuilder.buildVariableUse(indexVariable); - handleArtificialTree(indexUse1); - LocalVariableNode indexNode1 = new LocalVariableNode(indexUse1); - indexNode1.setInSource(false); - extendWithNode(indexNode1); - - IdentifierTree arrayUse1 = treeBuilder.buildVariableUse(arrayVariable); - handleArtificialTree(arrayUse1); - LocalVariableNode arrayNode1 = extendWithNode(new LocalVariableNode(arrayUse1)); - - MemberSelectTree lengthSelect = treeBuilder.buildArrayLengthAccess(arrayUse1); - handleArtificialTree(lengthSelect); - FieldAccessNode lengthAccessNode = new FieldAccessNode(lengthSelect, arrayNode1); - lengthAccessNode.setInSource(false); - extendWithNode(lengthAccessNode); - - BinaryTree lessThan = treeBuilder.buildLessThan(indexUse1, lengthSelect); - handleArtificialTree(lessThan); - - LessThanNode lessThanNode = - new LessThanNode(lessThan, indexNode1, lengthAccessNode); - lessThanNode.setInSource(false); - extendWithNode(lessThanNode); - extendWithExtendedNode(new ConditionalJump(loopEntry, loopExit)); - - // Loop body, starting with declaration of the loop iteration variable - addLabelForNextNode(loopEntry); - extendWithNode(new VariableDeclarationNode(variable)); - - IdentifierTree arrayUse2 = treeBuilder.buildVariableUse(arrayVariable); - handleArtificialTree(arrayUse2); - LocalVariableNode arrayNode2 = new LocalVariableNode(arrayUse2); - arrayNode2.setInSource(false); - extendWithNode(arrayNode2); - - IdentifierTree indexUse2 = treeBuilder.buildVariableUse(indexVariable); - handleArtificialTree(indexUse2); - LocalVariableNode indexNode2 = new LocalVariableNode(indexUse2); - indexNode2.setInSource(false); - extendWithNode(indexNode2); - - ArrayAccessTree arrayAccess = treeBuilder.buildArrayAccess(arrayUse2, indexUse2); - handleArtificialTree(arrayAccess); - ArrayAccessNode arrayAccessNode = - new ArrayAccessNode(arrayAccess, arrayNode2, indexNode2); - arrayAccessNode.setInSource(false); - extendWithNode(arrayAccessNode); - translateAssignment(variable, new LocalVariableNode(variable), arrayAccessNode); - - if (statement != null) { - scan(statement, p); - } - - // Loop back edge - addLabelForNextNode(updateStart); - - IdentifierTree indexUse3 = treeBuilder.buildVariableUse(indexVariable); - handleArtificialTree(indexUse3); - LocalVariableNode indexNode3 = new LocalVariableNode(indexUse3); - indexNode3.setInSource(false); - extendWithNode(indexNode3); - - LiteralTree oneTree = treeBuilder.buildLiteral(Integer.valueOf(1)); - handleArtificialTree(oneTree); - Node one = new IntegerLiteralNode(oneTree); - one.setInSource(false); - extendWithNode(one); - - BinaryTree addOneTree = - treeBuilder.buildBinary(intType, Tree.Kind.PLUS, indexUse3, oneTree); - handleArtificialTree(addOneTree); - Node addOneNode = new NumericalAdditionNode(addOneTree, indexNode3, one); - addOneNode.setInSource(false); - extendWithNode(addOneNode); - - AssignmentTree assignTree = treeBuilder.buildAssignment(indexUse3, addOneTree); - handleArtificialTree(assignTree); - Node assignNode = new AssignmentNode(assignTree, indexNode3, addOneNode); - assignNode.setInSource(false); - extendWithNode(assignNode); - - extendWithExtendedNode(new UnconditionalJump(conditionStart)); - } - - // Loop exit - addLabelForNextNode(loopExit); - - breakTargetL = oldBreakTargetL; - continueTargetL = oldContinueTargetL; - - return null; - } - - protected VariableTree createEnhancedForLoopIteratorVariable( - MethodInvocationTree iteratorCall, VariableElement variableElement) { - TypeMirror iteratorType = InternalUtils.typeOf(iteratorCall); - - // Declare and initialize a new, unique iterator variable - VariableTree iteratorVariable = - treeBuilder.buildVariableDecl( - iteratorType, // annotatedIteratorTypeTree, - uniqueName("iter"), - variableElement.getEnclosingElement(), - iteratorCall); - return iteratorVariable; - } - - protected VariableTree createEnhancedForLoopArrayVariable( - ExpressionTree expression, VariableElement variableElement) { - TypeMirror arrayType = InternalUtils.typeOf(expression); - - // Declare and initialize a temporary array variable - VariableTree arrayVariable = - treeBuilder.buildVariableDecl( - arrayType, - uniqueName("array"), - variableElement.getEnclosingElement(), - expression); - return arrayVariable; - } - - @Override - public Node visitForLoop(ForLoopTree tree, Void p) { - Name parentLabel = getLabel(getCurrentPath()); - - Label conditionStart = new Label(); - Label loopEntry = new Label(); - Label loopExit = new Label(); - - // If the loop is a labeled statement, then its continue - // target is identical for continues with no label and - // continues with the loop's label. - Label updateStart; - if (parentLabel != null) { - updateStart = continueLabels.get(parentLabel); - } else { - updateStart = new Label(); - } - - Label oldBreakTargetL = breakTargetL; - breakTargetL = loopExit; - - Label oldContinueTargetL = continueTargetL; - continueTargetL = updateStart; - - // Initializer - for (StatementTree init : tree.getInitializer()) { - scan(init, p); - } - - // Condition - addLabelForNextNode(conditionStart); - if (tree.getCondition() != null) { - unbox(scan(tree.getCondition(), p)); - ConditionalJump cjump = new ConditionalJump(loopEntry, loopExit); - extendWithExtendedNode(cjump); - } - - // Loop body - addLabelForNextNode(loopEntry); - if (tree.getStatement() != null) { - scan(tree.getStatement(), p); - } - - // Update - addLabelForNextNode(updateStart); - for (ExpressionStatementTree update : tree.getUpdate()) { - scan(update, p); - } - - extendWithExtendedNode(new UnconditionalJump(conditionStart)); - - // Loop exit - addLabelForNextNode(loopExit); - - breakTargetL = oldBreakTargetL; - continueTargetL = oldContinueTargetL; - - return null; - } - - @Override - public Node visitIdentifier(IdentifierTree tree, Void p) { - Node node; - if (TreeUtils.isFieldAccess(tree)) { - Node receiver = getReceiver(tree, TreeUtils.enclosingClass(getCurrentPath())); - node = new FieldAccessNode(tree, receiver); - } else { - Element element = TreeUtils.elementFromUse(tree); - switch (element.getKind()) { - case ANNOTATION_TYPE: - case CLASS: - case ENUM: - case INTERFACE: - case TYPE_PARAMETER: - node = new ClassNameNode(tree); - break; - case FIELD: - // Note that "this"/"super" is a field, but not a field access. - if (element.getSimpleName().contentEquals("this")) { - node = new ExplicitThisLiteralNode(tree); - } else { - node = new SuperNode(tree); - } - break; - case EXCEPTION_PARAMETER: - case LOCAL_VARIABLE: - case RESOURCE_VARIABLE: - case PARAMETER: - node = new LocalVariableNode(tree); - break; - case PACKAGE: - node = new PackageNameNode(tree); - break; - default: - throw new IllegalArgumentException( - "unexpected element kind : " + element.getKind()); - } - } - extendWithNode(node); - return node; - } - - @Override - public Node visitIf(IfTree tree, Void p) { - // all necessary labels - Label thenEntry = new Label(); - Label elseEntry = new Label(); - Label endIf = new Label(); - - // basic block for the condition - unbox(scan(tree.getCondition(), p)); - - ConditionalJump cjump = new ConditionalJump(thenEntry, elseEntry); - extendWithExtendedNode(cjump); - - // then branch - addLabelForNextNode(thenEntry); - StatementTree thenStatement = tree.getThenStatement(); - scan(thenStatement, p); - extendWithExtendedNode(new UnconditionalJump(endIf)); - - // else branch - addLabelForNextNode(elseEntry); - StatementTree elseStatement = tree.getElseStatement(); - if (elseStatement != null) { - scan(elseStatement, p); - } - - // label the end of the if statement - addLabelForNextNode(endIf); - - return null; - } - - @Override - public Node visitImport(ImportTree tree, Void p) { - assert false : "ImportTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public Node visitArrayAccess(ArrayAccessTree tree, Void p) { - Node array = scan(tree.getExpression(), p); - Node index = unaryNumericPromotion(scan(tree.getIndex(), p)); - return extendWithNode(new ArrayAccessNode(tree, array, index)); - } - - @Override - public Node visitLabeledStatement(LabeledStatementTree tree, Void p) { - // This method can set the break target after generating all Nodes - // in the contained statement, but it can't set the continue target, - // which may be in the middle of a sequence of nodes. Labeled loops - // must look up and use the continue Labels. - Name labelName = tree.getLabel(); - - Label breakL = new Label(labelName + "_break"); - Label continueL = new Label(labelName + "_continue"); - - breakLabels.put(labelName, breakL); - continueLabels.put(labelName, continueL); - - scan(tree.getStatement(), p); - - addLabelForNextNode(breakL); - - breakLabels.remove(labelName); - continueLabels.remove(labelName); - - return null; - } - - @Override - public Node visitLiteral(LiteralTree tree, Void p) { - Node r = null; - switch (tree.getKind()) { - case BOOLEAN_LITERAL: - r = new BooleanLiteralNode(tree); - break; - case CHAR_LITERAL: - r = new CharacterLiteralNode(tree); - break; - case DOUBLE_LITERAL: - r = new DoubleLiteralNode(tree); - break; - case FLOAT_LITERAL: - r = new FloatLiteralNode(tree); - break; - case INT_LITERAL: - r = new IntegerLiteralNode(tree); - break; - case LONG_LITERAL: - r = new LongLiteralNode(tree); - break; - case NULL_LITERAL: - r = new NullLiteralNode(tree); - break; - case STRING_LITERAL: - r = new StringLiteralNode(tree); - break; - default: - assert false : "unexpected literal tree"; - break; - } - assert r != null : "unexpected literal tree"; - Node result = extendWithNode(r); - return result; - } - - @Override - public Node visitMethod(MethodTree tree, Void p) { - assert false : "MethodTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public Node visitModifiers(ModifiersTree tree, Void p) { - assert false : "ModifiersTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public Node visitNewArray(NewArrayTree tree, Void p) { - // see JLS 15.10 - - ArrayType type = (ArrayType) InternalUtils.typeOf(tree); - TypeMirror elemType = type.getComponentType(); - - List dimensions = tree.getDimensions(); - List initializers = tree.getInitializers(); - - List dimensionNodes = new ArrayList(); - if (dimensions != null) { - for (ExpressionTree dim : dimensions) { - dimensionNodes.add(unaryNumericPromotion(scan(dim, p))); - } - } - - List initializerNodes = new ArrayList(); - if (initializers != null) { - for (ExpressionTree init : initializers) { - initializerNodes.add(assignConvert(scan(init, p), elemType)); - } - } - - Node node = new ArrayCreationNode(tree, type, dimensionNodes, initializerNodes); - return extendWithNode(node); - } - - @Override - public Node visitNewClass(NewClassTree tree, Void p) { - // see JLS 15.9 - - Tree enclosingExpr = tree.getEnclosingExpression(); - if (enclosingExpr != null) { - scan(enclosingExpr, p); - } - - // We ignore any class body because its methods should - // be visited separately. - // TODO: For anonymous classes we want to propagate the current store - // to the anonymous class. - // See Issues 266, 811. - - // Convert constructor arguments - ExecutableElement constructor = TreeUtils.elementFromUse(tree); - - List actualExprs = tree.getArguments(); - - List arguments = convertCallArguments(constructor, actualExprs); - - // TODO: for anonymous classes, don't use the identifier alone. - // See Issue 890. - Node constructorNode = scan(tree.getIdentifier(), p); - - Node node = new ObjectCreationNode(tree, constructorNode, arguments); - - Set thrownSet = new HashSet<>(); - // Add exceptions explicitly mentioned in the throws clause. - List thrownTypes = constructor.getThrownTypes(); - thrownSet.addAll(thrownTypes); - // Add Throwable to account for unchecked exceptions - TypeElement throwableElement = elements.getTypeElement("java.lang.Throwable"); - thrownSet.add(throwableElement.asType()); - - extendWithNodeWithExceptions(node, thrownSet); - - return node; - } - - /** - * Maps a {@code Tree} its directly enclosing {@code ParenthesizedTree} if one exists. - * - *

An invocation {@code visualize(cfg, entry, null);} does not output stores at the beginning - * of basic blocks. - * - * @param cfg the CFG to visualize - * @param entry the entry node of the control flow graph to be represented - * @param analysis an analysis containing information about the program represented by the CFG. - * The information includes {@link Store}s that are valid at the beginning of basic blocks - * reachable from {@code entry} and per-node information for value producing {@link Node}s. - * Can also be {@code null} to indicate that this information should not be output. - * @return possible analysis results, e.g. generated file names. - */ - /*@Nullable*/ Map visualize( - ControlFlowGraph cfg, Block entry, /*@Nullable*/ Analysis analysis); - - /** - * Delegate the visualization responsibility to the passed {@link Store} instance, which will - * call back to this visualizer instance for sub-components. - * - * @param store the store to visualize - */ - void visualizeStore(S store); - - /** - * Called by a {@code CFAbstractStore} to visualize the class name before calling the {@code - * CFAbstractStore#internalVisualize()} method. - * - * @param classCanonicalName the canonical name of the class - */ - void visualizeStoreHeader(String classCanonicalName); - - /** - * Called by {@code CFAbstractStore#internalVisualize()} to visualize a local variable. - * - * @param localVar the local variable - * @param value the value of the local variable - */ - void visualizeStoreLocalVar(FlowExpressions.LocalVariable localVar, A value); - - /** - * Called by {@code CFAbstractStore#internalVisualize()} to visualize the value of the current - * object {@code this} in this Store. - * - * @param value the value of the current object this - */ - void visualizeStoreThisVal(A value); - - /** - * Called by {@code CFAbstractStore#internalVisualize()} to visualize the value of fields - * collected by this Store. - * - * @param fieldAccess the field - * @param value the value of the field - */ - void visualizeStoreFieldVals(FlowExpressions.FieldAccess fieldAccess, A value); - - /** - * Called by {@code CFAbstractStore#internalVisualize()} to visualize the value of arrays - * collected by this Store. - * - * @param arrayValue the array - * @param value the value of the array - */ - void visualizeStoreArrayVal(FlowExpressions.ArrayAccess arrayValue, A value); - - /** - * Called by {@code CFAbstractStore#internalVisualize()} to visualize the value of pure method - * calls collected by this Store. - * - * @param methodCall the pure method call - * @param value the value of the pure method call - */ - void visualizeStoreMethodVals(FlowExpressions.MethodCall methodCall, A value); - - /** - * Called by {@code CFAbstractStore#internalVisualize()} to visualize the value of class names - * collected by this Store. - * - * @param className the class name - * @param value the value of the class name - */ - void visualizeStoreClassVals(FlowExpressions.ClassName className, A value); - - /** - * Called by {@code CFAbstractStore#internalVisualize()} to visualize the specific information - * collected according to the specific kind of Store. Currently, these Stores call this method: - * {@code LockStore}, {@code NullnessStore}, and {@code InitializationStore} to visualize - * additional information. - * - * @param keyName the name of the specific information to be visualized - * @param value the value of the specific information to be visualized - */ - void visualizeStoreKeyVal(String keyName, Object value); - - /** - * Called by {@code CFAbstractStore} to visualize any information after the invocation of {@code - * CFAbstractStore#internalVisualize()}. - */ - void visualizeStoreFooter(); - - /** - * Visualize a block based on the analysis. - * - * @param bb the block - * @param analysis the current analysis - */ - void visualizeBlock(Block bb, /*@Nullable*/ Analysis analysis); - - /** - * Visualize a SpecialBlock. - * - * @param sbb the special block - */ - void visualizeSpecialBlock(SpecialBlock sbb); - - /** - * Visualize the transferInput of a Block based on the analysis. - * - * @param bb the block - * @param analysis the current analysis - */ - void visualizeBlockTransferInput(Block bb, Analysis analysis); - - /** - * Visualize a Node based on the analysis. - * - * @param t the node - * @param analysis the current analysis - */ - void visualizeBlockNode(Node t, /*@Nullable*/ Analysis analysis); - - /** Shutdown method called once from the shutdown hook of the {@code BaseTypeChecker}. */ - void shutdown(); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/ControlFlowGraph.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/ControlFlowGraph.java deleted file mode 100644 index 0a2687aec2..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/ControlFlowGraph.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.checkerframework.dataflow.cfg; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.Tree; -import java.util.Collections; -import java.util.Deque; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.Set; -import org.checkerframework.dataflow.cfg.block.Block; -import org.checkerframework.dataflow.cfg.block.Block.BlockType; -import org.checkerframework.dataflow.cfg.block.ConditionalBlock; -import org.checkerframework.dataflow.cfg.block.ExceptionBlock; -import org.checkerframework.dataflow.cfg.block.SingleSuccessorBlock; -import org.checkerframework.dataflow.cfg.block.SpecialBlock; -import org.checkerframework.dataflow.cfg.block.SpecialBlockImpl; -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.dataflow.cfg.node.ReturnNode; - -/** - * A control flow graph (CFG for short) of a single method. - * - * @author Stefan Heule - */ -public class ControlFlowGraph { - - /** The entry block of the control flow graph. */ - protected final SpecialBlock entryBlock; - - /** The regular exit block of the control flow graph. */ - protected final SpecialBlock regularExitBlock; - - /** The exceptional exit block of the control flow graph. */ - protected final SpecialBlock exceptionalExitBlock; - - /** The AST this CFG corresponds to. */ - protected UnderlyingAST underlyingAST; - - /** - * Maps from AST {@link Tree}s to {@link Node}s. Every Tree that produces a value will have at - * least one corresponding Node. Trees that undergo conversions, such as boxing or unboxing, can - * map to two distinct Nodes. The Node for the pre-conversion value is stored in treeLookup, - * while the Node for the post-conversion value is stored in convertedTreeLookup. - */ - protected IdentityHashMap treeLookup; - - /** Map from AST {@link Tree}s to post-conversion {@link Node}s. */ - protected IdentityHashMap convertedTreeLookup; - - /** - * All return nodes (if any) encountered. Only includes return statements that actually return - * something - */ - protected final List returnNodes; - - public ControlFlowGraph( - SpecialBlock entryBlock, - SpecialBlockImpl regularExitBlock, - SpecialBlockImpl exceptionalExitBlock, - UnderlyingAST underlyingAST, - IdentityHashMap treeLookup, - IdentityHashMap convertedTreeLookup, - List returnNodes) { - super(); - this.entryBlock = entryBlock; - this.underlyingAST = underlyingAST; - this.treeLookup = treeLookup; - this.convertedTreeLookup = convertedTreeLookup; - this.regularExitBlock = regularExitBlock; - this.exceptionalExitBlock = exceptionalExitBlock; - this.returnNodes = returnNodes; - } - - /** @return the {@link Node} to which the {@link Tree} {@code t} corresponds. */ - public Node getNodeCorrespondingToTree(Tree t) { - if (convertedTreeLookup.containsKey(t)) { - return convertedTreeLookup.get(t); - } else { - return treeLookup.get(t); - } - } - - /** @return the entry block of the control flow graph. */ - public SpecialBlock getEntryBlock() { - return entryBlock; - } - - public List getReturnNodes() { - return returnNodes; - } - - public SpecialBlock getRegularExitBlock() { - return regularExitBlock; - } - - public SpecialBlock getExceptionalExitBlock() { - return exceptionalExitBlock; - } - - /** @return the AST this CFG corresponds to. */ - public UnderlyingAST getUnderlyingAST() { - return underlyingAST; - } - - /** @return the set of all basic block in this control flow graph */ - public Set getAllBlocks() { - Set visited = new HashSet<>(); - Queue worklist = new LinkedList<>(); - Block cur = entryBlock; - visited.add(entryBlock); - - // traverse the whole control flow graph - while (true) { - if (cur == null) { - break; - } - - Queue succs = new LinkedList<>(); - if (cur.getType() == BlockType.CONDITIONAL_BLOCK) { - ConditionalBlock ccur = ((ConditionalBlock) cur); - succs.add(ccur.getThenSuccessor()); - succs.add(ccur.getElseSuccessor()); - } else { - assert cur instanceof SingleSuccessorBlock; - Block b = ((SingleSuccessorBlock) cur).getSuccessor(); - if (b != null) { - succs.add(b); - } - } - - if (cur.getType() == BlockType.EXCEPTION_BLOCK) { - ExceptionBlock ecur = (ExceptionBlock) cur; - for (Set exceptionSuccSet : ecur.getExceptionalSuccessors().values()) { - succs.addAll(exceptionSuccSet); - } - } - - for (Block b : succs) { - if (!visited.contains(b)) { - visited.add(b); - worklist.add(b); - } - } - - cur = worklist.poll(); - } - - return visited; - } - - /** - * @return the list of all basic block in this control flow graph in reversed depth-first - * postorder sequence. - *

Blocks may appear more than once in the sequence. - */ - public List getDepthFirstOrderedBlocks() { - List dfsOrderResult = new LinkedList<>(); - Set visited = new HashSet<>(); - Deque worklist = new LinkedList<>(); - worklist.add(entryBlock); - while (!worklist.isEmpty()) { - Block cur = worklist.getLast(); - if (visited.contains(cur)) { - dfsOrderResult.add(cur); - worklist.removeLast(); - } else { - visited.add(cur); - Deque successors = getSuccessors(cur); - successors.removeAll(visited); - worklist.addAll(successors); - } - } - - Collections.reverse(dfsOrderResult); - return dfsOrderResult; - } - - /** - * Get a list of all successor Blocks for cur - * - * @return a Deque of successor Blocks - */ - private Deque getSuccessors(Block cur) { - Deque succs = new LinkedList<>(); - if (cur.getType() == BlockType.CONDITIONAL_BLOCK) { - ConditionalBlock ccur = ((ConditionalBlock) cur); - succs.add(ccur.getThenSuccessor()); - succs.add(ccur.getElseSuccessor()); - } else { - assert cur instanceof SingleSuccessorBlock; - Block b = ((SingleSuccessorBlock) cur).getSuccessor(); - if (b != null) { - succs.add(b); - } - } - - if (cur.getType() == BlockType.EXCEPTION_BLOCK) { - ExceptionBlock ecur = (ExceptionBlock) cur; - for (Set exceptionSuccSet : ecur.getExceptionalSuccessors().values()) { - succs.addAll(exceptionSuccSet); - } - } - return succs; - } - - /** @return the tree-lookup map */ - public IdentityHashMap getTreeLookup() { - return new IdentityHashMap<>(treeLookup); - } - - /** - * Get the {@link MethodTree} of the CFG if the argument {@link Tree} maps to a {@link Node} in - * the CFG or null otherwise. - */ - public /*@Nullable*/ MethodTree getContainingMethod(Tree t) { - if (treeLookup.containsKey(t)) { - if (underlyingAST.getKind() == UnderlyingAST.Kind.METHOD) { - UnderlyingAST.CFGMethod cfgMethod = (UnderlyingAST.CFGMethod) underlyingAST; - return cfgMethod.getMethod(); - } - } - return null; - } - - /** - * Get the {@link ClassTree} of the CFG if the argument {@link Tree} maps to a {@link Node} in - * the CFG or null otherwise. - */ - public /*@Nullable*/ ClassTree getContainingClass(Tree t) { - if (treeLookup.containsKey(t)) { - if (underlyingAST.getKind() == UnderlyingAST.Kind.METHOD) { - UnderlyingAST.CFGMethod cfgMethod = (UnderlyingAST.CFGMethod) underlyingAST; - return cfgMethod.getClassTree(); - } - } - return null; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/DOTCFGVisualizer.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/DOTCFGVisualizer.java deleted file mode 100644 index 1eb1cb87a2..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/DOTCFGVisualizer.java +++ /dev/null @@ -1,511 +0,0 @@ -package org.checkerframework.dataflow.cfg; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.tools.javac.tree.JCTree; -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Queue; -import java.util.Set; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.analysis.AbstractValue; -import org.checkerframework.dataflow.analysis.Analysis; -import org.checkerframework.dataflow.analysis.FlowExpressions; -import org.checkerframework.dataflow.analysis.Store; -import org.checkerframework.dataflow.analysis.TransferFunction; -import org.checkerframework.dataflow.analysis.TransferInput; -import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGMethod; -import org.checkerframework.dataflow.cfg.UnderlyingAST.CFGStatement; -import org.checkerframework.dataflow.cfg.block.Block; -import org.checkerframework.dataflow.cfg.block.Block.BlockType; -import org.checkerframework.dataflow.cfg.block.ConditionalBlock; -import org.checkerframework.dataflow.cfg.block.ExceptionBlock; -import org.checkerframework.dataflow.cfg.block.RegularBlock; -import org.checkerframework.dataflow.cfg.block.SingleSuccessorBlock; -import org.checkerframework.dataflow.cfg.block.SpecialBlock; -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.javacutil.ErrorReporter; - -/** - * Generate a graph description in the DOT language of a control graph. - * - * @author Stefan Heule - */ -public class DOTCFGVisualizer< - A extends AbstractValue, S extends Store, T extends TransferFunction> - implements CFGVisualizer { - - protected String outdir; - protected boolean verbose; - protected String checkerName; - - protected StringBuilder sbDigraph; - protected StringBuilder sbStore; - protected StringBuilder sbBlock; - - /** Mapping from class/method representation to generated dot file. */ - protected Map generated; - - @Override - public void init(Map args) { - this.outdir = (String) args.get("outdir"); - { - Object verb = args.get("verbose"); - this.verbose = - verb == null - ? false - : verb instanceof String - ? Boolean.getBoolean((String) verb) - : (boolean) verb; - } - this.checkerName = (String) args.get("checkerName"); - - this.generated = new HashMap<>(); - - this.sbDigraph = new StringBuilder(); - - this.sbStore = new StringBuilder(); - - this.sbBlock = new StringBuilder(); - } - - /** {@inheritDoc} */ - @Override - public /*@Nullable*/ Map visualize( - ControlFlowGraph cfg, Block entry, /*@Nullable*/ Analysis analysis) { - - String dotgraph = generateDotGraph(cfg, entry, analysis); - - String dotfilename = dotOutputFileName(cfg.underlyingAST); - // System.err.println("Output to DOT file: " + dotfilename); - - try { - FileWriter fstream = new FileWriter(dotfilename); - BufferedWriter out = new BufferedWriter(fstream); - out.write(dotgraph); - out.close(); - } catch (IOException e) { - ErrorReporter.errorAbort( - "Error creating dot file: " + dotfilename + "; ensure the path is valid", e); - } - - Map res = new HashMap<>(); - res.put("dotFileName", dotfilename); - - return res; - } - - /** Generate the dot representation as String. */ - protected String generateDotGraph( - ControlFlowGraph cfg, Block entry, /*@Nullable*/ Analysis analysis) { - this.sbDigraph.setLength(0); - Set visited = new HashSet<>(); - - // header - this.sbDigraph.append("digraph {\n"); - - Block cur = entry; - Queue worklist = new LinkedList<>(); - visited.add(entry); - // traverse control flow graph and define all arrows - while (true) { - if (cur == null) { - break; - } - - if (cur.getType() == BlockType.CONDITIONAL_BLOCK) { - ConditionalBlock ccur = ((ConditionalBlock) cur); - Block thenSuccessor = ccur.getThenSuccessor(); - addDotEdge(ccur.getId(), thenSuccessor.getId(), "then\\n" + ccur.getThenFlowRule()); - if (!visited.contains(thenSuccessor)) { - visited.add(thenSuccessor); - worklist.add(thenSuccessor); - } - Block elseSuccessor = ccur.getElseSuccessor(); - addDotEdge(ccur.getId(), elseSuccessor.getId(), "else\\n" + ccur.getElseFlowRule()); - if (!visited.contains(elseSuccessor)) { - visited.add(elseSuccessor); - worklist.add(elseSuccessor); - } - } else { - assert cur instanceof SingleSuccessorBlock; - Block b = ((SingleSuccessorBlock) cur).getSuccessor(); - if (b != null) { - addDotEdge( - cur.getId(), - b.getId(), - ((SingleSuccessorBlock) cur).getFlowRule().name()); - if (!visited.contains(b)) { - visited.add(b); - worklist.add(b); - } - } - } - - // exceptional edges - if (cur.getType() == BlockType.EXCEPTION_BLOCK) { - ExceptionBlock ecur = (ExceptionBlock) cur; - for (Entry> e : ecur.getExceptionalSuccessors().entrySet()) { - Set blocks = e.getValue(); - TypeMirror cause = e.getKey(); - String exception = cause.toString(); - if (exception.startsWith("java.lang.")) { - exception = exception.replace("java.lang.", ""); - } - - for (Block b : blocks) { - addDotEdge(cur.getId(), b.getId(), exception); - if (!visited.contains(b)) { - visited.add(b); - worklist.add(b); - } - } - } - } - - cur = worklist.poll(); - } - - generateDotNodes(visited, cfg, analysis); - - // footer - this.sbDigraph.append("}\n"); - - return this.sbDigraph.toString(); - } - - protected void generateDotNodes( - Set visited, ControlFlowGraph cfg, /*@Nullable*/ Analysis analysis) { - IdentityHashMap> processOrder = getProcessOrder(cfg); - this.sbDigraph.append(" node [shape=rectangle];\n\n"); - // definition of all nodes including their labels - for (Block v : visited) { - this.sbDigraph.append(" " + v.getId() + " ["); - if (v.getType() == BlockType.CONDITIONAL_BLOCK) { - this.sbDigraph.append("shape=polygon sides=8 "); - } else if (v.getType() == BlockType.SPECIAL_BLOCK) { - this.sbDigraph.append("shape=oval "); - } - this.sbDigraph.append("label=\""); - if (verbose) { - this.sbDigraph.append( - "Process order: " - + processOrder.get(v).toString().replaceAll("[\\[\\]]", "") - + "\\n"); - } - visualizeBlock(v, analysis); - } - - this.sbDigraph.append("\n"); - } - - /** @return the file name used for DOT output. */ - protected String dotOutputFileName(UnderlyingAST ast) { - StringBuilder srcloc = new StringBuilder(); - - StringBuilder outfile = new StringBuilder(outdir); - outfile.append('/'); - if (ast.getKind() == UnderlyingAST.Kind.ARBITRARY_CODE) { - CFGStatement cfgs = (CFGStatement) ast; - String clsname = cfgs.getClassTree().getSimpleName().toString(); - outfile.append(clsname); - outfile.append("-initializer-"); - outfile.append(ast.hashCode()); - - srcloc.append('<'); - srcloc.append(clsname); - srcloc.append("::initializer::"); - srcloc.append(((JCTree) cfgs.getCode()).pos); - srcloc.append('>'); - } else if (ast.getKind() == UnderlyingAST.Kind.METHOD) { - CFGMethod cfgm = (CFGMethod) ast; - String clsname = cfgm.getClassTree().getSimpleName().toString(); - String methname = cfgm.getMethod().getName().toString(); - outfile.append(clsname); - outfile.append('-'); - outfile.append(methname); - - srcloc.append('<'); - srcloc.append(clsname); - srcloc.append("::"); - srcloc.append(methname); - srcloc.append('('); - srcloc.append(cfgm.getMethod().getParameters()); - srcloc.append(")::"); - srcloc.append(((JCTree) cfgm.getMethod()).pos); - srcloc.append('>'); - } else { - ErrorReporter.errorAbort( - "Unexpected AST kind: " + ast.getKind() + " value: " + ast.toString()); - return null; - } - outfile.append('-'); - outfile.append(checkerName); - outfile.append(".dot"); - - // make path safe for Windows - String out = outfile.toString().replace("<", "_").replace(">", ""); - - generated.put(srcloc.toString(), out); - - return out; - } - - protected IdentityHashMap> getProcessOrder(ControlFlowGraph cfg) { - IdentityHashMap> depthFirstOrder = new IdentityHashMap<>(); - int count = 1; - for (Block b : cfg.getDepthFirstOrderedBlocks()) { - if (depthFirstOrder.get(b) == null) { - depthFirstOrder.put(b, new ArrayList()); - } - depthFirstOrder.get(b).add(count++); - } - return depthFirstOrder; - } - - /** - * Produce a representation of the contests of a basic block. - * - * @param bb basic block to visualize - */ - @Override - public void visualizeBlock(Block bb, /*@Nullable*/ Analysis analysis) { - - this.sbBlock.setLength(0); - - // loop over contents - List contents = new LinkedList<>(); - switch (bb.getType()) { - case REGULAR_BLOCK: - contents.addAll(((RegularBlock) bb).getContents()); - break; - case EXCEPTION_BLOCK: - contents.add(((ExceptionBlock) bb).getNode()); - break; - case CONDITIONAL_BLOCK: - break; - case SPECIAL_BLOCK: - break; - default: - assert false : "All types of basic blocks covered"; - } - boolean notFirst = false; - for (Node t : contents) { - if (notFirst) { - this.sbBlock.append("\\n"); - } - notFirst = true; - visualizeBlockNode(t, analysis); - } - - // handle case where no contents are present - boolean centered = false; - if (this.sbBlock.length() == 0) { - centered = true; - if (bb.getType() == BlockType.SPECIAL_BLOCK) { - visualizeSpecialBlock((SpecialBlock) bb); - } else if (bb.getType() == BlockType.CONDITIONAL_BLOCK) { - this.sbDigraph.append(" \",];\n"); - return; - } else { - this.sbDigraph.append("?? empty ?? \",];\n"); - return; - } - } - - // visualize transfer input if necessary - if (analysis != null) { - visualizeBlockTransferInput(bb, analysis); - } - - this.sbDigraph.append( - (this.sbBlock.toString() + (centered ? "" : "\\n")).replace("\\n", "\\l") - + " \",];\n"); - } - - @Override - public void visualizeSpecialBlock(SpecialBlock sbb) { - switch (sbb.getSpecialType()) { - case ENTRY: - this.sbBlock.append(""); - break; - case EXIT: - this.sbBlock.append(""); - break; - case EXCEPTIONAL_EXIT: - this.sbBlock.append(""); - break; - } - } - - @Override - public void visualizeBlockTransferInput(Block bb, Analysis analysis) { - assert analysis != null - : "analysis should be non-null when visualizing the transfer input of a block."; - - TransferInput input = analysis.getInput(bb); - this.sbStore.setLength(0); - - // split input representation to two lines - this.sbStore.append("Before:"); - S thenStore = input.getThenStore(); - if (!input.containsTwoStores()) { - S regularStore = input.getRegularStore(); - this.sbStore.append('['); - visualizeStore(regularStore); - this.sbStore.append(']'); - } else { - S elseStore = input.getElseStore(); - this.sbStore.append("[then="); - visualizeStore(thenStore); - this.sbStore.append(", else="); - visualizeStore(elseStore); - this.sbStore.append("]"); - } - // separator - this.sbStore.append("\\n~~~~~~~~~\\n"); - - // the transfer input before this block is added before the block content - this.sbBlock.insert(0, this.sbStore); - - if (verbose) { - Node lastNode; - switch (bb.getType()) { - case REGULAR_BLOCK: - List blockContents = ((RegularBlock) bb).getContents(); - lastNode = blockContents.get(blockContents.size() - 1); - break; - case EXCEPTION_BLOCK: - lastNode = ((ExceptionBlock) bb).getNode(); - break; - default: - lastNode = null; - } - if (lastNode != null) { - this.sbStore.setLength(0); - this.sbStore.append("\\n~~~~~~~~~\\n"); - this.sbStore.append("After:"); - visualizeStore(analysis.getResult().getStoreAfter(lastNode)); - this.sbBlock.append(this.sbStore); - } - } - } - - @Override - public void visualizeBlockNode(Node t, /*@Nullable*/ Analysis analysis) { - this.sbBlock.append(prepareString(t.toString()) + " [ " + prepareNodeType(t) + " ]"); - if (analysis != null) { - A value = analysis.getValue(t); - if (value != null) { - this.sbBlock.append(" > " + prepareString(value.toString())); - } - } - } - - protected String prepareNodeType(Node t) { - String name = t.getClass().getSimpleName(); - return name.replace("Node", ""); - } - - protected String prepareString(String s) { - return s.replace("\"", "\\\""); - } - - protected void addDotEdge(long sId, long eId, String labelContent) { - this.sbDigraph.append(" " + sId + " -> " + eId + " [label=\"" + labelContent + "\"];\n"); - } - - @Override - public void visualizeStore(S store) { - store.visualize(this); - } - - @Override - public void visualizeStoreThisVal(A value) { - this.sbStore.append(" this > " + value + "\\n"); - } - - @Override - public void visualizeStoreLocalVar(FlowExpressions.LocalVariable localVar, A value) { - this.sbStore.append(" " + localVar + " > " + toStringEscapeDoubleQuotes(value) + "\\n"); - } - - @Override - public void visualizeStoreFieldVals(FlowExpressions.FieldAccess fieldAccess, A value) { - this.sbStore.append(" " + fieldAccess + " > " + toStringEscapeDoubleQuotes(value) + "\\n"); - } - - @Override - public void visualizeStoreArrayVal(FlowExpressions.ArrayAccess arrayValue, A value) { - this.sbStore.append(" " + arrayValue + " > " + toStringEscapeDoubleQuotes(value) + "\\n"); - } - - @Override - public void visualizeStoreMethodVals(FlowExpressions.MethodCall methodCall, A value) { - this.sbStore.append( - " " + methodCall.toString().replace("\"", "\\\"") + " > " + value + "\\n"); - } - - @Override - public void visualizeStoreClassVals(FlowExpressions.ClassName className, A value) { - this.sbStore.append(" " + className + " > " + toStringEscapeDoubleQuotes(value) + "\\n"); - } - - @Override - public void visualizeStoreKeyVal(String keyName, Object value) { - this.sbStore.append(" " + keyName + " = " + value + "\\n"); - } - - protected String escapeDoubleQuotes(final String str) { - return str.replace("\"", "\\\""); - } - - protected String toStringEscapeDoubleQuotes(final Object obj) { - return escapeDoubleQuotes(String.valueOf(obj)); - } - - @Override - public void visualizeStoreHeader(String classCanonicalName) { - this.sbStore.append(classCanonicalName + " (\\n"); - } - - @Override - public void visualizeStoreFooter() { - this.sbStore.append(")"); - } - - /** - * Write a file {@code methods.txt} that contains a mapping from source code location to - * generated dot file. - */ - @Override - public void shutdown() { - try { - // Open for append, in case of multiple sub-checkers. - FileWriter fstream = new FileWriter(outdir + "/methods.txt", true); - BufferedWriter out = new BufferedWriter(fstream); - for (Map.Entry kv : generated.entrySet()) { - out.write(kv.getKey()); - out.append('\t'); - out.write(kv.getValue()); - out.append('\n'); - } - out.close(); - } catch (IOException e) { - ErrorReporter.errorAbort( - "Error creating methods.txt file in: " + outdir + "; ensure the path is valid", - e); - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/JavaSource2CFGDOT.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/JavaSource2CFGDOT.java deleted file mode 100644 index fa6ff55dc5..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/JavaSource2CFGDOT.java +++ /dev/null @@ -1,269 +0,0 @@ -package org.checkerframework.dataflow.cfg; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.util.TreePathScanner; -import com.sun.tools.javac.file.JavacFileManager; -import com.sun.tools.javac.main.JavaCompiler; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.Options; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import javax.lang.model.element.ExecutableElement; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import javax.xml.ws.Holder; -import org.checkerframework.dataflow.analysis.AbstractValue; -import org.checkerframework.dataflow.analysis.Analysis; -import org.checkerframework.dataflow.analysis.Store; -import org.checkerframework.dataflow.analysis.TransferFunction; -import org.checkerframework.javacutil.BasicTypeProcessor; -import org.checkerframework.javacutil.TreeUtils; - -/** - * Class to generate the DOT representation of the control flow graph of a given method. - * - * @author Stefan Heule - */ -public class JavaSource2CFGDOT { - - /** Main method. */ - public static void main(String[] args) { - if (args.length < 2) { - printUsage(); - System.exit(1); - } - String input = args[0]; - String output = args[1]; - File file = new File(input); - if (!file.canRead()) { - printError("Cannot read input file: " + file.getAbsolutePath()); - printUsage(); - System.exit(1); - } - - String method = "test"; - String clas = "Test"; - boolean pdf = false; - boolean error = false; - - for (int i = 2; i < args.length; i++) { - if (args[i].equals("-pdf")) { - pdf = true; - } else if (args[i].equals("-method")) { - if (i >= args.length - 1) { - printError("Did not find after -method."); - continue; - } - i++; - method = args[i]; - } else if (args[i].equals("-class")) { - if (i >= args.length - 1) { - printError("Did not find after -class."); - continue; - } - i++; - clas = args[i]; - } else { - printError("Unknown command-line argument: " + args[i]); - error = true; - } - } - - if (error) { - System.exit(1); - } - - generateDOTofCFG(input, output, method, clas, pdf); - } - - /** Print an error message. */ - protected static void printError(String string) { - System.err.println("ERROR: " + string); - } - - /** Print usage information. */ - protected static void printUsage() { - System.out.println( - "Generate the control flow graph of a Java method, represented as a DOT graph."); - System.out.println( - "Parameters: [-method ] [-class ] [-pdf]"); - System.out.println(" -pdf: Also generate the PDF by invoking 'dot'."); - System.out.println(" -method: The method to generate the CFG for (defaults to 'test')."); - System.out.println( - " -class: The class in which to find the method (defaults to 'Test')."); - } - - /** Just like method above but without analysis. */ - public static void generateDOTofCFG( - String inputFile, String outputDir, String method, String clas, boolean pdf) { - generateDOTofCFG(inputFile, outputDir, method, clas, pdf, null); - } - - /** - * Generate the DOT representation of the CFG for a method. - * - * @param inputFile java source input file - * @param outputDir source output directory - * @param method method name to generate the CFG for - * @param pdf also generate a PDF? - * @param analysis analysis to perform befor the visualization (or {@code null} if no analysis - * is to be performed). - */ - public static , S extends Store, T extends TransferFunction> - void generateDOTofCFG( - String inputFile, - String outputDir, - String method, - String clas, - boolean pdf, - /*@Nullable*/ Analysis analysis) { - Entry m = - getMethodTreeAndCompilationUnit(inputFile, method, clas); - generateDOTofCFG( - inputFile, outputDir, method, clas, pdf, analysis, m.getKey(), m.getValue()); - } - - public static , S extends Store, T extends TransferFunction> - void generateDOTofCFG( - String inputFile, - String outputDir, - String method, - String clas, - boolean pdf, - /*@Nullable*/ Analysis analysis, - MethodTree m, - CompilationUnitTree r) { - String fileName = (new File(inputFile)).getName(); - System.out.println("Working on " + fileName + "..."); - - if (m == null) { - printError("Method not found."); - System.exit(1); - } - - ControlFlowGraph cfg = CFGBuilder.build(r, null, m, null); - if (analysis != null) { - analysis.performAnalysis(cfg); - } - - Map args = new HashMap<>(); - args.put("outdir", outputDir); - args.put("checkerName", ""); - - CFGVisualizer viz = new DOTCFGVisualizer(); - viz.init(args); - Map res = viz.visualize(cfg, cfg.getEntryBlock(), analysis); - viz.shutdown(); - - if (pdf) { - producePDF((String) res.get("dotFileName")); - } - } - - /** Invoke DOT to generate a PDF. */ - protected static void producePDF(String file) { - try { - String command = "dot -Tpdf \"" + file + ".txt\" -o \"" + file + ".pdf\""; - Process child = Runtime.getRuntime().exec(command); - child.waitFor(); - } catch (InterruptedException | IOException e) { - e.printStackTrace(); - System.exit(1); - } - } - - /** - * @return the AST of a specific method in a specific class in a specific file (or null if no - * such method exists) - */ - public static /*@Nullable*/ MethodTree getMethodTree( - String file, final String method, String clas) { - return getMethodTreeAndCompilationUnit(file, method, clas).getKey(); - } - - /** - * @return the AST of a specific method in a specific class as well as the {@link - * CompilationUnitTree} in a specific file (or null they do not exist). - */ - public static Entry - getMethodTreeAndCompilationUnit(String file, final String method, String clas) { - final Holder m = new Holder<>(); - final Holder c = new Holder<>(); - BasicTypeProcessor typeProcessor = - new BasicTypeProcessor() { - @Override - protected TreePathScanner createTreePathScanner( - CompilationUnitTree root) { - c.value = root; - return new TreePathScanner() { - @Override - public Void visitMethod(MethodTree node, Void p) { - ExecutableElement el = TreeUtils.elementFromDeclaration(node); - if (el.getSimpleName().contentEquals(method)) { - m.value = node; - // stop execution by throwing an exception. this - // makes sure that compilation does not proceed, and - // thus the AST is not modified by further phases of - // the compilation (and we save the work to do the - // compilation). - throw new RuntimeException(); - } - return null; - } - }; - } - }; - - Context context = new Context(); - Options.instance(context).put("compilePolicy", "ATTR_ONLY"); - JavaCompiler javac = new JavaCompiler(context); - JavacFileManager fileManager = (JavacFileManager) context.get(JavaFileManager.class); - - JavaFileObject l = - fileManager.getJavaFileObjectsFromStrings(List.of(file)).iterator().next(); - - PrintStream err = System.err; - try { - // redirect syserr to nothing (and prevent the compiler from issuing - // warnings about our exception. - System.setErr( - new PrintStream( - new OutputStream() { - @Override - public void write(int b) throws IOException {} - })); - javac.compile(List.of(l), List.of(clas), List.of(typeProcessor)); - } catch (Throwable e) { - // ok - } finally { - System.setErr(err); - } - return new Entry() { - @Override - public CompilationUnitTree setValue(CompilationUnitTree value) { - return null; - } - - @Override - public CompilationUnitTree getValue() { - return c.value; - } - - @Override - public MethodTree getKey() { - return m.value; - } - }; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/UnderlyingAST.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/UnderlyingAST.java deleted file mode 100644 index dd646f110d..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/UnderlyingAST.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.checkerframework.dataflow.cfg; - -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.LambdaExpressionTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.Tree; - -/** - * Represents an abstract syntax tree of type {@link Tree} that underlies a given control flow - * graph. - * - * @author Stefan Heule - */ -public abstract class UnderlyingAST { - public enum Kind { - /** The underlying code is a whole method */ - METHOD, - /** The underlying code is a lambda expression */ - LAMBDA, - - /** The underlying code is an arbitrary Java statement or expression */ - ARBITRARY_CODE, - } - - protected final Kind kind; - - public UnderlyingAST(Kind kind) { - this.kind = kind; - } - - /** @return the code that corresponds to the CFG */ - public abstract Tree getCode(); - - public Kind getKind() { - return kind; - } - - /** If the underlying AST is a method. */ - public static class CFGMethod extends UnderlyingAST { - - /** The method declaration */ - protected final MethodTree method; - - /** The class tree this method belongs to. */ - protected final ClassTree classTree; - - public CFGMethod(MethodTree method, ClassTree classTree) { - super(Kind.METHOD); - this.method = method; - this.classTree = classTree; - } - - @Override - public Tree getCode() { - return method.getBody(); - } - - public MethodTree getMethod() { - return method; - } - - public ClassTree getClassTree() { - return classTree; - } - - @Override - public String toString() { - return "CFGMethod(\n" + method + "\n)"; - } - } - - /** If the underlying AST is a lambda. */ - public static class CFGLambda extends UnderlyingAST { - - private final LambdaExpressionTree lambda; - - public CFGLambda(LambdaExpressionTree lambda) { - super(Kind.LAMBDA); - this.lambda = lambda; - } - - @Override - public Tree getCode() { - return lambda.getBody(); - } - - public LambdaExpressionTree getLambdaTree() { - return lambda; - } - - @Override - public String toString() { - return "CFGLambda(\n" + lambda + "\n)"; - } - } - - /** If the underlying AST is a statement or expression. */ - public static class CFGStatement extends UnderlyingAST { - - protected final Tree code; - - /** The class tree this method belongs to. */ - protected final ClassTree classTree; - - public CFGStatement(Tree code, ClassTree classTree) { - super(Kind.ARBITRARY_CODE); - this.code = code; - this.classTree = classTree; - } - - @Override - public Tree getCode() { - return code; - } - - public ClassTree getClassTree() { - return classTree; - } - - @Override - public String toString() { - return "CFGStatement(\n" + code + "\n)"; - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/Block.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/Block.java deleted file mode 100644 index 2d58550568..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/Block.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -/** - * Represents a basic block in a control flow graph. - * - * @author Stefan Heule - */ -public interface Block { - - /** The types of basic blocks */ - public static enum BlockType { - - /** A regular basic block. */ - REGULAR_BLOCK, - - /** A conditional basic block. */ - CONDITIONAL_BLOCK, - - /** A special basic block. */ - SPECIAL_BLOCK, - - /** A basic block that can throw an exception. */ - EXCEPTION_BLOCK, - } - - /** @return the type of this basic block */ - BlockType getType(); - - /** @return the unique identifier of this block */ - long getId(); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/BlockImpl.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/BlockImpl.java deleted file mode 100644 index 0421a1e3f5..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/BlockImpl.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * Base class of the {@link Block} implementation hierarchy. - * - * @author Stefan Heule - */ -public abstract class BlockImpl implements Block { - - /** A unique ID for this node. */ - protected long id = BlockImpl.uniqueID(); - - /** The last ID that has already been used. */ - protected static long lastId = 0; - - /** The type of this basic block. */ - protected BlockType type; - - /** The set of predecessors. */ - protected Set predecessors; - - /** @return a fresh identifier */ - private static long uniqueID() { - return lastId++; - } - - public BlockImpl() { - predecessors = new HashSet<>(); - } - - @Override - public long getId() { - return id; - } - - @Override - public BlockType getType() { - return type; - } - - /** @return the list of predecessors of this basic block */ - public Set getPredecessors() { - return Collections.unmodifiableSet(predecessors); - } - - public void addPredecessor(BlockImpl pred) { - predecessors.add(pred); - } - - public void removePredecessor(BlockImpl pred) { - predecessors.remove(pred); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ConditionalBlock.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ConditionalBlock.java deleted file mode 100644 index dce04abdfe..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ConditionalBlock.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -import org.checkerframework.dataflow.analysis.Store; -import org.checkerframework.dataflow.cfg.node.Node; - -/** - * Represents a conditional basic block that contains exactly one boolean {@link Node}. - * - * @author Stefan Heule - */ -public interface ConditionalBlock extends Block { - - /** @return the entry block of the then branch */ - Block getThenSuccessor(); - - /** @return the entry block of the else branch */ - Block getElseSuccessor(); - - /** @return the flow rule for information flowing from this block to its then successor */ - Store.FlowRule getThenFlowRule(); - - /** @return the flow rule for information flowing from this block to its else successor */ - Store.FlowRule getElseFlowRule(); - - /** Set the flow rule for information flowing from this block to its then successor. */ - void setThenFlowRule(Store.FlowRule rule); - - /** Set the flow rule for information flowing from this block to its else successor. */ - void setElseFlowRule(Store.FlowRule rule); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ConditionalBlockImpl.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ConditionalBlockImpl.java deleted file mode 100644 index bd12522983..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ConditionalBlockImpl.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -import org.checkerframework.dataflow.analysis.Store; - -/** - * Implementation of a conditional basic block. - * - * @author Stefan Heule - */ -public class ConditionalBlockImpl extends BlockImpl implements ConditionalBlock { - - /** Successor of the then branch. */ - protected BlockImpl thenSuccessor; - - /** Successor of the else branch. */ - protected BlockImpl elseSuccessor; - - /** - * The rules below say that the THEN store before a conditional block flows to BOTH of the - * stores of the then successor, while the ELSE store before a conditional block flows to BOTH - * of the stores of the else successor. - */ - protected Store.FlowRule thenFlowRule = Store.FlowRule.THEN_TO_BOTH; - - protected Store.FlowRule elseFlowRule = Store.FlowRule.ELSE_TO_BOTH; - - /** - * Initialize an empty conditional basic block to be filled with contents and linked to other - * basic blocks later. - */ - public ConditionalBlockImpl() { - type = BlockType.CONDITIONAL_BLOCK; - } - - /** Set the then branch successor. */ - public void setThenSuccessor(BlockImpl b) { - thenSuccessor = b; - b.addPredecessor(this); - } - - /** Set the else branch successor. */ - public void setElseSuccessor(BlockImpl b) { - elseSuccessor = b; - b.addPredecessor(this); - } - - @Override - public Block getThenSuccessor() { - return thenSuccessor; - } - - @Override - public Block getElseSuccessor() { - return elseSuccessor; - } - - @Override - public Store.FlowRule getThenFlowRule() { - return thenFlowRule; - } - - @Override - public Store.FlowRule getElseFlowRule() { - return elseFlowRule; - } - - @Override - public void setThenFlowRule(Store.FlowRule rule) { - thenFlowRule = rule; - } - - @Override - public void setElseFlowRule(Store.FlowRule rule) { - elseFlowRule = rule; - } - - @Override - public String toString() { - return "ConditionalBlock()"; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ExceptionBlock.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ExceptionBlock.java deleted file mode 100644 index a549c5f03f..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ExceptionBlock.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -import java.util.Map; -import java.util.Set; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.cfg.node.Node; - -/** - * Represents a basic block that contains exactly one {@link Node} which can throw an exception. - * This block has exactly one non-exceptional successor, and one or more exceptional successors. - * - *

The following invariant holds. - * - *

- * getNode().getBlock() == this
- * 
- * - * @author Stefan Heule - */ -public interface ExceptionBlock extends SingleSuccessorBlock { - - /** @return the node of this block */ - Node getNode(); - - /** @return the list of exceptional successor blocks as an unmodifiable map */ - Map> getExceptionalSuccessors(); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ExceptionBlockImpl.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ExceptionBlockImpl.java deleted file mode 100644 index 2a6c3b4914..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/ExceptionBlockImpl.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.cfg.node.Node; - -/** - * Base class of the {@link Block} implementation hierarchy. - * - * @author Stefan Heule - */ -public class ExceptionBlockImpl extends SingleSuccessorBlockImpl implements ExceptionBlock { - - /** Set of exceptional successors. */ - protected Map> exceptionalSuccessors; - - public ExceptionBlockImpl() { - type = BlockType.EXCEPTION_BLOCK; - exceptionalSuccessors = new HashMap<>(); - } - - /** The node of this block. */ - protected Node node; - - /** Set the node. */ - public void setNode(Node c) { - node = c; - c.setBlock(this); - } - - @Override - public Node getNode() { - return node; - } - - /** Add an exceptional successor. */ - public void addExceptionalSuccessor(BlockImpl b, TypeMirror cause) { - if (exceptionalSuccessors == null) { - exceptionalSuccessors = new HashMap<>(); - } - Set blocks = exceptionalSuccessors.get(cause); - if (blocks == null) { - blocks = new HashSet(); - exceptionalSuccessors.put(cause, blocks); - } - blocks.add(b); - b.addPredecessor(this); - } - - @Override - public Map> getExceptionalSuccessors() { - if (exceptionalSuccessors == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(exceptionalSuccessors); - } - - @Override - public String toString() { - return "ExceptionBlock(" + node + ")"; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/RegularBlock.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/RegularBlock.java deleted file mode 100644 index 566449257b..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/RegularBlock.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -import java.util.List; -import org.checkerframework.dataflow.cfg.node.Node; - -/** - * A regular basic block that contains a sequence of {@link Node}s. - * - *

The following invariant holds. - * - *

- * forall n in getContents() :: n.getBlock() == this
- * 
- * - * @author Stefan Heule - */ -public interface RegularBlock extends SingleSuccessorBlock { - - /** @return the unmodifiable sequence of {@link Node}s. */ - List getContents(); - - /** @return the regular successor block */ - Block getRegularSuccessor(); - - /** Is this block empty (i.e., does it not contain any contents). */ - boolean isEmpty(); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/RegularBlockImpl.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/RegularBlockImpl.java deleted file mode 100644 index b302710d70..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/RegularBlockImpl.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import org.checkerframework.dataflow.cfg.node.Node; - -/** - * Implementation of a regular basic block. - * - * @author Stefan Heule - */ -public class RegularBlockImpl extends SingleSuccessorBlockImpl implements RegularBlock { - - /** Internal representation of the contents. */ - protected List contents; - - /** - * Initialize an empty basic block to be filled with contents and linked to other basic blocks - * later. - */ - public RegularBlockImpl() { - contents = new LinkedList<>(); - type = BlockType.REGULAR_BLOCK; - } - - /** Add a node to the contents of this basic block. */ - public void addNode(Node t) { - contents.add(t); - t.setBlock(this); - } - - /** Add multiple nodes to the contents of this basic block. */ - public void addNodes(List ts) { - for (Node t : ts) { - addNode(t); - } - } - - @Override - public List getContents() { - return Collections.unmodifiableList(contents); - } - - @Override - public BlockImpl getRegularSuccessor() { - return successor; - } - - @Override - public String toString() { - return "RegularBlock(" + contents + ")"; - } - - @Override - public boolean isEmpty() { - return contents.isEmpty(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SingleSuccessorBlock.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SingleSuccessorBlock.java deleted file mode 100644 index 038a69d3e4..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SingleSuccessorBlock.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import org.checkerframework.dataflow.analysis.Store; - -/** - * A basic block that has at exactly one non-exceptional successor. - * - * @author Stefan Heule - */ -public interface SingleSuccessorBlock extends Block { - - /** @return the non-exceptional successor block, or {@code null} if there is no successor. */ - /*@Nullable*/ Block getSuccessor(); - - /** @return the flow rule for information flowing from this block to its successor */ - Store.FlowRule getFlowRule(); - - /** Set the flow rule for information flowing from this block to its successor. */ - void setFlowRule(Store.FlowRule rule); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SingleSuccessorBlockImpl.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SingleSuccessorBlockImpl.java deleted file mode 100644 index 9e8872e850..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SingleSuccessorBlockImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import org.checkerframework.dataflow.analysis.Store; - -/** - * Implementation of a non-special basic block. - * - * @author Stefan Heule - */ -public abstract class SingleSuccessorBlockImpl extends BlockImpl implements SingleSuccessorBlock { - - /** Internal representation of the successor. */ - protected /*@Nullable*/ BlockImpl successor; - - /** - * The rule below say that EACH store at the end of a single successor block flow to the - * corresponding store of the successor. - */ - protected Store.FlowRule flowRule = Store.FlowRule.EACH_TO_EACH; - - @Override - public /*@Nullable*/ Block getSuccessor() { - return successor; - } - - /** Set a basic block as the successor of this block. */ - public void setSuccessor(BlockImpl successor) { - this.successor = successor; - successor.addPredecessor(this); - } - - @Override - public Store.FlowRule getFlowRule() { - return flowRule; - } - - @Override - public void setFlowRule(Store.FlowRule rule) { - flowRule = rule; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SpecialBlock.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SpecialBlock.java deleted file mode 100644 index dac9b4b8c2..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SpecialBlock.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -/** - * Represents a special basic block; i.e., one of the following: - * - *
    - *
  • Entry block of a method. - *
  • Regular exit block of a method. - *
  • Exceptional exit block of a method. - *
- * - * @author Stefan Heule - */ -public interface SpecialBlock extends SingleSuccessorBlock { - - /** The types of special basic blocks */ - public static enum SpecialBlockType { - - /** The entry block of a method */ - ENTRY, - - /** The exit block of a method */ - EXIT, - - /** A special exit block of a method for exceptional termination */ - EXCEPTIONAL_EXIT, - } - - /** @return the type of this special basic block */ - SpecialBlockType getSpecialType(); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SpecialBlockImpl.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SpecialBlockImpl.java deleted file mode 100644 index e6f25e8b1b..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/block/SpecialBlockImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.checkerframework.dataflow.cfg.block; - -public class SpecialBlockImpl extends SingleSuccessorBlockImpl implements SpecialBlock { - - /** The type of this special basic block. */ - protected SpecialBlockType specialType; - - public SpecialBlockImpl(SpecialBlockType type) { - this.specialType = type; - this.type = BlockType.SPECIAL_BLOCK; - } - - @Override - public SpecialBlockType getSpecialType() { - return specialType; - } - - @Override - public String toString() { - return "SpecialBlock(" + specialType + ")"; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AbstractNodeVisitor.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AbstractNodeVisitor.java deleted file mode 100644 index 39f1f84074..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AbstractNodeVisitor.java +++ /dev/null @@ -1,374 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/** - * A default implementation of the node visitor interface. The class introduces several 'summary' - * methods, that can be overridden to change the behavior of several related visit methods at once. - * An example is the {@code visitValueLiteral} method, that is called for every {@link - * ValueLiteralNode}. - * - *

This is useful to implement a visitor that performs the same operation (e.g., nothing) for - * most {@link Node}s and only has special behavior for a few. - * - * @author Stefan Heule - * @param return type of the visitor - * @param

parameter type of the visitor - */ -public abstract class AbstractNodeVisitor implements NodeVisitor { - - public abstract R visitNode(Node n, P p); - - public R visitValueLiteral(ValueLiteralNode n, P p) { - return visitNode(n, p); - } - - // Literals - @Override - public R visitShortLiteral(ShortLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - @Override - public R visitIntegerLiteral(IntegerLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - @Override - public R visitLongLiteral(LongLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - @Override - public R visitFloatLiteral(FloatLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - @Override - public R visitDoubleLiteral(DoubleLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - @Override - public R visitBooleanLiteral(BooleanLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - @Override - public R visitCharacterLiteral(CharacterLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - @Override - public R visitStringLiteral(StringLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - @Override - public R visitNullLiteral(NullLiteralNode n, P p) { - return visitValueLiteral(n, p); - } - - // Unary operations - @Override - public R visitNumericalMinus(NumericalMinusNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitNumericalPlus(NumericalPlusNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitBitwiseComplement(BitwiseComplementNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitNullChk(NullChkNode n, P p) { - return visitNode(n, p); - } - - // Binary operations - @Override - public R visitStringConcatenate(StringConcatenateNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitNumericalAddition(NumericalAdditionNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitNumericalSubtraction(NumericalSubtractionNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitNumericalMultiplication(NumericalMultiplicationNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitIntegerDivision(IntegerDivisionNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitFloatingDivision(FloatingDivisionNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitIntegerRemainder(IntegerRemainderNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitFloatingRemainder(FloatingRemainderNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitLeftShift(LeftShiftNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitSignedRightShift(SignedRightShiftNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitUnsignedRightShift(UnsignedRightShiftNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitBitwiseAnd(BitwiseAndNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitBitwiseOr(BitwiseOrNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitBitwiseXor(BitwiseXorNode n, P p) { - return visitNode(n, p); - } - - // Compound assignments - @Override - public R visitStringConcatenateAssignment(StringConcatenateAssignmentNode n, P p) { - return visitNode(n, p); - } - - // Comparison operations - @Override - public R visitLessThan(LessThanNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitLessThanOrEqual(LessThanOrEqualNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitGreaterThan(GreaterThanNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitGreaterThanOrEqual(GreaterThanOrEqualNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitEqualTo(EqualToNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitNotEqual(NotEqualNode n, P p) { - return visitNode(n, p); - } - - // Conditional operations - @Override - public R visitConditionalAnd(ConditionalAndNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitConditionalOr(ConditionalOrNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitConditionalNot(ConditionalNotNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitTernaryExpression(TernaryExpressionNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitAssignment(AssignmentNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitLocalVariable(LocalVariableNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitVariableDeclaration(VariableDeclarationNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitFieldAccess(FieldAccessNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitMethodAccess(MethodAccessNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitArrayAccess(ArrayAccessNode n, P p) { - return visitNode(n, p); - } - - public R visitThisLiteral(ThisLiteralNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitImplicitThisLiteral(ImplicitThisLiteralNode n, P p) { - return visitThisLiteral(n, p); - } - - @Override - public R visitExplicitThisLiteral(ExplicitThisLiteralNode n, P p) { - return visitThisLiteral(n, p); - } - - @Override - public R visitSuper(SuperNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitReturn(ReturnNode n, P p) { - return visitNode(n, p); - }; - - @Override - public R visitStringConversion(StringConversionNode n, P p) { - return visitNode(n, p); - }; - - @Override - public R visitNarrowingConversion(NarrowingConversionNode n, P p) { - return visitNode(n, p); - }; - - @Override - public R visitWideningConversion(WideningConversionNode n, P p) { - return visitNode(n, p); - }; - - @Override - public R visitInstanceOf(InstanceOfNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitTypeCast(TypeCastNode n, P p) { - return visitNode(n, p); - } - - // Statements - @Override - public R visitAssertionError(AssertionErrorNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitSynchronized(SynchronizedNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitThrow(ThrowNode n, P p) { - return visitNode(n, p); - } - - // Cases - @Override - public R visitCase(CaseNode n, P p) { - return visitNode(n, p); - } - - // Method and constructor invocations - @Override - public R visitMethodInvocation(MethodInvocationNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitObjectCreation(ObjectCreationNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitMemberReference(FunctionalInterfaceNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitArrayCreation(ArrayCreationNode n, P p) { - return visitNode(n, p); - } - - // Type, package and class names - @Override - public R visitArrayType(ArrayTypeNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitPrimitiveType(PrimitiveTypeNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitClassName(ClassNameNode n, P p) { - return visitNode(n, p); - } - - @Override - public R visitPackageName(PackageNameNode n, P p) { - return visitNode(n, p); - } - - // Parameterized types - @Override - public R visitParameterizedType(ParameterizedTypeNode n, P p) { - return visitNode(n, p); - } - - // Marker nodes - @Override - public R visitMarker(MarkerNode n, P p) { - return visitNode(n, p); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayAccessNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayAccessNode.java deleted file mode 100644 index 24ef689ee9..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayAccessNode.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.ArrayAccessTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.LinkedList; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for an array access: - * - *

- *   arrayref [ index ]
- * 
- * - * We allow array accesses without corresponding AST {@link Tree}s. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ArrayAccessNode extends Node { - - protected Tree tree; - protected Node array; - protected Node index; - - public ArrayAccessNode(Tree t, Node array, Node index) { - super(InternalUtils.typeOf(t)); - assert t instanceof ArrayAccessTree; - this.tree = t; - this.array = array; - this.index = index; - } - - public Node getArray() { - return array; - } - - public Node getIndex() { - return index; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitArrayAccess(this, p); - } - - @Override - public String toString() { - String base = getArray().toString() + "[" + getIndex().toString() + "]"; - return base; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ArrayAccessNode)) { - return false; - } - ArrayAccessNode other = (ArrayAccessNode) obj; - return getArray().equals(other.getArray()) && getIndex().equals(other.getIndex()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getArray(), getIndex()); - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.add(getArray()); - list.add(getIndex()); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayCreationNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayCreationNode.java deleted file mode 100644 index 5f277f2a0b..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayCreationNode.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.NewArrayTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for new array creation - * - *
- *   new type [1][2]
- *   new type [] = { expr1, expr2, ... }
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ArrayCreationNode extends Node { - - /** The tree is null when an array is created for variable arity method calls. */ - protected /*@Nullable*/ NewArrayTree tree; - /** - * The length of this list is the number of dimensions in the array. Each element is the size of - * the given dimension. - */ - protected List dimensions; - - protected List initializers; - - public ArrayCreationNode( - /*@Nullable*/ NewArrayTree tree, - TypeMirror type, - List dimensions, - List initializers) { - super(type); - this.tree = tree; - this.dimensions = dimensions; - this.initializers = initializers; - } - - public List getDimensions() { - return dimensions; - } - - public Node getDimension(int i) { - return dimensions.get(i); - } - - public List getInitializers() { - return initializers; - } - - public Node getInitializer(int i) { - return initializers.get(i); - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitArrayCreation(this, p); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("new " + type); - if (!dimensions.isEmpty()) { - boolean needComma = false; - sb.append(" ("); - for (Node dim : dimensions) { - if (needComma) { - sb.append(", "); - } - sb.append(dim); - needComma = true; - } - sb.append(")"); - } - if (!initializers.isEmpty()) { - boolean needComma = false; - sb.append(" = {"); - for (Node init : initializers) { - if (needComma) { - sb.append(", "); - } - sb.append(init); - needComma = true; - } - sb.append("}"); - } - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ArrayCreationNode)) { - return false; - } - ArrayCreationNode other = (ArrayCreationNode) obj; - - return getDimensions().equals(other.getDimensions()) - && getInitializers().equals(other.getInitializers()); - } - - @Override - public int hashCode() { - int hash = 0; - for (Node dim : dimensions) { - hash = HashCodeUtils.hash(hash, dim.hashCode()); - } - for (Node init : initializers) { - hash = HashCodeUtils.hash(hash, init.hashCode()); - } - return hash; - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.addAll(dimensions); - list.addAll(initializers); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayTypeNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayTypeNode.java deleted file mode 100644 index dfde575b5e..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ArrayTypeNode.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.ArrayTypeTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node representing a array type used in an expression such as a field access - * - *

type .class - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ArrayTypeNode extends Node { - - protected final ArrayTypeTree tree; - - public ArrayTypeNode(ArrayTypeTree tree) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitArrayType(this, p); - } - - @Override - public String toString() { - return tree.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ArrayTypeNode)) { - return false; - } - ArrayTypeNode other = (ArrayTypeNode) obj; - return getType().equals(other.getType()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getType()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssertionErrorNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssertionErrorNode.java deleted file mode 100644 index 0b4d747331..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssertionErrorNode.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree; -import com.sun.source.tree.Tree.Kind; -import java.util.Collection; -import java.util.LinkedList; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the {@link AssertionError} when an assertion fails. - * - *

- *   assert condition : detail ;
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class AssertionErrorNode extends Node { - - protected Tree tree; - protected Node condition; - protected Node detail; - - public AssertionErrorNode(Tree tree, Node condition, Node detail, TypeMirror type) { - // TODO: Find out the correct "type" for statements. - // Is it TypeKind.NONE? - super(type); - assert tree.getKind() == Kind.ASSERT; - this.tree = tree; - this.condition = condition; - this.detail = detail; - } - - public Node getCondition() { - return condition; - } - - public Node getDetail() { - return detail; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitAssertionError(this, p); - } - - @Override - public String toString() { - return "AssertionError(" + getDetail() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof AssertionErrorNode)) { - return false; - } - AssertionErrorNode other = (AssertionErrorNode) obj; - return getCondition().equals(other.getCondition()) && getDetail().equals(other.getDetail()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getCondition(), getDetail()); - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.add(getCondition()); - list.add(getDetail()); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssignmentContext.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssignmentContext.java deleted file mode 100644 index 5e6a1606de..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssignmentContext.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.ExpressionTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.VariableTree; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import org.checkerframework.javacutil.TreeUtils; - -/** - * An assignment context for a node, which represents the place to which the node with this context - * is 'assigned' to. An 'assignment' (as we use the term here) can occur for Java assignments, - * method calls (for all the actual parameters which get assigned to their formal parameters) or - * method return statements. - * - *

The main use of {@link AssignmentContext} is to be able to get the declared type of the - * left-hand side of the assignment for proper type-refinement. - * - * @author Stefan Heule - */ -public abstract class AssignmentContext { - - /** An assignment context for an assignment 'lhs = rhs'. */ - public static class AssignmentLhsContext extends AssignmentContext { - - protected final Node node; - - public AssignmentLhsContext(Node node) { - this.node = node; - } - - @Override - public Element getElementForType() { - Tree tree = node.getTree(); - if (tree == null) { - return null; - } else if (tree instanceof ExpressionTree) { - return TreeUtils.elementFromUse((ExpressionTree) tree); - } else if (tree instanceof VariableTree) { - return TreeUtils.elementFromDeclaration((VariableTree) tree); - } else { - assert false : "unexpected tree"; - return null; - } - } - - @Override - public Tree getContextTree() { - return node.getTree(); - } - } - - /** An assignment context for a method parameter. */ - public static class MethodParameterContext extends AssignmentContext { - - protected final ExecutableElement method; - protected final int paramNum; - - public MethodParameterContext(ExecutableElement method, int paramNum) { - this.method = method; - this.paramNum = paramNum; - } - - @Override - public Element getElementForType() { - return method.getParameters().get(paramNum); - } - - @Override - public Tree getContextTree() { - // TODO: what is the right assignment context? We might not have - // a tree for the invoked method. - return null; - } - } - - /** An assignment context for method return statements. */ - public static class MethodReturnContext extends AssignmentContext { - - protected final ExecutableElement method; - protected final Tree ret; - - public MethodReturnContext(MethodTree method) { - this.method = TreeUtils.elementFromDeclaration(method); - this.ret = method.getReturnType(); - } - - @Override - public Element getElementForType() { - return method; - } - - @Override - public Tree getContextTree() { - return ret; - } - } - - /** An assignment context for lambda return statements. */ - public static class LambdaReturnContext extends AssignmentContext { - - protected final ExecutableElement method; - - public LambdaReturnContext(ExecutableElement method) { - this.method = method; - } - - @Override - public Element getElementForType() { - return method; - } - - @Override - public Tree getContextTree() { - // TODO: what is the right assignment context? We might not have - // a tree for the invoked method. - return null; - } - } - - /** Returns an {@link Element} that has the type of this assignment context. */ - public abstract Element getElementForType(); - - public abstract Tree getContextTree(); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssignmentNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssignmentNode.java deleted file mode 100644 index 32723dd8e4..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/AssignmentNode.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.AssignmentTree; -import com.sun.source.tree.CompoundAssignmentTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.UnaryTree; -import com.sun.source.tree.VariableTree; -import java.util.Collection; -import java.util.LinkedList; -import org.checkerframework.dataflow.cfg.node.AssignmentContext.AssignmentLhsContext; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for an assignment: - * - *

- *   variable = expression
- *   expression . field = expression
- *   expression [ index ] = expression
- * 
- * - * We allow assignments without corresponding AST {@link Tree}s. - * - * @author Stefan Heule - */ -public class AssignmentNode extends Node { - - protected Tree tree; - protected Node lhs; - protected Node rhs; - - public AssignmentNode(Tree tree, Node target, Node expression) { - super(InternalUtils.typeOf(tree)); - assert tree instanceof AssignmentTree - || tree instanceof VariableTree - || tree instanceof CompoundAssignmentTree - || tree instanceof UnaryTree; - assert target instanceof FieldAccessNode - || target instanceof LocalVariableNode - || target instanceof ArrayAccessNode; - this.tree = tree; - this.lhs = target; - this.rhs = expression; - rhs.setAssignmentContext(new AssignmentLhsContext(lhs)); - } - - public Node getTarget() { - return lhs; - } - - public Node getExpression() { - return rhs; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitAssignment(this, p); - } - - @Override - public String toString() { - return getTarget() + " = " + getExpression(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof AssignmentNode)) { - return false; - } - AssignmentNode other = (AssignmentNode) obj; - return getTarget().equals(other.getTarget()) - && getExpression().equals(other.getExpression()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getTarget(), getExpression()); - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.add(getTarget()); - list.add(getExpression()); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BinaryOperationNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BinaryOperationNode.java deleted file mode 100644 index 424747b4ac..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BinaryOperationNode.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import java.util.Collection; -import java.util.LinkedList; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for a binary expression. - * - *

For example: - * - *

- *   lefOperandNode operator rightOperandNode
- * 
- * - * @author charleszhuochen - */ -public abstract class BinaryOperationNode extends Node { - - protected final BinaryTree tree; - protected final Node left; - protected final Node right; - - public BinaryOperationNode(BinaryTree tree, Node left, Node right) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - this.left = left; - this.right = right; - } - - public Node getLeftOperand() { - return left; - } - - public Node getRightOperand() { - return right; - } - - @Override - public BinaryTree getTree() { - return tree; - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.add(getLeftOperand()); - list.add(getRightOperand()); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseAndNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseAndNode.java deleted file mode 100644 index 18d7163f22..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseAndNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the bitwise or logical (single bit) and operation: - * - *
- *   expression & expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class BitwiseAndNode extends BinaryOperationNode { - - public BitwiseAndNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.AND; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitBitwiseAnd(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " & " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof BitwiseAndNode)) { - return false; - } - BitwiseAndNode other = (BitwiseAndNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseComplementNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseComplementNode.java deleted file mode 100644 index a1c2111b8c..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseComplementNode.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree.Kind; -import com.sun.source.tree.UnaryTree; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the bitwise complement operation: - * - *
- *   ~ expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class BitwiseComplementNode extends UnaryOperationNode { - - public BitwiseComplementNode(UnaryTree tree, Node operand) { - super(tree, operand); - assert tree.getKind() == Kind.BITWISE_COMPLEMENT; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitBitwiseComplement(this, p); - } - - @Override - public String toString() { - return "(~ " + getOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof BitwiseComplementNode)) { - return false; - } - BitwiseComplementNode other = (BitwiseComplementNode) obj; - return getOperand().equals(other.getOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseOrNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseOrNode.java deleted file mode 100644 index 66089133f2..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseOrNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the bitwise or logical (single bit) or operation: - * - *
- *   expression | expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class BitwiseOrNode extends BinaryOperationNode { - - public BitwiseOrNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.OR; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitBitwiseOr(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " | " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof BitwiseOrNode)) { - return false; - } - BitwiseOrNode other = (BitwiseOrNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseXorNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseXorNode.java deleted file mode 100644 index cdbe0ed93d..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BitwiseXorNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the bitwise or logical (single bit) xor operation: - * - *
- *   expression ^ expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class BitwiseXorNode extends BinaryOperationNode { - - public BitwiseXorNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.XOR; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitBitwiseXor(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " ^ " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof BitwiseXorNode)) { - return false; - } - BitwiseXorNode other = (BitwiseXorNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BooleanLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BooleanLiteralNode.java deleted file mode 100644 index 7f5a7a1eda..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/BooleanLiteralNode.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for a boolean literal: - * - *
- *   true
- *   false
- * 
- * - * @author Stefan Heule - */ -public class BooleanLiteralNode extends ValueLiteralNode { - - public BooleanLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.BOOLEAN_LITERAL); - } - - @Override - public Boolean getValue() { - return (Boolean) tree.getValue(); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitBooleanLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a BooleanLiteralNode - if (!(obj instanceof BooleanLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/CaseNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/CaseNode.java deleted file mode 100644 index a694dfb975..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/CaseNode.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.CaseTree; -import com.sun.source.tree.Tree.Kind; -import java.util.Collection; -import java.util.LinkedList; -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.Types; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for a case in a switch statement. Although a case has no abstract value, it can imply - * facts about the abstract values of its operands. - * - *
- *   case constant:
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class CaseNode extends Node { - - protected CaseTree tree; - protected Node switchExpr; - protected Node caseExpr; - - public CaseNode(CaseTree tree, Node switchExpr, Node caseExpr, Types types) { - super(types.getNoType(TypeKind.NONE)); - assert tree.getKind().equals(Kind.CASE); - this.tree = tree; - this.switchExpr = switchExpr; - this.caseExpr = caseExpr; - } - - public Node getSwitchOperand() { - return switchExpr; - } - - public Node getCaseOperand() { - return caseExpr; - } - - @Override - public CaseTree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitCase(this, p); - } - - @Override - public String toString() { - return "case " + getCaseOperand() + ":"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof CaseNode)) { - return false; - } - CaseNode other = (CaseNode) obj; - return getSwitchOperand().equals(other.getSwitchOperand()) - && getCaseOperand().equals(other.getCaseOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getSwitchOperand(), getCaseOperand()); - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.add(getSwitchOperand()); - list.add(getCaseOperand()); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/CharacterLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/CharacterLiteralNode.java deleted file mode 100644 index c1d51c7523..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/CharacterLiteralNode.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for a character literal. For example: - * - *
- *   'a'
- *   '\t'
- *   '\u03a9'
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class CharacterLiteralNode extends ValueLiteralNode { - - public CharacterLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.CHAR_LITERAL); - } - - @Override - public Character getValue() { - return (Character) tree.getValue(); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitCharacterLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a CharacterLiteralNode - if (obj == null || !(obj instanceof CharacterLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ClassNameNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ClassNameNode.java deleted file mode 100644 index c3e2471309..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ClassNameNode.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.MemberSelectTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.element.Element; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; -import org.checkerframework.javacutil.TreeUtils; - -/** - * A node representing a class name used in an expression such as a static method invocation. - * - *

parent.class .forName(...) - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ClassNameNode extends Node { - - protected final Tree tree; - /** The class named by this node */ - protected final Element element; - - /** The parent name, if any. */ - protected final /*@Nullable*/ Node parent; - - public ClassNameNode(IdentifierTree tree) { - super(InternalUtils.typeOf(tree)); - assert tree.getKind() == Tree.Kind.IDENTIFIER; - this.tree = tree; - this.element = TreeUtils.elementFromUse(tree); - this.parent = null; - } - - public ClassNameNode(ClassTree tree) { - super(InternalUtils.typeOf(tree)); - assert tree.getKind() == Tree.Kind.CLASS - || tree.getKind() == Tree.Kind.ENUM - || tree.getKind() == Tree.Kind.INTERFACE - || tree.getKind() == Tree.Kind.ANNOTATION_TYPE; - this.tree = tree; - this.element = TreeUtils.elementFromDeclaration(tree); - this.parent = null; - } - - public ClassNameNode(MemberSelectTree tree, Node parent) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - this.element = TreeUtils.elementFromUse(tree); - this.parent = parent; - } - - public ClassNameNode(TypeMirror type, Element element) { - super(type); - this.tree = null; - this.element = element; - this.parent = null; - } - - public Element getElement() { - return element; - } - - public Node getParent() { - return parent; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitClassName(this, p); - } - - @Override - public String toString() { - return getElement().getSimpleName().toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ClassNameNode)) { - return false; - } - ClassNameNode other = (ClassNameNode) obj; - if (getParent() == null) { - return other.getParent() == null && getElement().equals(other.getElement()); - } else { - return getParent().equals(other.getParent()) && getElement().equals(other.getElement()); - } - } - - @Override - public int hashCode() { - if (parent == null) { - return HashCodeUtils.hash(getElement()); - } - return HashCodeUtils.hash(getElement(), getParent()); - } - - @Override - public Collection getOperands() { - if (parent == null) { - return Collections.emptyList(); - } - return Collections.singleton(parent); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalAndNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalAndNode.java deleted file mode 100644 index fb5145ab89..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalAndNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for a conditional and expression: - * - *

- *   expression && expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ConditionalAndNode extends BinaryOperationNode { - - public ConditionalAndNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind().equals(Kind.CONDITIONAL_AND); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitConditionalAnd(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " && " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ConditionalAndNode)) { - return false; - } - ConditionalAndNode other = (ConditionalAndNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalNotNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalNotNode.java deleted file mode 100644 index 6a28c67a16..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalNotNode.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree.Kind; -import com.sun.source.tree.UnaryTree; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for a conditional not expression: - * - *
- *   ! expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ConditionalNotNode extends UnaryOperationNode { - - public ConditionalNotNode(UnaryTree tree, Node operand) { - super(tree, operand); - assert tree.getKind().equals(Kind.LOGICAL_COMPLEMENT); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitConditionalNot(this, p); - } - - @Override - public String toString() { - return "(!" + getOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ConditionalNotNode)) { - return false; - } - ConditionalNotNode other = (ConditionalNotNode) obj; - return getOperand().equals(other.getOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalOrNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalOrNode.java deleted file mode 100644 index e5cb0bfc13..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ConditionalOrNode.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for a conditional or expression: - * - *
- *   expression || expression
- * 
- * - * @author Stefan Heule - */ -public class ConditionalOrNode extends BinaryOperationNode { - - public ConditionalOrNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind().equals(Kind.CONDITIONAL_OR); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitConditionalOr(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " || " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ConditionalOrNode)) { - return false; - } - ConditionalOrNode other = (ConditionalOrNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/DoubleLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/DoubleLiteralNode.java deleted file mode 100644 index 60c25749a4..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/DoubleLiteralNode.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for a double literal. For example: - * - *
- *   -9.
- *   3.14159D
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class DoubleLiteralNode extends ValueLiteralNode { - - public DoubleLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.DOUBLE_LITERAL); - } - - @Override - public Double getValue() { - return (Double) tree.getValue(); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitDoubleLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a DoubleLiteralNode - if (obj == null || !(obj instanceof DoubleLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/EqualToNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/EqualToNode.java deleted file mode 100644 index b1fb5d8f68..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/EqualToNode.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for an equality check: - * - *
- *   expression == expression
- * 
- * - * @author Stefan Heule - */ -public class EqualToNode extends BinaryOperationNode { - - public EqualToNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind().equals(Kind.EQUAL_TO); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitEqualTo(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " == " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof EqualToNode)) { - return false; - } - EqualToNode other = (EqualToNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ExplicitThisLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ExplicitThisLiteralNode.java deleted file mode 100644 index abb3b5447e..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ExplicitThisLiteralNode.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.Tree; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for a reference to 'this'. - * - *
- *   this
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ExplicitThisLiteralNode extends ThisLiteralNode { - - protected Tree tree; - - public ExplicitThisLiteralNode(Tree t) { - super(InternalUtils.typeOf(t)); - assert t instanceof IdentifierTree && ((IdentifierTree) t).getName().contentEquals("this"); - tree = t; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitExplicitThisLiteral(this, p); - } - - @Override - public String toString() { - return getName(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FieldAccessNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FieldAccessNode.java deleted file mode 100644 index 1b8e856a17..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FieldAccessNode.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.MemberSelectTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.element.VariableElement; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.ElementUtils; -import org.checkerframework.javacutil.InternalUtils; -import org.checkerframework.javacutil.TreeUtils; - -/** - * A node for a field access, including a method accesses: - * - *
- *   expression . field
- * 
- * - * @author Stefan Heule - */ -public class FieldAccessNode extends Node { - - protected Tree tree; - protected VariableElement element; - protected String field; - protected Node receiver; - - // TODO: add method to get modifiers (static, access level, ..) - - public FieldAccessNode(Tree tree, Node receiver) { - super(InternalUtils.typeOf(tree)); - assert TreeUtils.isFieldAccess(tree); - this.tree = tree; - this.receiver = receiver; - this.field = TreeUtils.getFieldName(tree); - - if (tree instanceof MemberSelectTree) { - this.element = (VariableElement) TreeUtils.elementFromUse((MemberSelectTree) tree); - } else { - assert tree instanceof IdentifierTree; - this.element = (VariableElement) TreeUtils.elementFromUse((IdentifierTree) tree); - } - } - - public FieldAccessNode(Tree tree, VariableElement element, Node receiver) { - super(element.asType()); - this.tree = tree; - this.element = element; - this.receiver = receiver; - this.field = element.getSimpleName().toString(); - } - - public VariableElement getElement() { - return element; - } - - public Node getReceiver() { - return receiver; - } - - public String getFieldName() { - return field; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitFieldAccess(this, p); - } - - @Override - public String toString() { - return getReceiver() + "." + field; - } - - /** Is this a static field? */ - public boolean isStatic() { - return ElementUtils.isStatic(getElement()); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof FieldAccessNode)) { - return false; - } - FieldAccessNode other = (FieldAccessNode) obj; - return getReceiver().equals(other.getReceiver()) - && getFieldName().equals(other.getFieldName()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getReceiver(), getFieldName()); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(receiver); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatLiteralNode.java deleted file mode 100644 index ee8b5103ed..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatLiteralNode.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for a float literal. For example: - * - *
- *   8.0f
- *   6.022137e+23F
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class FloatLiteralNode extends ValueLiteralNode { - - public FloatLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.FLOAT_LITERAL); - } - - @Override - public Float getValue() { - return (Float) tree.getValue(); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitFloatLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a FloatLiteralNode - if (obj == null || !(obj instanceof FloatLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatingDivisionNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatingDivisionNode.java deleted file mode 100644 index 6eb6c41ac4..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatingDivisionNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the floating-point division: - * - *
- *   expression / expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class FloatingDivisionNode extends BinaryOperationNode { - - public FloatingDivisionNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.DIVIDE; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitFloatingDivision(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " / " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof FloatingDivisionNode)) { - return false; - } - FloatingDivisionNode other = (FloatingDivisionNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatingRemainderNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatingRemainderNode.java deleted file mode 100644 index d3a7918ff1..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FloatingRemainderNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the floating-point remainder: - * - *
- *   expression % expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class FloatingRemainderNode extends BinaryOperationNode { - - public FloatingRemainderNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.REMAINDER; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitFloatingRemainder(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " % " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof FloatingRemainderNode)) { - return false; - } - FloatingRemainderNode other = (FloatingRemainderNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FunctionalInterfaceNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FunctionalInterfaceNode.java deleted file mode 100644 index a0ddbaf10c..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/FunctionalInterfaceNode.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LambdaExpressionTree; -import com.sun.source.tree.MemberReferenceTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.LinkedList; -import org.checkerframework.javacutil.ErrorReporter; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for member references and lambdas. - * - *

The {@link Node#type} of a FunctionalInterfaceNode is determined by the assignment context the - * member reference or lambda is used in. - * - *

- *   FunctionalInterface func = param1, param2, ... → statement
- * 
- * - *
- *   FunctionalInterface func = param1, param2, ... → { ... }
- * 
- * - *
- *   FunctionalInterface func = member reference
- * 
- * - * @author David - */ -public class FunctionalInterfaceNode extends Node { - - protected Tree tree; - - public FunctionalInterfaceNode(MemberReferenceTree tree) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - } - - public FunctionalInterfaceNode(LambdaExpressionTree tree) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitMemberReference(this, p); - } - - @Override - public String toString() { - if (tree instanceof LambdaExpressionTree) { - return "FunctionalInterfaceNode:" + ((LambdaExpressionTree) tree).getBodyKind(); - } else if (tree instanceof MemberReferenceTree) { - return "FunctionalInterfaceNode:" + ((MemberReferenceTree) tree).getName(); - } else { - // This should never happen. - ErrorReporter.errorAbort("Invalid tree in FunctionalInterfaceNode"); - return null; // Dead code - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - FunctionalInterfaceNode that = (FunctionalInterfaceNode) o; - - if (tree != null ? !tree.equals(that.tree) : that.tree != null) return false; - - return true; - } - - @Override - public int hashCode() { - return tree != null ? tree.hashCode() : 0; - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/GreaterThanNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/GreaterThanNode.java deleted file mode 100644 index f1713a9241..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/GreaterThanNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the greater than comparison: - * - *
- *   expression > expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class GreaterThanNode extends BinaryOperationNode { - - public GreaterThanNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.GREATER_THAN; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitGreaterThan(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " > " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof GreaterThanNode)) { - return false; - } - GreaterThanNode other = (GreaterThanNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/GreaterThanOrEqualNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/GreaterThanOrEqualNode.java deleted file mode 100644 index 058ae7be84..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/GreaterThanOrEqualNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the greater than or equal comparison: - * - *
- *   expression >= expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class GreaterThanOrEqualNode extends BinaryOperationNode { - - public GreaterThanOrEqualNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.GREATER_THAN_EQUAL; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitGreaterThanOrEqual(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " >= " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof GreaterThanOrEqualNode)) { - return false; - } - GreaterThanOrEqualNode other = (GreaterThanOrEqualNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ImplicitThisLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ImplicitThisLiteralNode.java deleted file mode 100644 index 25a63617ad..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ImplicitThisLiteralNode.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree; -import javax.lang.model.type.TypeMirror; - -/** - * A node to model the implicit {@code this}, e.g., in a field access. - * - * @author Stefan Heule - */ -public class ImplicitThisLiteralNode extends ThisLiteralNode { - - public ImplicitThisLiteralNode(TypeMirror type) { - super(type); - } - - @Override - public Tree getTree() { - return null; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitImplicitThisLiteral(this, p); - } - - @Override - public String toString() { - return "(" + getName() + ")"; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/InstanceOfNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/InstanceOfNode.java deleted file mode 100644 index 78b4e06916..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/InstanceOfNode.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.InstanceOfTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Types; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the instanceof operator: - * - *

x instanceof Point - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class InstanceOfNode extends Node { - - /** The value being tested. */ - protected Node operand; - - /** The reference type being tested against. */ - protected TypeMirror refType; - - /** The tree associated with this node. */ - protected final InstanceOfTree tree; - - public InstanceOfNode(Tree tree, Node operand, TypeMirror refType, Types types) { - super(types.getPrimitiveType(TypeKind.BOOLEAN)); - assert tree.getKind() == Tree.Kind.INSTANCE_OF; - this.tree = (InstanceOfTree) tree; - this.operand = operand; - this.refType = refType; - } - - public Node getOperand() { - return operand; - } - - @Override - public TypeMirror getType() { - return type; - } - - public TypeMirror getRefType() { - return refType; - } - - @Override - public InstanceOfTree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitInstanceOf(this, p); - } - - @Override - public String toString() { - return "(" + getOperand() + " instanceof " + getRefType() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof InstanceOfNode)) { - return false; - } - InstanceOfNode other = (InstanceOfNode) obj; - // TODO: TypeMirror.equals may be too restrictive. - // Check whether Types.isSameType is the better comparison. - return getOperand().equals(other.getOperand()) && getRefType().equals(other.getRefType()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerDivisionNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerDivisionNode.java deleted file mode 100644 index e69947bea5..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerDivisionNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the integer division: - * - *

- *   expression / expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class IntegerDivisionNode extends BinaryOperationNode { - - public IntegerDivisionNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.DIVIDE; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitIntegerDivision(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " / " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof IntegerDivisionNode)) { - return false; - } - IntegerDivisionNode other = (IntegerDivisionNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerLiteralNode.java deleted file mode 100644 index 5bea779369..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerLiteralNode.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for an integer literal. For example: - * - *
- *   42
- * 
- * - * @author Stefan Heule - */ -public class IntegerLiteralNode extends ValueLiteralNode { - - int value; - - public IntegerLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.INT_LITERAL); - value = (Integer) tree.getValue(); - } - - @Override - public Integer getValue() { - return value; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitIntegerLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a IntegerLiteralNode - if (!(obj instanceof IntegerLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerRemainderNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerRemainderNode.java deleted file mode 100644 index d5399183a7..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/IntegerRemainderNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the integer remainder: - * - *
- *   expression % expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class IntegerRemainderNode extends BinaryOperationNode { - - public IntegerRemainderNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.REMAINDER; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitIntegerRemainder(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " % " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof IntegerRemainderNode)) { - return false; - } - IntegerRemainderNode other = (IntegerRemainderNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LeftShiftNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LeftShiftNode.java deleted file mode 100644 index 65a1e13d3c..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LeftShiftNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for bitwise left shift operations: - * - *
- *   expression << expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class LeftShiftNode extends BinaryOperationNode { - - public LeftShiftNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.LEFT_SHIFT; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitLeftShift(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " << " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof LeftShiftNode)) { - return false; - } - LeftShiftNode other = (LeftShiftNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LessThanNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LessThanNode.java deleted file mode 100644 index fcc901150a..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LessThanNode.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the less than comparison: - * - *
- *   expression < expression
- * 
- * - * We allow less than nodes without corresponding AST {@link Tree}s. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class LessThanNode extends BinaryOperationNode { - - public LessThanNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.LESS_THAN; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitLessThan(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " < " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof LessThanNode)) { - return false; - } - LessThanNode other = (LessThanNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LessThanOrEqualNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LessThanOrEqualNode.java deleted file mode 100644 index 0dfb65ec41..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LessThanOrEqualNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the less than or equal comparison: - * - *
- *   expression <= expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class LessThanOrEqualNode extends BinaryOperationNode { - - public LessThanOrEqualNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.LESS_THAN_EQUAL; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitLessThanOrEqual(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " <= " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof LessThanOrEqualNode)) { - return false; - } - LessThanOrEqualNode other = (LessThanOrEqualNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LocalVariableNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LocalVariableNode.java deleted file mode 100644 index 724d63a46b..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LocalVariableNode.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.VariableTree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.element.Element; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; -import org.checkerframework.javacutil.TreeUtils; - -/** - * A node for a local variable or a parameter: - * - *
- *   identifier
- * 
- * - * We allow local variable uses introduced by the {@link - * org.checkerframework.dataflow.cfg.CFGBuilder} without corresponding AST {@link Tree}s. - * - * @author Stefan Heule - */ -// TODO: don't use for parameters, as they don't have a tree -public class LocalVariableNode extends Node { - - protected Tree tree; - protected Node receiver; - - public LocalVariableNode(Tree t) { - super(InternalUtils.typeOf(t)); - // IdentifierTree for normal uses of the local variable or parameter, - // and VariableTree for the translation of an initializer block - assert t != null; - assert t instanceof IdentifierTree || t instanceof VariableTree; - tree = t; - this.receiver = null; - } - - public LocalVariableNode(Tree t, Node receiver) { - this(t); - this.receiver = receiver; - } - - public Element getElement() { - Element el; - if (tree instanceof IdentifierTree) { - el = TreeUtils.elementFromUse((IdentifierTree) tree); - } else { - assert tree instanceof VariableTree; - el = TreeUtils.elementFromDeclaration((VariableTree) tree); - } - return el; - } - - public Node getReceiver() { - return receiver; - } - - public String getName() { - if (tree instanceof IdentifierTree) { - return ((IdentifierTree) tree).getName().toString(); - } - return ((VariableTree) tree).getName().toString(); - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitLocalVariable(this, p); - } - - @Override - public String toString() { - return getName().toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof LocalVariableNode)) { - return false; - } - LocalVariableNode other = (LocalVariableNode) obj; - return getName().equals(other.getName()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getName()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LongLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LongLiteralNode.java deleted file mode 100644 index b92575ef90..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/LongLiteralNode.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for a long literal. For example: - * - *
- *   -3l
- *   0x80808080L
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class LongLiteralNode extends ValueLiteralNode { - - public LongLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.LONG_LITERAL); - } - - @Override - public Long getValue() { - return (Long) tree.getValue(); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitLongLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a LongLiteralNode - if (obj == null || !(obj instanceof LongLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MarkerNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MarkerNode.java deleted file mode 100644 index a7a892f3be..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MarkerNode.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.Types; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * MarkerNodes are no-op Nodes used for debugging information. They can hold a Tree and a message, - * which will be part of the String representation of the MarkerNode. - * - *

An example use case for MarkerNodes is representing switch statements. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class MarkerNode extends Node { - - protected /*@Nullable*/ Tree tree; - protected String message; - - public MarkerNode(/*@Nullable*/ Tree tree, String message, Types types) { - super(types.getNoType(TypeKind.NONE)); - this.tree = tree; - this.message = message; - } - - public String getMessage() { - return message; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitMarker(this, p); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("marker "); - sb.append("(" + message + ")"); - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof MarkerNode)) { - return false; - } - MarkerNode other = (MarkerNode) obj; - if (tree == null && other.getTree() != null) { - return false; - } - - return getTree().equals(other.getTree()) && getMessage().equals(other.getMessage()); - } - - @Override - public int hashCode() { - int hash = 0; - if (tree != null) { - hash = HashCodeUtils.hash(tree); - } - return HashCodeUtils.hash(hash, getMessage()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MethodAccessNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MethodAccessNode.java deleted file mode 100644 index 060f17b62d..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MethodAccessNode.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.ExpressionTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.element.ExecutableElement; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; -import org.checkerframework.javacutil.TreeUtils; - -/** - * A node for a method access, including a method accesses: - * - *

- *   expression . method ()
- * 
- * - * @author Stefan Heule - */ -public class MethodAccessNode extends Node { - - protected ExpressionTree tree; - protected ExecutableElement method; - protected Node receiver; - - // TODO: add method to get modifiers (static, access level, ..) - - public MethodAccessNode(ExpressionTree tree, Node receiver) { - super(InternalUtils.typeOf(tree)); - assert TreeUtils.isMethodAccess(tree); - this.tree = tree; - this.method = (ExecutableElement) TreeUtils.elementFromUse(tree); - this.receiver = receiver; - } - - public ExecutableElement getMethod() { - return method; - } - - public Node getReceiver() { - return receiver; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitMethodAccess(this, p); - } - - @Override - public String toString() { - return getReceiver() + "." + method.getSimpleName(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof MethodAccessNode)) { - return false; - } - MethodAccessNode other = (MethodAccessNode) obj; - return getReceiver().equals(other.getReceiver()) && getMethod().equals(other.getMethod()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getReceiver(), getMethod()); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(receiver); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MethodInvocationNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MethodInvocationNode.java deleted file mode 100644 index 9456f37808..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/MethodInvocationNode.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.MethodInvocationTree; -import com.sun.source.tree.Tree; -import com.sun.source.util.TreePath; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import org.checkerframework.dataflow.cfg.node.AssignmentContext.MethodParameterContext; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for method invocation - * - *
- *   target(arg1, arg2, ...)
- * 
- * - * CFGs may contain {@link MethodInvocationNode}s that correspond to no AST {@link Tree}, in which - * case, the tree field will be null. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class MethodInvocationNode extends Node { - - protected MethodInvocationTree tree; - protected MethodAccessNode target; - protected List arguments; - protected TreePath treePath; - - public MethodInvocationNode( - MethodInvocationTree tree, - MethodAccessNode target, - List arguments, - TreePath treePath) { - super(tree != null ? InternalUtils.typeOf(tree) : target.getMethod().getReturnType()); - this.tree = tree; - this.target = target; - this.arguments = arguments; - this.treePath = treePath; - - // set assignment contexts for parameters - int i = 0; - for (Node arg : arguments) { - AssignmentContext ctx = new MethodParameterContext(target.getMethod(), i++); - arg.setAssignmentContext(ctx); - } - } - - public MethodInvocationNode(MethodAccessNode target, List arguments, TreePath treePath) { - this(null, target, arguments, treePath); - } - - public MethodAccessNode getTarget() { - return target; - } - - public List getArguments() { - return arguments; - } - - public Node getArgument(int i) { - return arguments.get(i); - } - - public TreePath getTreePath() { - return treePath; - } - - @Override - public MethodInvocationTree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitMethodInvocation(this, p); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(target); - sb.append("("); - boolean needComma = false; - for (Node arg : arguments) { - if (needComma) { - sb.append(", "); - } - sb.append(arg); - needComma = true; - } - sb.append(")"); - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof MethodInvocationNode)) { - return false; - } - MethodInvocationNode other = (MethodInvocationNode) obj; - - return getTarget().equals(other.getTarget()) && getArguments().equals(other.getArguments()); - } - - @Override - public int hashCode() { - int hash = 0; - hash = HashCodeUtils.hash(target); - for (Node arg : arguments) { - hash = HashCodeUtils.hash(hash, arg.hashCode()); - } - return hash; - } - - @Override - public Collection getOperands() { - List list = new LinkedList(); - list.add(target); - list.addAll(arguments); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NarrowingConversionNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NarrowingConversionNode.java deleted file mode 100644 index 79a47283eb..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NarrowingConversionNode.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.TypesUtils; - -/** - * A node for the narrowing primitive conversion operation. See JLS 5.1.3 for the definition of - * narrowing primitive conversion. - * - *

A {@link NarrowingConversionNode} does not correspond to any tree node in the parsed AST. It - * is introduced when a value of some primitive type appears in a context that requires a different - * primitive with more bits of precision. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class NarrowingConversionNode extends Node { - - protected Tree tree; - protected Node operand; - - public NarrowingConversionNode(Tree tree, Node operand, TypeMirror type) { - super(type); - assert TypesUtils.isPrimitive(type) : "non-primitive type in narrowing conversion"; - this.tree = tree; - this.operand = operand; - } - - public Node getOperand() { - return operand; - } - - @Override - public TypeMirror getType() { - return type; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNarrowingConversion(this, p); - } - - @Override - public String toString() { - return "NarrowingConversion(" + getOperand() + ", " + type + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof NarrowingConversionNode)) { - return false; - } - NarrowingConversionNode other = (NarrowingConversionNode) obj; - return getOperand().equals(other.getOperand()) - && TypesUtils.areSamePrimitiveTypes(getType(), other.getType()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/Node.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/Node.java deleted file mode 100644 index fb5bf5335d..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/Node.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.LinkedList; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.cfg.CFGBuilder; -import org.checkerframework.dataflow.cfg.block.Block; - -/** - * A node in the abstract representation used for Java code inside a basic block. - * - *

The following invariants hold: - * - *

- * block == null || block instanceof RegularBlock || block instanceof ExceptionBlock
- * block instanceof RegularBlock ⇒ block.getContents().contains(this)
- * block instanceof ExceptionBlock ⇒ block.getNode() == this
- * block == null ⇔ "This object represents a parameter of the method."
- * 
- * - *
- * type != null
- * tree != null ⇒ node.getType() == InternalUtils.typeOf(node.getTree())
- * 
- * - * @author Stefan Heule - */ -public abstract class Node { - - /** The basic block this node belongs to (see invariant about this field above). */ - protected /*@Nullable*/ Block block; - - /** Is this node an l-value? */ - protected boolean lvalue = false; - - /** The assignment context of this node. See {@link AssignmentContext}. */ - protected /*@Nullable*/ AssignmentContext assignmentContext; - - /** - * Does this node represent a tree that appears in the source code (true) or one that the CFG - * builder added while desugaring (false). - */ - protected boolean inSource = true; - - /** - * The type of this node. For {@link Node}s with {@link Tree}s, this type is the type of the - * {@link Tree}. Otherwise, it is the type is set by the {@link CFGBuilder}. - */ - protected final TypeMirror type; - - public Node(TypeMirror type) { - assert type != null; - this.type = type; - } - - /** - * @return the basic block this node belongs to (or {@code null} if it represents the parameter - * of a method). - */ - public /*@Nullable*/ Block getBlock() { - return block; - } - - /** Set the basic block this node belongs to. */ - public void setBlock(Block b) { - block = b; - } - - /** - * Returns the {@link Tree} in the abstract syntax tree, or {@code null} if no corresponding - * tree exists. For instance, this is the case for an {@link ImplicitThisLiteralNode}. - * - * @return the corresponding {@link Tree} or {@code null}. - */ - public abstract /*@Nullable*/ Tree getTree(); - - /** - * Returns a {@link TypeMirror} representing the type of a {@link Node} A {@link Node} will - * always have a type even when it has no {@link Tree}. - * - * @return a {@link TypeMirror} representing the type of this {@link Node} - */ - public TypeMirror getType() { - return type; - } - - /** - * Accept method of the visitor pattern - * - * @param result type of the operation - * @param

parameter type - * @param visitor the visitor to be applied to this node - * @param p the parameter for this operation - */ - public abstract R accept(NodeVisitor visitor, P p); - - public boolean isLValue() { - return lvalue; - } - - /** Make this node an l-value. */ - public void setLValue() { - lvalue = true; - } - - public boolean getInSource() { - return inSource; - } - - public void setInSource(boolean inSrc) { - inSource = inSrc; - } - - public AssignmentContext getAssignmentContext() { - return assignmentContext; - } - - public void setAssignmentContext(AssignmentContext assignmentContext) { - this.assignmentContext = assignmentContext; - } - - /** @return a collection containing all of the operand {@link Node}s of this {@link Node}. */ - public abstract Collection getOperands(); - - /** - * @return a collection containing all of the operand {@link Node}s of this {@link Node}, as - * well as (transitively) the operands of its operands - */ - public Collection getTransitiveOperands() { - LinkedList operands = new LinkedList<>(getOperands()); - LinkedList transitiveOperands = new LinkedList<>(); - while (!operands.isEmpty()) { - Node next = operands.removeFirst(); - operands.addAll(next.getOperands()); - transitiveOperands.add(next); - } - return transitiveOperands; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NodeVisitor.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NodeVisitor.java deleted file mode 100644 index 8a2f513924..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NodeVisitor.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/** - * A visitor for a {@link Node} tree. - * - * @author Stefan Heule - * @param return type of the visitor. Use {@link Void} if the visitor does not have a return - * value. - * @param

parameter type of the visitor. Use {@link Void} if the visitor does not have a - * parameter. - */ -public interface NodeVisitor { - // Literals - R visitShortLiteral(ShortLiteralNode n, P p); - - R visitIntegerLiteral(IntegerLiteralNode n, P p); - - R visitLongLiteral(LongLiteralNode n, P p); - - R visitFloatLiteral(FloatLiteralNode n, P p); - - R visitDoubleLiteral(DoubleLiteralNode n, P p); - - R visitBooleanLiteral(BooleanLiteralNode n, P p); - - R visitCharacterLiteral(CharacterLiteralNode n, P p); - - R visitStringLiteral(StringLiteralNode n, P p); - - R visitNullLiteral(NullLiteralNode n, P p); - - // Unary operations - R visitNumericalMinus(NumericalMinusNode n, P p); - - R visitNumericalPlus(NumericalPlusNode n, P p); - - R visitBitwiseComplement(BitwiseComplementNode n, P p); - - R visitNullChk(NullChkNode n, P p); - - // Binary operations - R visitStringConcatenate(StringConcatenateNode n, P p); - - R visitNumericalAddition(NumericalAdditionNode n, P p); - - R visitNumericalSubtraction(NumericalSubtractionNode n, P p); - - R visitNumericalMultiplication(NumericalMultiplicationNode n, P p); - - R visitIntegerDivision(IntegerDivisionNode n, P p); - - R visitFloatingDivision(FloatingDivisionNode n, P p); - - R visitIntegerRemainder(IntegerRemainderNode n, P p); - - R visitFloatingRemainder(FloatingRemainderNode n, P p); - - R visitLeftShift(LeftShiftNode n, P p); - - R visitSignedRightShift(SignedRightShiftNode n, P p); - - R visitUnsignedRightShift(UnsignedRightShiftNode n, P p); - - R visitBitwiseAnd(BitwiseAndNode n, P p); - - R visitBitwiseOr(BitwiseOrNode n, P p); - - R visitBitwiseXor(BitwiseXorNode n, P p); - - // Compound assignments - R visitStringConcatenateAssignment(StringConcatenateAssignmentNode n, P p); - - // Comparison operations - R visitLessThan(LessThanNode n, P p); - - R visitLessThanOrEqual(LessThanOrEqualNode n, P p); - - R visitGreaterThan(GreaterThanNode n, P p); - - R visitGreaterThanOrEqual(GreaterThanOrEqualNode n, P p); - - R visitEqualTo(EqualToNode n, P p); - - R visitNotEqual(NotEqualNode n, P p); - - // Conditional operations - R visitConditionalAnd(ConditionalAndNode n, P p); - - R visitConditionalOr(ConditionalOrNode n, P p); - - R visitConditionalNot(ConditionalNotNode n, P p); - - R visitTernaryExpression(TernaryExpressionNode n, P p); - - R visitAssignment(AssignmentNode n, P p); - - R visitLocalVariable(LocalVariableNode n, P p); - - R visitVariableDeclaration(VariableDeclarationNode n, P p); - - R visitFieldAccess(FieldAccessNode n, P p); - - R visitMethodAccess(MethodAccessNode n, P p); - - R visitArrayAccess(ArrayAccessNode n, P p); - - R visitImplicitThisLiteral(ImplicitThisLiteralNode n, P p); - - R visitExplicitThisLiteral(ExplicitThisLiteralNode n, P p); - - R visitSuper(SuperNode n, P p); - - R visitReturn(ReturnNode n, P p); - - R visitStringConversion(StringConversionNode n, P p); - - R visitNarrowingConversion(NarrowingConversionNode n, P p); - - R visitWideningConversion(WideningConversionNode n, P p); - - R visitInstanceOf(InstanceOfNode n, P p); - - R visitTypeCast(TypeCastNode n, P p); - - // Blocks - - R visitSynchronized(SynchronizedNode n, P p); - - // Statements - R visitAssertionError(AssertionErrorNode n, P p); - - R visitThrow(ThrowNode n, P p); - - // Cases - R visitCase(CaseNode n, P p); - - // Method and constructor invocations - R visitMethodInvocation(MethodInvocationNode n, P p); - - R visitObjectCreation(ObjectCreationNode n, P p); - - R visitMemberReference(FunctionalInterfaceNode n, P p); - - R visitArrayCreation(ArrayCreationNode n, P p); - - // Type, package and class names - R visitArrayType(ArrayTypeNode n, P p); - - R visitPrimitiveType(PrimitiveTypeNode n, P p); - - R visitClassName(ClassNameNode n, P p); - - R visitPackageName(PackageNameNode n, P p); - - // Parameterized types - R visitParameterizedType(ParameterizedTypeNode n, P p); - - // Marker nodes - R visitMarker(MarkerNode n, P p); -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NotEqualNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NotEqualNode.java deleted file mode 100644 index debd7cbaf0..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NotEqualNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the not equal comparison: - * - *

- *   expression != expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class NotEqualNode extends BinaryOperationNode { - - public NotEqualNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.NOT_EQUAL_TO; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNotEqual(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " != " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof NotEqualNode)) { - return false; - } - NotEqualNode other = (NotEqualNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NullChkNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NullChkNode.java deleted file mode 100644 index 6609a29b59..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NullChkNode.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree; -import com.sun.source.tree.Tree.Kind; -import java.util.Collection; -import java.util.Collections; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for the unary 'nullchk' operation (generated by the Java compiler): - * - *
- *   <*nullchk*>expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class NullChkNode extends Node { - - protected Tree tree; - protected Node operand; - - public NullChkNode(Tree tree, Node operand) { - super(InternalUtils.typeOf(tree)); - assert tree.getKind() == Kind.OTHER; - this.tree = tree; - this.operand = operand; - } - - public Node getOperand() { - return operand; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNullChk(this, p); - } - - @Override - public String toString() { - return "(+ " + getOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof NumericalPlusNode)) { - return false; - } - NumericalPlusNode other = (NumericalPlusNode) obj; - return getOperand().equals(other.getOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NullLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NullLiteralNode.java deleted file mode 100644 index 1fcdeb4825..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NullLiteralNode.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for the null literal. - * - *
- *   null
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class NullLiteralNode extends ValueLiteralNode { - - public NullLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.NULL_LITERAL); - } - - @Override - public Void getValue() { - return (Void) tree.getValue(); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNullLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a NullLiteralNode - if (obj == null || !(obj instanceof NullLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalAdditionNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalAdditionNode.java deleted file mode 100644 index 4692856dd8..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalAdditionNode.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the numerical addition: - * - *
- *   expression + expression
- * 
- * - * @author Stefan Heule - */ -public class NumericalAdditionNode extends BinaryOperationNode { - - public NumericalAdditionNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.PLUS || tree.getKind() == Kind.PLUS_ASSIGNMENT; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNumericalAddition(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " + " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof NumericalAdditionNode)) { - return false; - } - NumericalAdditionNode other = (NumericalAdditionNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalMinusNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalMinusNode.java deleted file mode 100644 index 141ab580e0..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalMinusNode.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree.Kind; -import com.sun.source.tree.UnaryTree; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the unary minus operation: - * - *
- *   - expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class NumericalMinusNode extends UnaryOperationNode { - - public NumericalMinusNode(UnaryTree tree, Node operand) { - super(tree, operand); - assert tree.getKind() == Kind.UNARY_MINUS; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNumericalMinus(this, p); - } - - @Override - public String toString() { - return "(- " + getOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof NumericalMinusNode)) { - return false; - } - NumericalMinusNode other = (NumericalMinusNode) obj; - return getOperand().equals(other.getOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalMultiplicationNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalMultiplicationNode.java deleted file mode 100644 index 85561a1a02..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalMultiplicationNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the numerical multiplication: - * - *
- *   expression * expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class NumericalMultiplicationNode extends BinaryOperationNode { - - public NumericalMultiplicationNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.MULTIPLY; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNumericalMultiplication(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " * " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof NumericalMultiplicationNode)) { - return false; - } - NumericalMultiplicationNode other = (NumericalMultiplicationNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalPlusNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalPlusNode.java deleted file mode 100644 index 21b5b584d2..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalPlusNode.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree.Kind; -import com.sun.source.tree.UnaryTree; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the unary plus operation: - * - *
- *   + expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class NumericalPlusNode extends UnaryOperationNode { - - public NumericalPlusNode(UnaryTree tree, Node operand) { - super(tree, operand); - assert tree.getKind() == Kind.UNARY_PLUS; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNumericalPlus(this, p); - } - - @Override - public String toString() { - return "(+ " + getOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof NumericalPlusNode)) { - return false; - } - NumericalPlusNode other = (NumericalPlusNode) obj; - return getOperand().equals(other.getOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalSubtractionNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalSubtractionNode.java deleted file mode 100644 index a962eadd78..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/NumericalSubtractionNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the numerical subtraction: - * - *
- *   expression - expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class NumericalSubtractionNode extends BinaryOperationNode { - - public NumericalSubtractionNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.MINUS; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitNumericalSubtraction(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " - " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof NumericalSubtractionNode)) { - return false; - } - NumericalSubtractionNode other = (NumericalSubtractionNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ObjectCreationNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ObjectCreationNode.java deleted file mode 100644 index 8ab862a2ef..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ObjectCreationNode.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.NewClassTree; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for new object creation - * - *
- *   new constructor(arg1, arg2, ...)
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ObjectCreationNode extends Node { - - protected NewClassTree tree; - protected Node constructor; - protected List arguments; - - public ObjectCreationNode(NewClassTree tree, Node constructor, List arguments) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - this.constructor = constructor; - this.arguments = arguments; - } - - public Node getConstructor() { - return constructor; - } - - public List getArguments() { - return arguments; - } - - public Node getArgument(int i) { - return arguments.get(i); - } - - @Override - public NewClassTree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitObjectCreation(this, p); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("new " + constructor + "("); - boolean needComma = false; - for (Node arg : arguments) { - if (needComma) { - sb.append(", "); - } - sb.append(arg); - needComma = true; - } - sb.append(")"); - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ObjectCreationNode)) { - return false; - } - ObjectCreationNode other = (ObjectCreationNode) obj; - if (constructor == null && other.getConstructor() != null) { - return false; - } - - return getConstructor().equals(other.getConstructor()) - && getArguments().equals(other.getArguments()); - } - - @Override - public int hashCode() { - int hash = HashCodeUtils.hash(constructor); - for (Node arg : arguments) { - hash = HashCodeUtils.hash(hash, arg.hashCode()); - } - return hash; - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.add(constructor); - list.addAll(arguments); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/PackageNameNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/PackageNameNode.java deleted file mode 100644 index 3c69b8252b..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/PackageNameNode.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.MemberSelectTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.element.Element; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; -import org.checkerframework.javacutil.TreeUtils; - -/** - * A node representing a package name used in an expression such as a constructor invocation - * - *

package.class.object(...) - * - *

parent.package.class.object(...) - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class PackageNameNode extends Node { - - protected final Tree tree; - /** The package named by this node */ - protected final Element element; - - /** The parent name, if any. */ - protected final /*@Nullable*/ PackageNameNode parent; - - public PackageNameNode(IdentifierTree tree) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - this.element = TreeUtils.elementFromUse(tree); - this.parent = null; - } - - public PackageNameNode(MemberSelectTree tree, PackageNameNode parent) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - this.element = TreeUtils.elementFromUse(tree); - this.parent = parent; - } - - public Element getElement() { - return element; - } - - public PackageNameNode getParent() { - return parent; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitPackageName(this, p); - } - - @Override - public String toString() { - return getElement().getSimpleName().toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof PackageNameNode)) { - return false; - } - PackageNameNode other = (PackageNameNode) obj; - if (getParent() == null) { - return other.getParent() == null && getElement().equals(other.getElement()); - } else { - return getParent().equals(other.getParent()) && getElement().equals(other.getElement()); - } - } - - @Override - public int hashCode() { - if (parent == null) { - return HashCodeUtils.hash(getElement()); - } - return HashCodeUtils.hash(getElement(), getParent()); - } - - @Override - public Collection getOperands() { - if (parent == null) { - return Collections.emptyList(); - } - return Collections.singleton((Node) parent); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ParameterizedTypeNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ParameterizedTypeNode.java deleted file mode 100644 index 774ac8b7c5..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ParameterizedTypeNode.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.ParameterizedTypeTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for a parameterized type occurring in an expression: - * - *

- *   type<arg1, arg2>
- * 
- * - * Parameterized types don't represent any computation to be done at runtime, so we might choose to - * represent them differently by modifying the {@link Node}s in which parameterized types can occur, - * such as {@link ObjectCreationNode}s. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ParameterizedTypeNode extends Node { - - protected Tree tree; - - public ParameterizedTypeNode(Tree t) { - super(InternalUtils.typeOf(t)); - assert t instanceof ParameterizedTypeTree; - tree = t; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitParameterizedType(this, p); - } - - @Override - public String toString() { - return getTree().toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ParameterizedTypeNode)) { - return false; - } - ParameterizedTypeNode other = (ParameterizedTypeNode) obj; - return getTree().equals(other.getTree()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getTree()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/PrimitiveTypeNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/PrimitiveTypeNode.java deleted file mode 100644 index 379bb92024..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/PrimitiveTypeNode.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.PrimitiveTypeTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node representing a primitive type used in an expression such as a field access - * - *

type .class - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class PrimitiveTypeNode extends Node { - - protected final PrimitiveTypeTree tree; - - public PrimitiveTypeNode(PrimitiveTypeTree tree) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitPrimitiveType(this, p); - } - - @Override - public String toString() { - return tree.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof PrimitiveTypeNode)) { - return false; - } - PrimitiveTypeNode other = (PrimitiveTypeNode) obj; - return getType().equals(other.getType()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getType()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ReturnNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ReturnNode.java deleted file mode 100644 index b7222dfa18..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ReturnNode.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import com.sun.source.tree.LambdaExpressionTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.ReturnTree; -import com.sun.tools.javac.code.Symbol.MethodSymbol; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.Types; -import org.checkerframework.dataflow.cfg.node.AssignmentContext.LambdaReturnContext; -import org.checkerframework.dataflow.cfg.node.AssignmentContext.MethodReturnContext; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for a return statement: - * - *

- *   return
- *   return expression
- * 
- * - * @author Stefan Heule - */ -public class ReturnNode extends Node { - - protected ReturnTree tree; - protected /*@Nullable*/ Node result; - - public ReturnNode(ReturnTree t, /*@Nullable*/ Node result, Types types, MethodTree methodTree) { - super(types.getNoType(TypeKind.NONE)); - this.result = result; - tree = t; - result.setAssignmentContext(new MethodReturnContext(methodTree)); - } - - public ReturnNode( - ReturnTree t, - /*@Nullable*/ Node result, - Types types, - LambdaExpressionTree lambda, - MethodSymbol methodSymbol) { - super(types.getNoType(TypeKind.NONE)); - this.result = result; - tree = t; - result.setAssignmentContext(new LambdaReturnContext(methodSymbol)); - } - - public Node getResult() { - return result; - } - - @Override - public ReturnTree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitReturn(this, p); - } - - @Override - public String toString() { - if (result != null) { - return "return " + result; - } - return "return"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ReturnNode)) { - return false; - } - ReturnNode other = (ReturnNode) obj; - if ((result == null) != (other.result == null)) { - return false; - } - return (result == null || result.equals(other.result)); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(result); - } - - @Override - public Collection getOperands() { - if (result == null) { - return Collections.emptyList(); - } else { - return Collections.singletonList(result); - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ShortLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ShortLiteralNode.java deleted file mode 100644 index cd1db1e560..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ShortLiteralNode.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for a short literal. For example: - * - *
- *   5
- *   0x8fff
- * 
- * - * Java source and the AST representation do not have "short" literals. They have integer literals - * that may be narrowed to shorts depending on context. If we use explicit NarrowingConversionNodes, - * do we need ShortLiteralNodes too? TODO: Decide this question. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ShortLiteralNode extends ValueLiteralNode { - - public ShortLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.INT_LITERAL); - } - - @Override - public Short getValue() { - return (Short) tree.getValue(); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitShortLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a ShortLiteralNode - if (obj == null || !(obj instanceof ShortLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SignedRightShiftNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SignedRightShiftNode.java deleted file mode 100644 index ac4aa58783..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SignedRightShiftNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for bitwise right shift operations with sign extension: - * - *
- *   expression >> expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class SignedRightShiftNode extends BinaryOperationNode { - - public SignedRightShiftNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.RIGHT_SHIFT; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitSignedRightShift(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " >> " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof SignedRightShiftNode)) { - return false; - } - SignedRightShiftNode other = (SignedRightShiftNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConcatenateAssignmentNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConcatenateAssignmentNode.java deleted file mode 100644 index 0e6f006d7e..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConcatenateAssignmentNode.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree; -import com.sun.source.tree.Tree.Kind; -import java.util.Collection; -import java.util.LinkedList; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for the string concatenation compound assignment: - * - *
- *   variable += expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class StringConcatenateAssignmentNode extends Node { - protected Tree tree; - protected Node left; - protected Node right; - - public StringConcatenateAssignmentNode(Tree tree, Node left, Node right) { - super(InternalUtils.typeOf(tree)); - assert tree.getKind() == Kind.PLUS_ASSIGNMENT; - this.tree = tree; - this.left = left; - this.right = right; - } - - public Node getLeftOperand() { - return left; - } - - public Node getRightOperand() { - return right; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitStringConcatenateAssignment(this, p); - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.add(getLeftOperand()); - list.add(getRightOperand()); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConcatenateNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConcatenateNode.java deleted file mode 100644 index c69beea694..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConcatenateNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for string concatenation: - * - *
- *   expression + expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class StringConcatenateNode extends BinaryOperationNode { - - public StringConcatenateNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.PLUS; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitStringConcatenate(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " + " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof StringConcatenateNode)) { - return false; - } - StringConcatenateNode other = (StringConcatenateNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConversionNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConversionNode.java deleted file mode 100644 index 8ba8c6ff60..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringConversionNode.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the string conversion operation. See JLS 5.1.11 for the definition of string - * conversion. - * - *

A {@link StringConversionNode} does not correspond to any tree node in the parsed AST. It is - * introduced when a value of non-string type appears in a context that requires a {@link String}, - * such as in a string concatenation. A {@link StringConversionNode} should be treated as a - * potential call to the toString method of its operand, but does not necessarily call any method - * because null is converted to the string "null". - * - *

Conversion of primitive types to Strings requires first boxing and then string conversion. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class StringConversionNode extends Node { - - protected Tree tree; - protected Node operand; - - // TODO: The type of a string conversion should be a final - // TypeMirror representing java.lang.String. Currently we require - // the caller to pass in a TypeMirror instead of creating one - // through the javax.lang.model.type.Types interface. - public StringConversionNode(Tree tree, Node operand, TypeMirror type) { - super(type); - this.tree = tree; - this.operand = operand; - } - - public Node getOperand() { - return operand; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitStringConversion(this, p); - } - - @Override - public String toString() { - return "StringConversion(" + getOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof StringConversionNode)) { - return false; - } - StringConversionNode other = (StringConversionNode) obj; - return getOperand().equals(other.getOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringLiteralNode.java deleted file mode 100644 index c6ec1c90b8..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/StringLiteralNode.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; - -/** - * A node for an string literal. For example: - * - *

- *   "abc"
- * 
- * - * @author Stefan Heule - */ -public class StringLiteralNode extends ValueLiteralNode { - - public StringLiteralNode(LiteralTree t) { - super(t); - assert t.getKind().equals(Tree.Kind.STRING_LITERAL); - } - - @Override - public String getValue() { - return (String) tree.getValue(); - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitStringLiteral(this, p); - } - - @Override - public boolean equals(Object obj) { - // test that obj is a StringLiteralNode - if (!(obj instanceof StringLiteralNode)) { - return false; - } - // super method compares values - return super.equals(obj); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } - - @Override - public String toString() { - return "\"" + super.toString() + "\""; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SuperNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SuperNode.java deleted file mode 100644 index 797eae8e7a..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SuperNode.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for a reference to 'super'. - * - *
- *   super
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class SuperNode extends Node { - - protected Tree tree; - - public SuperNode(Tree t) { - super(InternalUtils.typeOf(t)); - assert t instanceof IdentifierTree && ((IdentifierTree) t).getName().contentEquals("super"); - tree = t; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitSuper(this, p); - } - - public String getName() { - return "super"; - } - - @Override - public String toString() { - return getName(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof SuperNode)) { - return false; - } - return true; - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getName()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SynchronizedNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SynchronizedNode.java deleted file mode 100644 index a17e2fa2e8..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/SynchronizedNode.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -/* - * This represents the start and end of synchronized code block. - * If startOfBlock == true it is the node preceding a synchronized code block. - * Otherwise it is the node immediately after a synchronized code block. - */ - -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.Types; -import org.checkerframework.dataflow.util.HashCodeUtils; - -public class SynchronizedNode extends Node { - - protected /*@Nullable*/ Tree tree; - protected Node expression; - protected boolean startOfBlock; - - public SynchronizedNode( - /*@Nullable*/ Tree tree, Node expression, boolean startOfBlock, Types types) { - super(types.getNoType(TypeKind.NONE)); - this.tree = tree; - this.expression = expression; - this.startOfBlock = startOfBlock; - } - - @Override - public Tree getTree() { - return tree; - } - - public Node getExpression() { - return expression; - } - - public boolean getIsStartOfBlock() { - return startOfBlock; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitSynchronized(this, p); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("synchronized "); - sb.append("(" + expression + ")"); - return sb.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof SynchronizedNode)) { - return false; - } - SynchronizedNode other = (SynchronizedNode) obj; - if (tree == null && other.getTree() != null) { - return false; - } - - return getTree().equals(other.getTree()) - && getExpression().equals(other.getExpression()) - && startOfBlock == other.startOfBlock; - } - - @Override - public int hashCode() { - int hash = 0; - if (tree != null) { - hash = HashCodeUtils.hash(tree); - } - hash = HashCodeUtils.hash(startOfBlock); - return HashCodeUtils.hash(hash, getExpression()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/TernaryExpressionNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/TernaryExpressionNode.java deleted file mode 100644 index 9a149a3325..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/TernaryExpressionNode.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.ConditionalExpressionTree; -import com.sun.source.tree.Tree.Kind; -import java.util.Collection; -import java.util.LinkedList; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for a conditional expression: - * - *
- *   expression ? expression : expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class TernaryExpressionNode extends Node { - - protected ConditionalExpressionTree tree; - protected Node condition; - protected Node thenOperand; - protected Node elseOperand; - - public TernaryExpressionNode( - ConditionalExpressionTree tree, Node condition, Node thenOperand, Node elseOperand) { - super(InternalUtils.typeOf(tree)); - assert tree.getKind().equals(Kind.CONDITIONAL_EXPRESSION); - this.tree = tree; - this.condition = condition; - this.thenOperand = thenOperand; - this.elseOperand = elseOperand; - } - - public Node getConditionOperand() { - return condition; - } - - public Node getThenOperand() { - return thenOperand; - } - - public Node getElseOperand() { - return elseOperand; - } - - @Override - public ConditionalExpressionTree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitTernaryExpression(this, p); - } - - @Override - public String toString() { - return "(" - + getConditionOperand() - + " ? " - + getThenOperand() - + " : " - + getElseOperand() - + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof TernaryExpressionNode)) { - return false; - } - TernaryExpressionNode other = (TernaryExpressionNode) obj; - return getConditionOperand().equals(other.getConditionOperand()) - && getThenOperand().equals(other.getThenOperand()) - && getElseOperand().equals(other.getElseOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getConditionOperand(), getThenOperand(), getElseOperand()); - } - - @Override - public Collection getOperands() { - LinkedList list = new LinkedList(); - list.add(getConditionOperand()); - list.add(getThenOperand()); - list.add(getElseOperand()); - return list; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ThisLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ThisLiteralNode.java deleted file mode 100644 index 3bb4c186e6..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ThisLiteralNode.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for a reference to 'this', either implicit or explicit. - * - *
- *   this
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public abstract class ThisLiteralNode extends Node { - - public ThisLiteralNode(TypeMirror type) { - super(type); - } - - public String getName() { - return "this"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ThisLiteralNode)) { - return false; - } - return true; - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getName()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ThrowNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ThrowNode.java deleted file mode 100644 index bb36e10a4a..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ThrowNode.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.ThrowTree; -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.Types; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for exception throws: - * - *
- *   throw expr
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class ThrowNode extends Node { - - protected ThrowTree tree; - protected Node expression; - - public ThrowNode(ThrowTree tree, Node expression, Types types) { - super(types.getNoType(TypeKind.NONE)); - this.tree = tree; - this.expression = expression; - } - - public Node getExpression() { - return expression; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitThrow(this, p); - } - - @Override - public String toString() { - return "throw " + expression; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ThrowNode)) { - return false; - } - ThrowNode other = (ThrowNode) obj; - return getExpression().equals(other.getExpression()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(expression); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(expression); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/TypeCastNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/TypeCastNode.java deleted file mode 100644 index f6e71bf6aa..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/TypeCastNode.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for the cast operator: - * - *

(Point) x - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class TypeCastNode extends Node { - - protected Tree tree; - protected Node operand; - - public TypeCastNode(Tree tree, Node operand, TypeMirror type) { - super(type); - this.tree = tree; - this.operand = operand; - } - - public Node getOperand() { - return operand; - } - - @Override - public TypeMirror getType() { - return type; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitTypeCast(this, p); - } - - @Override - public String toString() { - return "(" + getType() + ")" + getOperand(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof TypeCastNode)) { - return false; - } - TypeCastNode other = (TypeCastNode) obj; - // TODO: TypeMirror.equals may be too restrictive. - // Check whether Types.isSameType is the better comparison. - return getOperand().equals(other.getOperand()) && getType().equals(other.getType()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/UnaryOperationNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/UnaryOperationNode.java deleted file mode 100644 index cb33e6a3f1..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/UnaryOperationNode.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.UnaryTree; -import java.util.Collection; -import java.util.Collections; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for a postfix or an unary expression. - * - *

For example: - * - *

- *   operator expressionNode
- *
- *   expressionNode operator
- * 
- * - * @author charleszhuochen - */ -public abstract class UnaryOperationNode extends Node { - - protected final UnaryTree tree; - protected final Node operand; - - public UnaryOperationNode(UnaryTree tree, Node operand) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - this.operand = operand; - } - - public Node getOperand() { - return this.operand; - } - - @Override - public UnaryTree getTree() { - return tree; - } - - @Override - public Collection getOperands() { - return Collections.singletonList(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/UnsignedRightShiftNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/UnsignedRightShiftNode.java deleted file mode 100644 index 2609a7d7ae..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/UnsignedRightShiftNode.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.Tree.Kind; -import org.checkerframework.dataflow.util.HashCodeUtils; - -/** - * A node for bitwise right shift operations with zero extension: - * - *
- *   expression >>> expression
- * 
- * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class UnsignedRightShiftNode extends BinaryOperationNode { - - public UnsignedRightShiftNode(BinaryTree tree, Node left, Node right) { - super(tree, left, right); - assert tree.getKind() == Kind.UNSIGNED_RIGHT_SHIFT; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitUnsignedRightShift(this, p); - } - - @Override - public String toString() { - return "(" + getLeftOperand() + " >>> " + getRightOperand() + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof UnsignedRightShiftNode)) { - return false; - } - UnsignedRightShiftNode other = (UnsignedRightShiftNode) obj; - return getLeftOperand().equals(other.getLeftOperand()) - && getRightOperand().equals(other.getRightOperand()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getLeftOperand(), getRightOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ValueLiteralNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ValueLiteralNode.java deleted file mode 100644 index 4c9c18f0af..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/ValueLiteralNode.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.LiteralTree; -import java.util.Collection; -import java.util.Collections; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -/** - * A node for a literals that have some form of value: - * - *
    - *
  • integer literal - *
  • long literal - *
  • char literal - *
  • string literal - *
  • float literal - *
  • double literal - *
  • boolean literal - *
  • null literal - *
- * - * @author Stefan Heule - */ -public abstract class ValueLiteralNode extends Node { - - protected final LiteralTree tree; - - /** @return the value of the literal */ - public abstract /*@Nullable*/ Object getValue(); - - public ValueLiteralNode(LiteralTree tree) { - super(InternalUtils.typeOf(tree)); - this.tree = tree; - } - - @Override - public LiteralTree getTree() { - return tree; - } - - @Override - public String toString() { - return String.valueOf(getValue()); - } - - /** Compare the value of this nodes. */ - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ValueLiteralNode)) { - return false; - } - ValueLiteralNode other = (ValueLiteralNode) obj; - Object val = getValue(); - Object otherVal = other.getValue(); - return ((val == null || otherVal == null) && val == otherVal) || val.equals(otherVal); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getValue()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/VariableDeclarationNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/VariableDeclarationNode.java deleted file mode 100644 index 867cdf1ad9..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/VariableDeclarationNode.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.VariableTree; -import java.util.Collection; -import java.util.Collections; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.InternalUtils; - -/** - * A node for a local variable declaration: - * - *
- *   modifier type identifier;
- * 
- * - * Note: Does not have an initializer block, as that will be translated to a separate {@link - * AssignmentNode}. - * - * @author Stefan Heule - */ -public class VariableDeclarationNode extends Node { - - protected VariableTree tree; - protected String name; - - // TODO: make modifier accessible - - public VariableDeclarationNode(VariableTree t) { - super(InternalUtils.typeOf(t)); - tree = t; - name = tree.getName().toString(); - } - - public String getName() { - return name; - } - - @Override - public VariableTree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitVariableDeclaration(this, p); - } - - @Override - public String toString() { - return name; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof VariableDeclarationNode)) { - return false; - } - VariableDeclarationNode other = (VariableDeclarationNode) obj; - return getName().equals(other.getName()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getName()); - } - - @Override - public Collection getOperands() { - return Collections.emptyList(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/WideningConversionNode.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/WideningConversionNode.java deleted file mode 100644 index 9b949ea546..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/node/WideningConversionNode.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.checkerframework.dataflow.cfg.node; - -import com.sun.source.tree.Tree; -import java.util.Collection; -import java.util.Collections; -import javax.lang.model.type.TypeMirror; -import org.checkerframework.dataflow.util.HashCodeUtils; -import org.checkerframework.javacutil.TypesUtils; - -/** - * A node for the widening primitive conversion operation. See JLS 5.1.2 for the definition of - * widening primitive conversion. - * - *

A {@link WideningConversionNode} does not correspond to any tree node in the parsed AST. It is - * introduced when a value of some primitive type appears in a context that requires a different - * primitive with more bits of precision. - * - * @author Stefan Heule - * @author Charlie Garrett - */ -public class WideningConversionNode extends Node { - - protected Tree tree; - protected Node operand; - - public WideningConversionNode(Tree tree, Node operand, TypeMirror type) { - super(type); - assert TypesUtils.isPrimitive(type) : "non-primitive type in widening conversion"; - this.tree = tree; - this.operand = operand; - } - - public Node getOperand() { - return operand; - } - - @Override - public TypeMirror getType() { - return type; - } - - @Override - public Tree getTree() { - return tree; - } - - @Override - public R accept(NodeVisitor visitor, P p) { - return visitor.visitWideningConversion(this, p); - } - - @Override - public String toString() { - return "WideningConversion(" + getOperand() + ", " + type + ")"; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof WideningConversionNode)) { - return false; - } - WideningConversionNode other = (WideningConversionNode) obj; - return getOperand().equals(other.getOperand()) - && TypesUtils.areSamePrimitiveTypes(getType(), other.getType()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getOperand()); - } - - @Override - public Collection getOperands() { - return Collections.singletonList(getOperand()); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/playground/ConstantPropagationPlayground.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/playground/ConstantPropagationPlayground.java deleted file mode 100644 index 79088386a9..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/playground/ConstantPropagationPlayground.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.checkerframework.dataflow.cfg.playground; - -import org.checkerframework.dataflow.analysis.Analysis; -import org.checkerframework.dataflow.cfg.JavaSource2CFGDOT; -import org.checkerframework.dataflow.constantpropagation.Constant; -import org.checkerframework.dataflow.constantpropagation.ConstantPropagationStore; -import org.checkerframework.dataflow.constantpropagation.ConstantPropagationTransfer; - -public class ConstantPropagationPlayground { - - /** Run constant propagation for a specific file and create a PDF of the CFG in the end. */ - public static void main(String[] args) { - - /* Configuration: change as appropriate */ - String inputFile = "cfg-input.java"; // input file name and path - String outputDir = "cfg"; // output directory - String method = "test"; // name of the method to analyze - String clazz = "Test"; // name of the class to consider - - // run the analysis and create a PDF file - ConstantPropagationTransfer transfer = new ConstantPropagationTransfer(); - // TODO: correct processing environment - Analysis analysis = - new Analysis<>(null, transfer); - JavaSource2CFGDOT.generateDOTofCFG(inputFile, outputDir, method, clazz, true, analysis); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/Constant.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/Constant.java deleted file mode 100644 index a95af7fa43..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/Constant.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.checkerframework.dataflow.constantpropagation; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import java.util.Objects; -import org.checkerframework.dataflow.analysis.AbstractValue; - -public class Constant implements AbstractValue { - - /** What kind of abstract value is this? */ - protected Type type; - - /** The value of this abstract value (or null) */ - protected /*@Nullable*/ Integer value; - - public enum Type { - CONSTANT, - TOP, - BOTTOM, - } - - public Constant(Type type) { - assert !type.equals(Type.CONSTANT); - this.type = type; - } - - public Constant(Integer value) { - this.type = Type.CONSTANT; - this.value = value; - } - - public boolean isTop() { - return type.equals(Type.TOP); - } - - public boolean isBottom() { - return type.equals(Type.BOTTOM); - } - - public boolean isConstant() { - return type.equals(Type.CONSTANT); - } - - public Integer getValue() { - assert isConstant(); - return value; - } - - public Constant copy() { - if (isConstant()) { - return new Constant(value); - } - return new Constant(type); - } - - @Override - public Constant leastUpperBound(Constant other) { - if (other.isBottom()) { - return this.copy(); - } - if (this.isBottom()) { - return other.copy(); - } - if (other.isTop() || this.isTop()) { - return new Constant(Type.TOP); - } - if (other.getValue().equals(getValue())) { - return this.copy(); - } - return new Constant(Type.TOP); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof Constant)) { - return false; - } - Constant other = (Constant) obj; - return type == other.type && Objects.equals(value, other.value); - } - - @Override - public int hashCode() { - return type.hashCode() + (value != null ? value.hashCode() : 0); - } - - @Override - public String toString() { - switch (type) { - case TOP: - return "T"; - case BOTTOM: - return "-"; - case CONSTANT: - return value.toString(); - } - assert false; - return "???"; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/ConstantPropagationStore.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/ConstantPropagationStore.java deleted file mode 100644 index e7a718ee5b..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/ConstantPropagationStore.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.checkerframework.dataflow.constantpropagation; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import org.checkerframework.dataflow.analysis.FlowExpressions; -import org.checkerframework.dataflow.analysis.Store; -import org.checkerframework.dataflow.cfg.CFGVisualizer; -import org.checkerframework.dataflow.cfg.node.IntegerLiteralNode; -import org.checkerframework.dataflow.cfg.node.LocalVariableNode; -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.dataflow.constantpropagation.Constant.Type; - -public class ConstantPropagationStore implements Store { - - /** Information about variables gathered so far. */ - Map contents; - - public ConstantPropagationStore() { - contents = new HashMap<>(); - } - - protected ConstantPropagationStore(Map contents) { - this.contents = contents; - } - - public Constant getInformation(Node n) { - if (contents.containsKey(n)) { - return contents.get(n); - } - return new Constant(Type.TOP); - } - - public void mergeInformation(Node n, Constant val) { - Constant value; - if (contents.containsKey(n)) { - value = val.leastUpperBound(contents.get(n)); - } else { - value = val; - } - // TODO: remove (only two nodes supported atm) - assert n instanceof IntegerLiteralNode || n instanceof LocalVariableNode; - contents.put(n, value); - } - - public void setInformation(Node n, Constant val) { - // TODO: remove (only two nodes supported atm) - assert n instanceof IntegerLiteralNode || n instanceof LocalVariableNode; - contents.put(n, val); - } - - @Override - public ConstantPropagationStore copy() { - return new ConstantPropagationStore(new HashMap<>(contents)); - } - - @Override - public ConstantPropagationStore leastUpperBound(ConstantPropagationStore other) { - Map newContents = new HashMap<>(); - - // go through all of the information of the other class - for (Entry e : other.contents.entrySet()) { - Node n = e.getKey(); - Constant otherVal = e.getValue(); - if (contents.containsKey(n)) { - // merge if both contain information about a variable - newContents.put(n, otherVal.leastUpperBound(contents.get(n))); - } else { - // add new information - newContents.put(n, otherVal); - } - } - - for (Entry e : contents.entrySet()) { - Node n = e.getKey(); - Constant thisVal = e.getValue(); - if (!other.contents.containsKey(n)) { - // add new information - newContents.put(n, thisVal); - } - } - - return new ConstantPropagationStore(newContents); - } - - @Override - public ConstantPropagationStore widenedUpperBound(ConstantPropagationStore previous) { - return leastUpperBound(previous); - } - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } - if (!(o instanceof ConstantPropagationStore)) { - return false; - } - ConstantPropagationStore other = (ConstantPropagationStore) o; - // go through all of the information of the other object - for (Entry e : other.contents.entrySet()) { - Node n = e.getKey(); - Constant otherVal = e.getValue(); - if (otherVal.isBottom()) { - continue; // no information - } - if (contents.containsKey(n)) { - if (!otherVal.equals(contents.get(n))) { - return false; - } - } else { - return false; - } - } - // go through all of the information of the this object - for (Entry e : contents.entrySet()) { - Node n = e.getKey(); - Constant thisVal = e.getValue(); - if (thisVal.isBottom()) { - continue; // no information - } - if (other.contents.containsKey(n)) { - continue; - } else { - return false; - } - } - return true; - } - - @Override - public int hashCode() { - int s = 0; - for (Entry e : contents.entrySet()) { - if (!e.getValue().isBottom()) { - s += e.hashCode(); - } - } - return s; - } - - @Override - public String toString() { - // only output local variable information - Map smallerContents = new HashMap<>(); - for (Entry e : contents.entrySet()) { - if (e.getKey() instanceof LocalVariableNode) { - smallerContents.put(e.getKey(), e.getValue()); - } - } - return smallerContents.toString(); - } - - @Override - public boolean canAlias(FlowExpressions.Receiver a, FlowExpressions.Receiver b) { - return true; - } - - @Override - public void visualize(CFGVisualizer viz) { - // Do nothing since ConstantPropagationStore doesn't support visualize - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/ConstantPropagationTransfer.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/ConstantPropagationTransfer.java deleted file mode 100644 index d5da13a518..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/constantpropagation/ConstantPropagationTransfer.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.checkerframework.dataflow.constantpropagation; - -import java.util.List; -import org.checkerframework.dataflow.analysis.ConditionalTransferResult; -import org.checkerframework.dataflow.analysis.RegularTransferResult; -import org.checkerframework.dataflow.analysis.TransferFunction; -import org.checkerframework.dataflow.analysis.TransferInput; -import org.checkerframework.dataflow.analysis.TransferResult; -import org.checkerframework.dataflow.cfg.UnderlyingAST; -import org.checkerframework.dataflow.cfg.node.AbstractNodeVisitor; -import org.checkerframework.dataflow.cfg.node.AssignmentNode; -import org.checkerframework.dataflow.cfg.node.EqualToNode; -import org.checkerframework.dataflow.cfg.node.IntegerLiteralNode; -import org.checkerframework.dataflow.cfg.node.LocalVariableNode; -import org.checkerframework.dataflow.cfg.node.Node; - -public class ConstantPropagationTransfer - extends AbstractNodeVisitor< - TransferResult, - TransferInput> - implements TransferFunction { - - @Override - public ConstantPropagationStore initialStore( - UnderlyingAST underlyingAST, List parameters) { - ConstantPropagationStore store = new ConstantPropagationStore(); - return store; - } - - @Override - public TransferResult visitLocalVariable( - LocalVariableNode node, TransferInput before) { - ConstantPropagationStore store = before.getRegularStore(); - Constant value = store.getInformation(node); - return new RegularTransferResult<>(value, store); - } - - @Override - public TransferResult visitNode( - Node n, TransferInput p) { - return new RegularTransferResult<>(null, p.getRegularStore()); - } - - @Override - public TransferResult visitAssignment( - AssignmentNode n, TransferInput pi) { - ConstantPropagationStore p = pi.getRegularStore(); - Node target = n.getTarget(); - Constant info = null; - if (target instanceof LocalVariableNode) { - LocalVariableNode t = (LocalVariableNode) target; - info = p.getInformation(n.getExpression()); - p.setInformation(t, info); - } - return new RegularTransferResult<>(info, p); - } - - @Override - public TransferResult visitIntegerLiteral( - IntegerLiteralNode n, TransferInput pi) { - ConstantPropagationStore p = pi.getRegularStore(); - Constant c = new Constant(n.getValue()); - p.setInformation(n, c); - return new RegularTransferResult<>(c, p); - } - - @Override - public TransferResult visitEqualTo( - EqualToNode n, TransferInput pi) { - ConstantPropagationStore p = pi.getRegularStore(); - ConstantPropagationStore old = p.copy(); - Node left = n.getLeftOperand(); - Node right = n.getRightOperand(); - process(p, left, right); - process(p, right, left); - return new ConditionalTransferResult<>(null, p, old); - } - - protected void process(ConstantPropagationStore p, Node a, Node b) { - Constant val = p.getInformation(a); - if (b instanceof LocalVariableNode && val.isConstant()) { - p.setInformation(b, val); - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/Deterministic.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/Deterministic.java deleted file mode 100644 index 7e7d8b9cdc..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/Deterministic.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.checkerframework.dataflow.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * A method is called deterministic if it returns the same value (according to {@code ==}) - * every time it is called with the same parameters and in the same environment. The parameters - * include the receiver, and the environment includes all of the Java heap (that is, all fields of - * all objects and all static variables). - * - *

Determinism refers to the return value during a non-exceptional execution. If a method throws - * an exception, the Throwable does not have to be exactly the same object on each invocation (and - * generally should not be, to capture the correct stack trace). - * - *

This annotation is important to pluggable type-checking because, after a call to a - * {@code @Deterministic} method, flow-sensitive type refinement can assume that anything learned - * about the first invocation is true about subsequent invocations (so long as no - * non-{@code @}{@link SideEffectFree} method call intervenes). For example, the following code - * never suffers a null pointer exception, so the Nullness Checker need not issue a warning: - * - *

{@code
- * if (x.myDeterministicMethod() != null) {
- *   x.myDeterministicMethod().hashCode();
- * }
- * }
- * - *

Note that {@code @Deterministic} guarantees that the result is identical according to {@code - * ==}, not just equal according to {@code equals()}. This means that writing - * {@literal @}Deterministic on a method that returns a reference (including a String) is - * often erroneous unless the returned value is cached or interned. - * - *

Also see {@link Pure}, which means both deterministic and {@link SideEffectFree}. - * - *

Analysis: The Checker Framework performs a conservative analysis to verify a - * {@code @Deterministic} annotation. The Checker Framework issues a warning if the method uses any - * of the following Java constructs: - * - *

    - *
  1. Assignment to any expression, except for local variables (and method parameters). - *
  2. A method invocation of a method that is not {@link Deterministic}. - *
  3. Construction of a new object. - *
  4. Catching any exceptions. This is to prevent a method to get a hold of newly created objects - * and using these objects (or some property thereof) to change their return value. For - * instance, the following method must be forbidden. - *
    - * {@code @Deterministic
    - * int f() {
    - *   try {
    - *     int b = 0;
    - *     int a = 1/b;
    - *   } catch (Throwable t) {
    - *     return t.hashCode();
    - *   }
    - *   return 0;
    - * }
    - * }
    - *
- * - * A constructor can be {@code @Pure}, but a constructor invocation is not deterministic - * since it returns a different new object each time. TODO: Side-effect-free constructors could be - * allowed to set their own fields. - * - *

Note that the rules for checking currently imply that every {@code Deterministic} method is - * also {@link SideEffectFree}. This might change in the future; in general, a deterministic method - * does not need to be side-effect-free. - * - *

These rules are conservative: any code that passes the checks is deterministic, but the - * Checker Framework may issue false positive warnings, for code that uses one of the forbidden - * constructs but is deterministic nonetheless. - * - *

In fact, the rules are so conservative that checking is currently disabled by default, but can - * be enabled via the {@code -AcheckPurityAnnotations} command-line option. - * - *

- * - * @checker_framework.manual #type-refinement-purity Side effects, determinism, purity, and - * flow-sensitive analysis - * @author Stefan Heule - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface Deterministic {} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/Pure.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/Pure.java deleted file mode 100644 index 5a00db7a1b..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/Pure.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.checkerframework.dataflow.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * {@code Pure} is a method annotation that means both {@link SideEffectFree} and {@link - * Deterministic}. The more important of these, when performing pluggable type-checking, is usually - * {@link SideEffectFree}. - * - * @checker_framework.manual #type-refinement-purity Side effects, determinism, purity, and - * flow-sensitive analysis - * @author Stefan Heule - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface Pure { - /** The type of purity. */ - public static enum Kind { - /** The method has no visible side-effects. */ - SIDE_EFFECT_FREE, - - /** The method returns exactly the same value when called in the same environment. */ - DETERMINISTIC - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/SideEffectFree.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/SideEffectFree.java deleted file mode 100644 index 6a969c4364..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/SideEffectFree.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.checkerframework.dataflow.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * A method is called side-effect-free if it has no visible side-effects, such as setting a - * field of an object that existed before the method was called. - * - *

Only the visible side-effects are important. The method is allowed to cache the answer to a - * computationally expensive query, for instance. It is also allowed to modify newly-created - * objects, and a constructor is side-effect-free if it does not modify any objects that existed - * before it was called. - * - *

This annotation is important to pluggable type-checking because if some fact about an object - * is known before a call to such a method, then the fact is still known afterwards, even if the - * fact is about some non-final field. When any non-{@code @SideEffectFree} method is called, then a - * pluggable type-checker must assume that any field of any accessible object might have been - * modified, which annuls the effect of flow-sensitive type refinement and prevents the pluggable - * type-checker from making conclusions that are obvious to a programmer. - * - *

Also see {@link Pure}, which means both side-effect-free and {@link Deterministic}. - * - *

Analysis: The Checker Framework performs a conservative analysis to verify a - * {@code @SideEffectFree} annotation. The Checker Framework issues a warning if the method uses any - * of the following Java constructs: - * - *

    - *
  1. Assignment to any expression, except for local variables and method parameters. - *
  2. A method invocation of a method that is not {@code @SideEffectFree}. - *
  3. Construction of a new object where the constructor is not {@code @SideEffectFree}. - *
- * - * These rules are conservative: any code that passes the checks is side-effect-free, but the - * Checker Framework may issue false positive warnings, for code that uses one of the forbidden - * constructs but is side-effect-free nonetheless. In particular, a method that caches its result - * will be rejected. - * - *

In fact, the rules are so conservative that checking is currently disabled by default, but can - * be enabled via the {@code -AcheckPurityAnnotations} command-line option. - * - *

- * - * @checker_framework.manual #type-refinement-purity Side effects, determinism, purity, and - * flow-sensitive analysis - * @author Stefan Heule - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface SideEffectFree {} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/TerminatesExecution.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/TerminatesExecution.java deleted file mode 100644 index 4e83dcdb64..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/qual/TerminatesExecution.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.checkerframework.dataflow.qual; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * {@code TerminatesExecution} is a method annotation that indicates that a method terminates the - * execution of the program. This can be used to annotate methods such as {@code System.exit()}. - * - *

The annotation enables flow-sensitive type refinement to be more precise. For example, after - * - *

- * if (x == null) {
- *   System.err.println("Bad value supplied");
- *   System.exit(1);
- * }
- * 
- * - * the Nullness Checker can determine that {@code x} is non-null. - * - *

The annotation is a trusted annotation, meaning that it is not checked whether the - * annotated method really does terminate the program. - * - * @checker_framework.manual #type-refinement Automatic type refinement (flow-sensitive type - * qualifier inference) - * @author Stefan Heule - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface TerminatesExecution {} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/HashCodeUtils.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/HashCodeUtils.java deleted file mode 100644 index f898e3c9b4..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/HashCodeUtils.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.checkerframework.dataflow.util; - -/** - * Utility class to implement the {@code hashCode} method. - * - * @author Stefan Heule - */ -public class HashCodeUtils { - - /** Odd prime number. */ - private static int prime = 31; - - /** Seed. */ - private static int seed = 17; - - /** Add a boolean value to a given hash. */ - public static int hash(int hash, boolean item) { - return hash * prime + (item ? 1 : 0); - } - - /** Add a char value to a given hash. */ - public static int hash(int hash, char item) { - return hash * prime + item; - } - - /** Add an int value to a given hash. */ - public static int hash(int hash, int item) { - return hash * prime + item; - } - - /** Add a long value to a given hash. */ - public static int hash(int hash, long item) { - return hash * prime + (int) (item ^ (item >>> 32)); - } - - /** Add a float value to a given hash. */ - public static int hash(int hash, float item) { - return hash * prime + Float.floatToIntBits(item); - } - - /** Add a double value to a given hash. */ - public static int hash(int hash, double item) { - long l = Double.doubleToLongBits(item); - return seed * prime + (int) (l ^ (l >>> 32)); - } - - /** Add an object to a given hash. */ - public static int hash(int hash, Object item) { - if (item == null) { - return hash * prime; - } - return hash * prime + item.hashCode(); - } - - /** Hash a boolean value. */ - public static int hash(boolean item) { - return (item ? 1 : 0); - } - - /** Hash a char value. */ - public static int hash(char item) { - return item; - } - - /** Hash an int value. */ - public static int hash(int item) { - return item; - } - - /** Hash a long value. */ - public static int hash(long item) { - return (int) (item ^ (item >>> 32)); - } - - /** Hash a float value. */ - public static int hash(float item) { - return Float.floatToIntBits(item); - } - - /** Hash a double value. */ - public static int hash(double item) { - long l = Double.doubleToLongBits(item); - return (int) (l ^ (l >>> 32)); - } - - /** Hash an object. */ - public static int hash(Object item) { - if (item == null) { - return 0; - } - return item.hashCode(); - } - - /** Hash multiple objects. */ - public static int hash(Object... items) { - int result = seed; - for (Object item : items) { - result = result * prime + (item == null ? 0 : item.hashCode()); - } - return result; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/MostlySingleton.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/MostlySingleton.java deleted file mode 100644 index 7e9172da91..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/MostlySingleton.java +++ /dev/null @@ -1,151 +0,0 @@ -package org.checkerframework.dataflow.util; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Set; - -/** A set that is more efficient than HashSet for 0 and 1 elements. */ -public final class MostlySingleton implements Set { - private enum State { - EMPTY, - SINGLETON, - ANY - } - - private State state = State.EMPTY; - private T value; - private HashSet set; - - @Override - public int size() { - switch (state) { - case EMPTY: - return 0; - case SINGLETON: - return 1; - case ANY: - return set.size(); - default: - throw new AssertionError(); - } - } - - @Override - public boolean isEmpty() { - return size() == 0; - } - - @Override - public boolean contains(Object o) { - switch (state) { - case EMPTY: - return false; - case SINGLETON: - return Objects.equals(o, value); - case ANY: - return set.contains(o); - default: - throw new AssertionError(); - } - } - - @Override - @SuppressWarnings("fallthrough") - public boolean add(T e) { - switch (state) { - case EMPTY: - state = State.SINGLETON; - value = e; - return true; - case SINGLETON: - state = State.ANY; - set = new HashSet(); - set.add(value); - value = null; - // fallthrough - case ANY: - return set.add(e); - default: - throw new AssertionError(); - } - } - - @Override - public Iterator iterator() { - switch (state) { - case EMPTY: - return Collections.emptyIterator(); - case SINGLETON: - return new Iterator() { - private boolean hasNext = true; - - @Override - public boolean hasNext() { - return hasNext; - } - - @Override - public T next() { - if (hasNext) { - hasNext = false; - return value; - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - case ANY: - return set.iterator(); - default: - throw new AssertionError(); - } - } - - @Override - public Object[] toArray() { - throw new UnsupportedOperationException(); - } - - @Override - public S[] toArray(S[] a) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean addAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/NodeUtils.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/NodeUtils.java deleted file mode 100644 index cf7a090024..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/NodeUtils.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.checkerframework.dataflow.util; - -import com.sun.source.tree.Tree; -import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.tree.JCTree; -import javax.lang.model.type.TypeKind; -import org.checkerframework.dataflow.cfg.node.ConditionalOrNode; -import org.checkerframework.dataflow.cfg.node.FieldAccessNode; -import org.checkerframework.dataflow.cfg.node.Node; -import org.checkerframework.javacutil.TypesUtils; - -/** - * A utility class to operate on a given {@link Node}. - * - * @author Stefan Heule - */ -public class NodeUtils { - - /** - * @return true iff {@code node} corresponds to a boolean typed expression (either the primitive - * type {@code boolean}, or class type {@link java.lang.Boolean}) - */ - public static boolean isBooleanTypeNode(Node node) { - - if (node instanceof ConditionalOrNode) { - return true; - } - - // not all nodes have an associated tree, but those are all not of a - // boolean type. - Tree tree = node.getTree(); - if (tree == null) { - return false; - } - - Type type = ((JCTree) tree).type; - if (TypesUtils.isBooleanType(type)) { - return true; - } - - return false; - } - - /** - * @return true iff {@code node} is a {@link FieldAccessNode} that is an access to an array's - * length - */ - public static boolean isArrayLengthFieldAccess(Node node) { - if (!(node instanceof FieldAccessNode)) { - return false; - } - FieldAccessNode fieldAccess = (FieldAccessNode) node; - return fieldAccess.getFieldName().equals("length") - && fieldAccess.getReceiver().getType().getKind() == TypeKind.ARRAY; - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java deleted file mode 100644 index 0b298f1955..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityChecker.java +++ /dev/null @@ -1,491 +0,0 @@ -package org.checkerframework.dataflow.util; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey; -*/ - -import com.sun.source.tree.ArrayAccessTree; -import com.sun.source.tree.AssertTree; -import com.sun.source.tree.AssignmentTree; -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.BlockTree; -import com.sun.source.tree.BreakTree; -import com.sun.source.tree.CaseTree; -import com.sun.source.tree.CatchTree; -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.CompoundAssignmentTree; -import com.sun.source.tree.ConditionalExpressionTree; -import com.sun.source.tree.ContinueTree; -import com.sun.source.tree.DoWhileLoopTree; -import com.sun.source.tree.EmptyStatementTree; -import com.sun.source.tree.EnhancedForLoopTree; -import com.sun.source.tree.ExpressionStatementTree; -import com.sun.source.tree.ExpressionTree; -import com.sun.source.tree.ForLoopTree; -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.IfTree; -import com.sun.source.tree.InstanceOfTree; -import com.sun.source.tree.LabeledStatementTree; -import com.sun.source.tree.LambdaExpressionTree; -import com.sun.source.tree.LiteralTree; -import com.sun.source.tree.MemberReferenceTree; -import com.sun.source.tree.MemberSelectTree; -import com.sun.source.tree.MethodInvocationTree; -import com.sun.source.tree.NewArrayTree; -import com.sun.source.tree.NewClassTree; -import com.sun.source.tree.ParenthesizedTree; -import com.sun.source.tree.ReturnTree; -import com.sun.source.tree.SwitchTree; -import com.sun.source.tree.SynchronizedTree; -import com.sun.source.tree.ThrowTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.TryTree; -import com.sun.source.tree.TypeCastTree; -import com.sun.source.tree.UnaryTree; -import com.sun.source.tree.VariableTree; -import com.sun.source.tree.WhileLoopTree; -import com.sun.source.util.SimpleTreeVisitor; -import com.sun.tools.javac.tree.TreeScanner; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumSet; -import java.util.List; -import javax.lang.model.element.Element; -import org.checkerframework.dataflow.qual.Deterministic; -import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.Pure.Kind; -import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.javacutil.AnnotationProvider; -import org.checkerframework.javacutil.InternalUtils; -import org.checkerframework.javacutil.Pair; -import org.checkerframework.javacutil.TreeUtils; - -/** - * A visitor that determines the purity (as defined by {@link - * org.checkerframework.dataflow.qual.SideEffectFree}, {@link - * org.checkerframework.dataflow.qual.Deterministic}, and {@link - * org.checkerframework.dataflow.qual.Pure}) of a statement or expression. The entry point is method - * {@link #checkPurity}. - * - * @see SideEffectFree - * @see Deterministic - * @see Pure - * @author Stefan Heule - */ -public class PurityChecker { - - /** - * Compute whether the given statement is side-effect-free, deterministic, or both. Returns a - * result that can be queried. - */ - public static PurityResult checkPurity( - Tree statement, AnnotationProvider annoProvider, boolean assumeSideEffectFree) { - PurityCheckerHelper helper = new PurityCheckerHelper(annoProvider, assumeSideEffectFree); - PurityResult res = helper.scan(statement, new PurityResult()); - return res; - } - - /** - * Result of the {@link PurityChecker}. Can be queried regarding whether a given tree was - * side-effect-free, deterministic, or both; also gives reasons if the answer is "no". - */ - public static class PurityResult { - - protected final List> notSeFreeReasons; - protected final List> notDetReasons; - protected final List> notBothReasons; - protected EnumSet types; - - public PurityResult() { - notSeFreeReasons = new ArrayList<>(); - notDetReasons = new ArrayList<>(); - notBothReasons = new ArrayList<>(); - types = EnumSet.allOf(Pure.Kind.class); - } - - public EnumSet getTypes() { - return types; - } - - /** Is the method pure w.r.t. a given set of types? */ - public boolean isPure(Collection kinds) { - return types.containsAll(kinds); - } - - /** Get the {@code reason}s why the method is not side-effect-free. */ - public List> getNotSeFreeReasons() { - return notSeFreeReasons; - } - - /** Add {@code reason} as a reason why the method is not side-effect free. */ - public void addNotSeFreeReason(Tree t, String msgId) { - notSeFreeReasons.add(Pair.of(t, msgId)); - types.remove(Kind.SIDE_EFFECT_FREE); - } - - /** Get the {@code reason}s why the method is not deterministic. */ - public List> getNotDetReasons() { - return notDetReasons; - } - - /** Add {@code reason} as a reason why the method is not deterministic. */ - public void addNotDetReason(Tree t, String msgId) { - notDetReasons.add(Pair.of(t, msgId)); - types.remove(Kind.DETERMINISTIC); - } - - /** - * Get the {@code reason}s why the method is not both side-effect-free and deterministic. - */ - public List> getNotBothReasons() { - return notBothReasons; - } - - /** - * Add {@code reason} as a reason why the method is not both side-effect free and - * deterministic. - */ - public void addNotBothReason(Tree t, String msgId) { - notBothReasons.add(Pair.of(t, msgId)); - types.remove(Kind.DETERMINISTIC); - types.remove(Kind.SIDE_EFFECT_FREE); - } - } - - /** - * Helper class to keep {@link PurityChecker}'s interface clean. The implementation is heavily - * based on {@link TreeScanner}, but some parts of the AST are skipped (such as types or - * modifiers). Furthermore, scanning works differently in that the input parameter (usually - * named {@code p}) gets "threaded through", instead of using {@code reduce}. - */ - protected static class PurityCheckerHelper - extends SimpleTreeVisitor { - - protected final AnnotationProvider annoProvider; - /** - * True if all methods should be assumed to be @SideEffectFree, for the purposes of - * org.checkerframework.dataflow analysis. - */ - private final boolean assumeSideEffectFree; - - protected /*@Nullable*/ List methodParameter; - - public PurityCheckerHelper(AnnotationProvider annoProvider, boolean assumeSideEffectFree) { - this.annoProvider = annoProvider; - this.assumeSideEffectFree = assumeSideEffectFree; - } - - /** Scan a single node. */ - public PurityResult scan(Tree node, PurityResult p) { - return node == null ? p : node.accept(this, p); - } - - /** Scan a list of nodes. */ - public PurityResult scan(Iterable nodes, PurityResult p) { - PurityResult r = p; - if (nodes != null) { - for (Tree node : nodes) { - r = scan(node, r); - } - } - return r; - } - - @Override - protected PurityResult defaultAction(Tree node, PurityResult p) { - assert false : "this type of tree is unexpected here"; - return null; - } - - @Override - public PurityResult visitClass(ClassTree node, PurityResult p) { - return p; - } - - @Override - public PurityResult visitVariable(VariableTree node, PurityResult p) { - return scan(node.getInitializer(), p); - } - - @Override - public PurityResult visitEmptyStatement(EmptyStatementTree node, PurityResult p) { - return p; - } - - @Override - public PurityResult visitBlock(BlockTree node, PurityResult p) { - return scan(node.getStatements(), p); - } - - @Override - public PurityResult visitDoWhileLoop(DoWhileLoopTree node, PurityResult p) { - PurityResult r = scan(node.getStatement(), p); - r = scan(node.getCondition(), r); - return r; - } - - @Override - public PurityResult visitWhileLoop(WhileLoopTree node, PurityResult p) { - PurityResult r = scan(node.getCondition(), p); - r = scan(node.getStatement(), r); - return r; - } - - @Override - public PurityResult visitForLoop(ForLoopTree node, PurityResult p) { - PurityResult r = scan(node.getInitializer(), p); - r = scan(node.getCondition(), r); - r = scan(node.getUpdate(), r); - r = scan(node.getStatement(), r); - return r; - } - - @Override - public PurityResult visitEnhancedForLoop(EnhancedForLoopTree node, PurityResult p) { - PurityResult r = scan(node.getVariable(), p); - r = scan(node.getExpression(), r); - r = scan(node.getStatement(), r); - return r; - } - - @Override - public PurityResult visitLabeledStatement(LabeledStatementTree node, PurityResult p) { - return scan(node.getStatement(), p); - } - - @Override - public PurityResult visitSwitch(SwitchTree node, PurityResult p) { - PurityResult r = scan(node.getExpression(), p); - r = scan(node.getCases(), r); - return r; - } - - @Override - public PurityResult visitCase(CaseTree node, PurityResult p) { - PurityResult r = scan(node.getExpression(), p); - r = scan(node.getStatements(), r); - return r; - } - - @Override - public PurityResult visitSynchronized(SynchronizedTree node, PurityResult p) { - PurityResult r = scan(node.getExpression(), p); - r = scan(node.getBlock(), r); - return r; - } - - @Override - public PurityResult visitTry(TryTree node, PurityResult p) { - PurityResult r = scan(node.getResources(), p); - r = scan(node.getBlock(), r); - r = scan(node.getCatches(), r); - r = scan(node.getFinallyBlock(), r); - return r; - } - - @Override - public PurityResult visitCatch(CatchTree node, PurityResult p) { - p.addNotDetReason(node, "catch"); - PurityResult r = scan(node.getParameter(), p); - r = scan(node.getBlock(), r); - return r; - } - - @Override - public PurityResult visitConditionalExpression( - ConditionalExpressionTree node, PurityResult p) { - PurityResult r = scan(node.getCondition(), p); - r = scan(node.getTrueExpression(), r); - r = scan(node.getFalseExpression(), r); - return r; - } - - @Override - public PurityResult visitIf(IfTree node, PurityResult p) { - PurityResult r = scan(node.getCondition(), p); - r = scan(node.getThenStatement(), r); - r = scan(node.getElseStatement(), r); - return r; - } - - @Override - public PurityResult visitExpressionStatement(ExpressionStatementTree node, PurityResult p) { - return scan(node.getExpression(), p); - } - - @Override - public PurityResult visitBreak(BreakTree node, PurityResult p) { - return p; - } - - @Override - public PurityResult visitContinue(ContinueTree node, PurityResult p) { - return p; - } - - @Override - public PurityResult visitReturn(ReturnTree node, PurityResult p) { - return scan(node.getExpression(), p); - } - - @Override - public PurityResult visitThrow(ThrowTree node, PurityResult p) { - return scan(node.getExpression(), p); - } - - @Override - public PurityResult visitAssert(AssertTree node, PurityResult p) { - PurityResult r = scan(node.getCondition(), p); - r = scan(node.getDetail(), r); - return r; - } - - @Override - public PurityResult visitMethodInvocation(MethodInvocationTree node, PurityResult p) { - Element elt = TreeUtils.elementFromUse(node); - String reason = "call"; - if (!PurityUtils.hasPurityAnnotation(annoProvider, elt)) { - p.addNotBothReason(node, reason); - } else { - boolean det = PurityUtils.isDeterministic(annoProvider, elt); - boolean seFree = - (assumeSideEffectFree || PurityUtils.isSideEffectFree(annoProvider, elt)); - if (!det && !seFree) { - p.addNotBothReason(node, reason); - } else if (!det) { - p.addNotDetReason(node, reason); - } else if (!seFree) { - p.addNotSeFreeReason(node, reason); - } - } - PurityResult r = scan(node.getMethodSelect(), p); - r = scan(node.getArguments(), r); - return r; - } - - @Override - public PurityResult visitNewClass(NewClassTree node, PurityResult p) { - Element methodElement = InternalUtils.symbol(node); - boolean sideEffectFree = - (assumeSideEffectFree - || PurityUtils.isSideEffectFree(annoProvider, methodElement)); - if (sideEffectFree) { - p.addNotDetReason(node, "object.creation"); - } else { - p.addNotBothReason(node, "object.creation"); - } - PurityResult r = scan(node.getEnclosingExpression(), p); - r = scan(node.getArguments(), r); - r = scan(node.getClassBody(), r); - return r; - } - - @Override - public PurityResult visitNewArray(NewArrayTree node, PurityResult p) { - PurityResult r = scan(node.getDimensions(), p); - r = scan(node.getInitializers(), r); - return r; - } - - @Override - public PurityResult visitLambdaExpression(LambdaExpressionTree node, PurityResult p) { - PurityResult r = scan(node.getParameters(), p); - r = scan(node.getBody(), r); - return r; - } - - @Override - public PurityResult visitParenthesized(ParenthesizedTree node, PurityResult p) { - return scan(node.getExpression(), p); - } - - @Override - public PurityResult visitAssignment(AssignmentTree node, PurityResult p) { - ExpressionTree variable = node.getVariable(); - p = assignmentCheck(p, variable); - PurityResult r = scan(variable, p); - r = scan(node.getExpression(), r); - return r; - } - - protected PurityResult assignmentCheck(PurityResult p, ExpressionTree variable) { - if (TreeUtils.isFieldAccess(variable)) { - // rhs is a field access - p.addNotBothReason(variable, "assign.field"); - } else if (variable instanceof ArrayAccessTree) { - // rhs is array access - p.addNotBothReason(variable, "assign.array"); - } else { - // rhs is a local variable - assert isLocalVariable(variable); - } - return p; - } - - protected boolean isLocalVariable(ExpressionTree variable) { - return variable instanceof IdentifierTree && !TreeUtils.isFieldAccess(variable); - } - - @Override - public PurityResult visitCompoundAssignment(CompoundAssignmentTree node, PurityResult p) { - ExpressionTree variable = node.getVariable(); - p = assignmentCheck(p, variable); - PurityResult r = scan(variable, p); - r = scan(node.getExpression(), r); - return r; - } - - @Override - public PurityResult visitUnary(UnaryTree node, PurityResult p) { - return scan(node.getExpression(), p); - } - - @Override - public PurityResult visitBinary(BinaryTree node, PurityResult p) { - PurityResult r = scan(node.getLeftOperand(), p); - r = scan(node.getRightOperand(), r); - return r; - } - - @Override - public PurityResult visitTypeCast(TypeCastTree node, PurityResult p) { - PurityResult r = scan(node.getExpression(), p); - return r; - } - - @Override - public PurityResult visitInstanceOf(InstanceOfTree node, PurityResult p) { - PurityResult r = scan(node.getExpression(), p); - return r; - } - - @Override - public PurityResult visitArrayAccess(ArrayAccessTree node, PurityResult p) { - PurityResult r = scan(node.getExpression(), p); - r = scan(node.getIndex(), r); - return r; - } - - @Override - public PurityResult visitMemberSelect(MemberSelectTree node, PurityResult p) { - return scan(node.getExpression(), p); - } - - @Override - public PurityResult visitMemberReference(MemberReferenceTree node, PurityResult p) { - assert false : "this type of tree is unexpected here"; - return null; - } - - @Override - public PurityResult visitIdentifier(IdentifierTree node, PurityResult p) { - return p; - } - - @Override - public PurityResult visitLiteral(LiteralTree node, PurityResult p) { - return p; - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityUtils.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityUtils.java deleted file mode 100644 index c175877a24..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/util/PurityUtils.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.checkerframework.dataflow.util; - -import com.sun.source.tree.MethodTree; -import java.util.ArrayList; -import java.util.List; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import org.checkerframework.dataflow.qual.Deterministic; -import org.checkerframework.dataflow.qual.Pure; -import org.checkerframework.dataflow.qual.Pure.Kind; -import org.checkerframework.dataflow.qual.SideEffectFree; -import org.checkerframework.javacutil.AnnotationProvider; -import org.checkerframework.javacutil.InternalUtils; - -/** - * An utility class for working with the {@link SideEffectFree}, {@link Deterministic}, and {@link - * Pure} annotations. - * - * @see SideEffectFree - * @see Deterministic - * @see Pure - * @author Stefan Heule - */ -public class PurityUtils { - - /** Does the method {@code tree} have any purity annotation? */ - public static boolean hasPurityAnnotation(AnnotationProvider provider, MethodTree tree) { - return !getPurityKinds(provider, tree).isEmpty(); - } - - /** Does the method {@code methodElement} have any purity annotation? */ - public static boolean hasPurityAnnotation(AnnotationProvider provider, Element methodElement) { - return !getPurityKinds(provider, methodElement).isEmpty(); - } - - /** Is the method {@code tree} deterministic? */ - public static boolean isDeterministic(AnnotationProvider provider, MethodTree tree) { - Element methodElement = InternalUtils.symbol(tree); - return isDeterministic(provider, methodElement); - } - - /** Is the method {@code methodElement} deterministic? */ - public static boolean isDeterministic(AnnotationProvider provider, Element methodElement) { - List kinds = getPurityKinds(provider, methodElement); - return kinds.contains(Kind.DETERMINISTIC); - } - - /** Is the method {@code tree} side-effect-free? */ - public static boolean isSideEffectFree(AnnotationProvider provider, MethodTree tree) { - Element methodElement = InternalUtils.symbol(tree); - return isSideEffectFree(provider, methodElement); - } - - /** Is the method {@code methodElement} side-effect-free? */ - public static boolean isSideEffectFree(AnnotationProvider provider, Element methodElement) { - List kinds = getPurityKinds(provider, methodElement); - return kinds.contains(Kind.SIDE_EFFECT_FREE); - } - - /** @return the types of purity of the method {@code tree}. */ - public static List getPurityKinds(AnnotationProvider provider, MethodTree tree) { - Element methodElement = InternalUtils.symbol(tree); - return getPurityKinds(provider, methodElement); - } - - /** - * @return the types of purity of the method {@code methodElement}. TODO: should the return type - * be an EnumSet? - */ - public static List getPurityKinds( - AnnotationProvider provider, Element methodElement) { - AnnotationMirror pureAnnotation = provider.getDeclAnnotation(methodElement, Pure.class); - AnnotationMirror sefAnnotation = - provider.getDeclAnnotation(methodElement, SideEffectFree.class); - AnnotationMirror detAnnotation = - provider.getDeclAnnotation(methodElement, Deterministic.class); - - List kinds = new ArrayList<>(); - if (pureAnnotation != null) { - kinds.add(Kind.DETERMINISTIC); - kinds.add(Kind.SIDE_EFFECT_FREE); - } - if (sefAnnotation != null) { - kinds.add(Kind.SIDE_EFFECT_FREE); - } - if (detAnnotation != null) { - kinds.add(Kind.DETERMINISTIC); - } - return kinds; - } -} -- cgit v1.2.3

This map is used by {@link CFGTranslationPhaseOne#addToLookupMap(Node)} to associate a - * {@code ParenthesizedTree} with the dataflow {@code Node} that was used during inference. - * This map is necessary because dataflow does not create a {@code Node} for a {@code - * ParenthesizedTree.} - */ - private final Map parenMapping = new HashMap<>(); - - @Override - public Node visitParenthesized(ParenthesizedTree tree, Void p) { - parenMapping.put(tree.getExpression(), tree); - return scan(tree.getExpression(), p); - } - - @Override - public Node visitReturn(ReturnTree tree, Void p) { - ExpressionTree ret = tree.getExpression(); - // TODO: also have a return-node if nothing is returned - ReturnNode result = null; - if (ret != null) { - Node node = scan(ret, p); - Tree enclosing = - TreeUtils.enclosingOfKind( - getCurrentPath(), - new HashSet( - Arrays.asList(Kind.METHOD, Kind.LAMBDA_EXPRESSION))); - if (enclosing.getKind() == Kind.LAMBDA_EXPRESSION) { - LambdaExpressionTree lambdaTree = (LambdaExpressionTree) enclosing; - TreePath lambdaTreePath = - TreePath.getPath(getCurrentPath().getCompilationUnit(), lambdaTree); - Context ctx = ((JavacProcessingEnvironment) env).getContext(); - Element overriddenElement = - com.sun.tools.javac.code.Types.instance(ctx) - .findDescriptorSymbol( - ((Type) trees.getTypeMirror(lambdaTreePath)).tsym); - - result = - new ReturnNode( - tree, - node, - env.getTypeUtils(), - lambdaTree, - (MethodSymbol) overriddenElement); - } else { - result = new ReturnNode(tree, node, env.getTypeUtils(), (MethodTree) enclosing); - } - returnNodes.add(result); - extendWithNode(result); - } - extendWithExtendedNode(new UnconditionalJump(regularExitLabel)); - // TODO: return statements should also flow to an enclosing finally block - return result; - } - - @Override - public Node visitMemberSelect(MemberSelectTree tree, Void p) { - Node expr = scan(tree.getExpression(), p); - if (!TreeUtils.isFieldAccess(tree)) { - // Could be a selector of a class or package - Node result = null; - Element element = TreeUtils.elementFromUse(tree); - switch (element.getKind()) { - case ANNOTATION_TYPE: - case CLASS: - case ENUM: - case INTERFACE: - result = extendWithNode(new ClassNameNode(tree, expr)); - break; - case PACKAGE: - result = extendWithNode(new PackageNameNode(tree, (PackageNameNode) expr)); - break; - default: - assert false : "Unexpected element kind: " + element.getKind(); - return null; - } - return result; - } - - Node node = new FieldAccessNode(tree, expr); - - Element element = TreeUtils.elementFromUse(tree); - if (ElementUtils.isStatic(element) - || expr instanceof ImplicitThisLiteralNode - || expr instanceof ExplicitThisLiteralNode) { - // No NullPointerException can be thrown, use normal node - extendWithNode(node); - } else { - TypeElement npeElement = elements.getTypeElement("java.lang.NullPointerException"); - extendWithNodeWithException(node, npeElement.asType()); - } - - return node; - } - - @Override - public Node visitEmptyStatement(EmptyStatementTree tree, Void p) { - return null; - } - - @Override - public Node visitSynchronized(SynchronizedTree tree, Void p) { - // see JLS 14.19 - - Node synchronizedExpr = scan(tree.getExpression(), p); - SynchronizedNode synchronizedStartNode = - new SynchronizedNode(tree, synchronizedExpr, true, env.getTypeUtils()); - extendWithNode(synchronizedStartNode); - scan(tree.getBlock(), p); - SynchronizedNode synchronizedEndNode = - new SynchronizedNode(tree, synchronizedExpr, false, env.getTypeUtils()); - extendWithNode(synchronizedEndNode); - - return null; - } - - @Override - public Node visitThrow(ThrowTree tree, Void p) { - Node expression = scan(tree.getExpression(), p); - TypeMirror exception = expression.getType(); - ThrowNode throwsNode = new ThrowNode(tree, expression, env.getTypeUtils()); - NodeWithExceptionsHolder exNode = extendWithNodeWithException(throwsNode, exception); - exNode.setTerminatesExecution(true); - return throwsNode; - } - - @Override - public Node visitCompilationUnit(CompilationUnitTree tree, Void p) { - assert false : "CompilationUnitTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public Node visitTry(TryTree tree, Void p) { - List catches = tree.getCatches(); - BlockTree finallyBlock = tree.getFinallyBlock(); - - extendWithNode(new MarkerNode(tree, "start of try statement", env.getTypeUtils())); - - // TODO: Should we handle try-with-resources blocks by also generating code - // for automatically closing the resources? - List resources = tree.getResources(); - for (Tree resource : resources) { - scan(resource, p); - } - - List> catchLabels = new ArrayList<>(); - for (CatchTree c : catches) { - TypeMirror type = InternalUtils.typeOf(c.getParameter().getType()); - assert type != null : "exception parameters must have a type"; - catchLabels.add(Pair.of(type, new Label())); - } - - Label finallyLabel = null; - if (finallyBlock != null) { - finallyLabel = new Label(); - tryStack.pushFrame(new TryFinallyFrame(finallyLabel)); - } - - Label doneLabel = new Label(); - - tryStack.pushFrame(new TryCatchFrame(types, catchLabels)); - - scan(tree.getBlock(), p); - extendWithExtendedNode(new UnconditionalJump(firstNonNull(finallyLabel, doneLabel))); - - tryStack.popFrame(); - - int catchIndex = 0; - for (CatchTree c : catches) { - addLabelForNextNode(catchLabels.get(catchIndex).second); - scan(c, p); - catchIndex++; - extendWithExtendedNode( - new UnconditionalJump(firstNonNull(finallyLabel, doneLabel))); - } - - if (finallyLabel != null) { - tryStack.popFrame(); - addLabelForNextNode(finallyLabel); - scan(finallyBlock, p); - - TypeMirror throwableType = elements.getTypeElement("java.lang.Throwable").asType(); - extendWithNodeWithException( - new MarkerNode(tree, "end of finally block", env.getTypeUtils()), - throwableType); - } - - addLabelForNextNode(doneLabel); - - return null; - } - - @Override - public Node visitParameterizedType(ParameterizedTypeTree tree, Void p) { - return extendWithNode(new ParameterizedTypeNode(tree)); - } - - @Override - public Node visitUnionType(UnionTypeTree tree, Void p) { - assert false : "UnionTypeTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public Node visitArrayType(ArrayTypeTree tree, Void p) { - return extendWithNode(new ArrayTypeNode(tree)); - } - - @Override - public Node visitTypeCast(TypeCastTree tree, Void p) { - final Node operand = scan(tree.getExpression(), p); - final TypeMirror type = InternalUtils.typeOf(tree.getType()); - final Node node = new TypeCastNode(tree, operand, type); - final TypeElement cceElement = elements.getTypeElement("java.lang.ClassCastException"); - - extendWithNodeWithException(node, cceElement.asType()); - return node; - } - - @Override - public Node visitPrimitiveType(PrimitiveTypeTree tree, Void p) { - return extendWithNode(new PrimitiveTypeNode(tree)); - } - - @Override - public Node visitTypeParameter(TypeParameterTree tree, Void p) { - assert false : "TypeParameterTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public Node visitInstanceOf(InstanceOfTree tree, Void p) { - Node operand = scan(tree.getExpression(), p); - TypeMirror refType = InternalUtils.typeOf(tree.getType()); - InstanceOfNode node = new InstanceOfNode(tree, operand, refType, types); - extendWithNode(node); - return node; - } - - @Override - public Node visitUnary(UnaryTree tree, Void p) { - Node result = null; - Tree.Kind kind = tree.getKind(); - switch (kind) { - case BITWISE_COMPLEMENT: - case UNARY_MINUS: - case UNARY_PLUS: - { - // see JLS 15.14 and 15.15 - Node expr = scan(tree.getExpression(), p); - expr = unaryNumericPromotion(expr); - - // TypeMirror exprType = InternalUtils.typeOf(tree); - - switch (kind) { - case BITWISE_COMPLEMENT: - result = extendWithNode(new BitwiseComplementNode(tree, expr)); - break; - case UNARY_MINUS: - result = extendWithNode(new NumericalMinusNode(tree, expr)); - break; - case UNARY_PLUS: - result = extendWithNode(new NumericalPlusNode(tree, expr)); - break; - default: - assert false; - break; - } - break; - } - - case LOGICAL_COMPLEMENT: - { - // see JLS 15.15.6 - Node expr = scan(tree.getExpression(), p); - result = extendWithNode(new ConditionalNotNode(tree, unbox(expr))); - break; - } - - case POSTFIX_DECREMENT: - case POSTFIX_INCREMENT: - { - ExpressionTree exprTree = tree.getExpression(); - TypeMirror exprType = InternalUtils.typeOf(exprTree); - TypeMirror oneType = types.getPrimitiveType(TypeKind.INT); - Node expr = scan(exprTree, p); - - TypeMirror promotedType = binaryPromotedType(exprType, oneType); - - LiteralTree oneTree = treeBuilder.buildLiteral(Integer.valueOf(1)); - handleArtificialTree(oneTree); - - Node exprRHS = binaryNumericPromotion(expr, promotedType); - Node one = new IntegerLiteralNode(oneTree); - one.setInSource(false); - extendWithNode(one); - one = binaryNumericPromotion(one, promotedType); - - BinaryTree operTree = - treeBuilder.buildBinary( - promotedType, - (kind == Tree.Kind.POSTFIX_INCREMENT - ? Tree.Kind.PLUS - : Tree.Kind.MINUS), - exprTree, - oneTree); - handleArtificialTree(operTree); - Node operNode; - if (kind == Tree.Kind.POSTFIX_INCREMENT) { - operNode = new NumericalAdditionNode(operTree, exprRHS, one); - } else { - assert kind == Tree.Kind.POSTFIX_DECREMENT; - operNode = new NumericalSubtractionNode(operTree, exprRHS, one); - } - extendWithNode(operNode); - - Node narrowed = narrowAndBox(operNode, exprType); - // TODO: By using the assignment as the result of the expression, we - // act like a pre-increment/decrement. Fix this by saving the initial - // value of the expression in a temporary. - AssignmentNode assignNode = new AssignmentNode(tree, expr, narrowed); - extendWithNode(assignNode); - result = assignNode; - break; - } - case PREFIX_DECREMENT: - case PREFIX_INCREMENT: - { - ExpressionTree exprTree = tree.getExpression(); - TypeMirror exprType = InternalUtils.typeOf(exprTree); - TypeMirror oneType = types.getPrimitiveType(TypeKind.INT); - Node expr = scan(exprTree, p); - - TypeMirror promotedType = binaryPromotedType(exprType, oneType); - - LiteralTree oneTree = treeBuilder.buildLiteral(Integer.valueOf(1)); - handleArtificialTree(oneTree); - - Node exprRHS = binaryNumericPromotion(expr, promotedType); - Node one = new IntegerLiteralNode(oneTree); - one.setInSource(false); - extendWithNode(one); - one = binaryNumericPromotion(one, promotedType); - - BinaryTree operTree = - treeBuilder.buildBinary( - promotedType, - (kind == Tree.Kind.PREFIX_INCREMENT - ? Tree.Kind.PLUS - : Tree.Kind.MINUS), - exprTree, - oneTree); - handleArtificialTree(operTree); - Node operNode; - if (kind == Tree.Kind.PREFIX_INCREMENT) { - operNode = new NumericalAdditionNode(operTree, exprRHS, one); - } else { - assert kind == Tree.Kind.PREFIX_DECREMENT; - operNode = new NumericalSubtractionNode(operTree, exprRHS, one); - } - extendWithNode(operNode); - - Node narrowed = narrowAndBox(operNode, exprType); - AssignmentNode assignNode = new AssignmentNode(tree, expr, narrowed); - extendWithNode(assignNode); - result = assignNode; - break; - } - - case OTHER: - default: - // special node NLLCHK - if (tree.toString().startsWith("<*nullchk*>")) { - Node expr = scan(tree.getExpression(), p); - result = extendWithNode(new NullChkNode(tree, expr)); - break; - } - - assert false : "Unknown kind (" + kind + ") of unary expression: " + tree; - } - - return result; - } - - @Override - public Node visitVariable(VariableTree tree, Void p) { - - // see JLS 14.4 - - boolean isField = - getCurrentPath().getParentPath() != null - && getCurrentPath().getParentPath().getLeaf().getKind() == Kind.CLASS; - Node node = null; - - ClassTree enclosingClass = TreeUtils.enclosingClass(getCurrentPath()); - TypeElement classElem = TreeUtils.elementFromDeclaration(enclosingClass); - Node receiver = new ImplicitThisLiteralNode(classElem.asType()); - - if (isField) { - ExpressionTree initializer = tree.getInitializer(); - assert initializer != null; - node = - translateAssignment( - tree, - new FieldAccessNode( - tree, TreeUtils.elementFromDeclaration(tree), receiver), - initializer); - } else { - // local variable definition - VariableDeclarationNode decl = new VariableDeclarationNode(tree); - extendWithNode(decl); - - // initializer - - ExpressionTree initializer = tree.getInitializer(); - if (initializer != null) { - node = - translateAssignment( - tree, new LocalVariableNode(tree, receiver), initializer); - } - } - - return node; - } - - @Override - public Node visitWhileLoop(WhileLoopTree tree, Void p) { - Name parentLabel = getLabel(getCurrentPath()); - - Label loopEntry = new Label(); - Label loopExit = new Label(); - - // If the loop is a labeled statement, then its continue - // target is identical for continues with no label and - // continues with the loop's label. - Label conditionStart; - if (parentLabel != null) { - conditionStart = continueLabels.get(parentLabel); - } else { - conditionStart = new Label(); - } - - Label oldBreakTargetL = breakTargetL; - breakTargetL = loopExit; - - Label oldContinueTargetL = continueTargetL; - continueTargetL = conditionStart; - - // Condition - addLabelForNextNode(conditionStart); - if (tree.getCondition() != null) { - unbox(scan(tree.getCondition(), p)); - ConditionalJump cjump = new ConditionalJump(loopEntry, loopExit); - extendWithExtendedNode(cjump); - } - - // Loop body - addLabelForNextNode(loopEntry); - if (tree.getStatement() != null) { - scan(tree.getStatement(), p); - } - extendWithExtendedNode(new UnconditionalJump(conditionStart)); - - // Loop exit - addLabelForNextNode(loopExit); - - breakTargetL = oldBreakTargetL; - continueTargetL = oldContinueTargetL; - - return null; - } - - @Override - public Node visitLambdaExpression(LambdaExpressionTree tree, Void p) { - declaredLambdas.add(tree); - Node node = new FunctionalInterfaceNode(tree); - extendWithNode(node); - return node; - } - - @Override - public Node visitMemberReference(MemberReferenceTree tree, Void p) { - Tree enclosingExpr = tree.getQualifierExpression(); - if (enclosingExpr != null) { - scan(enclosingExpr, p); - } - - Node node = new FunctionalInterfaceNode(tree); - extendWithNode(node); - - return node; - } - - @Override - public Node visitWildcard(WildcardTree tree, Void p) { - assert false : "WildcardTree is unexpected in AST to CFG translation"; - return null; - } - - @Override - public Node visitOther(Tree tree, Void p) { - assert false : "Unknown AST element encountered in AST to CFG translation."; - return null; - } - } - - /** A tuple with 4 named elements. */ - private interface TreeInfo { - boolean isBoxed(); - - boolean isNumeric(); - - boolean isBoolean(); - - TypeMirror unboxedType(); - } - - private static A firstNonNull(A first, A second) { - if (first != null) { - return first; - } else if (second != null) { - return second; - } else { - throw new NullPointerException(); - } - } - - /* --------------------------------------------------------- */ - /* Utility routines for debugging CFG building */ - /* --------------------------------------------------------- */ - - /** - * Print a set of {@link Block}s and the edges between them. This is useful for examining the - * results of phase two. - */ - protected static void printBlocks(Set blocks) { - for (Block b : blocks) { - System.out.print(b.hashCode() + ": " + b); - switch (b.getType()) { - case REGULAR_BLOCK: - case SPECIAL_BLOCK: - { - Block succ = ((SingleSuccessorBlockImpl) b).getSuccessor(); - System.out.println(" -> " + (succ != null ? succ.hashCode() : "||")); - break; - } - case EXCEPTION_BLOCK: - { - Block succ = ((SingleSuccessorBlockImpl) b).getSuccessor(); - System.out.print(" -> " + (succ != null ? succ.hashCode() : "||") + " {"); - for (Map.Entry> entry : - ((ExceptionBlockImpl) b).getExceptionalSuccessors().entrySet()) { - System.out.print(entry.getKey() + " : " + entry.getValue() + ", "); - } - System.out.println("}"); - break; - } - case CONDITIONAL_BLOCK: - { - Block tSucc = ((ConditionalBlockImpl) b).getThenSuccessor(); - Block eSucc = ((ConditionalBlockImpl) b).getElseSuccessor(); - System.out.println( - " -> T " - + (tSucc != null ? tSucc.hashCode() : "||") - + " F " - + (eSucc != null ? eSucc.hashCode() : "||")); - break; - } - } - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/CFGVisualizer.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/CFGVisualizer.java deleted file mode 100644 index 9378d83726..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/cfg/CFGVisualizer.java +++ /dev/null @@ -1,167 +0,0 @@ -package org.checkerframework.dataflow.cfg; - -/*>>> -import org.checkerframework.checker.nullness.qual.Nullable; -*/ - -import java.util.Map; -import org.checkerframework.dataflow.analysis.AbstractValue; -import org.checkerframework.dataflow.analysis.Analysis; -import org.checkerframework.dataflow.analysis.FlowExpressions; -import org.checkerframework.dataflow.analysis.Store; -import org.checkerframework.dataflow.analysis.TransferFunction; -import org.checkerframework.dataflow.cfg.block.Block; -import org.checkerframework.dataflow.cfg.block.SpecialBlock; -import org.checkerframework.dataflow.cfg.node.Node; - -/** - * Perform some visualization on a control flow graph. The particular operations depend on the - * implementation. - */ -public interface CFGVisualizer< - A extends AbstractValue, S extends Store, T extends TransferFunction> { - /** - * Initialization method guaranteed to be called once before the first invocation of {@link - * visualize}. - * - * @param args implementation-dependent options - */ - void init(Map args); - - /** - * Output a visualization representing the control flow graph starting at {@code entry}. The - * concrete actions are implementation dependent. - * - *

This is always true, except for cases where the Java type information prevents - * aliasing and none of the subexpressions can alias 'other'. - */ - public boolean containsModifiableAliasOf(Store store, Receiver other) { - return this.equals(other) || store.canAlias(this, other); - } - } - - public static class FieldAccess extends Receiver { - protected Receiver receiver; - protected VariableElement field; - - public Receiver getReceiver() { - return receiver; - } - - public VariableElement getField() { - return field; - } - - public FieldAccess(Receiver receiver, FieldAccessNode node) { - super(node.getType()); - this.receiver = receiver; - this.field = node.getElement(); - } - - public FieldAccess(Receiver receiver, TypeMirror type, VariableElement fieldElement) { - super(type); - this.receiver = receiver; - this.field = fieldElement; - } - - public boolean isFinal() { - return ElementUtils.isFinal(field); - } - - public boolean isStatic() { - return ElementUtils.isStatic(field); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof FieldAccess)) { - return false; - } - FieldAccess fa = (FieldAccess) obj; - return fa.getField().equals(getField()) && fa.getReceiver().equals(getReceiver()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getField(), getReceiver()); - } - - @Override - public boolean containsModifiableAliasOf(Store store, Receiver other) { - return super.containsModifiableAliasOf(store, other) - || receiver.containsModifiableAliasOf(store, other); - } - - @Override - public boolean containsSyntacticEqualReceiver(Receiver other) { - return syntacticEquals(other) || receiver.containsSyntacticEqualReceiver(other); - } - - @Override - public boolean syntacticEquals(Receiver other) { - if (!(other instanceof FieldAccess)) { - return false; - } - FieldAccess fa = (FieldAccess) other; - return super.syntacticEquals(other) - || (fa.getField().equals(getField()) - && fa.getReceiver().syntacticEquals(getReceiver())); - } - - @Override - public String toString() { - if (receiver instanceof ClassName) { - return receiver.getType() + "." + field; - } else { - return receiver + "." + field; - } - } - - @Override - public boolean containsOfClass(Class clazz) { - return getClass().equals(clazz) || receiver.containsOfClass(clazz); - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return isFinal() && getReceiver().isUnmodifiableByOtherCode(); - } - } - - public static class ThisReference extends Receiver { - public ThisReference(TypeMirror type) { - super(type); - } - - @Override - public boolean equals(Object obj) { - return obj != null && obj instanceof ThisReference; - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(0); - } - - @Override - public String toString() { - return "this"; - } - - @Override - public boolean containsOfClass(Class clazz) { - return getClass().equals(clazz); - } - - @Override - public boolean syntacticEquals(Receiver other) { - return other instanceof ThisReference; - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return true; - } - - @Override - public boolean containsModifiableAliasOf(Store store, Receiver other) { - return false; // 'this' is not modifiable - } - } - - /** - * A ClassName represents the occurrence of a class as part of a static field access or method - * invocation. - */ - public static class ClassName extends Receiver { - public ClassName(TypeMirror type) { - super(type); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ClassName)) { - return false; - } - ClassName other = (ClassName) obj; - return getType().toString().equals(other.getType().toString()); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(getType().toString()); - } - - @Override - public String toString() { - return getType().toString() + ".class"; - } - - @Override - public boolean containsOfClass(Class clazz) { - return getClass().equals(clazz); - } - - @Override - public boolean syntacticEquals(Receiver other) { - return this.equals(other); - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return true; - } - - @Override - public boolean containsModifiableAliasOf(Store store, Receiver other) { - return false; // not modifiable - } - } - - public static class Unknown extends Receiver { - public Unknown(TypeMirror type) { - super(type); - } - - @Override - public boolean equals(Object obj) { - return obj == this; - } - - @Override - public int hashCode() { - return System.identityHashCode(this); - } - - @Override - public String toString() { - return "?"; - } - - @Override - public boolean containsModifiableAliasOf(Store store, Receiver other) { - return true; - } - - @Override - public boolean containsOfClass(Class clazz) { - return getClass().equals(clazz); - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return false; - } - } - - public static class LocalVariable extends Receiver { - protected Element element; - - public LocalVariable(LocalVariableNode localVar) { - super(localVar.getType()); - this.element = localVar.getElement(); - } - - public LocalVariable(Element elem) { - super(ElementUtils.getType(elem)); - this.element = elem; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof LocalVariable)) { - return false; - } - LocalVariable other = (LocalVariable) obj; - VarSymbol vs = (VarSymbol) element; - VarSymbol vsother = (VarSymbol) other.element; - // Use TypeAnnotationUtils.unannotatedType(type).toString().equals(...) instead of Types.isSameType(...) - // because Types requires a processing environment, and FlowExpressions is - // designed to be independent of processing environment. See also - // calls to getType().toString() in FlowExpressions. - return vsother.name.contentEquals(vs.name) - && TypeAnnotationUtils.unannotatedType(vsother.type) - .toString() - .equals(TypeAnnotationUtils.unannotatedType(vs.type).toString()) - && vsother.owner.toString().equals(vs.owner.toString()); - } - - public Element getElement() { - return element; - } - - @Override - public int hashCode() { - VarSymbol vs = (VarSymbol) element; - return HashCodeUtils.hash( - vs.name.toString(), - TypeAnnotationUtils.unannotatedType(vs.type).toString(), - vs.owner.toString()); - } - - @Override - public String toString() { - return element.toString(); - } - - @Override - public boolean containsOfClass(Class clazz) { - return getClass().equals(clazz); - } - - @Override - public boolean syntacticEquals(Receiver other) { - if (!(other instanceof LocalVariable)) { - return false; - } - LocalVariable l = (LocalVariable) other; - return l.equals(this); - } - - @Override - public boolean containsSyntacticEqualReceiver(Receiver other) { - return syntacticEquals(other); - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return true; - } - } - - public static class ValueLiteral extends Receiver { - - protected final Object value; - - public ValueLiteral(TypeMirror type, ValueLiteralNode node) { - super(type); - value = node.getValue(); - } - - public ValueLiteral(TypeMirror type, Object value) { - super(type); - this.value = value; - } - - @Override - public boolean containsOfClass(Class clazz) { - return getClass().equals(clazz); - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return true; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ValueLiteral)) { - return false; - } - ValueLiteral other = (ValueLiteral) obj; - if (value == null) { - return type.toString().equals(other.type.toString()) && other.value == null; - } - return type.toString().equals(other.type.toString()) && value.equals(other.value); - } - - @Override - public String toString() { - if (TypesUtils.isString(type)) { - return "\"" + value + "\""; - } else if (type.getKind() == TypeKind.LONG) { - return value.toString() + "L"; - } - return value == null ? "null" : value.toString(); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(value, type.toString()); - } - - @Override - public boolean syntacticEquals(Receiver other) { - return this.equals(other); - } - - @Override - public boolean containsModifiableAliasOf(Store store, Receiver other) { - return false; // not modifiable - } - - public Object getValue() { - return value; - } - } - - /** A method call. */ - public static class MethodCall extends Receiver { - - protected final Receiver receiver; - protected final List parameters; - protected final ExecutableElement method; - - public MethodCall( - TypeMirror type, - ExecutableElement method, - Receiver receiver, - List parameters) { - super(type); - this.receiver = receiver; - this.parameters = parameters; - this.method = method; - } - - @Override - public boolean containsOfClass(Class clazz) { - if (getClass().equals(clazz)) { - return true; - } - if (receiver.containsOfClass(clazz)) { - return true; - } - for (Receiver p : parameters) { - if (p.containsOfClass(clazz)) { - return true; - } - } - return false; - } - - /** @return the method call receiver (for inspection only - do not modify) */ - public Receiver getReceiver() { - return receiver; - } - - /** - * @return the method call parameters (for inspection only - do not modify any of the - * parameters) - */ - public List getParameters() { - return Collections.unmodifiableList(parameters); - } - - /** @return the ExecutableElement for the method call */ - public ExecutableElement getElement() { - return method; - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return false; - } - - @Override - public boolean containsSyntacticEqualReceiver(Receiver other) { - return syntacticEquals(other) || receiver.syntacticEquals(other); - } - - @Override - public boolean syntacticEquals(Receiver other) { - if (!(other instanceof MethodCall)) { - return false; - } - MethodCall otherMethod = (MethodCall) other; - if (!receiver.syntacticEquals(otherMethod.receiver)) { - return false; - } - if (parameters.size() != otherMethod.parameters.size()) { - return false; - } - int i = 0; - for (Receiver p : parameters) { - if (!p.syntacticEquals(otherMethod.parameters.get(i))) { - return false; - } - i++; - } - return method.equals(otherMethod.method); - } - - public boolean containsSyntacticEqualParameter(LocalVariable var) { - for (Receiver p : parameters) { - if (p.containsSyntacticEqualReceiver(var)) { - return true; - } - } - return false; - } - - @Override - public boolean containsModifiableAliasOf(Store store, Receiver other) { - if (receiver.containsModifiableAliasOf(store, other)) { - return true; - } - for (Receiver p : parameters) { - if (p.containsModifiableAliasOf(store, other)) { - return true; - } - } - return false; // the method call itself is not modifiable - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof MethodCall)) { - return false; - } - MethodCall other = (MethodCall) obj; - int i = 0; - for (Receiver p : parameters) { - if (!p.equals(other.parameters.get(i))) { - return false; - } - i++; - } - return receiver.equals(other.receiver) && method.equals(other.method); - } - - @Override - public int hashCode() { - int hash = HashCodeUtils.hash(method, receiver); - for (Receiver p : parameters) { - hash = HashCodeUtils.hash(hash, p); - } - return hash; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - if (receiver instanceof ClassName) { - result.append(receiver.getType()); - } else { - result.append(receiver); - } - result.append("."); - String methodName = method.getSimpleName().toString(); - result.append(methodName); - result.append("("); - boolean first = true; - for (Receiver p : parameters) { - if (!first) { - result.append(", "); - } - result.append(p.toString()); - first = false; - } - result.append(")"); - return result.toString(); - } - } - - /** A deterministic method call. */ - public static class ArrayAccess extends Receiver { - - protected final Receiver receiver; - protected final Receiver index; - - public ArrayAccess(TypeMirror type, Receiver receiver, Receiver index) { - super(type); - this.receiver = receiver; - this.index = index; - } - - @Override - public boolean containsOfClass(Class clazz) { - if (getClass().equals(clazz)) { - return true; - } - if (receiver.containsOfClass(clazz)) { - return true; - } - return index.containsOfClass(clazz); - } - - public Receiver getReceiver() { - return receiver; - } - - public Receiver getIndex() { - return index; - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return false; - } - - @Override - public boolean containsSyntacticEqualReceiver(Receiver other) { - return syntacticEquals(other) - || receiver.syntacticEquals(other) - || index.syntacticEquals(other); - } - - @Override - public boolean syntacticEquals(Receiver other) { - if (!(other instanceof ArrayAccess)) { - return false; - } - ArrayAccess otherArrayAccess = (ArrayAccess) other; - if (!receiver.syntacticEquals(otherArrayAccess.receiver)) { - return false; - } - return index.syntacticEquals(otherArrayAccess.index); - } - - @Override - public boolean containsModifiableAliasOf(Store store, Receiver other) { - if (receiver.containsModifiableAliasOf(store, other)) { - return true; - } - return index.containsModifiableAliasOf(store, other); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ArrayAccess)) { - return false; - } - ArrayAccess other = (ArrayAccess) obj; - return receiver.equals(other.receiver) && index.equals(other.index); - } - - @Override - public int hashCode() { - return HashCodeUtils.hash(receiver, index); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append(receiver.toString()); - result.append("["); - result.append(index.toString()); - result.append("]"); - return result.toString(); - } - } - - public static class ArrayCreation extends Receiver { - - protected List dimensions; - protected List initializers; - - public ArrayCreation(TypeMirror type, List dimensions, List initializers) { - super(type); - this.dimensions = dimensions; - this.initializers = initializers; - } - - public List getDimensions() { - return dimensions; - } - - public List getInitializers() { - return initializers; - } - - @Override - public boolean containsOfClass(Class clazz) { - for (Node n : dimensions) { - if (n.getClass().equals(clazz)) return true; - } - for (Node n : initializers) { - if (n.getClass().equals(clazz)) return true; - } - return false; - } - - @Override - public boolean isUnmodifiableByOtherCode() { - return false; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((dimensions == null) ? 0 : dimensions.hashCode()); - result = prime * result + ((initializers == null) ? 0 : initializers.hashCode()); - result = prime * result + HashCodeUtils.hash(getType().toString()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof ArrayCreation)) { - return false; - } - ArrayCreation other = (ArrayCreation) obj; - return this.dimensions.equals(other.getDimensions()) - && this.initializers.equals(other.getInitializers()) - && getType().toString().equals(other.getType().toString()); - } - - @Override - public boolean syntacticEquals(Receiver other) { - return this.equals(other); - } - - @Override - public boolean containsSyntacticEqualReceiver(Receiver other) { - return syntacticEquals(other); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("new " + type); - if (!dimensions.isEmpty()) { - boolean needComma = false; - sb.append(" ("); - for (Node dim : dimensions) { - if (needComma) { - sb.append(", "); - } - sb.append(dim); - needComma = true; - } - sb.append(")"); - } - if (!initializers.isEmpty()) { - boolean needComma = false; - sb.append(" = {"); - for (Node init : initializers) { - if (needComma) { - sb.append(", "); - } - sb.append(init); - needComma = true; - } - sb.append("}"); - } - return sb.toString(); - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/RegularTransferResult.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/RegularTransferResult.java deleted file mode 100644 index b4044fae83..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/RegularTransferResult.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -import java.util.Map; -import javax.lang.model.type.TypeMirror; - -/** - * Implementation of a {@link TransferResult} with just one non-exceptional store. The result of - * {@code getThenStore} and {@code getElseStore} is equal to the only underlying store. - * - * @author Stefan Heule - * @param the {@link Store} used to keep track of intermediate results - */ -public class RegularTransferResult, S extends Store> - extends TransferResult { - - /** The regular result store. */ - protected S store; - - private final boolean storeChanged; - - /** - * Create a {@code TransferResult} with {@code resultStore} as the resulting store. If the - * corresponding {@link org.checkerframework.dataflow.cfg.node.Node} is a boolean node, then - * {@code resultStore} is used for both the 'then' and 'else' edge. - * - *

If the given {@link Node} cannot be reached (in the control flow graph), then {@code null} - * is returned. - */ - protected S runAnalysisFor(Node node, boolean before) { - Block block = node.getBlock(); - TransferInput transferInput = stores.get(block); - if (transferInput == null) { - return null; - } - return runAnalysisFor(node, before, transferInput); - } - - /** - * Runs the analysis again within the block of {@code node} and returns the store at the - * location of {@code node}. If {@code before} is true, then the store immediately before the - * {@link Node} {@code node} is returned. Otherwise, the store after {@code node} is returned. - */ - public static , S extends Store> S runAnalysisFor( - Node node, boolean before, TransferInput transferInput) { - assert node != null; - Block block = node.getBlock(); - assert transferInput != null; - Analysis analysis = transferInput.analysis; - Node oldCurrentNode = analysis.currentNode; - - if (analysis.isRunning) { - return analysis.currentInput.getRegularStore(); - } - analysis.isRunning = true; - try { - switch (block.getType()) { - case REGULAR_BLOCK: - { - RegularBlock rb = (RegularBlock) block; - - // Apply transfer function to contents until we found the node - // we - // are looking for. - TransferInput store = transferInput; - TransferResult transferResult = null; - for (Node n : rb.getContents()) { - analysis.currentNode = n; - if (n == node && before) { - return store.getRegularStore(); - } - transferResult = analysis.callTransferFunction(n, store); - if (n == node) { - return transferResult.getRegularStore(); - } - store = new TransferInput<>(n, analysis, transferResult); - } - // This point should never be reached. If the block of 'node' is - // 'block', then 'node' must be part of the contents of 'block'. - assert false; - return null; - } - - case EXCEPTION_BLOCK: - { - ExceptionBlock eb = (ExceptionBlock) block; - - // apply transfer function to content - assert eb.getNode() == node; - if (before) { - return transferInput.getRegularStore(); - } - analysis.currentNode = node; - TransferResult transferResult = - analysis.callTransferFunction(node, transferInput); - return transferResult.getRegularStore(); - } - - default: - // Only regular blocks and exceptional blocks can hold nodes. - assert false; - break; - } - - return null; - } finally { - analysis.currentNode = oldCurrentNode; - analysis.isRunning = false; - } - } -} diff --git a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/ConditionalTransferResult.java b/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/ConditionalTransferResult.java deleted file mode 100644 index 99a8a525ec..0000000000 --- a/third_party/checker_framework_dataflow/java/org/checkerframework/dataflow/analysis/ConditionalTransferResult.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.checkerframework.dataflow.analysis; - -import java.util.Map; -import javax.lang.model.type.TypeMirror; - -/** - * Implementation of a {@link TransferResult} with two non-exceptional store; one for the 'then' - * edge and one for 'else'. The result of {@code getRegularStore} will be the least upper bound of - * the two underlying stores. - * - * @author Stefan Heule - * @param the {@link Store} used to keep track of intermediate results - */ -public class ConditionalTransferResult, S extends Store> - extends TransferResult { - - private final boolean storeChanged; - - /** The 'then' result store. */ - protected S thenStore; - - /** The 'else' result store. */ - protected S elseStore; - - /** - * Create a {@code ConditionalTransferResult} with {@code thenStore} as the resulting store if - * the corresponding {@link org.checkerframework.dataflow.cfg.node.Node} evaluates to {@code - * true} and {@code elseStore} otherwise. - * - *