Пример #1
0
        ////////////////////////////////////////////////////////////////////////////////

        internal EXPR BindToProperty(EXPR pObject, PropWithType pwt, BindingFlag bindFlags, EXPR args, AggregateType pOtherType, EXPRMEMGRP pMemGroup)
        {
            Debug.Assert(pwt.Sym != null &&
                    pwt.Sym.IsPropertySymbol() &&
                    pwt.GetType() != null &&
                    pwt.Prop().getClass() == pwt.GetType().getAggregate());
            Debug.Assert(pwt.Prop().Params.size == 0 || pwt.Prop().isIndexer());
            Debug.Assert(pOtherType == null ||
                    !pwt.Prop().isIndexer() &&
                    pOtherType.getAggregate() == pwt.Prop().RetType.getAggregate());

            bool fConstrained;
            MethWithType mwtGet;
            MethWithType mwtSet;
            EXPR pObjectThrough = null;

            // We keep track of the type of the pObject which we're doing the call through so that we can report 
            // protection access errors later, either below when binding the get, or later when checking that
            // the setter is actually an lvalue.  If we're actually doing a base.prop call then we do not
            // need to ensure that the left side of the dot is an instance of the derived class, otherwise
            // we save it away for later.
            if (0 == (bindFlags & BindingFlag.BIND_BASECALL))
            {
                pObjectThrough = pObject;
            }

            bool bIsMatchingStatic;
            PostBindProperty((bindFlags & BindingFlag.BIND_BASECALL) != 0, pwt, pObject, out mwtGet, out mwtSet);

            if (mwtGet &&
                    (!mwtSet ||
                     mwtSet.GetType() == mwtGet.GetType() ||
                     GetSymbolLoader().HasBaseConversion(mwtGet.GetType(), mwtSet.GetType())
                     )
                )
            {
                pObject = AdjustMemberObject(mwtGet, pObject, out fConstrained, out bIsMatchingStatic);
            }
            else if (mwtSet)
            {
                pObject = AdjustMemberObject(mwtSet, pObject, out fConstrained, out bIsMatchingStatic);
            }
            else
            {
                pObject = AdjustMemberObject(pwt, pObject, out fConstrained, out bIsMatchingStatic);
            }
            pMemGroup.SetOptionalObject(pObject);

            CType pReturnType = GetTypes().SubstType(pwt.Prop().RetType, pwt.GetType());
            Debug.Assert(pOtherType == pReturnType || pOtherType == null);

            if (pObject != null && !pObject.isOK())
            {
                EXPRPROP pResult = GetExprFactory().CreateProperty(pReturnType, pObjectThrough, args, pMemGroup, pwt, null, null);
                if (!bIsMatchingStatic)
                {
                    pResult.SetMismatchedStaticBit();
                }
                pResult.SetError();
                return pResult;
            }

            // if we are doing a get on this thing, and there is no get, and
            // most importantly, we are not leaving the arguments to be bound by the array index
            // then error...
            if ((bindFlags & BindingFlag.BIND_RVALUEREQUIRED) != 0)
            {
                if (!mwtGet)
                {
                    if (pOtherType != null)
                    {
                        return GetExprFactory().MakeClass(pOtherType);
                    }
                    ErrorContext.ErrorRef(ErrorCode.ERR_PropertyLacksGet, pwt);
                }
                else if (((bindFlags & BindingFlag.BIND_BASECALL) != 0) && mwtGet.Meth().isAbstract)
                {
                    // if the get exists, but is abstract, forbid the call as well...
                    if (pOtherType != null)
                    {
                        return GetExprFactory().MakeClass(pOtherType);
                    }
                    ErrorContext.Error(ErrorCode.ERR_AbstractBaseCall, pwt);
                }
                else
                {
                    CType type = null;
                    if (pObjectThrough != null)
                    {
                        type = pObjectThrough.type;
                    }

                    ACCESSERROR error = SemanticChecker.CheckAccess2(mwtGet.Meth(), mwtGet.GetType(), ContextForMemberLookup(), type);
                    if (error != ACCESSERROR.ACCESSERROR_NOERROR)
                    {
                        // if the get exists, but is not accessible, give an error.
                        if (pOtherType != null)
                        {
                            return GetExprFactory().MakeClass(pOtherType);
                        }

                        if (error == ACCESSERROR.ACCESSERROR_NOACCESSTHRU)
                        {
                            ErrorContext.Error(ErrorCode.ERR_BadProtectedAccess, pwt, type, ContextForMemberLookup());
                        }
                        else
                        {
                            ErrorContext.ErrorRef(ErrorCode.ERR_InaccessibleGetter, pwt);
                        }
                    }
                }
            }

            EXPRPROP result = GetExprFactory().CreateProperty(pReturnType, pObjectThrough, args, pMemGroup, pwt, mwtGet, mwtSet);
            if (!bIsMatchingStatic)
            {
                result.SetMismatchedStaticBit();
            }

            Debug.Assert(EXPRFLAG.EXF_BASECALL == (EXPRFLAG)BindingFlag.BIND_BASECALL);
            if ((EXPRFLAG.EXF_BASECALL & (EXPRFLAG)bindFlags) != 0)
            {
                result.flags |= EXPRFLAG.EXF_BASECALL;
            }
            else if (fConstrained && pObject != null)
            {
                // Use the constrained prefix.
                result.flags |= EXPRFLAG.EXF_CONSTRAINED;
            }

            if (result.GetOptionalArguments() != null)
            {
                verifyMethodArgs(result, pObjectThrough != null ? pObjectThrough.type : null);
            }

            if (mwtSet && objectIsLvalue(result.GetMemberGroup().GetOptionalObject()))
            {
                result.flags |= EXPRFLAG.EXF_LVALUE;
            }
            if (pOtherType != null)
            {
                result.flags |= EXPRFLAG.EXF_SAMENAMETYPE;
            }

            return result;
        }
Пример #2
0
        protected void PostBindProperty(bool fBaseCall, PropWithType pwt, EXPR pObject, out MethWithType pmwtGet, out MethWithType pmwtSet)
        {
            pmwtGet = new MethWithType();
            pmwtSet = new MethWithType();
            // Get the accessors.
            if (pwt.Prop().methGet != null)
            {
                pmwtGet.Set(pwt.Prop().methGet, pwt.GetType());
            }
            else
            {
                pmwtGet.Clear();
            }

            if (pwt.Prop().methSet != null)
            {
                pmwtSet.Set(pwt.Prop().methSet, pwt.GetType());
            }
            else
            {
                pmwtSet.Clear();
            }

            // If it is virtual, find a remap of the method to something more specific.  This
            // may alter where the accessors are found.
            if (fBaseCall && pObject != null)
            {
                if (pmwtGet)
                {
                    RemapToOverride(GetSymbolLoader(), pmwtGet, pObject.type);
                }
                if (pmwtSet)
                {
                    RemapToOverride(GetSymbolLoader(), pmwtSet, pObject.type);
                }
            }

            if (pwt.Prop().RetType != null)
            {
                checkUnsafe(pwt.Prop().RetType);
            }
        }