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, postordering
error, job, nf, ts
bypass, 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
LocalInstance s
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
LocalInstance s
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
Initializer s and
Constructor s 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
Item s as appropriate for the peer's node
and the input Item s. |
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, safeConfluence
begin, catchErrors, enter, enterError, errorQueue, hasErrors, job, leaveCall, leaveCall, nodeFactory, typeSystem
bypass, bypass, bypassChildren, override, visitChildren
copy, enter, finish, finish, leave, override, toString, visitEdge, visitEdgeNoOverride
protected 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 ErrorHandlingVisitor
n
- The root of the subtree to be traversed.ErrorHandlingVisitor
which should be
used to visit the children of n
.SemanticException
NodeVisitor.enter(Node, Node)
protected Node leaveCall(Node old, Node n, NodeVisitor v) throws SemanticException
leaveCall
in class DataFlow<DefiniteAssignmentChecker.FlowItem>
SemanticException
protected void setupClassBody(ClassType ct, ClassBody n) throws SemanticException
SemanticException
protected void checkStaticFinalFieldsInit(ClassBody cb) throws SemanticException
cb
- The ClassBody of the class declaring the fields to check.SemanticException
protected void checkNonStaticFinalFieldsInit(ClassBody cb) throws SemanticException
cb
- The ClassBody of the class declaring the fields to check.SemanticException
protected 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.SemanticException
public 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)
DataFlow
createCFGBuilder
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)
Initializer
s and
Constructor
s 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 Term
s, otherwise
confluence(List, Term)
is called instead.confluence
in class DataFlow<DefiniteAssignmentChecker.FlowItem>
items
- List of Item
s that flow into node
.
This method will only be called if the list has at least 2
elements.itemKeys
- List of FlowGraph.ExceptionEdgeKey
s for
the edges that the corresponding Item
s 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 Item
s 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)
DataFlow
Item
s as appropriate for the peer's node
and the input Item
s. 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.SemanticException
protected void checkLocal(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Local l, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
l
is used correctly.SemanticException
protected void checkLocalInstanceInit(LocalInstance li, DefiniteAssignmentChecker.FlowItem dfIn, Position pos) throws SemanticException
SemanticException
protected void checkLocalAssign(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, LocalInstance li, Position pos, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
SemanticException
protected void checkFieldAssign(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, FieldAssign a, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
SemanticException
protected void checkClassBody(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, ClassBody cb, DefiniteAssignmentChecker.FlowItem dfIn, DefiniteAssignmentChecker.FlowItem dfOut) throws SemanticException
LocalInstance
s
localsUsed
, which is the set of locals used in the inner
class declared by cb
are initialized before the class declaration.SemanticException
protected void checkLocalsUsedByInnerClass(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, ClassBody cb, java.util.Set<LocalInstance> localsUsed, DefiniteAssignmentChecker.FlowItem dfIn, DefiniteAssignmentChecker.FlowItem dfOut) throws SemanticException
LocalInstance
s
localsUsed
, which is the set of locals used in the inner
class declared by cb
are initialized before the class declaration.SemanticException
protected void checkOther(FlowGraph<DefiniteAssignmentChecker.FlowItem> graph, Node n, DefiniteAssignmentChecker.FlowItem dfIn) throws SemanticException
SemanticException