private static bool IsSpecPublic(Field f)
        {
            // F: 
            Contract.Requires(f != null);

            return f.Attributes.HasAttribute(ContractNodes.SpecPublicAttributeName);
        }
        /// <summary>
        /// Find shadow field in given type corresponding to field.
        /// </summary>
        public static Field FindShadow(this TypeNode parent, Field field)
        {
            if (field == null || field.Name == null)
            {
                return null;
            }

            MemberList members = parent.GetMembersNamed(field.Name);

            for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++)
            {
                Field f = members[i] as Field;
                if (f != null) return f;
            }

            return null;
        }
Beispiel #3
0
    private Field GetReturnValueClosureField(TypeNode declaringType, TypeNode resultType, FieldFlags flags, int uniqueKey)
    {
      Contract.Requires(declaringType != null);
      
      Contract.Assume(declaringType.Template == null);
      Identifier name = Identifier.For("_result" + uniqueKey.ToString()); // unique name for this field

      Field f = declaringType.GetField(name);
      if (f != null) return f;

      f = new Field(declaringType,
        null,
        flags,
        name,
        resultType,
        null);

      declaringType.Members.Add(f);
      // remember we added it so we can make it part of initializations
      if (f.IsStatic)
      {
        topLevelStaticResultField = f;
      }
      else
      {
        topLevelClosureResultField = f;
      }
      return f;
    }
 public static List<int> FieldElementsPeerPositions(Field f)
 {
     List<int> res = new List<int>();
     if (f == null) return res;
     AttributeList al = f.GetAllAttributes(SystemTypes.ElementsPeerAttribute);
     if (al == null) return res;
     foreach (AttributeNode attr in al)
     {
         ExpressionList exprs = attr.Expressions;
         int value = -10;
         if (exprs == null || exprs.Count == 0) 
             value = -1; // default value for attribute w/o param
         else
         {
             Expression arg = exprs[0];
             Literal lit = arg as Literal;
             if (lit != null && lit.Value is int)
                 value = (int)lit.Value;
         }
         if (value == -1)  // all positions are ElementsPeer
         {
             return ElementsPositions(f.Type);
         }
         else // a specific type argument is ElementsPeer
         {
             res.Add(value);
         }
     }
     return res;
 }
        public override void VisitField(Field field)
        {
            base.VisitField(field);

            var type = HelperMethods.Unspecialize(field.Type);

            if (type == contractClass)
            {
                if (field.Type.TemplateArguments != null)
                {
                    var inst = this.OriginalType.GetTemplateInstance(field.Type, field.Type.TemplateArguments);
                    field.Type = inst;
                }
                else
                {
                    field.Type = this.OriginalType;
                }
            }
        }
Beispiel #6
0
        private static string GetFieldQualifiers(Field field)
        {
            string qualifiers = string.Empty;

            if (field.IsStatic)
                qualifiers += "static ";

            return qualifiers;
        }
        public override void VisitField(Field field)
        {
            if (field == null) return;

            this.CheckField(field);
        }
Beispiel #8
0
 private void PrepareGuardedClass(TypeNode typeNode) {
   SpecSharpCompilerOptions options = this.currentOptions as SpecSharpCompilerOptions;
   if (!(options != null && (options.DisableGuardedClassesChecks || options.Compatibility))) {
     if (typeNode is Class && typeNode.Contract != null && (typeNode.Contract.InvariantCount > 0 || typeNode.Contract.ModelfieldContractCount > 0) ||
       typeNode is Class && this.currentPreprocessorDefinedSymbols != null && this.currentPreprocessorDefinedSymbols.ContainsKey("GuardAllClasses")) {
       if (typeNode.Interfaces == null) {
         typeNode.Interfaces = new InterfaceList();
       }
       if (typeNode.Template == null) { //we have to be careful when we are passed a typeNode of a specialized generic type as it shares the contract of the 'real' generic typeNode
         #region Add the field "frame" to the class.
         Field frameField = new Field(typeNode, null, FieldFlags.Public, Identifier.For("SpecSharp::frameGuard"), SystemTypes.Guard, null);
         frameField.CciKind = CciMemberKind.Auxiliary;
         typeNode.Contract.FrameField = frameField;
         typeNode.Members.Add(frameField);
         This thisParameter = new This(typeNode);
         Method frameGetter = new Method(typeNode, NoDefaultExpose(), Identifier.For("get_SpecSharp::FrameGuard"), null, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Guard),
           new Block(new StatementList(new Return(new BinaryExpression(new MemberBinding(thisParameter, frameField), new Literal(SystemTypes.NonNullType, SystemTypes.Type), System.Compiler.NodeType.ExplicitCoercion, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Guard))))));
         // Pretend this method is [Delayed] so that we can call it from a delayed constructor.
         frameGetter.Attributes.Add(new AttributeNode(new Literal(ExtendedRuntimeTypes.DelayedAttribute, SystemTypes.Type), null, AttributeTargets.Method));
         frameGetter.CciKind = CciMemberKind.FrameGuardGetter;
         frameGetter.Attributes.Add(new AttributeNode(new Literal(SystemTypes.PureAttribute, SystemTypes.Type), null, AttributeTargets.Method));
         frameGetter.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.SpecialName;
         frameGetter.CallingConvention = CallingConventionFlags.HasThis;
         frameGetter.ThisParameter = thisParameter;
         typeNode.Contract.FramePropertyGetter = frameGetter;
         typeNode.Members.Add(frameGetter);
         Property frameProperty = new Property(typeNode, null, PropertyFlags.None, Identifier.For("SpecSharp::FrameGuard"), frameGetter, null);
         typeNode.Members.Add(frameProperty);
         typeNode.Contract.FrameProperty = frameProperty;
         #endregion
         typeNode.Contract.InitFrameSetsMethod = new Method(typeNode, NoDefaultExpose(), Identifier.For("SpecSharp::InitGuardSets"), null, SystemTypes.Void, null);
         typeNode.Contract.InitFrameSetsMethod.CciKind = CciMemberKind.Auxiliary;
         typeNode.Contract.InitFrameSetsMethod.Flags = MethodFlags.Public | MethodFlags.HideBySig | MethodFlags.SpecialName;
       }
     }
   }
 }
