Beispiel #1
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());

    }
}
Beispiel #2
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);
            }
        }
    }
}
Beispiel #3
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;
}
Beispiel #4
0
void ComClassMembersInAContainer::Init
(
    BCSYM_Container *pContainer
)
{
    // Free the memory.
    m_nra.FreeHeap();

    if (pContainer != NULL)
    {
        BCITER_CHILD bichild(pContainer);
        unsigned cMembers = 0;
        BCSYM_NamedRoot *pRoot;
        BCSYM_NamedRoot **ppRoot;

        while (pRoot = bichild.GetNext())
        {
            if (!Filter(pRoot))
                continue;

            cMembers++;

            if (pRoot->IsProperty())
            {
                BCSYM_Property *pProperty = pRoot->PProperty();

                if (pProperty->GetProperty() && Filter(pProperty->GetProperty()))
                {
                    cMembers++;
                }
                if (pProperty->SetProperty() && Filter(pProperty->SetProperty()))
                {
                    cMembers++;
                }
            }
        }

        IfFalseThrow(cMembers + 1 > cMembers);
        ppRoot = m_ppRoot = m_ppNext = (BCSYM_NamedRoot **)m_nra.Alloc(VBMath::Multiply(
            (cMembers + 1), 
            sizeof(BCSYM_NamedRoot *)));
        m_count = cMembers;

        bichild.Init(pContainer);

        while (pRoot = bichild.GetNext())
        {
            if (!Filter(pRoot))
                continue;

            *ppRoot = pRoot;
            ppRoot++;

            if (pRoot->IsProperty())
            {
                BCSYM_Property *pProperty = pRoot->PProperty();

                if (pProperty->GetProperty() && Filter(pProperty->GetProperty()))
                {
                    *ppRoot = pProperty->GetProperty();
                    ppRoot++;
                }
                if (pProperty->SetProperty() && Filter(pProperty->SetProperty()))
                {
                    *ppRoot = pProperty->SetProperty();
                    ppRoot++;
                }
            }
        }

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

        qsort(m_ppNext, ppRoot - m_ppNext, sizeof(BCSYM_NamedRoot *), SortSymbolsByLocation);
    }
    else
    {
        m_count = 0;
        m_ppNext = NULL;
        m_ppRoot = NULL;
    }
}