diff --git a/src/main/java/tfm/arcs/pdg/DataDependencyArc.java b/src/main/java/tfm/arcs/pdg/DataDependencyArc.java index 649f84c789dcafcb8636386d68d3252167d00933..a0c7725cf42669b15fe24240ab4f6f24a82772fb 100644 --- a/src/main/java/tfm/arcs/pdg/DataDependencyArc.java +++ b/src/main/java/tfm/arcs/pdg/DataDependencyArc.java @@ -21,6 +21,10 @@ public class DataDependencyArc extends Arc { super(variable); } + public DataDependencyArc() { + super(); + } + @Override public Map getDotAttributes() { Map map = super.getDotAttributes(); diff --git a/src/main/java/tfm/arcs/sdg/ReturnArc.java b/src/main/java/tfm/arcs/sdg/ReturnArc.java deleted file mode 100644 index ea3a55aea343f82d0445164b71d4174301fa2a35..0000000000000000000000000000000000000000 --- a/src/main/java/tfm/arcs/sdg/ReturnArc.java +++ /dev/null @@ -1,16 +0,0 @@ -package tfm.arcs.sdg; - -import org.jgrapht.io.Attribute; -import org.jgrapht.io.DefaultAttribute; -import tfm.arcs.Arc; - -import java.util.Map; - -public class ReturnArc extends Arc { - @Override - public Map getDotAttributes() { - Map map = super.getDotAttributes(); - map.put("style", DefaultAttribute.createAttribute("dashed")); - return map; - } -} diff --git a/src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java b/src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java index 5331beb798e20fc8eb7eb65d9e3b78aff714f5fc..ab9d7cb4038e0b224cb0ffa78e194f15d8a3b25c 100644 --- a/src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java +++ b/src/main/java/tfm/graphs/sdg/MethodCallReplacerVisitor.java @@ -252,17 +252,34 @@ class MethodCallReplacerVisitor extends VoidVisitorAdapter { } } - // 'Return' node - GraphNode returnNode = sdg.addNode("return", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_CALL_RETURN)); - sdg.addControlDependencyArc(methodCallNode, returnNode); + // Add 'output' node of the call - sdg.addReturnArc(returnNode, originalMethodCallNode); + // First, check if method has an output node - methodCFG.vertexSet().stream() - .filter(node -> node.getAstNode() instanceof ReturnStmt) - .map(node -> (GraphNode) node) - .forEach(node -> sdg.addReturnArc(node, returnNode)); + if (methodDeclaration.getType().isVoidType()) { + return; + } + + // If not void, find the output node + + Optional> optionalDeclarationOutputNode = sdg.outgoingEdgesOf(methodDeclarationNode).stream() + .filter(arc -> sdg.getEdgeTarget(arc).getNodeType() == NodeType.METHOD_OUTPUT) + .map(arc -> (GraphNode) sdg.getEdgeTarget(arc)) + .findFirst(); + + if (!optionalDeclarationOutputNode.isPresent()) { + // Method return type is void, do nothing + return; + } + + GraphNode declarationOutputNode = optionalDeclarationOutputNode.get(); + + // If method has output node, then create output call node and link them + GraphNode callReturnNode = sdg.addNode("output", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_CALL_RETURN)); + sdg.addControlDependencyArc(methodCallNode, callReturnNode); + sdg.addDataDependencyArc(callReturnNode, originalMethodCallNode); + sdg.addParameterInOutArc(declarationOutputNode, callReturnNode); Logger.log("MethodCallReplacerVisitor", String.format("%s | Method '%s' called", methodCallExpr, methodDeclaration.getNameAsString())); } diff --git a/src/main/java/tfm/graphs/sdg/SDG.java b/src/main/java/tfm/graphs/sdg/SDG.java index d25f3aacf33c9b44809d5f185d9c8149c3642f7c..bcabf954e58db1138a129225495192c013e432ff 100644 --- a/src/main/java/tfm/graphs/sdg/SDG.java +++ b/src/main/java/tfm/graphs/sdg/SDG.java @@ -1,24 +1,18 @@ package tfm.graphs.sdg; import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.stmt.EmptyStmt; import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.ReturnStmt; import tfm.arcs.Arc; -import tfm.arcs.cfg.ControlFlowArc; import tfm.arcs.pdg.ControlDependencyArc; import tfm.arcs.pdg.DataDependencyArc; import tfm.arcs.sdg.CallArc; import tfm.arcs.sdg.ParameterInOutArc; -import tfm.arcs.sdg.ReturnArc; import tfm.arcs.sdg.SummaryArc; import tfm.graphs.Buildable; import tfm.graphs.Graph; import tfm.graphs.cfg.CFG; -import tfm.graphs.pdg.PDG; import tfm.nodes.*; import tfm.slicing.Slice; import tfm.slicing.Sliceable; @@ -27,9 +21,6 @@ import tfm.utils.Context; import tfm.utils.Utils; import java.util.*; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; public class SDG extends Graph implements Sliceable, Buildable> { private boolean built = false; @@ -75,6 +66,10 @@ public class SDG extends Graph implements Sliceable, Buildable from, GraphNode to) { + this.addDataDependencyArc(from, to, null); + } + public void addDataDependencyArc(GraphNode from, GraphNode to, String variable) { this.addEdge(from, to, new DataDependencyArc(variable)); } @@ -83,14 +78,10 @@ public class SDG extends Graph implements Sliceable, Buildable from, GraphNode to) { + public void addParameterInOutArc(GraphNode from, GraphNode to) { this.addEdge(from, to, new ParameterInOutArc()); } - public void addReturnArc(GraphNode from, GraphNode to) { - this.addEdge(from, to, new ReturnArc()); - } - public void addSummaryArc(GraphNode from, GraphNode to) { this.addEdge(from, to, new SummaryArc()); } diff --git a/src/main/java/tfm/graphs/sdg/SDGBuilder.java b/src/main/java/tfm/graphs/sdg/SDGBuilder.java index 149976ce6e8c5c57d2c5d2f9327a6767bdf9ade2..33a13fd9a8d6663cd855b2393babfc56b080e2b5 100644 --- a/src/main/java/tfm/graphs/sdg/SDGBuilder.java +++ b/src/main/java/tfm/graphs/sdg/SDGBuilder.java @@ -3,21 +3,17 @@ package tfm.graphs.sdg; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.stmt.ExpressionStmt; +import com.github.javaparser.ast.stmt.EmptyStmt; +import com.github.javaparser.ast.stmt.ReturnStmt; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import tfm.arcs.Arc; import tfm.graphs.pdg.PDG; import tfm.graphs.sdg.sumarcs.NaiveSummaryArcsBuilder; import tfm.graphs.sdg.sumarcs.SummaryArcsBuilder; import tfm.nodes.GraphNode; +import tfm.nodes.TypeNodeFactory; import tfm.nodes.type.NodeType; import tfm.utils.Context; -import tfm.utils.Utils; - -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; class SDGBuilder extends VoidVisitorAdapter { @@ -60,6 +56,22 @@ class SDGBuilder extends VoidVisitorAdapter { // Add CFG sdg.setMethodCFG(methodDeclaration, pdg.getCfg()); + + // Add output node + if (methodDeclaration.getType().isVoidType()) { + // If method return type is void, do nothing + return; + } + + GraphNode outputNode = sdg.addNode("output", new EmptyStmt(), TypeNodeFactory.fromType(NodeType.METHOD_OUTPUT)); + + sdg.addControlDependencyArc(methodDeclarationNode, outputNode); + + // Add return arc from all return statements to the output node + pdg.getCfg().vertexSet().stream() + .filter(node -> node.getAstNode() instanceof ReturnStmt) + .map(node -> (GraphNode) node) + .forEach(node -> sdg.addDataDependencyArc(node, outputNode)); } @Override diff --git a/src/main/java/tfm/nodes/type/NodeType.java b/src/main/java/tfm/nodes/type/NodeType.java index 1851d62c70cdfac56c70381a6af46b789bbc247c..c44bcafdb493cd8ea67e39c674c76c3b69136f58 100644 --- a/src/main/java/tfm/nodes/type/NodeType.java +++ b/src/main/java/tfm/nodes/type/NodeType.java @@ -24,4 +24,6 @@ public enum NodeType { FORMAL_OUT, /** A node representing the return value of a non-void method call. */ METHOD_CALL_RETURN, + /** A node representing the return value of a non-void method declaration. */ + METHOD_OUTPUT }