예제 #1
0
void CompileableMethodsInAContainer::Init
(
    BCSYM_Container *pContainer,
    bool fLookOnlyInCurrentPartialType
)
{
    // Free the memory.
    m_nra.FreeHeap();

    if (pContainer != NULL)
    {
        // Look in only this container and ignore its other partial containers
        //
        BCITER_CHILD_ALL bichild(pContainer, fLookOnlyInCurrentPartialType);

        unsigned cMethods = 0;
        BCSYM_NamedRoot *pRoot;
        BCSYM_Proc **ppProc;

        while (pRoot = bichild.GetNext())
        {
            if (pRoot->IsMethodImpl() ||
                    pRoot->IsSyntheticMethod() ||
                    pRoot->IsProperty() ||
                    pRoot->IsEventDecl())
            {
                cMethods++;
            }
        }

        IfFalseThrow(cMethods + 1 > cMethods);
        ppProc = m_ppNext = (BCSYM_Proc **)m_nra.Alloc(VBMath::Multiply(
            (cMethods + 1), 
            sizeof(BCSYM_Proc *)));

        bichild.Reset();

        while (pRoot = bichild.GetNext())
        {
            if (pRoot->IsMethodImpl() ||
                    pRoot->IsSyntheticMethod() ||
                    pRoot->IsProperty() ||
                    pRoot->IsEventDecl())
            {
                *ppProc = pRoot->PProc();
                ppProc++;
            }
        }

        // Sort the list in file definition order.
        extern int _cdecl SortSymbolsByLocation(const void *arg1, const void *arg2);

        qsort(m_ppNext, ppProc - m_ppNext, sizeof(BCSYM_Proc *), SortSymbolsByLocation);
    }
    else
    {
        m_ppNext = NULL;
    }
}
예제 #2
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());

    }
}
예제 #3
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
}