Beispiel #9
0
 internal static void TryAddDebuggerBrowsableNeverAttribute(Field field)
 {
     Contract.Requires(field != null);
     TryAddDebuggerBrowsableNeverAttribute(field, System.AttributeTargets.Field);
 }
        private static bool FieldAssociatedWithParameter(Field field, Method originalMethod, out Parameter p)
        {
            string fname = field.Name.Name;

            if (fname.EndsWith("__this"))
            {
                // check that it is not a nested one
                if (fname.Length > 8 && !fname.Substring(2, fname.Length - 8).Contains("__"))
                {
                    p = originalMethod.ThisParameter;
                    return true;
                }
            }

            foreach (Parameter par in originalMethod.Parameters)
            {
                string pname = par.Name.Name;
                if (fname == pname)
                {
                    p = par;
                    return true;
                }
            }

            p = null;
            return false;
        }
Beispiel #11
0
        public static bool IsClosureField(TypeNode container, Field field)
        {
            Contract.Requires(container != null);
            Contract.Requires(field != null);

            var type = Unspecialize(field.DeclaringType);

            if (IsClosureType(container, type)) return true;
            
            // can be a direct member of a type inside container for caching delegates
            
            if (!field.IsPrivate) return false;
            
            if (!(field.Type.IsDelegateType())) return false;
            
            if (!IsInsideOf(field, container)) return false;
            
            if (!IsCompilerGenerated(field)) return false;
            
            return true;
        }
Beispiel #12
0
 bool IsAccessibleFrom(Field field, Method from)
 {
 }
Beispiel #13
0
        public override Expression VisitLocal(Local local)
        {
            if (HelperMethods.IsClosureType(this.declaringType, local.Type))
            {
                MemberBinding mb;
                if (!closureLocals.TryGetValue(local, out mb))
                {
                    // Forwarder would be null, if enclosing method with async closure is not generic
                    var localType = forwarder != null ? forwarder.VisitTypeReference(local.Type) : local.Type;

                    var closureField = new Field(this.closureClass, null, FieldFlags.Public, local.Name, localType, null);
                    this.closureClass.Members.Add(closureField);
                    mb = new MemberBinding(this.checkMethod.ThisParameter, closureField);
                    closureLocals.Add(local, mb);

                    // initialize the closure field
                    var instantiatedField = GetMemberInstanceReference(closureField, this.closureClassInstance);
                    this.ClosureInitializer.Statements.Add(new AssignmentStatement(new MemberBinding(this.ClosureLocal, instantiatedField), local));

                }
                return mb;
            }
            return local;
        }
Beispiel #14
0
    private static Expression CreateProperResultAccess(ReturnValue returnValue, Expression closureObject, Field resultField)
    {
      Contract.Requires(returnValue != null);
      Contract.Requires(resultField != null);

      var fieldAccess = new MemberBinding(closureObject, resultField);

      if (resultField.Type != returnValue.Type)
      {
        // must cast to generic type expected in this context (box instance unbox.any Generic)
        return new BinaryExpression(new BinaryExpression(fieldAccess, new Literal(resultField.Type), NodeType.Box), new Literal(returnValue.Type), NodeType.UnboxAny);
      }
      else
      {
        return fieldAccess;
      }
    }
Beispiel #15
0
    private Method FindAndInstantiateBaseClassInvariantMethod(Class asClass, out Field baseReentrancyFlag)
    {
      baseReentrancyFlag = null;
      if (asClass == null || asClass.BaseClass == null) return null;
      if (!this.Emit(RuntimeContractEmitFlags.InheritContracts)) return null; // don't call base class invariant if we don't inherit

      var baseClass = asClass.BaseClass;

      if (!this.InheritInvariantsAcrossAssemblies && (baseClass.DeclaringModule != asClass.DeclaringModule))
        return null;

      var result = baseClass.GetMethod(Identifier.For("$InvariantMethod$"), null);

      if (result != null && !HelperMethods.IsVisibleFrom(result, asClass)) return null;

      if (result == null && baseClass.Template != null)
      {
        // instantiation of generated method has not happened.
        var generic = baseClass.Template.GetMethod(Identifier.For("$InvariantMethod$"), null);
        if (generic != null)
        {
          if (!HelperMethods.IsVisibleFrom(generic, asClass)) return null;
          // generate proper reference.
          result = GetMethodInstanceReference(generic, baseClass);
        }
      }
      // extract base reentrancy flag
      if (result != null) {
        var instantiatedParent = result.DeclaringType;
        baseReentrancyFlag = instantiatedParent.GetField(Identifier.For("$evaluatingInvariant$"));

        if (baseReentrancyFlag == null && baseClass.Template != null)
        {
          // instantiation of generated baseReentrancy flag has not happened.
          var generic = baseClass.Template.GetField(Identifier.For("$evaluatingInvariant$"));
          if (generic != null)
          {
            if (HelperMethods.IsVisibleFrom(generic, asClass))
            {
              baseReentrancyFlag = GetFieldInstanceReference(generic, baseClass);
            }
          }
        }
      }

      return result;
    }
