// // SymbolLoader forwarders (end) ///////////////////////////////////////////////////////////////////////////////// // // Utility methods // protected ACCESSERROR CheckAccessCore(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru) { Debug.Assert(symCheck != null); Debug.Assert(atsCheck == null || symCheck.parent == atsCheck.getAggregate()); Debug.Assert(typeThru == null || typeThru.IsAggregateType() || typeThru.IsTypeParameterType() || typeThru.IsArrayType() || typeThru.IsNullableType() || typeThru.IsErrorType()); switch (symCheck.GetAccess()) { default: throw Error.InternalCompilerError(); //return ACCESSERROR.ACCESSERROR_NOACCESS; case ACCESS.ACC_UNKNOWN: return(ACCESSERROR.ACCESSERROR_NOACCESS); case ACCESS.ACC_PUBLIC: return(ACCESSERROR.ACCESSERROR_NOERROR); case ACCESS.ACC_PRIVATE: case ACCESS.ACC_PROTECTED: if (symWhere == null) { return(ACCESSERROR.ACCESSERROR_NOACCESS); } break; case ACCESS.ACC_INTERNAL: case ACCESS.ACC_INTERNALPROTECTED: // Check internal, then protected. if (symWhere == null) { return(ACCESSERROR.ACCESSERROR_NOACCESS); } if (symWhere.SameAssemOrFriend(symCheck)) { return(ACCESSERROR.ACCESSERROR_NOERROR); } if (symCheck.GetAccess() == ACCESS.ACC_INTERNAL) { return(ACCESSERROR.ACCESSERROR_NOACCESS); } break; } // Should always have atsCheck for private and protected access check. // We currently don't need it since access doesn't respect instantiation. // We just use symWhere.parent.AsAggregateSymbol() instead. AggregateSymbol aggCheck = symCheck.parent.AsAggregateSymbol(); // Find the inner-most enclosing AggregateSymbol. AggregateSymbol aggWhere = null; for (Symbol symT = symWhere; symT != null; symT = symT.parent) { if (symT.IsAggregateSymbol()) { aggWhere = symT.AsAggregateSymbol(); break; } if (symT.IsAggregateDeclaration()) { aggWhere = symT.AsAggregateDeclaration().Agg(); break; } } if (aggWhere == null) { return(ACCESSERROR.ACCESSERROR_NOACCESS); } // First check for private access. for (AggregateSymbol agg = aggWhere; agg != null; agg = agg.GetOuterAgg()) { if (agg == aggCheck) { return(ACCESSERROR.ACCESSERROR_NOERROR); } } if (symCheck.GetAccess() == ACCESS.ACC_PRIVATE) { return(ACCESSERROR.ACCESSERROR_NOACCESS); } // Handle the protected case - which is the only real complicated one. Debug.Assert(symCheck.GetAccess() == ACCESS.ACC_PROTECTED || symCheck.GetAccess() == ACCESS.ACC_INTERNALPROTECTED); // Check if symCheck is in aggWhere or a base of aggWhere, // or in an outer agg of aggWhere or a base of an outer agg of aggWhere. AggregateType atsThru = null; if (typeThru != null && !symCheck.isStatic) { atsThru = SymbolLoader.GetAggTypeSym(typeThru); } // Look for aggCheck among the base classes of aggWhere and outer aggs. bool found = false; for (AggregateSymbol agg = aggWhere; agg != null; agg = agg.GetOuterAgg()) { Debug.Assert(agg != aggCheck); // We checked for this above. // Look for aggCheck among the base classes of agg. if (agg.FindBaseAgg(aggCheck)) { found = true; // aggCheck is a base class of agg. Check atsThru. // For non-static protected access to be legal, atsThru must be an instantiation of // agg or a CType derived from an instantiation of agg. In this case // all that matters is that agg is in the base AggregateSymbol chain of atsThru. The // actual AGGTYPESYMs involved don't matter. if (atsThru == null || atsThru.getAggregate().FindBaseAgg(agg)) { return(ACCESSERROR.ACCESSERROR_NOERROR); } } } // the CType in whice the method is being called has no relationship with the // CType on which the method is defined surely this is NOACCESS and not NOACCESSTHRU if (found == false) { return(ACCESSERROR.ACCESSERROR_NOACCESS); } return((atsThru == null) ? ACCESSERROR.ACCESSERROR_NOACCESS : ACCESSERROR.ACCESSERROR_NOACCESSTHRU); }