public override IEnumerable <ThrowInfo> Throw(FlowController flow, FlowOutputSet outSet, ThrowStmt throwStmt, MemoryEntry throwedValue) { //TODO this is only simple implementation var exceptionObj = (ObjectValue)throwedValue.PossibleValues.First(); var catchBlocks = outSet.ReadControlVariable(CatchBlocks_Storage).ReadMemory(outSet.Snapshot); var throwBranches = new List <ThrowInfo>(); //find catch blocks with valid scope and matching catch condition foreach (InfoValue <CatchBlockDescription> blockInfo in catchBlocks.PossibleValues) { var throwedType = outSet.ObjectType(exceptionObj).QualifiedName; //check catch condition if (blockInfo.Data.CatchedType.QualifiedName != throwedType) { continue; } var branch = new ThrowInfo(blockInfo.Data, throwedValue); throwBranches.Add(branch); } return(throwBranches); }
/// <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); }