Beispiel #16
0
    public override void VisitTypeNode(TypeNode typeNode) {
      if (typeNode == null) return;

      if (HelperMethods.IsContractTypeForSomeOtherType(typeNode, this.rewriterNodes) != null) {
        return;
      }
      Method savedInvariantMethod = this.InvariantMethod;
      Field savedReentrancyFlag = this.ReentrancyFlag;
      this.InvariantMethod = null;
      this.ReentrancyFlag = null;
      var savedState = this.currentState;
      this.currentState = new CurrentState(typeNode);
      var savedEmitFlags = this.AdaptRuntimeOptionsBasedOnAttributes(typeNode.Attributes);

      try
      {
        if (this.Emit(RuntimeContractEmitFlags.Invariants) && rewriterNodes.InvariantMethod != null)
        {
          InvariantList userWrittenInvariants = typeNode.Contract == null ? null : typeNode.Contract.Invariants;
          Class asClass = typeNode as Class;
          Field baseReentrancyFlag;
          Method baseInvariantMethod = FindAndInstantiateBaseClassInvariantMethod(asClass, out baseReentrancyFlag);


          if ((userWrittenInvariants != null && 0 < userWrittenInvariants.Count) || baseInvariantMethod != null)
          {
            Field reEntrancyFlag = null;
            var isStructWithExplicitLayout = IsStructWithExplicitLayout(typeNode as Struct);
            if (isStructWithExplicitLayout)
            {
              this.HandleError(new Warning(1044, String.Format("Struct '{0}' has explicit layout and an invariant. Invariant recursion guards will not be emitted and evaluation of invariants may occur too eagerly.", typeNode.FullName), new SourceContext()));
            }
            else
            {
              #region Find or create re-entrancy flag to the class
              if (baseReentrancyFlag != null)
              {
                // grab base reEntrancyFlag
                reEntrancyFlag = baseReentrancyFlag;
              }
              else
              {
                FieldFlags reentrancyFlagProtection;
                if (typeNode.IsSealed)
                {
                  reentrancyFlagProtection = FieldFlags.Private | FieldFlags.CompilerControlled;
                }
                else if (this.InheritInvariantsAcrossAssemblies)
                {
                  reentrancyFlagProtection = FieldFlags.Family | FieldFlags.CompilerControlled;
                }
                else
                {
                  reentrancyFlagProtection = FieldFlags.FamANDAssem | FieldFlags.CompilerControlled;
                }
                reEntrancyFlag = new Field(typeNode, null, reentrancyFlagProtection, Identifier.For("$evaluatingInvariant$"), SystemTypes.Boolean, null);
                RewriteHelper.TryAddCompilerGeneratedAttribute(reEntrancyFlag);
                RewriteHelper.TryAddDebuggerBrowsableNeverAttribute(reEntrancyFlag);
                typeNode.Members.Add(reEntrancyFlag);
              }
              #endregion Add re-entrancy flag to the class
            }
            Block newBody = new Block(new StatementList(3));
            // newBody ::=
            //   if (this.$evaluatingInvariant$){
            //     return (true); // don't really return true since this is a void method, but it means the invariant is assumed to hold
            //   this.$evaluatingInvariant$ := true;
            //   try{
            //     <evaluate invariants and call base invariant method>
            //   } finally {
            //     this.$evaluatingInvariant$ := false;
            //   }
            Method invariantMethod =
              new Method(
                typeNode,
                new AttributeList(),
                Identifier.For("$InvariantMethod$"),
                null,
                SystemTypes.Void,
                newBody);
            RewriteHelper.TryAddCompilerGeneratedAttribute(invariantMethod);
            invariantMethod.CallingConvention = CallingConventionFlags.HasThis;
            if (this.InheritInvariantsAcrossAssemblies)
              invariantMethod.Flags = MethodFlags.Family | MethodFlags.Virtual;
            else
              invariantMethod.Flags = MethodFlags.FamANDAssem | MethodFlags.Virtual;
            invariantMethod.Attributes.Add(new AttributeNode(new MemberBinding(null, this.runtimeContracts.ContractNodes.InvariantMethodAttribute.GetConstructor()), null));

            #region call base class invariant
            if (baseInvariantMethod != null)
            {
              newBody.Statements.Add(
                new ExpressionStatement(
                new MethodCall(
                new MemberBinding(invariantMethod.ThisParameter, baseInvariantMethod), null, NodeType.Call, SystemTypes.Void)));
            }
            #endregion
            #region Add re-entrancy test to the method
            Block invariantExit = new Block();
            if (reEntrancyFlag != null)
            {
              Block reEntrancyTest = new Block(new StatementList());
              reEntrancyTest.Statements.Add(
                new Branch(new MemberBinding(invariantMethod.ThisParameter, reEntrancyFlag), invariantExit));
              reEntrancyTest.Statements.Add(
                new AssignmentStatement(new MemberBinding(invariantMethod.ThisParameter, reEntrancyFlag), Literal.True)
                );
              newBody.Statements.Add(reEntrancyTest);
            }
            #endregion Add re-entrancy test to the method

            Block invariantChecks = new Block(new StatementList());
            if (userWrittenInvariants != null)
            {
              #region Filter out invariants that aren't runtime checkable
              var filteredInvariants = new InvariantList();
              foreach (var i in userWrittenInvariants) {
                if (!EmitInvariant(i, this.skipQuantifiers)) continue;
                filteredInvariants.Add(i);
              }
              #endregion Filter out invariants that aren't runtime checkable
              #region Duplicate the invariants
              // need to duplicate the invariants so they aren't shared
              Duplicator d = new Duplicator(typeNode.DeclaringModule, typeNode);
              InvariantList duplicatedInvariants = d.VisitInvariantList(filteredInvariants);
              // F: seems to have the invariant duplictedInvariants != null
              Contract.Assume(duplicatedInvariants != null);

              #endregion Duplicate the invariants
              #region Rewrite the body of the invariant method
              // then we need to replace calls to Contract.Invariant with calls to Contract.RewriterInvariant
              // in the body of the invariant method
              RewriteInvariant rc = new RewriteInvariant(this.runtimeContracts);
              rc.VisitInvariantList(duplicatedInvariants);
              #endregion Rewrite the body of the invariant method
              for (int i = 0, n = duplicatedInvariants.Count; i < n; i++)
              {
                Expression e = duplicatedInvariants[i].Condition;
                var blockExpr = e as BlockExpression;
                if (blockExpr != null)
                {
                  invariantChecks.Statements.Add(blockExpr.Block);
                }
                else
                {
                  invariantChecks.Statements.Add(new ExpressionStatement(e));
                }
              }
            }
            Block finallyB = new Block(new StatementList(1));
            if (reEntrancyFlag != null)
            {
              finallyB.Statements.Add(
                new AssignmentStatement(new MemberBinding(invariantMethod.ThisParameter, reEntrancyFlag), Literal.False)
                );
            }
            this.cleanUpCodeCoverage.VisitBlock(invariantChecks);
            Block b = RewriteHelper.CreateTryFinallyBlock(invariantMethod, invariantChecks, finallyB);
            newBody.Statements.Add(b);
            newBody.Statements.Add(invariantExit);
            newBody.Statements.Add(new Return());

            // set the field "this.InvariantMethod" to this one so it is used in calls within each method
            // but don't add it yet to the class so it doesn't get visited!
            this.InvariantMethod = invariantMethod;
            this.ReentrancyFlag = reEntrancyFlag;
          }
        }

        base.VisitTypeNode(typeNode);
        // Now add invariant method to the class
        if (this.InvariantMethod != null)
        {
          typeNode.Members.Add(this.InvariantMethod);
        }
        return;
      }
      finally
      {
        this.InvariantMethod = savedInvariantMethod;
        this.ReentrancyFlag = savedReentrancyFlag;
        this.currentState = savedState;
        this.contractEmitFlags = savedEmitFlags;
      }
    }
