//
// SymbolLoader forwarders (end)
/////////////////////////////////////////////////////////////////////////////////
//
// Utility methods
//
private 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 is AggregateType ||
typeThru is TypeParameterType ||
typeThru is ArrayType ||
typeThru is NullableType ||
typeThru is ErrorType);
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;
}
// Find the inner-most enclosing AggregateSymbol.
AggregateSymbol aggWhere = null;
for (Symbol symT = symWhere; symT != null; symT = symT.parent)
{
if (symT is AggregateSymbol aggSym)
{
aggWhere = aggSym;
break;
}
if (symT is AggregateDeclaration aggDec)
{
aggWhere = aggDec.Agg();
break;
}
}
if (aggWhere == null)
{
return(ACCESSERROR.ACCESSERROR_NOACCESS);
}
// 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 as AggregateSymbol instead.
AggregateSymbol aggCheck = symCheck.parent as AggregateSymbol;
// 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 which 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);
}