예제 #1
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);
            }
        }
    }
}
예제 #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());

    }
}
bool CLSComplianceChecker::IsTypeCLSCompliant(
    BCSYM * RawType,
    BCSYM_NamedRoot * NamedContext)
{
    BCSYM *ActualType = RawType->ChaseToType();

    if (!ActualType ||
        (ActualType->IsNamedRoot() &&
         ActualType->PNamedRoot()->IsBadNamedRoot()))
    {
        return true;
    }

    // Return true for generic params because its constraints are anyway verified separately
    //
    if (ActualType->IsGenericParam())
    {
        return true;
    }

    VSASSERT( ActualType->IsContainer(),
                    "What else can a chased type be ?");

    if (ActualType->IsGenericBinding())
    {
        NameTypeArguments **RawTypeArgumentsSets =
            RawType->IsNamedType() ? RawType->PNamedType()->GetArgumentsArray() : NULL;

        unsigned CountOfRawTypeArgumentsSets =
            RawType->IsNamedType() ? RawType->PNamedType()->GetNameCount() : 0;

        NameTypeArguments *CurrentRawTypeArgumentsSet = NULL;
        unsigned CurrentRawTypeArgumentsSetIndex = CountOfRawTypeArgumentsSets;

        for(BCSYM_GenericTypeBinding *GenericBinding = ActualType->PGenericTypeBinding();
            GenericBinding;
            GenericBinding = GenericBinding->GetParentBinding())
        {
            if (RawTypeArgumentsSets && CurrentRawTypeArgumentsSetIndex > 0)
            {
                CurrentRawTypeArgumentsSet = RawTypeArgumentsSets[--CurrentRawTypeArgumentsSetIndex];

                if (CurrentRawTypeArgumentsSet &&
                    CurrentRawTypeArgumentsSet->m_BoundGenericBinding != GenericBinding)
                {
                    // Lost the one to one mapping between actual type and raw type, so
                    // invalidate and do not use the raw type argument locations.

                    CurrentRawTypeArgumentsSet = NULL;
                }
            }

            unsigned GenericArgumentCount = GenericBinding->GetArgumentCount();
            for(unsigned Index = 0; Index < GenericArgumentCount; Index++)
            {
                BCSYM *ArgumentType = GenericBinding->GetArgument(Index);

                if (!IsTypeCLSCompliant(ArgumentType, NamedContext))
                {
                    Location *ErrorLocation = NULL;

                    if (CurrentRawTypeArgumentsSet &&
                        CurrentRawTypeArgumentsSet->m_ArgumentCount > 0)
                    {
                        ErrorLocation = CurrentRawTypeArgumentsSet->GetArgumentLocation(Index);
                    }

                    if (!ErrorLocation)
                    {
                        ErrorLocation =
                            RawType->IsNamedType() ?
                                RawType->GetLocation() :
                                NamedContext->GetLocation();
                    }

                    ReportErrorAtLocation(
                        WRNID_TypeNotCLSCompliant1,
                        ErrorLocation,
                        NamedContext,
                        ArgumentType->ChaseToType()->GetErrorName(m_Compiler));
                }
            }
        }

        return IsTypeCLSCompliant(ActualType->PGenericTypeBinding()->GetGeneric(), NamedContext);
    }

    return ActualType->PContainer()->IsCLSCompliant();
}