Beispiel #17
0
    private Class MakeContractException() {
      Class contractExceptionType;

      #region If we're rewriting an assembly for v4 or above and it *isn't* Silverlight (so serialization support is needed), then use new embedded dll as the type
      if (4 <= TargetPlatform.MajorVersion) {
        var iSafeSerializationData = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.Serialization"), Identifier.For("ISafeSerializationData")) as Interface;
        if (iSafeSerializationData != null) {
          // Just much easier to write the C# and have the compiler generate everything than to try and create it all manually
          System.Reflection.Assembly embeddedAssembly;
          Stream embeddedAssemblyStream;
          embeddedAssembly = System.Reflection.Assembly.GetExecutingAssembly();
          embeddedAssemblyStream = embeddedAssembly.GetManifestResourceStream("Microsoft.Contracts.Foxtrot.InternalException.dll");
          byte[] data = new byte[0];
          using (var br = new BinaryReader(embeddedAssemblyStream)) {
            var len = embeddedAssemblyStream.Length;
            if (len < Int32.MaxValue)
              data = br.ReadBytes((int)len);
            AssemblyNode assemblyNode = AssemblyNode.GetAssembly(data, TargetPlatform.StaticAssemblyCache, true, false, true);
            contractExceptionType = assemblyNode.GetType(Identifier.For(""), Identifier.For("ContractException")) as Class;
          }
          if (contractExceptionType == null)
            throw new RewriteException("Tried to create the ContractException type from the embedded dll, but failed");
          var d = new Duplicator(this.targetAssembly, this.RuntimeContractType);
          d.FindTypesToBeDuplicated(new TypeNodeList(contractExceptionType));

          var ct = d.Visit(contractExceptionType);
          contractExceptionType = (Class)ct;
          contractExceptionType.Flags |= TypeFlags.NestedPrivate;
          this.RuntimeContractType.Members.Add(contractExceptionType);
          return contractExceptionType;
        }
      }
      #endregion

      contractExceptionType = new Class(this.targetAssembly, this.RuntimeContractType, new AttributeList(), TypeFlags.Class | TypeFlags.NestedPrivate | TypeFlags.Serializable, null, Identifier.For("ContractException"), SystemTypes.Exception, null, null);

      RewriteHelper.TryAddCompilerGeneratedAttribute(contractExceptionType);

      var kindField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_Kind"), contractNodes.ContractFailureKind, null);
      var userField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_UserMessage"), SystemTypes.String, null);
      var condField = new Field(contractExceptionType, null, FieldFlags.Private, Identifier.For("_Condition"), SystemTypes.String, null);
      contractExceptionType.Members.Add(kindField);
      contractExceptionType.Members.Add(userField);
      contractExceptionType.Members.Add(condField);

      #region Constructor for setting the fields
      var parameters = new ParameterList();
      var kindParam = new Parameter(Identifier.For("kind"), this.contractNodes.ContractFailureKind);
      var failureParam = new Parameter(Identifier.For("failure"), SystemTypes.String);
      var usermsgParam = new Parameter(Identifier.For("usermsg"), SystemTypes.String);
      var conditionParam = new Parameter(Identifier.For("condition"), SystemTypes.String);
      var innerParam = new Parameter(Identifier.For("inner"), SystemTypes.Exception);
      parameters.Add(kindParam);
      parameters.Add(failureParam);
      parameters.Add(usermsgParam);
      parameters.Add(conditionParam);
      parameters.Add(innerParam);
      var body = new Block(new StatementList());
      var ctor = new InstanceInitializer(contractExceptionType, null, parameters, body);
      ctor.Flags |= MethodFlags.Public | MethodFlags.HideBySig;
      ctor.CallingConvention = CallingConventionFlags.HasThis;
      body.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, contractExceptionType.BaseClass.GetConstructor(SystemTypes.String, SystemTypes.Exception)), new ExpressionList(failureParam, innerParam))));
      body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, kindField), kindParam));
      body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, userField), usermsgParam));
      body.Statements.Add(new AssignmentStatement(new MemberBinding(ctor.ThisParameter, condField), conditionParam));
      body.Statements.Add(new Return());
      contractExceptionType.Members.Add(ctor);
      #endregion

      if (SystemTypes.SerializationInfo != null && SystemTypes.SerializationInfo.BaseClass != null) {
        // Silverlight (e.g.) is a platform that doesn't support serialization. So check to make sure the type really exists.
        // 
        var baseCtor = SystemTypes.Exception.GetConstructor(SystemTypes.SerializationInfo, SystemTypes.StreamingContext);

        if (baseCtor != null) {
          #region Deserialization Constructor
          parameters = new ParameterList();
          var info = new Parameter(Identifier.For("info"), SystemTypes.SerializationInfo);
          var context = new Parameter(Identifier.For("context"), SystemTypes.StreamingContext);
          parameters.Add(info);
          parameters.Add(context);
          body = new Block(new StatementList());
          ctor = new InstanceInitializer(contractExceptionType, null, parameters, body);
          ctor.Flags |= MethodFlags.Private | MethodFlags.HideBySig;
          ctor.CallingConvention = CallingConventionFlags.HasThis;
          // : base(info, context) 
          body.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(ctor.ThisParameter, baseCtor), new ExpressionList(info, context))));
          // _Kind = (ContractFailureKind)info.GetInt32("Kind");
          var getInt32 = SystemTypes.SerializationInfo.GetMethod(Identifier.For("GetInt32"), SystemTypes.String);
          body.Statements.Add(new AssignmentStatement(
              new MemberBinding(new This(), kindField),
              new MethodCall(new MemberBinding(info, getInt32), new ExpressionList(new Literal("Kind", SystemTypes.String)))
              ));
          // _UserMessage = info.GetString("UserMessage");
          var getString = SystemTypes.SerializationInfo.GetMethod(Identifier.For("GetString"), SystemTypes.String);
          body.Statements.Add(new AssignmentStatement(
              new MemberBinding(new This(), userField),
              new MethodCall(new MemberBinding(info, getString), new ExpressionList(new Literal("UserMessage", SystemTypes.String)))
              ));
          // _Condition = info.GetString("Condition");
          body.Statements.Add(new AssignmentStatement(
              new MemberBinding(new This(), condField),
              new MethodCall(new MemberBinding(info, getString), new ExpressionList(new Literal("Condition", SystemTypes.String)))
              ));
          body.Statements.Add(new Return());
          contractExceptionType.Members.Add(ctor);
          #endregion

          #region GetObjectData

          var securityCriticalCtor = SystemTypes.SecurityCriticalAttribute.GetConstructor();
          var securityCriticalAttribute = new AttributeNode(new MemberBinding(null, securityCriticalCtor), null, System.AttributeTargets.Method);
          var attrs = new AttributeList(securityCriticalAttribute);
          parameters = new ParameterList();
          info = new Parameter(Identifier.For("info"), SystemTypes.SerializationInfo);
          context = new Parameter(Identifier.For("context"), SystemTypes.StreamingContext);
          parameters.Add(info);
          parameters.Add(context);
          body = new Block(new StatementList());
          var getObjectDataName = Identifier.For("GetObjectData");
          var getObjectData = new Method(contractExceptionType, attrs, getObjectDataName, parameters, SystemTypes.Void, body);
          getObjectData.CallingConvention = CallingConventionFlags.HasThis;
          // public override
          getObjectData.Flags = MethodFlags.Public | MethodFlags.Virtual;
          // base.GetObjectData(info, context);
          var baseGetObjectData = SystemTypes.Exception.GetMethod(getObjectDataName, SystemTypes.SerializationInfo, SystemTypes.StreamingContext);
          body.Statements.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(new This(), baseGetObjectData), new ExpressionList(info, context), NodeType.Call, SystemTypes.Void)
            ));
          // info.AddValue("Kind", _Kind);
          var addValueObject = SystemTypes.SerializationInfo.GetMethod(Identifier.For("AddValue"), SystemTypes.String, SystemTypes.Object);
          body.Statements.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("Kind", SystemTypes.String), new BinaryExpression(new MemberBinding(new This(), kindField), new Literal(contractNodes.ContractFailureKind), NodeType.Box)), NodeType.Call, SystemTypes.Void)
            ));
          // info.AddValue("UserMessage", _UserMessage);
          body.Statements.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("UserMessage", SystemTypes.String), new MemberBinding(new This(), userField)), NodeType.Call, SystemTypes.Void)
            ));
          // info.AddValue("Condition", _Condition);
          body.Statements.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(info, addValueObject), new ExpressionList(new Literal("Condition", SystemTypes.String), new MemberBinding(new This(), condField)), NodeType.Call, SystemTypes.Void)
            ));

          body.Statements.Add(new Return());
          contractExceptionType.Members.Add(getObjectData);
          #endregion
        }
      }

      this.RuntimeContractType.Members.Add(contractExceptionType);
      return contractExceptionType;
    }
 public static bool FieldIsAdditive(Field field) {
   if (field == null) return false;
   AttributeNode attr = field.GetAttribute(SystemTypes.AdditiveAttribute);
   if (attr == null) return false;
   ExpressionList exprs = attr.Expressions;
   if (exprs == null || exprs.Count != 1) return true;
   Literal lit = exprs[0] as Literal;
   if (lit != null && (lit.Value is bool)) return (bool)lit.Value;
   else return false;
 }
        public override Field VisitField(Field field)
        {
            if (field == null) return null;

            if (!this.IncludeModels && HelperMethods.HasAttribute(field.Attributes, ContractNodes.ModelAttributeName))
                return null;

            return base.VisitField(field);
        }
