void CLSComplianceChecker::ValidateNonCLSCompliantMemberInCLSCompliantContainer(
    BCSYM_NamedRoot * Member,
    BCSYM_Container * ParentOfMember)
{
    VSASSERT( ParentOfMember->IsCLSCompliant(),
                    "Members of non-CLS compliant types unexpected!!!");

    // 

    VSASSERT( Member->IsMember(), "Non-member unexpected!!!");

    if (ParentOfMember->IsInterface())
    {
        // Non CLS compliant |1 is not allowed in a CLS compliant interface.

        ReportErrorOnSymbol(
            WRNID_NonCLSMemberInCLSInterface1,
            Member,
            StringOfSymbol(m_Compiler, Member));
    }
    else if (Member->IsProc() &&
             Member->PProc()->IsMustOverrideKeywordUsed())
    {
        // Non CLS compliant mustoverride member is not allowed in a CLS compliant |1.

        ReportErrorOnSymbol(
            WRNID_NonCLSMustOverrideInCLSType1,
            Member,
            StringOfSymbol(m_Compiler, ParentOfMember));
    }
}
Ejemplo n.º 2
0
Location*
Bindable::BindableMemberInfo::GetLocationToReportError()
{
    if (SourceOfSyntheticMember)
    {
        if (syntheticContext == HandlesOfBaseWithEvents)
        {
            if (Member->IsProperty())
            {
                if (Member->PProperty()->CreatedByHandlesClause())
                {
                    return Member->PProperty()->CreatedByHandlesClause()->GetLocationOfWithEventsVar();
                }
            }
            else
            {
                VSASSERT( Member->IsSyntheticMethod(),
                                "What other members can be synthesized for handling a base withevents ?");
                VSASSERT( Member->PProc()->GetAssociatedPropertyDef(),
                            "what other synthetic method besides a Propety_Get and a Property_Set can be synthesized for handling a base withevents?");

                if (Member->PProc()->GetAssociatedPropertyDef()->CreatedByHandlesClause())
                {
                    return Member->PProc()->GetAssociatedPropertyDef()->
                                CreatedByHandlesClause()->GetLocationOfWithEventsVar();
                }
            }
        }

        return SourceOfSyntheticMember->GetLocation();
    }

    return Member->GetLocation();
}
Ejemplo n.º 3
0
/**********
*TemporaryManager::FreeTemporary
*       Frees one temporary indicating that it is not required.
***********/
void
TemporaryManager::FreeTemporary
(
    BCSYM_Variable *TemporaryToDelete
)
{
    VSASSERT(TemporaryToDelete->IsTemporary(), "Temporary expected!!!");

    // Find the temporary and decrement its use count.
    for (Temporary *Cursor = m_Temporaries; Cursor; Cursor = Cursor->Next)
    {
        VSASSERT(Cursor->Symbol, "this temporary doesn't have a symbol!");

        if (Cursor->Symbol == TemporaryToDelete)
        {
            VSASSERT(Cursor->UseCount != 0, "Inconsistency in temporary variable allocations!!!");

            Cursor->UseCount--;
            if (Cursor->UseCount == 0)
            {
                Cursor->IsCurrentlyInUse = false;
            }

            break;
        }
    }
}
Ejemplo n.º 4
0
BCSYM_Proc*
Bindable::SynthesizeConstructor
(
    bool SynthesizeSharedConstructor
)
{
    VSASSERT(CurrentContainer()->IsClass(),
                    "why would a non-class need to synthesize constructors ?");

    BCSYM_Class *Class = CurrentContainer()->PClass();

    Symbols
        SymbolAllocator(
            CurrentCompilerInstance(),
            CurrentAllocator(),
            NULL,
            CurrentGenericBindingCache());

	Declared::SyntheticConstructorTypeEnum makeWhat = Declared::SyntheticConstructorType::Instance;
	if (SynthesizeSharedConstructor) {
		makeWhat = Declared::SyntheticConstructorType::Shared;
	} else if (Class->IsMustInherit()) {
		makeWhat = Declared::SyntheticConstructorType::MustInherit;
	}
    BCSYM_Proc *Constructor =
        Declared::BuildSyntheticConstructor(
            &SymbolAllocator,
            CurrentCompilerInstance(),
            NULL,
			makeWhat);  // No Symbol list to add this symbol to
                    // We will add it manually to the hash

    VSASSERT( Constructor,
                    "Unexpected failure in synthesizing constructor");

    // Add the Consatructor to the container's hash
    //
    Symbols::AddSymbolToHash(
        Class->GetHash(),
        Constructor,
        true,       // set the parent of this member
        Class->IsStdModule(),
        false);     // container is not namespace

#if IDE

    // Add this to the list of symbols created in bindable.
    // This list is used to delete these from their respective
    // hashes during decompilation from bindable.
    //
    SymbolAllocator.GetAliasOfSymbol(
        Constructor,
        ACCESS_Private,
        CurrentContainer()->GetBindableSymbolList());
#endif

    return Constructor;
}
void CLSComplianceChecker::VerifyOverloadsForCLSCompliance(BCSYM_Proc * PossiblyOverloadedProc)
{
    // Check the Overloads for overloading by Array Rank or
    // overloading on Array of Arrays

    // we don't allow bad members because they could have
    // been bad during overloads verification in bindable.
    //
    VSASSERT( !PossiblyOverloadedProc->IsBad(),
                    "Bad members unexpected!!!");

    if (!Bindable::IsMethod(PossiblyOverloadedProc) &&
        !Bindable::IsProperty(PossiblyOverloadedProc))
    {
        return;
    }

    for(BCSYM_NamedRoot *NextPossibleOverload = PossiblyOverloadedProc->GetNextOverload();
        NextPossibleOverload;
        NextPossibleOverload = NextPossibleOverload->GetNextOverload())
    {
        VSASSERT( NextPossibleOverload->IsProc(),
                    "How can a non-proc be involved in overloads ?");

        BCSYM_Proc *NextOverload = NextPossibleOverload->PProc();

        if (!IsAccessibleOutsideAssembly(NextOverload))
        {
            continue;
        }

        VerifyOverloadsForCLSCompliance(
            PossiblyOverloadedProc,
            NextOverload);
    }

    // 














}
Ejemplo n.º 6
0
bool
Bindable::CheckForAccessibleEventsInContainer
(
    BCSYM *TypePossiblyContainingEvents,
    BCSYM *TypeOfWithEventsVar,
    bool ConsiderEventSourcePropertiesToo,
    bool &AnyEventDefined
)
{
    // Note: the calling function is expected to initialize AnyEventDefine to false.
    // We don't do this here because the function is recursive.

    VSASSERT(TypePossiblyContainingEvents &&
             TypePossiblyContainingEvents->IsContainer(),
                "Non-container unexpected!!!");

    // will hold a list of members marked as Shadowing in here
    //
    MembersHashTable ShadowingMembers;

    // Resolve shadowing etc. for the type of the withevents variable before looking for accessible events in it
    ResolveShadowingOverloadingOverridingAndCheckGenericsForContainer(TypePossiblyContainingEvents->PContainer(), m_CompilationCaches);

    return CheckForAccessibleEventsWorker(
                TypePossiblyContainingEvents,
                TypeOfWithEventsVar,
                &ShadowingMembers,
                ConsiderEventSourcePropertiesToo,
                AnyEventDefined);
}
Ejemplo n.º 7
0
int __cdecl SortSymbolsByNameAndExternalAccess
(
    const void *arg1,
    const void *arg2
)
{
    BCSYM_NamedRoot *Member1 = *(BCSYM_NamedRoot **)arg1;
    BCSYM_NamedRoot *Member2 = *(BCSYM_NamedRoot **)arg2;

    VSASSERT(Member1 && Member2, "How can the symbols be compared be NULL?");

    // We add locations to all members imported from COM typelibs, since we may need the ordering data later if we
    // need to embed No-PIA local types. In other situations, we expect that metadata members do not have locations.
    // Exception: as per the comment in MetaData::ImportChildren, we also get locations for members from PIAs.
    AssertIfTrue(Member1->HasLocation() && !Member1->GetContainingProject()->GetAssemblyIdentity()->IsImportedFromCOMTypeLib() && !Member1->GetContainingProject()->GetAssemblyIdentity()->IsPrimaryInteropAssembly());
    AssertIfTrue(Member2->HasLocation() && !Member2->GetContainingProject()->GetAssemblyIdentity()->IsImportedFromCOMTypeLib() && !Member2->GetContainingProject()->GetAssemblyIdentity()->IsPrimaryInteropAssembly());


    // First sort by name.
    int i = SortSymbolsByName(arg1, arg2);

    // Now sort by access external to this assembly.
    if (i == 0)
    {
#pragma prefast(suppress: 26010 26011, "If access is outside of the array limits, then the whole symbol is busted")
        i = MapAccessToAccessOutsideAssembly[Member1->GetAccess()] - MapAccessToAccessOutsideAssembly[Member2->GetAccess()];
    }

    return i;
}
void CLSComplianceChecker::VerifyConstraintsAreCLSCompliant(BCSYM_NamedRoot * ContainerOrProc)
{
    VSASSERT(ContainerOrProc->IsContainer() || ContainerOrProc->IsProc(),
                "Symbol kind unexpected during generic constraint CLS compliance checking!!!");

    // Check the Generic parameter constraint types too for CLS Compliance.
    // If not a generic type or method, it will not have any generic
    // parameters.

    for(BCSYM_GenericParam *GenericParam = ContainerOrProc->GetFirstGenericParam();
        GenericParam;
        GenericParam = GenericParam->GetNextParam())
    {
        for (BCSYM_GenericTypeConstraint *Constraint = GenericParam->GetTypeConstraints();
             Constraint;
             Constraint = Constraint->Next())
        {
            BCSYM *ConstraintType = Constraint->GetRawType();

            if (IsTypeCLSCompliant(ConstraintType, GenericParam))
            {
                continue;
            }

            ReportErrorOnSymbol(
                WRNID_GenericConstraintNotCLSCompliant1,
                Constraint,
                GenericParam,
                ConstraintType->ChaseToType()->GetErrorName(m_Compiler));
        }
    }
}
Ejemplo n.º 9
0
void Location::SetLocation
(
    _In_ const Location * pNewLocation // the location to copy
)
{
    VSASSERT( pNewLocation, "You can't pass NULL to SetLocation( Location *)");
    *this = *pNewLocation;
}
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::VerifyThatMembersAreNotMarkedCLSCompliant(BCSYM_Container * Container)
{
    VSASSERT( !Container->IsCLSCompliant(),
                    "CLS compliant container unexpected!!!");

    // Members nested inside Non CLS Compliant Types cannot be
    // marked as CLS Compliant.
    //
    // For Top Level types, it is okay to be marked as CLS Compliant
    // even though inside a Non-CLS Compliant assembly.
    //
    if (Container->IsNamespace())
    {
        return;
    }

    BCITER_CHILD Members(Container);
    while (BCSYM_NamedRoot *Member = Members.GetNext())
    {
        if (Member->IsBad())
        {
            continue;
        }

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

        // Need to do this so that we handle the operators. Operators
        // do not by themselves show up in this (bindable hash) hash
        // we are looking in, so we will find them through their functions
        // instead.
        //
        if (Member->IsProc() &&
            Member->PProc()->IsUserDefinedOperatorMethod())
        {
            Member = Member->PProc()->GetAssociatedOperatorDef();
        }

        // We don't want to report errors for synthetic members.
        // Eg: withevents property, the withevents variable _prop, etc.
        // If we don't skip errors for these, we would end up reporting
        // the same errors on both these and the original symbols from
        // which they were synthesized resulting in duplicate errors.
        //
        if (IsSyntheticMember(Member))
        {
            continue;
        }

        VerifyMemberNotMarkedCLSCompliant(Member);
    }
}
Ejemplo n.º 12
0
void* NorlsAllocator::_AllocNonZero(size_t& sz)
{
    AssertIfFalse((size_t)nextFree % sizeof(void*) == 0);
    AssertIfFalse((size_t)limitFree % sizeof(void*) == 0);

    void * p = nextFree;
    if (sz == 0 && p == NULL)
    {
        sz = 1;
    }

    size_t roundSize = VBMath::RoundUpAllocSize(sz);
    size_t available = limitFree - nextFree;

    if ( available < roundSize )
    {
        AllocNewPage(sz);
    }

    p = nextFree;
    nextFree += roundSize; // this shouldn't overflow because we got the memory for the request (we would have thrown in AllocNewPage() otherwise)

    MakeCurrentPageWriteableInternal();

    AssertIfFalse((size_t)nextFree % sizeof(void*) == 0);
    AssertIfFalse((size_t)limitFree % sizeof(void*) == 0);
    AssertIfFalse((size_t)p % sizeof(void*) == 0);

#if NRLSTRACK
    m_nTotalAllocated += roundSize;
    m_dwAllocThreadId  = 0;
#endif NRLSTRACK

    sz = roundSize;
#if NRLSTRACK
    VSASSERT(m_dwAllocThreadId == 0," NorlsAlloc: only 1 thread allowed at a time");
    m_dwAllocThreadId = GetCurrentThreadId();
    m_nSeqNo+=1;


#if NRLSTRACK_GETSTACKS
    //
    NrlsHeapData  *pdata =
        (NrlsHeapData *) VsDebugAllocInternal(TrackingHeapToUse(),
                HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS,
                (sizeof (NrlsHeapData )), __FILE__, __LINE__, INSTANCE_GLOBAL, NULL);

    pdata->m_ptrNextBlock = m_pLastBlock; // linked list of allocations: point to prior one
    pdata->m_size = sz;  // record the size
    pdata->m_data = p;  // record the actual allocation
    m_pLastBlock = pdata; // track the most recent one
#endif NRLSTRACK_GETSTACKS
#endif NRLSTRACK
    return p;
}
Ejemplo n.º 13
0
/*
 * Allocate (duplicate) a wide char string.
 */
