public class InitChecker extends DataFlow<InitChecker.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 |
InitChecker.BottomItem |
protected static class |
InitChecker.ClassBodyInfo
This class is just a data structure containing relevant information
needed for performing initialization checking of a class declaration.
|
protected static class |
InitChecker.DataFlowItem
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.
|
protected static class |
InitChecker.FlowItem |
protected static class |
InitChecker.InitCount
Class representing the initialization counts of variables.
|
protected static class |
InitChecker.MinMaxInitCount
Class to record counts of the minimum and maximum number of times
a variable or field has been initialized or assigned to.
|
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 InitChecker.FlowItem |
BOTTOM |
protected InitChecker.ClassBodyInfo |
currCBI |
dataflowOnEntry, detectBackEdges, flowCounter, flowgraphStack, forward, postordering
error, job, nf, ts
bypass, bypassParent
Constructor and Description |
---|
InitChecker(Job job,
TypeSystem ts,
NodeFactory nf) |
Modifier and Type | Method and Description |
---|---|
void |
check(FlowGraph<InitChecker.FlowItem> graph,
Term n,
boolean entry,
InitChecker.FlowItem inItem,
java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> outItems)
Check that the conditions of initialization are not broken.
|
protected void |
checkClassBody(FlowGraph<InitChecker.FlowItem> graph,
ClassBody cb,
InitChecker.DataFlowItem dfIn,
InitChecker.DataFlowItem 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 |
checkFieldAssign(FlowGraph<InitChecker.FlowItem> graph,
FieldAssign a,
InitChecker.DataFlowItem dfIn,
InitChecker.DataFlowItem dfOut)
Check that the assignment to a field is correct.
|
protected void |
checkLocal(FlowGraph<InitChecker.FlowItem> graph,
Local l,
InitChecker.DataFlowItem dfIn,
InitChecker.DataFlowItem dfOut)
Check that the local variable
l is used correctly. |
protected void |
checkLocalAssign(FlowGraph<InitChecker.FlowItem> graph,
LocalAssign a,
InitChecker.DataFlowItem dfIn,
InitChecker.DataFlowItem dfOut)
Check that the assignment to a local variable is correct.
|
protected void |
checkLocalInstanceInit(LocalInstance li,
InitChecker.DataFlowItem dfIn,
Position pos) |
protected void |
checkLocalsUsedByInnerClass(FlowGraph<InitChecker.FlowItem> graph,
ClassBody cb,
java.util.Set<LocalInstance> localsUsed,
InitChecker.DataFlowItem dfIn,
InitChecker.DataFlowItem 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<InitChecker.FlowItem> graph,
Node n,
InitChecker.DataFlowItem dfIn,
InitChecker.DataFlowItem dfOut)
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.
|
InitChecker.FlowItem |
confluence(java.util.List<InitChecker.FlowItem> inItems,
FlowGraph.Peer<InitChecker.FlowItem> peer,
FlowGraph<InitChecker.FlowItem> graph)
The confluence operator is essentially the union of all of the
inItems.
|
protected InitChecker.FlowItem |
confluence(java.util.List<InitChecker.FlowItem> items,
java.util.List<FlowGraph.EdgeKey> itemKeys,
FlowGraph.Peer<InitChecker.FlowItem> peer,
FlowGraph<InitChecker.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. |
InitChecker.FlowItem |
createInitialItem(FlowGraph<InitChecker.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<InitChecker.FlowItem> graph,
ConstructorDecl cd,
InitChecker.DataFlowItem dfIn,
InitChecker.DataFlowItem dfOut)
Perform necessary actions upon seeing the ConstructorDecl
cd . |
protected void |
finishInitializer(FlowGraph<InitChecker.FlowItem> graph,
Initializer initializer,
InitChecker.DataFlowItem dfIn,
InitChecker.DataFlowItem dfOut)
Perform necessary actions upon seeing the Initializer
initializer . |
java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> |
flow(InitChecker.FlowItem trueItem,
InitChecker.FlowItem falseItem,
InitChecker.FlowItem otherItem,
FlowGraph<InitChecker.FlowItem> graph,
FlowGraph.Peer<InitChecker.FlowItem> peer)
Perform the appropriate flow operations for the Terms.
|
protected java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> |
flow(java.util.List<InitChecker.FlowItem> inItems,
java.util.List<FlowGraph.EdgeKey> inItemKeys,
FlowGraph<InitChecker.FlowItem> graph,
FlowGraph.Peer<InitChecker.FlowItem> peer)
Produce new
Item s as appropriate for the peer's node
and the input Item s. |
protected java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> |
flowConstructorCall(InitChecker.DataFlowItem inItem,
FlowGraph<InitChecker.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,InitChecker.FlowItem> |
flowFieldAssign(InitChecker.DataFlowItem inItem,
FlowGraph<InitChecker.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,InitChecker.FlowItem> |
flowFormal(InitChecker.DataFlowItem inItem,
FlowGraph<InitChecker.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,InitChecker.FlowItem> |
flowLocalAssign(InitChecker.DataFlowItem inItem,
FlowGraph<InitChecker.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,InitChecker.FlowItem> |
flowLocalDecl(InitChecker.DataFlowItem inItem,
FlowGraph<InitChecker.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,InitChecker.FlowItem> |
flowOther(InitChecker.DataFlowItem inItem,
FlowGraph<InitChecker.FlowItem> graph,
Node n,
java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
Allow subclasses to override if necessary.
|
protected FlowGraph<InitChecker.FlowItem> |
initGraph(CodeNode code,
Term root)
Initialise 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, createCFGBuilder, 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 InitChecker.ClassBodyInfo currCBI
protected static final InitChecker.FlowItem BOTTOM
public InitChecker(Job job, TypeSystem ts, NodeFactory nf)
protected FlowGraph<InitChecker.FlowItem> initGraph(CodeNode code, Term root)
initGraph
in class DataFlow<InitChecker.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<InitChecker.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 InitChecker.FlowItem createInitialItem(FlowGraph<InitChecker.FlowItem> graph, Term node, boolean entry)
createInitialItem
in class DataFlow<InitChecker.FlowItem>
protected InitChecker.FlowItem confluence(java.util.List<InitChecker.FlowItem> items, java.util.List<FlowGraph.EdgeKey> itemKeys, FlowGraph.Peer<InitChecker.FlowItem> peer, FlowGraph<InitChecker.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<InitChecker.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 InitChecker.FlowItem confluence(java.util.List<InitChecker.FlowItem> inItems, FlowGraph.Peer<InitChecker.FlowItem> peer, FlowGraph<InitChecker.FlowItem> graph)
confluence
in class DataFlow<InitChecker.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,InitChecker.FlowItem> flow(java.util.List<InitChecker.FlowItem> inItems, java.util.List<FlowGraph.EdgeKey> inItemKeys, FlowGraph<InitChecker.FlowItem> graph, FlowGraph.Peer<InitChecker.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<InitChecker.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,InitChecker.FlowItem> flow(InitChecker.FlowItem trueItem, InitChecker.FlowItem falseItem, InitChecker.FlowItem otherItem, FlowGraph<InitChecker.FlowItem> graph, FlowGraph.Peer<InitChecker.FlowItem> peer)
flow
in class DataFlow<InitChecker.FlowItem>
protected java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> flowFormal(InitChecker.DataFlowItem inItem, FlowGraph<InitChecker.FlowItem> graph, Formal f, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> flowLocalDecl(InitChecker.DataFlowItem inItem, FlowGraph<InitChecker.FlowItem> graph, LocalDecl ld, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> flowLocalAssign(InitChecker.DataFlowItem inItem, FlowGraph<InitChecker.FlowItem> graph, LocalAssign a, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> flowFieldAssign(InitChecker.DataFlowItem inItem, FlowGraph<InitChecker.FlowItem> graph, FieldAssign a, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> flowConstructorCall(InitChecker.DataFlowItem inItem, FlowGraph<InitChecker.FlowItem> graph, ConstructorCall cc, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> flowOther(InitChecker.DataFlowItem inItem, FlowGraph<InitChecker.FlowItem> graph, Node n, java.util.Set<FlowGraph.EdgeKey> succEdgeKeys)
protected boolean isFieldsTargetAppropriate(Field f)
public void check(FlowGraph<InitChecker.FlowItem> graph, Term n, boolean entry, InitChecker.FlowItem inItem, java.util.Map<FlowGraph.EdgeKey,InitChecker.FlowItem> outItems) throws SemanticException
check
in class DataFlow<InitChecker.FlowItem>
SemanticException
- if the properties this dataflow
analysis is checking for is not satisfied.protected void finishInitializer(FlowGraph<InitChecker.FlowItem> graph, Initializer initializer, InitChecker.DataFlowItem dfIn, InitChecker.DataFlowItem dfOut)
initializer
.protected void finishConstructorDecl(FlowGraph<InitChecker.FlowItem> graph, ConstructorDecl cd, InitChecker.DataFlowItem dfIn, InitChecker.DataFlowItem dfOut)
cd
.protected void checkLocal(FlowGraph<InitChecker.FlowItem> graph, Local l, InitChecker.DataFlowItem dfIn, InitChecker.DataFlowItem dfOut) throws SemanticException
l
is used correctly.SemanticException
protected void checkLocalInstanceInit(LocalInstance li, InitChecker.DataFlowItem dfIn, Position pos) throws SemanticException
SemanticException
protected void checkLocalAssign(FlowGraph<InitChecker.FlowItem> graph, LocalAssign a, InitChecker.DataFlowItem dfIn, InitChecker.DataFlowItem dfOut) throws SemanticException
SemanticException
protected void checkFieldAssign(FlowGraph<InitChecker.FlowItem> graph, FieldAssign a, InitChecker.DataFlowItem dfIn, InitChecker.DataFlowItem dfOut) throws SemanticException
SemanticException
protected void checkClassBody(FlowGraph<InitChecker.FlowItem> graph, ClassBody cb, InitChecker.DataFlowItem dfIn, InitChecker.DataFlowItem 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<InitChecker.FlowItem> graph, ClassBody cb, java.util.Set<LocalInstance> localsUsed, InitChecker.DataFlowItem dfIn, InitChecker.DataFlowItem 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<InitChecker.FlowItem> graph, Node n, InitChecker.DataFlowItem dfIn, InitChecker.DataFlowItem dfOut) throws SemanticException
SemanticException