public class DefiniteAssignmentChecker extends DataFlow<DefiniteAssignmentChecker.FlowItem>
checkOther to check that the uses of these
local variables are correctly initialized. (The implementation of the method will
probably call checkLocalInstanceInit to see if the local used is initialized).
If language extensions have new constructs that assign to local variables,
they can override the method flowOther to capture the way
the new construct's initialization behavior.| Modifier and Type | Class and Description |
|---|---|
protected static class |
DefiniteAssignmentChecker.AssignmentStatus
Class representing the initialization counts of variables.
|
protected static class |
DefiniteAssignmentChecker.ClassBodyInfo
This class is just a data structure containing relevant information
needed for performing initialization checking of a class declaration.
|
protected static class |
DefiniteAssignmentChecker.FlowItem
Dataflow items for this dataflow are maps of VarInstances to counts
of the min and max number of times those variables/fields have
been initialized.
|
DataFlow.BoolItem<FlowItem extends DataFlow.Item>, DataFlow.ConditionNavigator<FlowItem extends DataFlow.Item>, DataFlow.FlowGraphSource<FlowItem extends DataFlow.Item>, DataFlow.Frame<FlowItem extends DataFlow.Item>, DataFlow.Item| Modifier and Type | Field and Description |
|---|---|
protected static DefiniteAssignmentChecker.FlowItem |
BOTTOM |
protected DefiniteAssignmentChecker.ClassBodyInfo |
currCBI |
dataflowOnEntry, detectBackEdges, flowCounter, flowgraphStack, forward, postorderingerror, job, nf, tsbypass, bypassParent| Constructor and Description |
|---|
DefiniteAssignmentChecker(Job job,
TypeSystem ts,
NodeFactory nf) |
| Modifier and Type | Method and Description |
|---|---|
void |
check(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
Term n,
boolean entry,
DefiniteAssignmentChecker.FlowItem inItem,
java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> outItems)
Check that the conditions of initialization are not broken.
|
protected void |
checkClassBody(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
ClassBody cb,
DefiniteAssignmentChecker.FlowItem dfIn,
DefiniteAssignmentChecker.FlowItem dfOut)
Check that the set of
LocalInstances
localsUsed, which is the set of locals used in the inner
class declared by cb
are initialized before the class declaration. |
protected void |
checkField(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
Field f,
DefiniteAssignmentChecker.FlowItem dfIn)
Check that the field
f is used correctly. |
protected void |
checkFieldAssign(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
FieldAssign a,
DefiniteAssignmentChecker.FlowItem dfIn)
Check that the assignment to a field is correct.
|
protected void |
checkLocal(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
Local l,
DefiniteAssignmentChecker.FlowItem dfIn)
Check that the local variable
l is used correctly. |
protected void |
checkLocalAssign(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
LocalInstance li,
Position pos,
DefiniteAssignmentChecker.FlowItem dfIn)
Check that the assignment to a local variable is correct.
|
protected void |
checkLocalInstanceInit(LocalInstance li,
DefiniteAssignmentChecker.FlowItem dfIn,
Position pos) |
protected void |
checkLocalsUsedByInnerClass(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
ClassBody cb,
java.util.Set<LocalInstance> localsUsed,
DefiniteAssignmentChecker.FlowItem dfIn,
DefiniteAssignmentChecker.FlowItem dfOut)
Check that the set of
LocalInstances
localsUsed, which is the set of locals used in the inner
class declared by cb
are initialized before the class declaration. |
protected void |
checkNonStaticFinalFieldsInit(ClassBody cb)
Check that each non static final field has been initialized exactly once,
taking into account the fact that constructors may call other
constructors.
|
protected void |
checkOther(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
Node n,
DefiniteAssignmentChecker.FlowItem dfIn)
Allow subclasses to override the checking of other nodes, if needed.
|
protected void |
checkStaticFinalFieldsInit(ClassBody cb)
Check that each static final field is initialized exactly once.
|
DefiniteAssignmentChecker.FlowItem |
confluence(java.util.List<DefiniteAssignmentChecker.FlowItem> inItems,
FlowGraph.Peer<DefiniteAssignmentChecker.FlowItem> peer,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph)
The confluence operator is essentially the union of all of the
inItems.
|
protected DefiniteAssignmentChecker.FlowItem |
confluence(java.util.List<DefiniteAssignmentChecker.FlowItem> items,
java.util.List<FlowGraph.EdgeKey> itemKeys,
FlowGraph.Peer<DefiniteAssignmentChecker.FlowItem> peer,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph)
The confluence operator for
Initializers and
Constructors needs to be a
little special, as we are only concerned with non-exceptional flows in
these cases. |
protected CFGBuilder<DefiniteAssignmentChecker.FlowItem> |
createCFGBuilder(TypeSystem ts,
FlowGraph<DefiniteAssignmentChecker.FlowItem> g)
Construct a CFGBuilder.
|
DefiniteAssignmentChecker.FlowItem |
createInitialItem(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
Term node,
boolean entry)
The initial item to be given to the entry point of the dataflow contains
the init counts for the final fields.
|
protected void |
dataflow(Expr root)
Construct a flow graph for the
Expr provided, and call
dataflow(FlowGraph). |
protected NodeVisitor |
enterCall(Node parent,
Node n)
Overridden superclass method.
|
protected void |
finishConstructorDecl(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
ConstructorDecl cd,
DefiniteAssignmentChecker.FlowItem dfIn,
DefiniteAssignmentChecker.FlowItem dfOut)
Perform necessary actions upon seeing the ConstructorDecl
cd. |
protected void |
finishFieldDecl(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
FieldDecl fd,
DefiniteAssignmentChecker.FlowItem dfIn,
DefiniteAssignmentChecker.FlowItem dfOut)
Perform necessary actions upon seeing the FieldDecl
fd. |
protected void |
finishInitializer(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
Initializer initializer,
DefiniteAssignmentChecker.FlowItem dfIn,
DefiniteAssignmentChecker.FlowItem dfOut)
Perform necessary actions upon seeing the Initializer
initializer. |
java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> |
flow(DefiniteAssignmentChecker.FlowItem trueItem,
DefiniteAssignmentChecker.FlowItem falseItem,
DefiniteAssignmentChecker.FlowItem otherItem,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
FlowGraph.Peer<DefiniteAssignmentChecker.FlowItem> peer)
Perform the appropriate flow operations for the Terms.
|
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> |
flow(java.util.List<DefiniteAssignmentChecker.FlowItem> inItems,
java.util.List<FlowGraph.EdgeKey> inItemKeys,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
FlowGraph.Peer<DefiniteAssignmentChecker.FlowItem> peer)
Produce new
Items as appropriate for the peer's node
and the input Items. |
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> |
flowConstructorCall(DefiniteAssignmentChecker.FlowItem inItem,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
ConstructorCall cc,
java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
Perform the appropriate flow operations for a constructor call
|
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> |
flowFieldAssign(DefiniteAssignmentChecker.FlowItem inItem,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
FieldAssign a,
java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
Perform the appropriate flow operations for assignment to a field
|
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> |
flowFormal(DefiniteAssignmentChecker.FlowItem inItem,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
Formal f,
java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
Perform the appropriate flow operations for declaration of a formal
parameter
|
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> |
flowLocalAssign(DefiniteAssignmentChecker.FlowItem inItem,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
LocalAssign a,
java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
Perform the appropriate flow operations for assignment to a local
variable
|
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> |
flowLocalDecl(DefiniteAssignmentChecker.FlowItem inItem,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
LocalDecl ld,
java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
Perform the appropriate flow operations for declaration of a local
variable
|
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> |
flowOther(DefiniteAssignmentChecker.FlowItem inItem,
FlowGraph<DefiniteAssignmentChecker.FlowItem> graph,
Node n,
java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
Allow subclasses to override if necessary.
|
protected FlowGraph<DefiniteAssignmentChecker.FlowItem> |
initGraph(CodeNode code,
Term root)
Initialize the FlowGraph to be used in the dataflow analysis.
|
protected boolean |
isFieldsTargetAppropriate(Field f)
Determine if we are interested in this field on the basis of the
target of the field.
|
protected Node |
leaveCall(Node old,
Node n,
NodeVisitor v)
Postpone the checking of constructors until the end of the class
declaration is encountered, to ensure that all initializers are
processed first.
|
protected void |
setupClassBody(ClassType ct,
ClassBody n) |
check, constructItemsFromCondition, createFrame, createInitialItem, currentFlowGraph, dataflow, dataflow, dataflow, dumpFlowGraph, enterCall, filterItems, filterItemsExceptionSubclass, filterItemsNonError, filterItemsNonException, findSCCs, flow, flow, flow, flowBooleanConditions, flowToBooleanFlow, hasTrueFalseBranches, initGraph, itemsToMap, itemToMap, lang, leave, post, safeConfluence, safeConfluence, safeConfluencebegin, catchErrors, enter, enterError, errorQueue, hasErrors, job, leaveCall, leaveCall, nodeFactory, typeSystembypass, bypass, bypassChildren, override, visitChildrencopy, enter, finish, finish, leave, override, toString, visitEdge, visitEdgeNoOverrideprotected DefiniteAssignmentChecker.ClassBodyInfo currCBI
protected static final DefiniteAssignmentChecker.FlowItem BOTTOM
public DefiniteAssignmentChecker(Job job, TypeSystem ts, NodeFactory nf)
protected FlowGraph<DefiniteAssignmentChecker.FlowItem> initGraph(CodeNode code, Term root)
initGraph in class DataFlow<DefiniteAssignmentChecker.FlowItem>protected NodeVisitor enterCall(Node parent, Node n) throws SemanticException
enterCall in class ErrorHandlingVisitorn - The root of the subtree to be traversed.ErrorHandlingVisitor which should be
used to visit the children of n.SemanticExceptionNodeVisitor.enter(Node, Node)protected Node leaveCall(Node old, Node n, NodeVisitor v) throws SemanticException
leaveCall in class DataFlow<DefiniteAssignmentChecker.FlowItem>SemanticExceptionprotected void setupClassBody(ClassType ct, ClassBody n) throws SemanticException
SemanticExceptionprotected void checkStaticFinalFieldsInit(ClassBody cb) throws SemanticException
cb - The ClassBody of the class declaring the fields to check.SemanticExceptionprotected void checkNonStaticFinalFieldsInit(ClassBody cb) throws SemanticException
cb - The ClassBody of the class declaring the fields to check.SemanticExceptionprotected void dataflow(Expr root) throws SemanticException
Expr provided, and call
dataflow(FlowGraph). Is also responsible for calling
post(FlowGraph, Term) after
dataflow(FlowGraph) has been called.
There is no need to push a CFG onto the stack, as dataflow is not
performed on entry in this analysis.SemanticExceptionpublic DefiniteAssignmentChecker.FlowItem createInitialItem(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Term node, boolean entry)
createInitialItem in class DataFlow<DefiniteAssignmentChecker.FlowItem>protected CFGBuilder<DefiniteAssignmentChecker.FlowItem> createCFGBuilder(TypeSystem ts, FlowGraph<DefiniteAssignmentChecker.FlowItem> g)
DataFlowcreateCFGBuilder in class DataFlow<DefiniteAssignmentChecker.FlowItem>ts - The type systemg - The flow graph to that the CFGBuilder will construct.protected DefiniteAssignmentChecker.FlowItem confluence(java.util.List<DefiniteAssignmentChecker.FlowItem> items, java.util.List<FlowGraph.EdgeKey> itemKeys, FlowGraph.Peer<DefiniteAssignmentChecker.FlowItem> peer, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph)
Initializers and
Constructors needs to be a
little special, as we are only concerned with non-exceptional flows in
these cases.
This method ensures that a slightly different confluence is performed
for these Terms, otherwise
confluence(List, Term) is called instead.confluence in class DataFlow<DefiniteAssignmentChecker.FlowItem>items - List of Items that flow into node.
This method will only be called if the list has at least 2
elements.itemKeys - List of FlowGraph.ExceptionEdgeKeys for
the edges that the corresponding Items in
items flowed from.peer - Peer for which the items are
flowing into.public DefiniteAssignmentChecker.FlowItem confluence(java.util.List<DefiniteAssignmentChecker.FlowItem> inItems, FlowGraph.Peer<DefiniteAssignmentChecker.FlowItem> peer, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph)
confluence in class DataFlow<DefiniteAssignmentChecker.FlowItem>inItems - List of Items that flow into node.
this method will only be called if the list has at least 2
elements.peer - Peer for which the items are
flowing into.protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> flow(java.util.List<DefiniteAssignmentChecker.FlowItem> inItems, java.util.List<FlowGraph.EdgeKey> inItemKeys, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, FlowGraph.Peer<DefiniteAssignmentChecker.FlowItem> peer)
DataFlowItems as appropriate for the peer's node
and the input Items. The default
implementation of this method is simply to call confluence
for the list of inItems, and pass the result to flow(Item, FlowGraph,
Term, Set). Subclasses may want to override this method if a finer-grained
dataflow is required. Some subclasses may wish to override this method
to call flowToBooleanFlow.flow in class DataFlow<DefiniteAssignmentChecker.FlowItem>inItems - all the Items flowing into the node.inItemKeys - the FlowGraph.EdgeKeys for the items in the list inItemsgraph - the FlowGraph which the dataflow is operating onpublic java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> flow(DefiniteAssignmentChecker.FlowItem trueItem, DefiniteAssignmentChecker.FlowItem falseItem, DefiniteAssignmentChecker.FlowItem otherItem, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, FlowGraph.Peer<DefiniteAssignmentChecker.FlowItem> peer)
flow in class DataFlow<DefiniteAssignmentChecker.FlowItem>protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> flowFormal(DefiniteAssignmentChecker.FlowItem inItem, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Formal f, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> flowLocalDecl(DefiniteAssignmentChecker.FlowItem inItem, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, LocalDecl ld, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> flowLocalAssign(DefiniteAssignmentChecker.FlowItem inItem, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, LocalAssign a, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> flowFieldAssign(DefiniteAssignmentChecker.FlowItem inItem, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, FieldAssign a, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> flowConstructorCall(DefiniteAssignmentChecker.FlowItem inItem, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, ConstructorCall cc, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> flowOther(DefiniteAssignmentChecker.FlowItem inItem, FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Node n, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected boolean isFieldsTargetAppropriate(Field f)
public void check(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Term n, boolean entry, DefiniteAssignmentChecker.FlowItem inItem, java.util.Map<FlowGraph.EdgeKey,DefiniteAssignmentChecker.FlowItem> outItems) throws SemanticException
check in class DataFlow<DefiniteAssignmentChecker.FlowItem>SemanticException - if the properties this dataflow
analysis is checking for is not satisfied.protected void finishFieldDecl(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, FieldDecl fd, DefiniteAssignmentChecker.FlowItem dfIn, DefiniteAssignmentChecker.FlowItem dfOut)
fd.protected void finishConstructorDecl(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, ConstructorDecl cd, DefiniteAssignmentChecker.FlowItem dfIn, DefiniteAssignmentChecker.FlowItem dfOut)
cd.protected void finishInitializer(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Initializer initializer, DefiniteAssignmentChecker.FlowItem dfIn, DefiniteAssignmentChecker.FlowItem dfOut)
initializer.protected void checkField(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Field f, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
f is used correctly.
See JLS 2nd Ed. | 16: Every blank final field must have a definitely
assigned value when any access of its value occurs.SemanticExceptionprotected void checkLocal(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Local l, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
l is used correctly.SemanticExceptionprotected void checkLocalInstanceInit(LocalInstance li, DefiniteAssignmentChecker.FlowItem dfIn, Position pos) throws SemanticException
SemanticExceptionprotected void checkLocalAssign(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, LocalInstance li, Position pos, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
SemanticExceptionprotected void checkFieldAssign(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, FieldAssign a, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
SemanticExceptionprotected void checkClassBody(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, ClassBody cb, DefiniteAssignmentChecker.FlowItem dfIn, DefiniteAssignmentChecker.FlowItem dfOut) throws SemanticException
LocalInstances
localsUsed, which is the set of locals used in the inner
class declared by cb
are initialized before the class declaration.SemanticExceptionprotected void checkLocalsUsedByInnerClass(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, ClassBody cb, java.util.Set<LocalInstance> localsUsed, DefiniteAssignmentChecker.FlowItem dfIn, DefiniteAssignmentChecker.FlowItem dfOut) throws SemanticException
LocalInstances
localsUsed, which is the set of locals used in the inner
class declared by cb
are initialized before the class declaration.SemanticExceptionprotected void checkOther(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Node n, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
SemanticException