PWSTR NorlsAllocator::AllocStr(PCWSTR str)
{
    if (str == NULL)
        return NULL;

    size_t str_len = wcslen(str);

    // integer overflow
    if (!(str_len < str_len + 1))
    {
        VSASSERT(str_len < str_len + 1, "Invalid");
        return NULL;
    }

    PWSTR strNew = (PWSTR) Alloc((str_len + 1) * sizeof(WCHAR));
    HRESULT hr;
    hr = StringCchCopyW (strNew, str_len + 1, str);
    VSASSERT (SUCCEEDED (hr), "Invalid");
    return strNew;
}
Ejemplo n.º 14
0
//
// CryptHash::GetCryptHash()
//      caller needs to allocate memory for pvHash based on GetHashSize()
//
bool CryptHash::GetCryptHash(void *pvHash, DWORD cbHash) const 
{
    VSASSERT(cbHash == GetCryptHashSize(),"Wrong hash size");
    DWORD cbT = cbHash;
    bool fSucceed = ::CryptGetHashParam(m_hHash, HP_HASHVAL, PBYTE(pvHash), &cbT, 0);
    
    if(!fSucceed)
    {
        ::memset(pvHash, 0, cbHash);
    }
    
    return fSucceed;
}
Ejemplo n.º 15
0
int __cdecl SortSymbolsByNameAndOperatorAndLocation
(
    const void *arg1,
    const void *arg2
)
{
    // 


    BCSYM_NamedRoot *Member1 = *(BCSYM_NamedRoot **)arg1;
    BCSYM_NamedRoot *Member2 = *(BCSYM_NamedRoot **)arg2;

    VSASSERT(Member1 && Member2, "How can the symbols to be compared be NULL?");

    // First sort by name.
    int i = SortSymbolsByName(arg1, arg2);

    // Now sort by operator kind.
    if (i == 0)
    {
        bool Member1IsOperator = IsUserDefinedOperator(Member1);
        bool Member2IsOperator = IsUserDefinedOperator(Member2);

        if (Member1IsOperator)
        {
            if (Member2IsOperator)
            {
                UserDefinedOperators Operator1 = Member1->PUserDefinedOperator()->GetOperator();
                UserDefinedOperators Operator2 = Member2->PUserDefinedOperator()->GetOperator();

                i = (Operator1 == Operator2) ? 0 : (Operator1 > Operator2) ? 1 : -1;
            }
            else
            {
                i = 1;
            }
        }
        else if (Member2IsOperator)
        {
            i = -1;
        }
    }

    if (i == 0)
    {
        i = SortSymbolsByLocation(arg1, arg2);
    }

    return i;
}
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;
}
void CLSComplianceChecker::VerifyBasesForCLSCompliance(BCSYM_Container * Container)
{
    VSASSERT( Container->IsCLSCompliant(),
                    "Non-CLS compliant container unexpected!!!");

    if (Container->IsClass())
    {
        BCSYM *RawBaseType = Container->PClass()->GetRawBase();

        // Report an error if this inherited class is not compliant.
        //
        if (!IsTypeCLSCompliant(RawBaseType, Container))
        {
            ReportErrorOnSymbol(
                WRNID_BaseClassNotCLSCompliant2,
                Container,
                Container->GetName(),
                RawBaseType->ChaseToType()->GetErrorName(m_Compiler));
        }
    }
    else if (Container->IsInterface())
    {
        for (BCSYM_Implements *Impl =
                Container->PInterface()->GetFirstImplements();
             Impl;
             Impl = Impl->GetNext())
        {
            if (Impl->IsBad())
            {
                continue;
            }

            BCSYM *RawBaseType = Impl->GetRawRoot();

            // Report an error if this inherited interface is not compliant.
            //
            if (!IsTypeCLSCompliant(RawBaseType, Container))
            {
                ReportErrorOnSymbol(
                    WRNID_InheritedInterfaceNotCLSCompliant2,
                    Container,
                    Container->GetName(),
                    RawBaseType->ChaseToType()->GetErrorName(m_Compiler));
            }
        }
    }
}
Ejemplo n.º 18
0
//============================================================================
// Update the tracked locations
//============================================================================
void LineMarkerTable::PostNotifyOfEdit(
    VBTextBuffer * pVBTextBuffer,
    EditInfoLists * pEditLists,
    EditCache SingleEdit,
    bool LastEdit)
{
    VSASSERT(SingleEdit.oAdjust != 0, L"oAdjust should never be 0 inside LineMarkerTable::PostNotifyOfEdit()");

    CompilerIdeLock lock(m_lock);

    // We need to refresh the task list if an error location changes
    if (m_pSourceFile->GetProject() &&
        m_pSourceFile->GetProject()->GetCompilerTaskProvider() &&
        GetCompilerPackage())
    {
        bool fUpdatedErrors = UpdateTrackedOffsetsAndLocations<ErrorLocation>(m_errorLocations, pVBTextBuffer, pEditLists, SingleEdit, LastEdit);
        bool fUpdatedOutOfProcBuildErrors = UpdateTrackedOffsetsAndLocations<ErrorLocation>(m_outOfProcBuildErrorLocations, pVBTextBuffer, pEditLists, SingleEdit, LastEdit);

        if (fUpdatedOutOfProcBuildErrors)
        {
            m_pSourceFile->SignalOutOfProcBuildErrorLocationsUpdated();
        }

        if (fUpdatedErrors || fUpdatedOutOfProcBuildErrors)
        {
            m_pSourceFile->GetProject()->GetCompilerTaskProvider()->TaskListNeedsRefresh();
            GetCompilerSharedState()->RefreshTaskList();
        }
    }

    // Stop tracking errors we no longer care about (IsInvalid or the force remove flag is set)
    if (LastEdit)
    {
        RemoveInvalidErrorLocations();
    }

    UpdateTrackedOffsetsAndLocations<TrackedLocation>(m_declLocations, pVBTextBuffer, pEditLists, SingleEdit, LastEdit);
    UpdateTrackedOffsetsAndLocations<TrackedLocation>(m_trackedCodeBlockLocations, pVBTextBuffer, pEditLists, SingleEdit, LastEdit);

    m_fPreNotified = false;
}
Ejemplo n.º 19
0
CSingleList<Bindable::OperatorInfo> *
Bindable::RelationalOperatorPool::CollateUnmatchedOperators()
{
    VSASSERT(!IsCollated, "Collating the pool after it has already been collated!");
#if DEBUG
    IsCollated = true;
#endif

    CSingleList<OperatorInfo> *Result = new(m_Allocator) CSingleList<OperatorInfo>;

    Result->Splice(&m_IsTrue);
    Result->Splice(&m_IsFalse);
    Result->Splice(&m_Equal);
    Result->Splice(&m_NotEqual);
    Result->Splice(&m_Less);
    Result->Splice(&m_LessEqual);
    Result->Splice(&m_GreaterEqual);
    Result->Splice(&m_Greater);

    return Result;
}
Ejemplo n.º 20
0
//============================================================================
// Check wither this named root is included in this iterator.
//============================================================================
bool ComClassMembersInAContainer::Filter
(
    BCSYM_NamedRoot *pRoot
)
{
    if (pRoot->GetAccess() != ACCESS_Public)
        return false;   // must be Public
    if (!pRoot->IsProc())
        return false;   // must be a procedure
    if (pRoot->IsSyntheticMethod())
        return false;   // can't be a synthetic method
    if (pRoot->IsDllDeclare())
        return false;   // can't be a declare
    if (pRoot->IsEventDecl())
        return false;   // can't be an event

    BCSYM_Proc *pProc = pRoot->DigThroughAlias()->PProc();

    if (pProc->IsAnyConstructor())
        return false;   // can't be a constructor
    if (pProc->IsShared())
        return false;   // can't be shared/static

    bool ComVisible;    // can't be <ComVisible(False)>
    if (pProc->GetPWellKnownAttrVals()->GetCOMVisibleData(&ComVisible) && !ComVisible)
        return false;

    if (pProc->IsProperty()) // Can't be a synthetic property (e.g., SYNTH_WithEventsGet)
    {
        BCSYM_Proc *pProcGet = pProc->PProperty()->GetProperty();
        if (pProcGet != NULL && pProcGet->IsSyntheticMethod())
        {
            return false;
        }
        // Check the setter just for sanity. I'm not expecting ever to find a synthetic readonly property.
        VSASSERT(((pProcGet = pProc->PProperty()->SetProperty()) == NULL) || !pProcGet->IsSyntheticMethod(), "A synthetic readonly property slipped through on a ComClass interface.");
    }

    return true;
}
void CLSComplianceChecker::VerifyEnumUnderlyingTypeForCLSCompliance(BCSYM_Container * PossibleEnum)
{
    VSASSERT( PossibleEnum->IsCLSCompliant(),
                    "Non-CLS compliant container unexpected!!!");

    if (!PossibleEnum->IsEnum())
    {
        return;
    }

    BCSYM *UnderlyingType = PossibleEnum->PClass()->GetUnderlyingTypeForEnum();

    if (!IsTypeCLSCompliant(UnderlyingType, PossibleEnum))
    {
        // Underlying type '|1' of enum is not CLS Compliant.

        ReportErrorOnSymbol(
            WRNID_EnumUnderlyingTypeNotCLS1,
            PossibleEnum,
            UnderlyingType->GetErrorName(m_Compiler));
    }
}
Ejemplo n.º 22
0
void
Bindable::RelationalOperatorPool::Add
(
    UserDefinedOperators Operator,
    BCSYM_UserDefinedOperator *Symbol
)
{
    VSASSERT(!IsCollated, "Adding to the pool after it has already been collated!");

    switch (Operator)
    {
        case OperatorIsTrue:       AddMatchingOperator(m_IsTrue, m_IsFalse, Symbol); break;
        case OperatorIsFalse:      AddMatchingOperator(m_IsFalse, m_IsTrue, Symbol); break;
        case OperatorEqual:        AddMatchingOperator(m_Equal, m_NotEqual, Symbol); break;
        case OperatorNotEqual:     AddMatchingOperator(m_NotEqual, m_Equal, Symbol); break;
        case OperatorLess:         AddMatchingOperator(m_Less, m_Greater, Symbol); break;
        case OperatorLessEqual:    AddMatchingOperator(m_LessEqual, m_GreaterEqual, Symbol); break;
        case OperatorGreaterEqual: AddMatchingOperator(m_GreaterEqual, m_LessEqual, Symbol); break;
        case OperatorGreater:      AddMatchingOperator(m_Greater, m_Less, Symbol); break;

#if DEBUG
        case OperatorUNDEF: __fallthrough;
        case OperatorMAXVALID: __fallthrough;
        case OperatorNot2: __fallthrough;
        case OperatorOr2: __fallthrough;
        case OperatorAnd2: __fallthrough;
        case OperatorShiftLeft2: __fallthrough;
        case OperatorShiftRight2: __fallthrough;
        case OperatorMAX:
            VSFAIL("unexpected operator kind");
            __fallthrough;
#endif
        default:
            // do nothing
            break;
    }
}
Ejemplo n.º 23
0
//-----------------------------------------------------------------
static void ScanItem (const CH * pchStart, const CH * pchEnd, HTOK * pk)
{
    if(pchStart == NULL || pk == NULL)
    {
        VSASSERT(false,"");
        return;
    }
    
    HRESULT hr;

    pk->id     = hi_Unknown;
    pk->pch    = (CH*)pchStart;
    pk->cch    = 0;
    pk->bEnd   = false;

    if (pchStart >= pchEnd)
    {
        pk->id = hi_Eof;
        return;
    }
    const CH * pchScan = pchStart;
    
    switch (*pchScan)
    {
//  case _CH(0):
//      pk->id = hi_Eof;
//      break;
//
//  case _CH('\n'):
//  case _CH('\r'):
//      pchScan = AdvanceLineBreak((CH*)pchScan);
//      pk->id = hi_Eol;
//      break;
    
    case _CH('<'):
        {
            const CH * pchName;
            int cch;
            
            pchScan++;          
            pk->id = hi_Error;
            switch (*pchScan)
            {
            case _CH('!'):
                pk->id = hi_Error;
                pchScan++;
                while (_CH('>') != *pchScan)
                {
                    const CH * pch;
                    int        cch;

                    SKIPWHITE_RET

                    if (IsAAlpha(*pchScan))
                        hr = ScanName(pchScan, pchEnd, &pch, &cch);
                    else
                    {
                        switch(*pchScan)
                        {
                        case CH('\''):
                        case CH('"'):
                            hr = ScanValue(pchScan, pchEnd, &pch, &cch);
                            break;

                        case CH('-'):
                            hr = ScanComment(pchScan, pchEnd, &pch, &cch);
                            break;
                        
                        default:
                            hr = S_OK;
                            pch = pchScan;
                            cch = 1;
                            break;
                        }
                    }

                    pchScan = pch + cch;
                    if (FAILED(hr) || (pchScan >= pchEnd))
                        return;
                }
                pk->id = hi_TagSpecial;
                break;

            case _CH('%'):  // ASP 'tag'
                pk->id = hi_TagSpecial;
                do {
                    do {
                        pchScan++;
                    } while ((pchScan < pchEnd) && (_CH('>') != *pchScan));
                } while ((pchScan < pchEnd) &&  (*(pchScan-1) != _CH('%')));
                break;

            case _CH('/'):
                pk->bEnd = true;
                pchScan++;
                break;

            case _CH('?'):  //
                pk->id = hi_TagSpecial;
                pchScan++;
                while ((pchScan < pchEnd) && (_CH('>') != *pchScan))
                    pchScan++;
                break;

            }
            if (pk->id != hi_TagSpecial)
            {
                pk->id = hi_Error;
                SKIPWHITE_RET
                if (!IsAAlpha(*pchScan))
                    return;
                pchName = pchScan;
                while ((pchScan < pchEnd) && IsAAlNum(*pchScan))
                    pchScan++;
                if (pchScan >= pchEnd)
                    return;
                cch = (int)(pchScan - pchName);
                if (cch <= cchMaxTag && cch > 0)
                {
                    CH * pszName = (CH*)_alloca((cch+1)*CBCH );
                    strcchcopy(pszName, cch+1, pchName);
                    pk->id = LookupElement(pszName);
                }
                else
                    return;
                if (!pk->bEnd)
                {
                    // scan attributes and comments
                    for(;;)
                    {
                        HATT    hatt;
                        HRESULT hr = ScanAttribute(pchScan, pchEnd, &hatt);
                        if (FAILED(hr))
                        {
                            pk->id = hi_Error;
                            return;
                        }
                        if (S_FALSE == hr)
                            break;
                        pchScan = hatt.pchValue ? hatt.pchValue + hatt.cchValue : hatt.pchName + hatt.cchName;
                    }
                }
            }
            // Skip over whitespace and, if this is an empty element, the closing '/' (e.g. "<foo ... />")
            while ((pchScan < pchEnd) && ((*pchScan <= 32) || (*pchScan == _CH('/'))))
                pchScan++;
            if ((pchScan >= pchEnd) || (_CH('>') != *pchScan))
                pk->id = hi_Error;
            pchScan++;
        }
        break;

//  case _CH('&'):
//      pk->id = hi_Entity;
//      if (!ScanEntity(pchScan, &pk->ch, &pchScan))
//          goto L_Text;
//      break;
    
    default:
//L_Text:
        pk->id = hi_Text;
        for (bool f = true; f && (pchScan < pchEnd); )
        {
            switch (*pchScan)
            {
//          case _CH(0):
//          case _CH('\n'):
//          case _CH('\r'):
//          case _CH('&'):
            case _CH('<'):
                f = false;
                break;
            default:
                pchScan++;
                break;
            }
        }
        break;
    }
Ejemplo n.º 24
0
//-----------------------------------------------------------------
// FindAttribute - Find a specific attribute
//
// Returns:
//   S_OK     Found Attribute
//   S_FALSE  Attribute not found
//   E_FAIL   Syntax error
//
static HRESULT FindAttribute (const CH * pchTag, const CH *pchEnd, const CH * pszAName, const CH **ppchVal, int * pcchVal)
{
    if(pchTag == NULL || pszAName == NULL || *pszAName == NULL)
    {
        VSASSERT(false,"");
        return E_INVALIDARG;
    }
    
    HRESULT    hr;
    const CH * pch;
    int        cch;
    int        cchAttIn = slen(pszAName);
    const CH * pchScan = pchTag;
    const CH * pchVal  = 0;
    
    *ppchVal = 0;
    *pcchVal = 0;

    if (*pchScan == _CH('<'))
        pchScan++;

    // don't look in ! tags or end tags
    if (*pchScan == _CH('!') || *pchScan == _CH('/') || *pchScan == _CH('?'))
        return S_FALSE;

    SKIPWHITE_FAIL

    hr = ScanName(pchScan, pchEnd, &pch, &cch);
    if (FAILED(hr))
        return E_FAIL;
    pchScan = pch + cch;
    if (pchScan >= pchEnd)
        return S_FALSE;  // no attributes

    for(;;)
    {
        HATT    hatt;
        HRESULT hr = ScanAttribute(pchScan, pchEnd, &hatt);
        if (FAILED(hr))
            return E_FAIL;
        if (S_FALSE == hr)
            break;
        pchScan = hatt.pchValue ? hatt.pchValue + hatt.cchValue : hatt.pchName + hatt.cchName;
        if (!hatt.pchName || !hatt.cchName)
            continue; // comment

        if ((cchAttIn == hatt.cchName) && (0 == icmpn(hatt.pchName, pszAName, cchAttIn)))        
        {
            /// strip quotes, if any
            CH ch = *hatt.pchValue;
            if (ch == _CH('"') || ch == _CH('\''))
            {
                VSASSERT(ch == hatt.pchValue[hatt.cchValue-1],"");
                hatt.pchValue++;
                hatt.cchValue -= 2;
            }
            // done!
            *ppchVal = hatt.pchValue;
            *pcchVal = hatt.cchValue;
            return S_OK;
        }
    }
    return S_FALSE;
}
Ejemplo n.º 25
0
/*****************************************************************************
;ValidateHandlesLists

Given Method() Handles X1.SomeEvent

    1. verify that X1 is a valid WithEvents variable
    2. verify that X1 sources SomeEvent()
*****************************************************************************/
void
Bindable::ValidateAndHookUpHandles
(
    BCSYM_HandlesList *HandlesEntry,
    BCSYM_MethodImpl *HandlingMethod
)
{
    VSASSERT( !HandlesEntry->IsBad(), "Bad handles unexpected here!!");
    VSASSERT( CurrentContainer()->IsClass(),
                    "Non-classes/non-structures/non-modules cannot have handles clauses!!");

    // Dev10#489103: if the handling method is bad, then we can't really tell whether it handles the event:
    if (HandlingMethod->IsBadParamTypeOrReturnType())
    {
        HandlesEntry->SetIsBad();
        return;
    }

    Symbols
        SymbolFactory(
            CurrentCompilerInstance(),
            CurrentAllocator(),
            NULL,
            CurrentGenericBindingCache());

    BCSYM_Class *ContainerOfHandlingMethod = CurrentContainer()->PClass();

    BCSYM *TypeToFindEventIn;
    BCSYM_Property *EventSourceProperty = NULL;
    BCSYM_Property *WithEventsProperty;
    BCSYM *InstanceTypeThroughWhichEventIsAccessed;

    if (HandlesEntry->IsMyBase())
    {
        TypeToFindEventIn = TypeHelpers::GetBaseClass(ContainerOfHandlingMethod, SymbolFactory);

        // A bad base is no base
        if (!TypeToFindEventIn)
        {
            HandlesEntry->SetIsBad();
            return;
        }

        InstanceTypeThroughWhichEventIsAccessed = ContainerOfHandlingMethod;
    }
    else if (HandlesEntry->IsEventFromMeOrMyClass())
    {
        if (ContainerOfHandlingMethod->IsGeneric())
        {
            TypeToFindEventIn =
                SynthesizeOpenGenericBinding(
                    ContainerOfHandlingMethod,
                    SymbolFactory);
        }
        else
        {
            TypeToFindEventIn = ContainerOfHandlingMethod;
        }

        InstanceTypeThroughWhichEventIsAccessed = ContainerOfHandlingMethod;
    }
    else
    {
        WithEventsProperty = HandlesEntry->GetWithEventsProperty();

        VSASSERT( WithEventsProperty,
                        "How can a non-bad handles entry not have a withevents property ?");

        BCSYM_Variable *WithEventsVar = WithEventsProperty->CreatedByWithEventsDecl();

        VSASSERT( WithEventsVar,
                        "How can a non-bad handles entry not refer to a withevents var ?");

        if (WithEventsVar->IsBad() ||
            WithEventsVar->IsBadVariableType())
        {
            HandlesEntry->SetIsBad();
            return;
        }

        BCSYM *TypeOfWithEventsVar = WithEventsProperty->GetType();

        VSASSERT( TypeOfWithEventsVar->IsContainer() ||
                  (TypeOfWithEventsVar->IsGenericParam() &&
                        TypeOfWithEventsVar->PGenericParam()->IsReferenceType()),
                            "What else can the type of a withevents variable be ?");

        if (HandlesEntry->GetEventSourcePropertyName())
        {
            // If withevents variable type is type parameter, then search in its class constraint,
            // else search in the withevents variable type itself.
            //
            EventSourceProperty =
                GetEventSourceProperty(
                    TypeOfWithEventsVar,
                    HandlesEntry->GetEventSourcePropertyName());

            if (!EventSourceProperty)
            {
                // "'Handles' must specify a 'WithEvents' variable or 'MyBase' qualified with a single identifier."

                ReportErrorOnSymbol(
                    IsStdModule(CurrentContainer()) ?
                        ERRID_HandlesSyntaxInModule :
                        ERRID_HandlesSyntaxInClass,
                    CurrentErrorLog(HandlingMethod),
                    HandlesEntry);

                HandlesEntry->SetIsBad();
                return;
            }

            // 






            HandlesEntry->SetEventSourceProperty(EventSourceProperty);

            // 


            VSASSERT( EventSourceProperty->GetType()->IsContainer(),
                            "Referring Property - What else can a type that is not a named type be ?");

            TypeToFindEventIn = EventSourceProperty->GetType();
        }
        else
        {
            TypeToFindEventIn = TypeOfWithEventsVar;
        }

        InstanceTypeThroughWhichEventIsAccessed = TypeToFindEventIn;
    }

    VSASSERT( TypeToFindEventIn, "No type to find the event in ?");

    bool IsBadName;
    BCSYM_NamedRoot *EventDecl =
        Semantics::EnsureNamedRoot
        (
            Semantics::InterpretName
            (
                HandlesEntry->GetEventName(),
                *(HandlesEntry->GetLocationOfEvent()),
                TypeToFindEventIn->IsContainer() ?
                    TypeToFindEventIn->PContainer()->GetHash() :
                    NULL,
                TypeToFindEventIn->IsGenericParam() ?
                    TypeToFindEventIn->PGenericParam() :
                    NULL,
                NameSearchIgnoreParent | NameSearchEventReference | NameSearchIgnoreExtensionMethods,
                InstanceTypeThroughWhichEventIsAccessed,
                ContainerOfHandlingMethod->GetHash(),     // Current Context
                CurrentErrorLog(HandlingMethod),
                CurrentCompilerInstance(),
                CurrentCompilerHost(),
                m_CompilationCaches,
                CurrentSourceFile(HandlingMethod),
                false,                                    // don't perform obsolete checks
                IsBadName,
                NULL,   // the binding context is not required here since the synthesized
                        // code has the withevents variable from which the type binding
                        // information is obtained
                NULL,
                -1
            )
        );


    if (IsBadName)
    {
        HandlesEntry->SetIsBad();
        return;
    }

    if (!EventDecl || !EventDecl->IsEventDecl())
    {
        ReportErrorAtLocation(
            ERRID_EventNotFound1,
            CurrentErrorLog(HandlingMethod),
            HandlesEntry->GetLocationOfEvent(),
            HandlesEntry->GetEventName());

        HandlesEntry->SetIsBad();
        return;
    }

    if (EventDecl->IsBad())
    {
        HandlesEntry->SetIsBad();
        return;
    }


    BCSYM_EventDecl *Event = EventDecl->PEventDecl();
    HandlesEntry->SetEvent(Event);

    // [....] - 11/17/2005
    // See Bug # 544269
    // The call to ResolveAllNamedTypesForContainer needed to be replaced with a call
    // to ResolveShadowingOverloadingAndOverridingForContainer because event signatures
    // are not necessarily setup untill after ResolveShadowingOverloadingAndOverriding
    // has been called.

    // Go and bind the event we are comparing against up to the state we need for
    // validating handles.
    ResolveShadowingOverloadingOverridingAndCheckGenericsForContainer(Event->GetContainer(), m_CompilationCaches);


    // Check for bad param types here (VSW#172753).
    if (Event->GetDelegate() &&
        Event->GetDelegate()->IsContainer() &&
        DefinedInMetaData(Event->GetDelegate()->PContainer()))
    {
        for (BCSYM_Param *Param = Event->GetFirstParam();
             Param;
             Param = Param->GetNext())
        {
            if (Param->GetType()->IsBad())
            {
                Param->GetType()->PNamedRoot()->ReportError(
                    CurrentCompilerInstance(),
                    CurrentErrorLog(HandlingMethod),
                    HandlesEntry->GetLocationOfEvent());

                HandlesEntry->SetIsBad();
                return;
            }
        }
    }

    BCSYM_GenericBinding *EventGenericBindingContext =
        DeriveGenericBindingForMemberReference(TypeToFindEventIn, Event, SymbolFactory, CurrentCompilerHost());

   MethodConversionClass MethodConversion = Semantics::ClassifyMethodConversion(
            HandlingMethod,
            GenericBindingInfo(),
            Event,
            EventGenericBindingContext,
            false, //IgnoreReturnValueErrorsForInference
            &SymbolFactory,
            CurrentCompilerHost());

    SourceFile * SourceFile = HandlingMethod->GetSourceFile();

    if (!Semantics::IsSupportedMethodConversion(
            SourceFile->GetOptionFlags() & OPTION_OptionStrict,
            MethodConversion))
    {
        // "Method '|1' cannot handle Event '|2' because they do not have the same signature."

        StringBuffer HandlingMethodRepresentation;
        HandlingMethod->GetBasicRep(CurrentCompilerInstance(), NULL, &HandlingMethodRepresentation);

        StringBuffer EventRepresentation;
        Event->GetBasicRep(CurrentCompilerInstance(), NULL, &EventRepresentation, EventGenericBindingContext);

        ReportErrorAtLocation(
            ERRID_EventHandlerSignatureIncompatible2,
            CurrentErrorLog(HandlingMethod),
            HandlesEntry->GetLocationOfEvent(),
            HandlingMethodRepresentation.GetString(),
            EventRepresentation.GetString());

        HandlesEntry->SetIsBad();
        return;
    }

    // Hook up handlers to the events they specify in their handles clauses

    if (HandlesEntry->IsMyBase() ||
        HandlesEntry->IsEventFromMeOrMyClass())
    {
        // For these cases, we search for valid MyBase, Me, MyClass handles clauses and set up the
        // addhandlers in all constructors that directly call a base constructor. This is done in
        // semantics in initializefields because that is when the information whether it directly
        // calls the base constructor is known.
        //

        const bool BuildSharedConstructor = true;

        if (HandlesEntry->GetEvent()->IsShared() &&
            HandlingMethod->IsShared())
        {
            // Make sure a shared constructor is present, else synthesize one

            if (!ContainerOfHandlingMethod->GetSharedConstructor(CurrentCompilerInstance()))
            {
                // Synthesize one
                SynthesizeConstructor(BuildSharedConstructor);
            }
        }
        else
        {
            // Make sure an Instance constructor is present, else synthesize one

            if (!ContainerOfHandlingMethod->GetFirstInstanceConstructor(CurrentCompilerInstance()))
            {
                // Synthesize one
                SynthesizeConstructor(!BuildSharedConstructor);
            }
        }
    }
    else
    {
        VSASSERT( WithEventsProperty->SetProperty(),
                        "How can there be no set accessor for a withevents property ?");


        if (WithEventsProperty->IsShared() &&
            !HandlingMethod->IsShared())
        {
            // "Events of shared WithEvents variables cannot be handled by non-shared methods."

            ReportErrorAtLocation(
                ERRID_SharedEventNeedsSharedHandler,
                CurrentErrorLog(HandlingMethod),
                HandlesEntry->GetLocationOfWithEventsVar());

            HandlesEntry->SetIsBad();
            return;
        }

        // 

        // hookup the handler list info for the above handles entry on to the WithEvents_Set.
        // GenWithEventsSetCode() will write synthetic code for these later
        //
        WithEventsProperty->SetProperty()->AddToHandlerList(
            HandlingMethod,
            Event,
            EventGenericBindingContext,
            EventSourceProperty,
            CurrentAllocator());

    }
}
Ejemplo n.º 26
0
BCSYM_Property*
Bindable::SynthesizeWithEventsProperty
(
    BCSYM_Variable *WithEventsVar,
    Symbols &SymbolFactory
)
{
    VSASSERT(CurrentContainer()->IsClass(),
                    "why would a non-class need to synthesize withevents properties ?");

    BCSYM_Class *Class = CurrentContainer()->PClass();
    BCSYM_Property *WithEventsProperty;

    WithEventsProperty =
        Declared::BuildWithEventsProperty(
            WithEventsVar->PVariable(),
            DeriveGenericBindingForMemberReference(
                IsGenericOrHasGenericParent(CurrentContainer()) ?
                    (BCSYM *)SynthesizeOpenGenericBinding(Class, SymbolFactory) :
                    CurrentContainer(),
                WithEventsVar,
                SymbolFactory,
                CurrentCompilerHost()),
            &SymbolFactory,
            // note to GenSyntheticCode() that generated code should call the base class.
            // Always safe because we only get here if we tried to handle an event that
            // was defined in a base class of the current one
            //
            true,
            Class->IsStdModule(),
            CurrentCompilerInstance(),
            NULL,   // No symbols list to put the property in, we put it in the hash manually below
            NULL);  // No symbols list to put the get, set in, we put it in the hash manually below

    WithEventsProperty->SetMemberThatCreatedSymbol(WithEventsVar);

    WithEventsProperty->GetProperty()->SetMemberThatCreatedSymbol(WithEventsVar);
    WithEventsProperty->SetProperty()->SetMemberThatCreatedSymbol(WithEventsVar);

    // Add the Property to the container's hash
    //
    Symbols::AddSymbolToHash(
        Class->GetHash(),
        WithEventsProperty,
        true,       // set the parent of this member
        Class->IsStdModule(),
        false);     // container is not namespace


    VSASSERT( Class->GetUnBindableChildrenHash(),
                "How can a class not have an unbindable members hash ?");

    // Add the get accessor of the Property to the container's unbindable members hash
    //
    Symbols::AddSymbolToHash(
        Class->GetUnBindableChildrenHash(),
        WithEventsProperty->GetProperty(),
        true,       // set the parent of this member
        Class->IsStdModule(),
        false);     // container is not namespace

    // Add the set accessor of the Property to the container's unbindable members hash
    //
    Symbols::AddSymbolToHash(
        Class->GetUnBindableChildrenHash(),
        WithEventsProperty->SetProperty(),
        true,       // set the parent of this member
        Class->IsStdModule(),
        false);     // container is not namespace

#if IDE

    // Add these to the list of symbols created in bindable.
    // This list is used to delete these from their respective hashes during decompilation
    // from bindable.
    //
    SymbolFactory.GetAliasOfSymbol(
        WithEventsProperty,
        ACCESS_Private,
        CurrentContainer()->GetBindableSymbolList());

    SymbolFactory.GetAliasOfSymbol(
        WithEventsProperty->GetProperty(),
        ACCESS_Private,
        CurrentContainer()->GetBindableSymbolList());

    SymbolFactory.GetAliasOfSymbol(
        WithEventsProperty->SetProperty(),
        ACCESS_Private,
        CurrentContainer()->GetBindableSymbolList());

#endif

    return WithEventsProperty;
}
Ejemplo n.º 27
0
BCSYM_Variable*
Bindable::BindWithEventsVariable
(
    _In_z_ STRING *WithEventVarName,
    bool &InAccessible,
    bool &WithEventsVarFoundInBase
)
{
    InAccessible = false;
    WithEventsVarFoundInBase = false;

    VSASSERT( CurrentContainer()->IsClass(), "How can a non-class have handles clauses ?");

    BCSYM_Class *Class = CurrentContainer()->PClass();
    bool IsShadowed = false;

    BCSYM_NamedRoot *Member;
    for(Member = Class->SimpleBind(NULL, WithEventVarName);
        Member;
        Member = Member->GetNextOfSameName())
    {
        if (Member->IsVariable() &&
            Member->PVariable()->GetVarkind() == VAR_WithEvents)
        {
            return Member->PVariable();
        }

        // Ignore synthesized properties in checking for shadowing.

        if (!Member->CreatedByWithEventsDecl() || !Member->IsProperty())
        {
            IsShadowed = true;
        }
    }


    for(BCSYM_Class *Base = Class->GetCompilerBaseClass();
        !IsShadowed && Base;
        Base = Base->GetCompilerBaseClass())
    {
        for(Member = Base->SimpleBind(NULL, WithEventVarName);
            Member;
            Member = Member->GetNextOfSameName())
        {
            if (Member->IsVariable() &&
                Member->PVariable()->GetVarkind() == VAR_WithEvents)
            {
                if (IsAccessible(Member))
                {
                    WithEventsVarFoundInBase = true;
                    return Member->PVariable();
                }

                InAccessible = true;
            }
            else
            {
                if (IsAccessible(Member) &&
                    // Ignore synthesized properties in checking for shadowing.
                    (!Member->CreatedByWithEventsDecl() || !Member->IsProperty()))
                {
                    IsShadowed = true;
                }
            }
        }
    }

    return NULL;
}
Ejemplo n.º 28
0
void
Bindable::ValidateWithEventsVarsInHandlesListsAndSynthesizePropertiesIfRequired()
{
    BCSYM_Container *ContainerOfHandlingMethods = CurrentContainer();

    if (!IsClass(ContainerOfHandlingMethods) &&
        !IsStructure(ContainerOfHandlingMethods) &&
        !IsStdModule(ContainerOfHandlingMethods))
    {
        return;
    }

    Symbols
        SymbolFactory(
            CurrentCompilerInstance(),
            CurrentAllocator(),
            NULL,
            CurrentGenericBindingCache());

    BCITER_CHILD Members(ContainerOfHandlingMethods);
    while(BCSYM_NamedRoot *Member = Members.GetNext())
    {
        // only method implementations can have handles clauses
        if (!Member->IsMethodImpl())
        {
            continue;
        }

        BCSYM_Proc *Proc = Member->PProc();
        BCITER_Handles iterHandles(Member->PMethodImpl());
        BCSYM_HandlesList *Handles = iterHandles.GetNext();

        if (!Handles)
        {
            continue;
        }

        ErrorTable *ErrorLog = CurrentErrorLog(Proc);

        for(;
            Handles;
            Handles = iterHandles.GetNext())
        {
            if (Handles->IsMyBase() ||
                Handles->IsEventFromMeOrMyClass())
            {
                continue;
            }

            bool FoundInBase;
            BCSYM_Variable *WithEventsVar =
                GetWithEventsVarReferredToInHandlesClause(
                    Handles,
                    FoundInBase);

            if (!WithEventsVar)
            {
                // "Handles clause requires a WithEvents variable."
                ReportErrorAtLocation(
                    ERRID_NoWithEventsVarOnHandlesList,
                    ErrorLog,
                    Handles->GetLocationOfWithEventsVar());

                Handles->SetIsBad();
            }
            else if (WithEventsVar->IsBad() ||
                     WithEventsVar->IsBadVariableType() ||   // the type of the variable is good, but is not a class or interface
                     WithEventsVar->GetType()->IsBad())      // the type of the variable is bad
            {
                // Any metadata errors on a symbol should be reported at the location
                // the symbol is used in source code
                //
                if (DefinedInMetaData(WithEventsVar->GetContainer()))
                {
                    VSASSERT( !DefinedInMetaData(CurrentContainer()),
                                    "How can Current Context for handles clauses not be in VB Source Code ?!");

                    WithEventsVar->ReportError(
                        CurrentCompilerInstance(),
                        ErrorLog,
                        Handles->GetLocationOfWithEventsVar());
                }

                Handles->SetIsBad();
            }
            else
            {
                // get the withevents property if possible
                BCSYM_Property *WithEventsProperty =
                    GetWithEventsPropertyForWithEventsVariable(WithEventsVar->PVariable());

                // Create it if it doesn't exist (for handling events defined on
                // WithEvent vars that exist on a base class).
                //
                if (!WithEventsProperty)
                {
                    VSASSERT(FoundInBase,
                                "Why do we have to synthesize a property for a withevents variable in the current class ? It should already have been synthesized in declared!!");

                    WithEventsProperty =
                        SynthesizeWithEventsProperty(WithEventsVar->PVariable(), SymbolFactory);

                    WithEventsProperty->SetCreatedByHandlesClause(Handles);
                }

                Handles->SetWithEventsProperty(WithEventsProperty);
            }
        }
    }
}
Ejemplo n.º 29
0
bool
Bindable::CheckForAccessibleEventsWorker
(
    BCSYM *TypePossiblyContainingEvents,
    BCSYM *TypeOfWithEventsVar,
    MembersHashTable *ShadowingMembers,
    bool ConsiderEventSourcePropertiesToo,
    bool &AnyEventDefined
)
{
    VSASSERT( TypePossiblyContainingEvents->IsContainer(),
                    "Looking for events in non-container unexpected!!!");

    // 


    // ---- attributes on all symbols in the EventDecl container. This is needed
    // in order to verify if a property is an EventSource which is determined by
    // an attribute on the property.
    //
    if (ConsiderEventSourcePropertiesToo)
    {
        ----AttributesOnAllSymbolsInContainer(TypePossiblyContainingEvents->PContainer(), m_CompilationCaches);
    }

    BCITER_CHILD ContainerIterator;
    ContainerIterator.Init(TypePossiblyContainingEvents->PContainer());

    for(BCSYM_NamedRoot *EventDecl = ContainerIterator.GetNext();
        EventDecl != NULL;
        EventDecl = ContainerIterator.GetNext())
    {
        // Was the event decl we just found shadowed out by somebody on a nearer base class/interface?
        //
        if (IsMemberShadowed(EventDecl, ShadowingMembers))
            continue;

        bool IsMemberAccessible =
            IsAccessible(
                EventDecl,
                TypePossiblyContainingEvents->IsGenericBinding() ?
                    TypePossiblyContainingEvents->PGenericBinding() :
                    NULL,
                CurrentContainer(),
                TypeOfWithEventsVar);

        // Keep track of who is shadowing in this container - we'll need the info if the event we find is on a derived container
        if (IsMemberAccessible && EventDecl->IsShadowing())
        {
            ShadowingMembers->Add(EventDecl);
        }

        if (ConsiderEventSourcePropertiesToo &&
            EventDecl->IsProperty() &&
            ValidEventSourceProperty(EventDecl->PProperty()))
        {
            IsMemberAccessible =
                IsMemberAccessible &&
                IsAccessible(
                    EventDecl->PProperty()->GetProperty(),
                    TypePossiblyContainingEvents->IsGenericBinding() ?
                        TypePossiblyContainingEvents->PGenericBinding() :
                        NULL,
                    CurrentContainer(),
                    TypeOfWithEventsVar);

            BCSYM *PropertyReturnType = EventDecl->PProperty()->GetType();

            // 


            // We only care about properties returning classes or interfaces
            // because only classes and interfaces can be specified in a
            // handles clause.
            //

            VSASSERT(IsClassOrInterface(PropertyReturnType),
                        "Invalid event source property found. Should have been disallowed earlier!!!");

            // We've come across a Property that returns an Event source.  Dig through it.
            //
            if (CheckForAccessibleEvents(
                    PropertyReturnType,                // Property return type
                    false,                             // i.e. don't consider EventSource properties, because
                                                       //    we only allow at most 3 names i.e. x.y.z in the
                                                       //    handles clause and and only y is allowed to be the
                                                       //    referring event source property.
                    AnyEventDefined))
            {
                // there are events on this WithEvents variable - and they are accessible
            }
            else
            {
                continue;
            }
        }
        else if (EventDecl->IsEventDecl())
        {
            // there are events on this WithEvents variable - whether they are accessible is another matter
            //
            AnyEventDefined = true;
        }
        else
        {
            // Screen out everthing that isn't an Event declaration or possible Event Source
            //
            continue;
        }

        // This assert will guard against any bad changes to the conditions checks above
        VSASSERT( AnyEventDefined,
                        "How can we get here when we have not found any event or event source ?");

        // Determine if the event is accessible
        // It must be visible to the WithEvents container that references the event
        //
        if (IsMemberAccessible)
        {
            return true;
        }

    } // trawl container members looking for events/properties that may return events


    // Look recursively in bases too
    BasesIter Bases(TypePossiblyContainingEvents->PContainer());

    BCSYM_GenericTypeBinding *BaseGenericBinding;
    while (BCSYM_Container *Base = Bases.GetNextBase(&BaseGenericBinding))
    {
        if (Base->IsBad()) continue;

        if (CheckForAccessibleEventsWorker(
                BaseGenericBinding ?
                    (BCSYM *)BaseGenericBinding :
                    Base,
                TypeOfWithEventsVar,
                ShadowingMembers,
                false,  // Don't consider event source properties in based as available
                        // because we don't allow binding to them in the handles clause
                        // (for no other better reason than leaving this implementation
                        //  as it was without complicating things, since this is not a
                        //  user feature anyway.)
                AnyEventDefined))
        {
            return true;
        }
    }

    return false; // no visible events found
}
Ejemplo n.º 30
0
bool // true - there are events defined on the WithEvents variable AND they are visible to ContainerOfWithEventsVar
Bindable::CheckForAccessibleEvents
(
    BCSYM *TypeOfWithEventsVar,
    bool ConsiderEventSourcePropertiesToo,
    bool &AnyEventDefined
)
{
    // Note: the calling function is expected to initialize AnyEventDefine to false.
    // We don't do this here because the function is recursive.

    if (TypeOfWithEventsVar->IsBad())
    {
        // This has the effect of sometimes missing an event def we could have found had we not punted.
        // But does it make sense to dig into an interface that is junk?

        return false;
    }

    BCSYM *TypePossiblyContainingEvents;

    if (TypeOfWithEventsVar->IsGenericParam())
    {
        TypePossiblyContainingEvents =
            GetClassConstraint(
                TypeOfWithEventsVar->PGenericParam(),
                CurrentCompilerHost(),
                CurrentAllocator(),
                true,   // ReturnArraysAs"System.Array"
                true    // ReturnValuesAs"System.ValueType"or"System.Enum"
                );

        // See if there are any events in the class constraint
        //
        // Note that the class constraint needs to be checked separately to
        // preserve the shadowing semantics for the events found.
        //
        if (TypePossiblyContainingEvents &&
            !TypePossiblyContainingEvents->IsBad() &&
            CheckForAccessibleEventsInContainer(
                TypePossiblyContainingEvents,
                TypeOfWithEventsVar,
                ConsiderEventSourcePropertiesToo,
                AnyEventDefined))
        {
            return true;
        }

        VSASSERT(TypePossiblyContainingEvents ||
                 TypeOfWithEventsVar->PGenericParam()->IsReferenceType(), "Unexpected withevents type!!!");

        // See if there are any events in the Interface constraints

        BCITER_Constraints ConstraintsIter(TypeOfWithEventsVar->PGenericParam(), true, CurrentCompilerInstance());

        while (BCSYM_GenericConstraint *Constraint = ConstraintsIter.Next())
        {
            VSASSERT(!Constraint->IsBadConstraint(), "Bad constraint unexpected!!!");

            if (!Constraint->IsGenericTypeConstraint())
            {
                continue;
            }

            TypePossiblyContainingEvents = Constraint->PGenericTypeConstraint()->GetType();

            if (!TypePossiblyContainingEvents ||
                TypePossiblyContainingEvents->IsBad() ||
                !TypePossiblyContainingEvents->IsInterface())
            {
                continue;
            }

            if (CheckForAccessibleEventsInContainer(
                    TypePossiblyContainingEvents,
                    TypeOfWithEventsVar,
                    ConsiderEventSourcePropertiesToo,
                    AnyEventDefined))
            {
                return true;
            }
        }

        return false;
    }
    else
    {
        TypePossiblyContainingEvents = TypeOfWithEventsVar;

        return
            CheckForAccessibleEventsInContainer(
                TypePossiblyContainingEvents,
                TypeOfWithEventsVar,
                ConsiderEventSourcePropertiesToo,
                AnyEventDefined);
    }

    return false;
}