override public void VisitUnaryEx(UnaryEx x) { _serializer.StartSerialize(typeof(UnaryEx).Name, SerializeSpan(x.Span), new NodeObj("Operation", x.Operation.ToString())); base.VisitUnaryEx(x); _serializer.EndSerialize(); }
/// <summary> /// Connects TrueBranch and FalseBranch to From. TrueBranch is followed from From if the condition holds, /// FalseBranch is followed from From if the condition does not hold. /// /// If decompose is true, it decomposes the condition expression using logical operations with respect to /// shortcircuit evaluation. /// Note that analyzer now expects that the condition expressions are decomposed and it no longer supports /// condition expressions that are not decomposed. /// </summary> /// <param name="condition">the condition of the branching.</param> /// <param name="From">the basic block where from which the branching starts.</param> /// <param name="TrueBranch">the branch which is taken if the condition holds.</param> /// <param name="FalseBranch">the branch which is taken if the condition does not hold.</param> /// <param name="decompose"></param> internal static void ConnectConditionalBranching(Expression condition, BasicBlock From, BasicBlock TrueBranch, BasicBlock FalseBranch, bool decompose = true) { var binaryCondition = condition as BinaryEx; if (!decompose || binaryCondition == null || (binaryCondition.PublicOperation != Operations.And && binaryCondition.PublicOperation != Operations.Or && binaryCondition.PublicOperation != Operations.Xor)) { ConditionalEdge.AddConditionalEdge(From, TrueBranch, condition); DirectEdge.ConnectDirectEdge(From, FalseBranch); return; } BasicBlock intermediateBasicBlock = null; switch (binaryCondition.PublicOperation) { case Operations.And: intermediateBasicBlock = new BasicBlock(); ConnectConditionalBranching(binaryCondition.LeftExpr, From, intermediateBasicBlock, FalseBranch); From = intermediateBasicBlock; ConnectConditionalBranching(binaryCondition.RightExpr, From, TrueBranch, FalseBranch); break; case Operations.Or: intermediateBasicBlock = new BasicBlock(); ConnectConditionalBranching(binaryCondition.LeftExpr, From, TrueBranch, intermediateBasicBlock); From = intermediateBasicBlock; ConnectConditionalBranching(binaryCondition.RightExpr, From, TrueBranch, FalseBranch); break; case Operations.Xor: // Expands A xor B to (A and !B) || (!A and B) // Expansion expands A to A and !A and B to B and !B // For A and !A we the AST elements cannot be shared (must be unique) - the same for B and !B // We thus make copies of ast elements of left and right expression and use the copies to represent !A and !B var leftNegation = new UnaryEx(Operations.LogicNegation, CFGVisitor.DeepCopyAstExpressionCopyVisitor(binaryCondition.LeftExpr)); var rightNegation = new UnaryEx(Operations.LogicNegation, CFGVisitor.DeepCopyAstExpressionCopyVisitor(binaryCondition.RightExpr)); var leftExpression = new BinaryEx(Operations.And, binaryCondition.LeftExpr, rightNegation); var rightExpression = new BinaryEx(Operations.And, leftNegation, binaryCondition.RightExpr); var xorExpression = new BinaryEx(Operations.Or, leftExpression, rightExpression); ConnectConditionalBranching(xorExpression, From, TrueBranch, FalseBranch); /* * // Translation of xor in the level of control flow graph. More efficient than expansion of AST (translation in the level of program code). * // Does not work because AST of sharing AST elements * var intermediateBasicBlock1 = new BasicBlock(); * var intermediateBasicBlock2 = new BasicBlock(); * VisitIfStmtRec(binaryCondition.LeftExpr, intermediateBasicBlock1, intermediateBasicBlock2); * FromBlock = intermediateBasicBlock1; * VisitIfStmtRec(binaryCondition.RightExpr, FalseSink, TrueSink); * FromBlock = intermediateBasicBlock2; * VisitIfStmtRec(binaryCondition.RightExpr, TrueSink, FalseSink);*/ break; } }
/// <summary> /// Makes the assumption in case of <c>false</c> as a condition result. /// </summary> /// <param name="langElement">The language element to assume.</param> /// <param name="memoryContext">The memory context of the code block and it's variables.</param> /// <param name="flowOutputSet">The Output set of a program point.</param> private void AssumeFalse(LangElement langElement, MemoryContext memoryContext, FlowOutputSet flowOutputSet) { if (langElement is BinaryEx) { BinaryEx binaryExpression = (BinaryEx)langElement; if (binaryExpression.PublicOperation == Operations.Equal) { AssumeNotEquals(binaryExpression.LeftExpr, binaryExpression.RightExpr, memoryContext); } else if (binaryExpression.PublicOperation == Operations.NotEqual) { AssumeEquals(binaryExpression.LeftExpr, binaryExpression.RightExpr, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.GreaterThan) { AssumeLesserThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, true, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.GreaterThanOrEqual) { AssumeLesserThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, false, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.LessThan) { AssumeGreaterThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, true, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.LessThanOrEqual) { AssumeGreaterThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, false, memoryContext, flowOutputSet.Snapshot); } } else if (langElement is UnaryEx) { UnaryEx unaryExpression = (UnaryEx)langElement; if (unaryExpression.PublicOperation == Operations.LogicNegation) { AssumeTrue(unaryExpression.Expr, memoryContext, flowOutputSet); } } else if (langElement is VarLikeConstructUse) { var variableLikeUse = (VarLikeConstructUse)langElement; AssumeFalseElementUse(variableLikeUse, memoryContext, flowOutputSet.Snapshot); } else if (langElement is IssetEx) { IssetEx issetEx = (IssetEx)langElement; AssumeIsset(issetEx, memoryContext, flowOutputSet.Snapshot, false); } }
public override void VisitUnaryEx(UnaryEx x) { ConsumeToken(TokenFacts.GetOperationToken(x.Operation), x.OperationPosition); VisitElement(x.Expr); }
/// <summary> /// Visit unary expression. /// </summary> /// <param name="x"></param> virtual public void VisitUnaryEx(UnaryEx x) { VisitElement(x.Expr); }
public override void VisitUnaryEx(UnaryEx x) { var operand = CreateRValue(x.Expr); Result(new UnaryExPoint(x, operand)); }
/// <inheritdoc /> public override void VisitUnaryEx(UnaryEx x) { RValueResult(x); }
/// <summary> /// Initializes a new instance of the <see cref="UnaryExPoint" /> class. /// </summary> /// <param name="expression">Unary expression</param> /// <param name="operand">Program point with unary operand</param> internal UnaryExPoint(UnaryEx expression, ValuePoint operand) { Expression = expression; Operand = operand; }
/// <summary> /// Makes the assumption in case of <c>false</c> as a condition result. /// </summary> /// <param name="langElement">The language element to assume.</param> /// <param name="memoryContext">The memory context of the code block and it's variables.</param> /// <param name="flowOutputSet">The Output set of a program point.</param> void AssumeFalse(LangElement langElement, MemoryContext memoryContext, FlowOutputSet flowOutputSet) { if (langElement is BinaryEx) { BinaryEx binaryExpression = (BinaryEx)langElement; if (binaryExpression.PublicOperation == Operations.Equal) { AssumeNotEquals(binaryExpression.LeftExpr, binaryExpression.RightExpr, memoryContext); } else if (binaryExpression.PublicOperation == Operations.NotEqual) { AssumeEquals(binaryExpression.LeftExpr, binaryExpression.RightExpr, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.GreaterThan) { AssumeLesserThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, true, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.GreaterThanOrEqual) { AssumeLesserThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, false, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.LessThan) { AssumeGreaterThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, true, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.LessThanOrEqual) { AssumeGreaterThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, false, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.And || binaryExpression.PublicOperation == Operations.Or || binaryExpression.PublicOperation == Operations.Xor) { ConditionForm conditionForm = ConditionForm.SomeNot; // !(a AND b) --> !a OR !b if (binaryExpression.PublicOperation == Operations.Or) { conditionForm = ConditionForm.None; // !(a OR b) --> !a AND !b } else if (binaryExpression.PublicOperation == Operations.Xor) { conditionForm = ConditionForm.NotExactlyOne; //!(a XOR b) --> !((a OR b) AND !(a AND b)) --> (!a AND !b) OR (a AND b) } MemoryContext currentMemoryContext = new MemoryContext(log, flowOutputSet); ConditionParts condition = new ConditionParts(conditionForm, flowOutputSet, log, binaryExpression.LeftExpr, binaryExpression.RightExpr); condition.MakeAssumption(currentMemoryContext); memoryContext.UnionMerge(currentMemoryContext); } } else if (langElement is UnaryEx) { UnaryEx unaryExpression = (UnaryEx)langElement; if (unaryExpression.PublicOperation == Operations.LogicNegation) { AssumeTrue(unaryExpression.Expr, memoryContext, flowOutputSet); } } else if (langElement is DirectVarUse) { DirectVarUse directVarUse = (DirectVarUse)langElement; AssumeFalseDirectVarUse(directVarUse, memoryContext, flowOutputSet.Snapshot); } else if (langElement is IssetEx) { IssetEx issetEx = (IssetEx)langElement; AssumeIsset(issetEx, memoryContext, flowOutputSet.Snapshot, false); } }
/// <summary> /// Makes the assumption in case of <c>true</c> as a condition result. /// </summary> /// <param name="langElement">The language element to assume.</param> /// <param name="memoryContext">The memory context of the code block and it's variables.</param> /// <param name="flowOutputSet">The Output set of a program point.</param> void AssumeTrue(LangElement langElement, MemoryContext memoryContext, FlowOutputSet flowOutputSet) { if (langElement is BinaryEx) { BinaryEx binaryExpression = (BinaryEx)langElement; if (binaryExpression.PublicOperation == Operations.Equal) { AssumeEquals(binaryExpression.LeftExpr, binaryExpression.RightExpr, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.NotEqual) { AssumeNotEquals(binaryExpression.LeftExpr, binaryExpression.RightExpr, memoryContext); } else if (binaryExpression.PublicOperation == Operations.GreaterThan) { AssumeGreaterThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, false, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.GreaterThanOrEqual) { AssumeGreaterThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, true, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.LessThan) { AssumeLesserThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, false, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.LessThanOrEqual) { AssumeLesserThan(binaryExpression.LeftExpr, binaryExpression.RightExpr, true, memoryContext, flowOutputSet.Snapshot); } else if (binaryExpression.PublicOperation == Operations.And || binaryExpression.PublicOperation == Operations.Or || binaryExpression.PublicOperation == Operations.Xor) { ConditionForm conditionForm = ConditionForm.All; if (binaryExpression.PublicOperation == Operations.Or) { conditionForm = ConditionForm.Some; } else if (binaryExpression.PublicOperation == Operations.Xor) { conditionForm = ConditionForm.ExactlyOne; } MemoryContext currentMemoryContext = new MemoryContext(log, flowOutputSet); ConditionParts condition = new Weverca.Analysis.FlowResolver.Deprecated.ConditionParts(conditionForm, flowOutputSet, log, binaryExpression.LeftExpr, binaryExpression.RightExpr); condition.MakeAssumption(currentMemoryContext); memoryContext.UnionMerge(currentMemoryContext); } } else if (langElement is UnaryEx) { UnaryEx unaryExpression = (UnaryEx)langElement; if (unaryExpression.PublicOperation == Operations.LogicNegation) { AssumeFalse(unaryExpression.Expr, memoryContext, flowOutputSet); } } else if (langElement is DirectVarUse) { DirectVarUse directVarUse = (DirectVarUse)langElement; AssumeTrueDirectVarUse(directVarUse, memoryContext, flowOutputSet.Snapshot); } else if (langElement is IssetEx) { IssetEx issetEx = (IssetEx)langElement; AssumeIsset(issetEx, memoryContext, flowOutputSet.Snapshot, true); } }
/// <inheritdoc /> override public void VisitUnaryEx(UnaryEx x) { VisitElement(x.Expr); result = new UnaryEx(x.PublicOperation, (Expression)result); }