private void fatalError(FlowController flow, bool removeFlowChildren) { var catchedType = new GenericQualifiedName(new QualifiedName(new Name(string.Empty))); var catchVariable = new VariableIdentifier(string.Empty); var description = new CatchBlockDescription(flow.ProgramEnd, catchedType, catchVariable); var info = new ThrowInfo(description, new MemoryEntry()); var throws = new ThrowInfo[] { info }; flow.SetThrowBranching(throws, removeFlowChildren); }
/// <summary> /// Merges information at the entry of the catch block. /// /// Snapshot has to contain merged info present in inputs (no matter what snapshots contain till now) /// This merged info can be than changed with snapshot updatable operations /// NOTE: Further changes of inputs can't change extended snapshot /// </summary> /// <param name="inputs">Input snapshots that should be merged (snapshots of program points where the catched exception is thrown).</param> /// <param name="catchDescription">Catch description.</param> protected virtual void extendAtCatchEntry(ISnapshotReadonly[] inputs, CatchBlockDescription catchDescription) { extend(inputs); }
/// <inheritdoc /> public void ExtendAtCatchEntry(ISnapshotReadonly[] inputs, CatchBlockDescription catchDescription) { checkCanUpdate(); extendAtCatchEntry(inputs, catchDescription); _statistics.Report(Statistic.SnapshotExtendings); }
internal CatchPoint(ProgramPointBase throwingPoint, CatchBlockDescription catchDescription) { ThrowingPoint = throwingPoint; CatchDescription = catchDescription; }
/// <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); }