Beispiel #20
0
    private static Field GetInstanceField(TypeNode originalReturnType, Field possiblyGenericField, TypeNode instanceDeclaringType)
    {
      Contract.Requires(instanceDeclaringType != null);

      if (instanceDeclaringType.Template == null) return possiblyGenericField;
      var declaringTemplate = instanceDeclaringType;
      while (declaringTemplate.Template != null) { declaringTemplate = declaringTemplate.Template; }
      Contract.Assume(declaringTemplate == possiblyGenericField.DeclaringType);

      return Rewriter.GetFieldInstanceReference(possiblyGenericField, instanceDeclaringType);
#if false
      Field f = instanceDeclaringType.GetField(possiblyGenericField.Name);
      if (f != null)
      {
        // already instantiated
        return f;
      }
      // pseudo instance
      Field instance = new Field(instanceDeclaringType, possiblyGenericField.Attributes, possiblyGenericField.Flags, possiblyGenericField.Name, originalReturnType, null);
      instanceDeclaringType.Members.Add(instance);
      return instance;
#endif
    }
Beispiel #21
0
            public override void VisitMemberBinding(MemberBinding memberBinding)
            {
                Field f = memberBinding.BoundMember as Field;
                if (f != null)
                {
                    this.Found = f;
                    return;
                }

                base.VisitMemberBinding(memberBinding);
            }
