/// <inheritdoc /> public override void TryScopeStart(FlowOutputSet outSet, IEnumerable <CatchBlockDescription> catchBlockStarts) { var catchBlocks = outSet.GetControlVariable(new VariableName(".catchBlocks")); List <Value> result = new List <Value>(); foreach (var stack in catchBlocks.ReadMemory(outSet.Snapshot).PossibleValues) { result.Add(outSet.CreateInfo(new TryBlockStack((stack as InfoValue <TryBlockStack>).Data, catchBlockStarts))); } catchBlocks.WriteMemory(outSet.Snapshot, new MemoryEntry(result)); }
/// <inheritdoc /> public override void Catch(CatchPoint catchPoint, FlowOutputSet outSet) { if (catchPoint.CatchDescription.CatchedType.QualifiedName.Equals(new QualifiedName(new Name("")))) { return; } var catchBlocks = outSet.GetControlVariable(new VariableName(".catchBlocks")); var stack = new List <HashSet <CatchBlockDescription> >(); foreach (var value in catchBlocks.ReadMemory(outSet.Snapshot).PossibleValues) { if (stack.Count == 0) { for (int i = 0; i < (value as InfoValue <TryBlockStack>).Data.blocks.Count; i++) { stack.Add(new HashSet <CatchBlockDescription>()); } } for (int i = 0; i < (value as InfoValue <TryBlockStack>).Data.blocks.Count; i++) { foreach (var block in (value as InfoValue <TryBlockStack>).Data.blocks[i]) { stack[i].Add(block); } } } for (int i = stack.Count - 1; i >= 0; i--) { if (stack[i].Where(a => a.CatchedType.QualifiedName.Equals(catchPoint.CatchDescription.CatchedType.QualifiedName)).Count() > 0) { stack.RemoveLast(); break; } stack.RemoveLast(); } outSet.GetControlVariable(new VariableName(".catchBlocks")).WriteMemory(outSet.Snapshot, new MemoryEntry(outSet.CreateInfo(new TryBlockStack(stack)))); outSet.GetVariable(catchPoint.CatchDescription.CatchVariable).WriteMemory(outSet.Snapshot, catchPoint.ThrowedValue); }
public override void TryScopeStart(FlowOutputSet outSet, IEnumerable <CatchBlockDescription> catchBlockStarts) { var blockStarts = new List <InfoValue>(); //NOTE this is only simple implementation without resolving try block stack foreach (var blockStart in catchBlockStarts) { var blockValue = outSet.CreateInfo(blockStart); blockStarts.Add(blockValue); } var catchBlocks = outSet.GetControlVariable(CatchBlocks_Storage); catchBlocks.WriteMemory(outSet.Snapshot, new MemoryEntry(blockStarts)); }
public override void TryScopeEnd(FlowOutputSet outSet, IEnumerable <CatchBlockDescription> catchBlockEnds) { //NOTE in simple implementation we don't resolve try block stack var endingBlocks = new HashSet <CatchBlockDescription>(catchBlockEnds); var catchBlocks = outSet.GetControlVariable(CatchBlocks_Storage); var catchBlockValues = catchBlocks.ReadMemory(outSet.Snapshot); var remainingCatchBlocks = new List <InfoValue>(); foreach (InfoValue <CatchBlockDescription> block in catchBlockValues.PossibleValues) { if (!endingBlocks.Contains(block.Data)) { remainingCatchBlocks.Add(block); } } catchBlocks.WriteMemory(outSet.Snapshot, new MemoryEntry(remainingCatchBlocks)); }
/// <summary> /// Process throw statement according to current flow /// </summary> /// <param name="flow">Flow controller which provides API usefull for throw resolvings</param> /// <param name="outSet">Flow output set</param> /// <param name="throwStmt">Processed throw statement</param> /// <param name="throwedValue">Value that was supplied into throw statement</param> /// <returns> /// All possible ThrowInfo branches /// </returns> public override IEnumerable <ThrowInfo> Throw(FlowController flow, FlowOutputSet outSet, ThrowStmt throwStmt, MemoryEntry throwedValue) { var catchBlocks = outSet.GetControlVariable(new VariableName(".catchBlocks")); var stack = new List <HashSet <CatchBlockDescription> >(); foreach (var value in catchBlocks.ReadMemory(outSet.Snapshot).PossibleValues) { if (stack.Count == 0) { for (int i = 0; i < (value as InfoValue <TryBlockStack>).Data.blocks.Count; i++) { stack.Add(new HashSet <CatchBlockDescription>()); } } for (int i = 0; i < (value as InfoValue <TryBlockStack>).Data.blocks.Count; i++) { foreach (var block in (value as InfoValue <TryBlockStack>).Data.blocks[i]) { stack[i].Add(block); } } } Dictionary <CatchBlockDescription, List <Value> > result = new Dictionary <CatchBlockDescription, List <Value> >(); int numberOfWarnings = 0; foreach (Value value in throwedValue.PossibleValues) { bool foundMatch = false; if (value is ObjectValue) { TypeValue type = outSet.ObjectType(value as ObjectValue); var exceptionName = new QualifiedName(new Name("Exception")); if (type.Declaration.BaseClasses.Where(a => a.Equals(exceptionName)).Count() == 0 && !type.QualifiedName.Equals(exceptionName)) { AnalysisWarningHandler.SetWarning(outSet, new AnalysisWarning(flow.CurrentScript.FullName, "Only objects derived from Exception can be thrown", throwStmt, flow.CurrentProgramPoint, AnalysisWarningCause.ONLY_OBJECT_CAM_BE_THROWN)); foundMatch = false; } else { for (int i = stack.Count - 1; i >= 0; i--) { foreach (var block in stack[i]) { if (type.QualifiedName == block.CatchedType.QualifiedName) { var key = block; if (!result.ContainsKey(key)) { result[key] = new List <Value>(); } result[key].Add(value); foundMatch = true; } else { for (int j = type.Declaration.BaseClasses.Count - 1; j >= 0; j--) { if (type.Declaration.BaseClasses[j] == block.CatchedType.QualifiedName) { var key = block; if (!result.ContainsKey(key)) { result[key] = new List <Value>(); } result[key].Add(value); foundMatch = true; break; } } } if (foundMatch) { break; } } if (foundMatch) { break; } } } } else if (value is AnyObjectValue || value is AnyValue) { for (int i = stack.Count - 1; i >= 0; i--) { foreach (var block in stack[i]) { var key = block; if (!result.ContainsKey(key)) { result[key] = new List <Value>(); } result[key].Add(value); foundMatch = true; } } } else { AnalysisWarningHandler.SetWarning(outSet, new AnalysisWarning(flow.CurrentScript.FullName, "Only objects can be thrown", throwStmt, flow.CurrentProgramPoint, AnalysisWarningCause.ONLY_OBJECT_CAM_BE_THROWN)); numberOfWarnings++; foundMatch = false; } if (!foundMatch) { var key = new CatchBlockDescription(flow.ProgramEnd, new GenericQualifiedName(new QualifiedName(new Name(""))), new VariableIdentifier("")); if (!result.ContainsKey(key)) { result[key] = new List <Value>(); } result[key].Add(value); } } List <ThrowInfo> res = new List <ThrowInfo>(); foreach (var entry in result) { res.Add(new ThrowInfo(entry.Key, new MemoryEntry(entry.Value))); } if (numberOfWarnings >= throwedValue.Count) { fatalError(flow, true); } else if (numberOfWarnings > 0) { fatalError(flow, false); } return(res); }