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()); }
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; }
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; }
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); }