bool CLSComplianceChecker::IsAccessibleOutsideAssembly(BCSYM_NamedRoot * Member)
{
    // Namespaces are always public
    //
    if (Member->IsNamespace())
    {
        return true;
    }

    ACCESS AccessOfMember = Member->GetAccess();

    if (AccessOfMember == ACCESS_Private ||
        AccessOfMember == ACCESS_Friend)
    {
        return false;
    }


    if (AccessOfMember == ACCESS_Protected ||
        AccessOfMember == ACCESS_ProtectedFriend)
    {
        BCSYM_Container *ContainerOfMember = Member->GetContainer();

        VSASSERT( ContainerOfMember,
                    "How can a non-namespace entity not be enclosed in another container ?");

        // If the containing class is notinheritable, then the protected members are
        // not accessible outside the assembly since nobody can inherit the class.
        //
        // Confirmed this with [....] and jsmiller
        //
        if (ContainerOfMember->IsClass() &&
            ContainerOfMember->PClass()->IsNotInheritable())
        {
            return false;
        }

        return true;
    }

    VSASSERT( AccessOfMember == ACCESS_Public,
                    "What else can the access be ?");

    return true;
}
void CLSComplianceChecker::VerifyCLSComplianceForContainerAndNestedTypes(BCSYM_Container * Container)
{
    // Partial types are processed when their main type is processed
    //
    if (Container->IsPartialTypeAndHasMainType())
    {
        return;
    }

    ACCESS Access = Container->GetAccess();

    // If the type is not accessible outside the assembly, then
    // don't bother checking for CLS compliance
    //
    if (!IsAccessibleOutsideAssembly(Container))
    {
        return;
    }

    // If the type is a synthetic type, then don't do any checking
    // eg: implicit delegate generated for event
    //
    if (IsSyntheticMember(Container))
    {
        return;
    }

    VerifyCLSComplianceForContainer(Container);

    BCSYM_Container *CurrentContainer = Container;
    do
    {
        for(BCSYM_Container *NestedContainer = CurrentContainer->GetNestedTypes();
            NestedContainer;
            NestedContainer = NestedContainer->GetNextNestedType())
        {
            VerifyCLSComplianceForContainerAndNestedTypes(NestedContainer);
        }

    } while(CurrentContainer = CurrentContainer->GetNextPartialType());
}
예제 #3
0
void AllEmitableTypesInFileInOrderIterator::GetEmitableTypesInContainer
(
    BCSYM_Container *pContainer,
    _Inout_ int &NestingLevel
)
{
    if (pContainer->IsPartialTypeAndHasMainType())
    {
        return;
    }

    if (!pContainer->IsNamespace())
    {
        EmitableTypeWrapper Wrapper = { pContainer, NestingLevel };

        m_pListOfEmitableTypes.AddElement(Wrapper);
    }

    NestingLevel++;

    BCSYM_Container *pCurrentPartialContainer = pContainer;
    do
    {
        for(BCSYM_Container *pNestedContainer = pCurrentPartialContainer->GetNestedTypes();
            pNestedContainer;
            pNestedContainer = pNestedContainer->GetNextNestedType())
        {
            GetEmitableTypesInContainer(
                pNestedContainer,
                NestingLevel);
        }
    }
    while (pCurrentPartialContainer = pCurrentPartialContainer->GetNextPartialType());

    NestingLevel--;

    return;
}
bool CLSComplianceChecker::ContainerIsPartOfRootNamespace(BCSYM_Container * Container)
{
    if (!Container->IsNamespace())
    {
        return false;
    }

    SourceFile *ContainingSourceFile = Container->GetSourceFile();

    VSASSERT( ContainingSourceFile,
                "Non source container unexpected!!!");

    // RootNamespace can be NULL for non-existent files specified in project files
    //
    BCSYM_Namespace *RootNamespace =
        ContainingSourceFile->GetRootNamespace() ?
            ContainingSourceFile->GetRootNamespace() :
            ContainingSourceFile->GetUnnamedNamespace();

    VSASSERT( RootNamespace,
                "NULL rootnamespace unexpected!!!");

    for(BCSYM_Container *NextContaineraboveRootNamespace = RootNamespace;
        NextContaineraboveRootNamespace;
        NextContaineraboveRootNamespace = NextContaineraboveRootNamespace->GetContainer())
    {
        if (NextContaineraboveRootNamespace == Container)
        {
            return true;
        }

        VSASSERT( !NextContaineraboveRootNamespace->IsSameContainer(Container),
                    "How can there be multiple instances per file for namespaces above the rootnamespace ?");
    }

    return false;
}
예제 #5
0
bool TypeExtensionIterator::MoveNext()
{
    BCSYM_NamedRoot * pNamed = NULL;
    do
    {
        pNamed = m_childIterator.GetNext();
        if (pNamed && pNamed->IsContainer())
        {
            BCSYM_Container *pContainer = pNamed->PContainer();

            // Perf: We are only interested in looking at types marked as containing extension methods.  So only load the 
            // type's children if the type says it contains extension methods.

            BCSYM *pContainerAfterDiggingThroughAlias = pContainer->DigThroughAlias();

            if (pContainerAfterDiggingThroughAlias->IsClass())
            {
                if (pContainerAfterDiggingThroughAlias->PClass()->ContainsExtensionMethods())
                {
                    pContainer->EnsureChildrenLoaded();
                }
            }
            else if (!pContainer->GetCompilerFile() ||
                (pContainer->GetCompilerFile()->IsMetaDataFile() && pContainer->GetCompilerFile()->ContainsExtensionMethods()))
            {
                pContainer->EnsureChildrenLoaded();
            }
        }
    }
    while (pNamed && ! pNamed->IsTypeExtension());

    if (pNamed)
    {
        m_pCurrent = pNamed->PClass();
    }
    else
    {
        m_pCurrent = NULL;
    }

    return m_pCurrent;
}
예제 #6
0
void Bindable::ValidateWithEventsVarsAndHookUpHandlersInContainer()
{

    VSASSERT( GetStatusOfValidateWithEventsVarsAndHookUpHandlers() != InProgress,
                    "How can we have have event validation cycles ?");

    if (GetStatusOfValidateWithEventsVarsAndHookUpHandlers() == Done)
    {
        return;
    }

    BCSYM_Container *Container = CurrentContainer();
    if (!Container->IsClass() ||
        TypeHelpers::IsEnumType(Container->PClass()))
    {
        SetStatusOfValidateWithEventsVarsAndHookUpHandlers(Done);
        return;
    }

    SetStatusOfValidateWithEventsVarsAndHookUpHandlers(InProgress);

    // Makes sure validation of withevents and shadowing, etc. of the types
    // of the withevents variables in bases are done.
    //
    BCSYM_Class *Base = Container->PClass()->GetCompilerBaseClass();
    if (Base)
    {
        ValidateWithEventsVarsAndHookUpHandlersInContainer(Base, m_CompilationCaches);
    }

    // Need to use the SAFE iterator because more members might
    // be added to the Container during hookuping of Handles.
    // This adding of member will happen while the iterator is
    // still in use.
    //
    BCITER_CHILD_SAFE Members(Container);

    // Validate all the withevent vars in this container
    while (BCSYM_NamedRoot *Member = Members.GetNext())
    {
        if (IsWithEventsVariable(Member))
        {
            ValidateWithEventsVar(Member->PVariable());
        }
    }

    // Validate and hookup all the handles clauses specified in this container
    Members.Reset();
    while (BCSYM_NamedRoot *Member = Members.GetNext())
    {
        // Only methods with implementation can have handles clauses
        //
        if (!Member->IsMethodImpl())
        {
            continue;
        }

        BCITER_Handles iterHandles( Member->PMethodImpl() );

        for(BCSYM_HandlesList *HandlesEntry = iterHandles.GetNext();
            HandlesEntry;
            HandlesEntry = iterHandles.GetNext())
        {
            if (HandlesEntry->IsBad())
            {
                continue;
            }

            ValidateAndHookUpHandles(
                HandlesEntry,
                Member->PMethodImpl());
        }
    }

    SetStatusOfValidateWithEventsVarsAndHookUpHandlers(Done);
}