Beispiel #22
0
 private static void AddEnumValue(EnumNode enumType, string name, object value)
 {
   var enumValue = new Field(enumType, null, FieldFlags.Assembly | FieldFlags.HasDefault | FieldFlags.Literal | FieldFlags.Static, Identifier.For(name), enumType, new Literal(value, SystemTypes.Int32));
   enumType.Members.Add(enumValue);
 }
Beispiel #23
0
 internal static void TryAddCompilerGeneratedAttribute(Field field)
 {
   Contract.Requires(field != null);
     TryAddCompilerGeneratedAttribute(field, System.AttributeTargets.Field);
 }
Beispiel #24
0
 internal static Field GetFieldInstanceReference(Field fieldOfGenericType, TypeNode instantiatedParentType) {
   return (Field)GetMemberInstanceReference(fieldOfGenericType, instantiatedParentType);
 }
Beispiel #25
0
 /// <summary>
 /// Write out a field name
 /// </summary>
 /// <param name="field">The field for which to write out the name</param>
 /// <param name="sb">The string builder to which the name is written</param>
 private static void WriteField(Field field, StringBuilder sb)
 {
     WriteType(field.DeclaringType, sb);
     sb.Append('.');
     sb.Append(field.Name.Name);
 }
Beispiel #26
0
    public override Expression VisitOldExpression(OldExpression oldExpression) {
      if (this.topLevelClosureClass != null) {
        #region In Closure ==> Create a field
        // Since we're within a closure, we can't create a local to hold the value of the old expression
        // but instead have to create a field for it. That field can be a member of the top-level
        // closure class since nothing mentioned in the old expression (except possibly for the
        // bound variables of enclosing quantifications) should be anything captured from
        // an inner anonymous delegate.

        // BUT, first we have to know if the old expression depends on any of the bound
        // variables of the closures in which it is located. If not, then we can implement
        // it as a scalar and just generate the assignment "closure_class.field := e" for
        // "Old(e)" to take a snapshot of e's value in the prestate. If it does depend on
        // any of the bound variables, then we need to generate a set of for-loops that
        // compute the indices and values of e for each tuple of indices so it can be retrieved
        // (given the indices) in the post-state.
        CollectBoundVariables cbv = new CollectBoundVariables(this.stackOfBoundVariables);
        cbv.VisitExpression(oldExpression.expression);

        SubstituteClosureClassWithinOldExpressions subst =
            new SubstituteClosureClassWithinOldExpressions(this.closureLocals);
        Expression e = subst.VisitExpression(oldExpression.expression);
        if (cbv.FoundVariables.Count == 0) {
          #region Use a scalar for the old variable
          Local closureLocal;
          if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal))
          {
            Contract.Assume(false, "can't find closure local!");
          }
          #region Define a scalar
          var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass);
          Field f = new Field(clTemplate,
            null,
            FieldFlags.CompilerControlled | FieldFlags.Public,
            Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr.
            oldExpression.Type,
            null);
          clTemplate.Members.Add(f);
          // now produce properly instantiated field
          f = (Field)Rewriter.GetMemberInstanceReference(f, this.topLevelClosureClass);
          #endregion
          #region Generate code to store value in prestate
          this.prestateValuesOfOldExpressions.Statements.Add(new AssignmentStatement(new MemberBinding(closureLocal, f), e));
          #endregion
          #region Return expression to be used in poststate
          // Return an expression that will evaluate in the poststate to the value of the old
          // expression in the prestate. This will be this.up.f where "up" is the field C#
          // generated to point to the instance of the top-level closure class.
          if (this.PointerToTopLevelClosureClass == null) {
            // then the old expression occurs in the top-level closure class. Just return "this.f"
            // where "this" refers to the top-level closure class.
            return new MemberBinding(new This(this.currentClosureClass), f);
          } else {
            return new MemberBinding(
              new MemberBinding(new This(this.currentClosureClass), this.PointerToTopLevelClosureClass),
              f);
          }
          #endregion
          #endregion
        } else {
          // the Old expression *does* depend upon at least one of the bound variable
          // in a ForAll or Exists expression
          #region Use an indexed variable for the old variable
          TypeNode oldVariableTypeDomain;
          #region Decide if domain is one-dimensional or not
          bool oneDimensional = cbv.FoundVariables.Count == 1 && cbv.FoundVariables[0].Type.IsValueType;
          if (oneDimensional) {
            // a one-dimensional old-expression can use the index variable directly
            oldVariableTypeDomain = cbv.FoundVariables[0].Type;
          } else {
            oldVariableTypeDomain = SystemTypes.GenericList.GetTemplateInstance(this.module, SystemTypes.Int32);
          }
          #endregion
          TypeNode oldVariableTypeRange = oldExpression.Type;
          TypeNode oldVariableType = SystemTypes.GenericDictionary.GetTemplateInstance(this.module, oldVariableTypeDomain, oldVariableTypeRange);
          Local closureLocal;
          if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal))
          {
            Contract.Assume(false, "can't find closure local");
          }
          #region Define an indexed variable
          var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass);
          Field f = new Field(clTemplate,
            null,
            FieldFlags.CompilerControlled | FieldFlags.Assembly, // can't be private or protected because it needs to be accessed from inner (closure) classes that don't inherit from the class this field is added to.
            Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr.
            oldVariableType,
            null);
          clTemplate.Members.Add(f);
          // instantiate f
          f = (Field)Rewriter.GetMemberInstanceReference(f, closureLocal.Type);
          #endregion
          #region Generate code to initialize the indexed variable
          Statement init = new AssignmentStatement(
            new MemberBinding(closureLocal, f),
            new Construct(new MemberBinding(null, oldVariableType.GetConstructor()), null));
          this.prestateValuesOfOldExpressions.Statements.Add(init);
          #endregion
          #region Generate code to store values in prestate
          #region Create assignment: this.closure.f[i,j,k,...] = e;
          Method setItem = oldVariableType.GetMethod(Identifier.For("set_Item"), oldVariableTypeDomain, oldVariableTypeRange);
          Expression index;
          if (oneDimensional) {
            index = cbv.FoundVariables[0];
          } else {
            //InstanceInitializer ctor =
            //  ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1));
            //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList(
            index = Literal.Null;
          }
          MethodCall mc = new MethodCall(new MemberBinding(new MemberBinding(closureLocal, f), setItem),
            new ExpressionList(index, e));
          Statement stat = new ExpressionStatement(mc);
          #endregion
          List<Local> locals = new List<Local>(this.stackOfBoundVariables.Count);
          TrivialHashtable paramMap = new TrivialHashtable();
          #region Generate a local for each bound variable to use in for-loop
          foreach (Variable v in this.stackOfBoundVariables) {
            Local l = new Local(Identifier.Empty, v.Type);
            paramMap[v.UniqueKey] = l;
            locals.Add(l);
          }
          #endregion
          #region Substitute locals for bound variables in old expression *AND* in inner loop bounds
          SubstituteParameters sps = new SubstituteParameters(paramMap, this.stackOfBoundVariables);
          sps.Visit(stat);
          #endregion
          #region Create nested for-loops around assignment
          // keep track of when the first variable is used (from innermost to outermost)
          // as soon as the first one is needed because the old expression depends on it,
          // then keep all enclosing loops. It would be possible to keep only those where
          // the necessary loops have loop bounds that depend on an enclosing loop, but I
          // haven't calculated that, so just keep them all. For instance, if the old expression
          // depends on j and the loops are "for i,0,n" and inside that "for j,0,i", then need
          // both loops. If the inner loop bounds were 0 and n, then wouldn't need the outer
          // loop.
          bool usedAVariable = false;
          for (int i = this.stackOfBoundVariables.Count - 1; 0 <= i; i--) {
            if (!usedAVariable
              && !cbv.FoundVariables.Contains(this.stackOfBoundVariables[i])) continue;
            usedAVariable = true;
            Expression lowerBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression(
              this.stackOfMethods[i].Operands[0]);
            lowerBound = subst.VisitExpression(lowerBound);
            lowerBound = sps.VisitExpression(lowerBound);
            Expression upperBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression(
              this.stackOfMethods[i].Operands[1]);
            upperBound = subst.VisitExpression(upperBound);
            upperBound = sps.VisitExpression(upperBound);
            stat = RewriteHelper.GenerateForLoop(locals[i], lowerBound, upperBound, stat);
          }
          #endregion
          this.prestateValuesOfOldExpressions.Statements.Add(stat);
          #endregion
          #region Return expression to be used in poststate
          Method getItem = oldVariableType.GetMethod(Identifier.For("get_Item"), oldVariableTypeDomain);
          if (oneDimensional) {
            index = cbv.FoundReferences[0];
          } else {
            //InstanceInitializer ctor =
            //  ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1));
            //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList(
            index = Literal.Null;
          }
          // Return an expression that will evaluate in the poststate to the value of the old
          // expression in the prestate. This will be this.up.f[i,j,k,...] where "up" is the field C#
          // generated to point to the instance of the top-level closure class.
          MemberBinding thisDotF;
          if (this.PointerToTopLevelClosureClass == null) {
            // then the old expression occurs in the top-level closure class. Just return "this.f"
            // where "this" refers to the top-level closure class.
            Contract.Assume(f != null);
            thisDotF = new MemberBinding(new This(clTemplate), HelperMethods.Unspecialize(f));
          } else {
            thisDotF = new MemberBinding(
              new MemberBinding(new This(clTemplate), this.PointerToTopLevelClosureClass),
              f);
          }
          return new MethodCall(new MemberBinding(thisDotF, getItem), new ExpressionList(index));
          #endregion
          #endregion
        }
        #endregion
      } else {
        #region Not in closure ==> Create a local variable
        Local l = GetLocalForOldExpression(oldExpression);
        #region Make sure local can be seen in the debugger (for the entire method, unfortunately)
        if (currentMethod.LocalList == null) {
          currentMethod.LocalList = new LocalList();
        }
        currentMethod.LocalList.Add(l);
        currentMethod.Body.HasLocals = true;
        #endregion
        this.prestateValuesOfOldExpressions.Statements.Add(
          new AssignmentStatement(l, oldExpression.expression));

        // Return an expression that will evaluate in the poststate to the value of the old
        // expression in the prestate. When we're not in a closure, this is just the local
        // itself.
        return l;
        #endregion
      }
    }
