private static void InterpretConstructAttributes(ReachabilitySummary summary, string fieldIdentifier, WholeProgram wholeProgram) { if (summary != null) { // For now we assume the argument is a field -- we really should support types and methods too IFieldDefinition fieldWithAttributes = LookupFieldWithIdentifier(fieldIdentifier, wholeProgram); foreach (ICustomAttribute customAttribute in fieldWithAttributes.Attributes) { IMethodDefinition constructorDefinition = GarbageCollectHelper.UnspecializeAndResolveMethodReference(customAttribute.Constructor); ITypeDefinition constructorType = constructorDefinition.ContainingTypeDefinition; // Mark attribute constructor reachable summary.NonvirtuallyCalledMethods.Add(constructorDefinition); // Mark named argument property setters reachable foreach (IMetadataNamedArgument namedArgument in customAttribute.NamedArguments) { IName setterName = wholeProgram.Host().NameTable.GetNameFor("set_" + namedArgument.ArgumentName.Value); IMethodDefinition setterMethod = TypeHelper.GetMethod(constructorType, setterName, namedArgument.ArgumentValue.Type); if (setterMethod != Dummy.Method) { // We treat this as a non-virtual call because we know the exact runtime-type of the attribute summary.NonvirtuallyCalledMethods.Add(setterMethod); } else { // Note this won't find a property defined in a super class of the attribute (unsound). // We'll want to fix this if try to generalize this code to handle arbitrary attributes throw new Exception("Couldn't find setter " + setterName + " for type " + namedArgument.ArgumentValue.Type + " in " + constructorType); } } } } else { throw new Exception("Cannot construct subtypes outside of a summarized method."); } }
public ReachabilitySummary SummarizeMethod(IMethodDefinition method, WholeProgram wholeProgram) { if (method.IsExternal == false && method.IsAbstract == false) { ReachabilitySummary summary = new ReachabilitySummary(); IMethodDefinition target; // foreach MSIL instruction in the method foreach (var op in method.Body.Operations) { switch (op.OperationCode) { // non virtual method calls: just add static type case OperationCode.Newobj: case OperationCode.Call: case OperationCode.Calli: target = (op.Value as IMethodReference).ResolvedMethod; summary.NonvirtuallyCalledMethods.Add(target); break; case OperationCode.Ldvirtftn: case OperationCode.Callvirt: target = (op.Value as IMethodReference).ResolvedMethod; if (target.IsVirtual == false) { summary.NonvirtuallyCalledMethods.Add(target); } else { ITypeDefinition typeDefiningTarget = target.ContainingTypeDefinition; IMethodDefinition targetUnspecialized = GarbageCollectHelper.UnspecializeAndResolveMethodReference(op.Value as IMethodReference); // find all possible implementations of virtual call foreach (ITypeDefinition subType in new ITypeDefinition[] { typeDefiningTarget }.Concat(wholeProgram.ClassHierarchy().AllSubClassesOfClass(typeDefiningTarget))) { if (GarbageCollectHelper.TypeIsConstructable(subType)) { // walk class hierarchy from subType up to (including) typeDefiningTarget, looking for targetUnspecialized. ICollection <IMethodDefinition> implementationsOfMethodDefinitionForSubType = GarbageCollectHelper.Implements(subType, typeDefiningTarget, targetUnspecialized); // we have to have found at least 1 implementation Contract.Assert(implementationsOfMethodDefinitionForSubType.Count() > 0); // add all of them as virtually called methods foreach (IMethodDefinition implementationOfTarget in implementationsOfMethodDefinitionForSubType) { summary.VirtuallyCalledMethods.Add(implementationOfTarget); } } } } break; default: break; } } return(summary); } else { return(null); } }