Beispiel #27
0
 public override Field VisitField(Field field)
 {
     if (field == null) return null;
     WriteStart(GetFieldQualifiers(field));
     this.VisitTypeReference(field.Type);
     Write(" {0}", field.Name.Name);
     if (field.Initializer != null)
     {
         Write(" = ");
         field.Initializer = this.VisitExpression(field.Initializer);
     }
     WriteFinish(";");
     return field;
 }
Beispiel #28
0
    /// <summary>
    /// If there is an anonymous delegate within a postcondition, then there
    /// will be a call to a delegate constructor.
    /// That call looks like "d..ctor(o,m)" where d is the type of the delegate.
    /// There are two cases depending on whether the anonymous delegate captured
    /// anything. In both cases, m is the method implementing the anonymous delegate.
    /// 
    /// (1) It does capture something. Then o is the instance of the closure class
    /// implementing the delegate, and m is an instance method in the closure
    /// class.
    /// (2) It does *not* capture anything. Then o is the literal for null and
    /// m is a static method that was added directly to the class.
    /// 
    /// This method will cause m to be visited to collect any old expressions
    /// that occur in it. But those old expressions are not turned into locals,
    /// but fields. The fields are created as either (1) members of the closure class,
    /// or (2) members of the class in which the method containing the contract
    /// containing the Old expression is defined.
    /// The fields are initialized when (1) the closure class instance is created,
    /// or (2) ... ??? (when!?)
    /// So set up enough state so that when those old expressions are visited, the
    /// correct ASTs can be built.
    /// </summary>
    /// <param name="cons">The AST representing the call to the constructor
    /// of the delegate type.</param>
    /// <returns>Whatever the base visitor returns</returns>
    public override Expression VisitConstruct(Construct cons) {
      if (cons.Type is DelegateNode) {
        UnaryExpression ue = cons.Operands[1] as UnaryExpression;
        if (ue == null) goto JustVisit;
        MemberBinding mb = ue.Operand as MemberBinding;
        if (mb == null) goto JustVisit;
        Method m = mb.BoundMember as Method;

        Contract.Assume(m != null);

        if (m.IsStatic) {
          // then there is no closure class, m is just a static method the compiler
          // added to the class itself
          goto JustVisit;
        }
        if (HelperMethods.IsCompilerGenerated(m)) {
          Local l = cons.Operands[0] as Local;
          if (l == null) goto JustVisit; // but then what is it??
          TypeNode savedClosureClass = this.currentClosureClass;
          this.currentClosureClass = l.Type;
          if (savedClosureClass == null) {
            // then this is the top-level closure class
            // have to treat it special: it doesn't contain a field that points 
            // to the top-level closure class. The field introduced to hold the value of the
            // old expression will be declared in this class.
            this.topLevelClosureClass = this.currentClosureClass;
          } else {
            // Find the field in this.closureClass that the C# compiler generated
            // to point to the top-level closure
            foreach (Member mem in this.currentClosureClass.Members) {
              Field f = mem as Field;
              if (f == null) continue;
              if (f.Type == this.topLevelClosureClass) {
                this.PointerToTopLevelClosureClass = f;
                break;
              }
            }
          }

          this.VisitBlock(m.Body);

          if (savedClosureClass == null) {
            this.topLevelClosureClass = null;
          }
          this.currentClosureClass = savedClosureClass;
          this.PointerToTopLevelClosureClass = null;
        }
      }
      JustVisit:
      return base.VisitConstruct(cons);
    }
        private void CheckField(Field field)
        {
            Contract.Requires(field != null);

            string s = HelperMethods.GetStringFromAttribute(field, ContractNodes.SpecPublicAttributeName);
            if (s != null)
            {
                // okay if it is null, then it just doesn't have a named substitute to use in documentation, etc.
                // make sure it is the name of a (public) field or (public) property, but it might be inherited

                // Search class hierarchy for a field or a property

                TypeNode t = field.DeclaringType;
                bool error = true;

                while (t != null && error)
                {
                    Contract.Assert(t != null);

                    MemberList mems = t.GetMembersNamed(Identifier.For(s));
                    for (int i = 0, n = /*mems == null ? 0 : */ mems.Count; /*error && */i < n; i++)
                    {
                        Member mem = mems[i];
                        Field f = mem as Field;
                        
                        if (f != null)
                        {
                            if (!f.IsPublic) continue;

                            //if (f.Type != field.Type) continue; // REVIEW: When it becomes possible, allow widening
                            error = false;
                            
                            break;
                        }

                        Property p = mem as Property;
                        if (p != null)
                        {
                            Method getter = p.Getter;
                            
                            if (getter == null) continue; // found by Clousot.
                            
                            if (!getter.IsPublic) continue;
                            
                            //if (getter.ReturnType != field.Type) continue; // REVIEW: When it becomes possible, allow widening
                            error = false;
                            
                            break;
                        }
                    }

                    t = t.BaseType;
                }

                if (error)
                {
                    this.HandleError(
                        new Error(1010, "Field '" +
                                        field.FullName +
                                        "' is marked [ContractPublicPropertyName(\"" + s +
                                        "\")], but no public field/property named '" +
                                        s + "' with type '" + field.Type + "' can be found",
                            field.SourceContext));
                }
            }
        }
Beispiel #30
0
 public virtual Field VisitField(Field field)
 {
     if (field == null) return null;
     field.Attributes = this.VisitAttributeList(field.Attributes);
     field.Type = this.VisitTypeReference(field.Type);
     field.Initializer = this.VisitExpression(field.Initializer);
     field.ImplementedInterfaces = this.VisitInterfaceReferenceList(field.ImplementedInterfaces);
     return field;
 }