Esempio n. 1
0
        /// <summary>
        /// Lookup a type within the assembly using its canonical CLR metadata name.
        /// </summary>
        /// <param name="metadataName"></param>
        /// <param name="includeReferences">
        /// If search within assembly fails, lookup in assemblies referenced by the primary module.
        /// For source assembly, this is equivalent to all assembly references given to compilation.
        /// </param>
        /// <param name="isWellKnownType">
        /// Extra restrictions apply when searching for a well-known type.  In particular, the type must be public.
        /// </param>
        /// <param name="useCLSCompliantNameArityEncoding">
        /// While resolving the name, consider only types following CLS-compliant generic type names and arity encoding (ECMA-335, section 10.7.2).
        /// I.e. arity is inferred from the name and matching type must have the same emitted name and arity.
        /// </param>
        /// <param name="warnings">
        /// A diagnostic bag to receive warnings if we should allow multiple definitions and pick one.
        /// </param>
        /// <returns>Null if the type can't be found.</returns>
        internal NamedTypeSymbol GetTypeByMetadataName(
            string metadataName,
            bool includeReferences,
            bool isWellKnownType,
            bool useCLSCompliantNameArityEncoding = false,
            DiagnosticBag warnings = null)
        {
            NamedTypeSymbol  type = null;
            MetadataTypeName mdName;

            if (metadataName.IndexOf('+') >= 0)
            {
                var parts = metadataName.Split(_nestedTypeNameSeparators);
                if (parts.Length > 0)
                {
                    mdName = MetadataTypeName.FromFullName(parts[0], useCLSCompliantNameArityEncoding);
                    type   = GetTopLevelTypeByMetadataName(ref mdName, assemblyOpt: null, includeReferences: includeReferences, isWellKnownType: isWellKnownType, warnings: warnings);
                    for (int i = 1; (object)type != null && !type.IsErrorType() && i < parts.Length; i++)
                    {
                        mdName = MetadataTypeName.FromTypeName(parts[i]);
                        NamedTypeSymbol temp = type.LookupMetadataType(ref mdName);
                        type = (!isWellKnownType || IsValidWellKnownType(temp)) ? temp : null;
                    }
                }
            }
            else
            {
                mdName = MetadataTypeName.FromFullName(metadataName, useCLSCompliantNameArityEncoding);
                type   = GetTopLevelTypeByMetadataName(ref mdName, assemblyOpt: null, includeReferences: includeReferences, isWellKnownType: isWellKnownType, warnings: warnings);
            }

            return(((object)type == null || type.IsErrorType()) ? null : type);
        }
        internal override Symbol GetDeclaredSpecialTypeMember(SpecialMember member)
        {
#if DEBUG
            foreach (var module in this.Modules)
            {
                Debug.Assert(module.GetReferencedAssemblies().Length == 0);
            }
#endif

            if (
                _lazySpecialTypeMembers == null ||
                ReferenceEquals(
                    _lazySpecialTypeMembers[(int)member],
                    ErrorTypeSymbol.UnknownResultType
                    )
                )
            {
                if (_lazySpecialTypeMembers == null)
                {
                    var specialTypeMembers = new Symbol[(int)SpecialMember.Count];

                    for (int i = 0; i < specialTypeMembers.Length; i++)
                    {
                        specialTypeMembers[i] = ErrorTypeSymbol.UnknownResultType;
                    }

                    Interlocked.CompareExchange(
                        ref _lazySpecialTypeMembers,
                        specialTypeMembers,
                        null
                        );
                }

                var             descriptor = SpecialMembers.GetDescriptor(member);
                NamedTypeSymbol type       = GetDeclaredSpecialType(
                    (SpecialType)descriptor.DeclaringTypeId
                    );
                Symbol result = null;

                if (!type.IsErrorType())
                {
                    result = CSharpCompilation.GetRuntimeMember(
                        type,
                        descriptor,
                        CSharpCompilation.SpecialMembersSignatureComparer.Instance,
                        accessWithinOpt: null
                        );
                }

                Interlocked.CompareExchange(
                    ref _lazySpecialTypeMembers[(int)member],
                    result,
                    ErrorTypeSymbol.UnknownResultType
                    );
            }

            return(_lazySpecialTypeMembers[(int)member]);
        }
 /// <summary>
 /// Return true if the given type is valid as a calling convention modifier type.
 /// </summary>
 internal static bool IsCallingConventionModifier(NamedTypeSymbol modifierType)
 {
     Debug.Assert(modifierType.ContainingAssembly is not null || modifierType.IsErrorType());
     return((object?)modifierType.ContainingAssembly == modifierType.ContainingAssembly?.CorLibrary &&
            modifierType.Arity == 0 &&
            modifierType.Name != "CallConv" &&
            modifierType.Name.StartsWith("CallConv", StringComparison.Ordinal) &&
            modifierType.IsCompilerServicesTopLevelType());
 }
Esempio n. 4
0
        /// <summary>
        /// Checks if an applied attribute with the given attributeType matches the namespace name and type name of the given early attribute's description
        /// and the attribute description has a signature with parameter count equal to the given attribute syntax's argument list count.
        /// NOTE: We don't allow early decoded attributes to have optional parameters.
        /// </summary>
        internal static bool IsTargetEarlyAttribute(NamedTypeSymbol attributeType, AttributeSyntax attributeSyntax, AttributeDescription description)
        {
            Debug.Assert(!attributeType.IsErrorType());

            int argumentCount = (attributeSyntax.ArgumentList != null) ?
                                attributeSyntax.ArgumentList.Arguments.Count((arg) => arg.NameEquals == null) :
                                0;

            return(AttributeData.IsTargetEarlyAttribute(attributeType, argumentCount, description));
        }
        internal override void EarlyDecodeWellKnownAttributeType(NamedTypeSymbol attributeType, AttributeSyntax attributeSyntax)
        {
            Debug.Assert(!attributeType.IsErrorType());

            // NOTE: OptionalAttribute is decoded specially before any of the other attributes and stored in the parameter
            // symbol (rather than in the EarlyWellKnownAttributeData) because it is needed during overload resolution.
            if (CSharpAttributeData.IsTargetEarlyAttribute(attributeType, attributeSyntax, AttributeDescription.OptionalAttribute))
            {
                lazyHasOptionalAttribute = ThreeState.True;
            }
        }
Esempio n. 6
0
        private DiagnosticInfo DeriveUseSiteDiagnosticFromBase()
        {
            NamedTypeSymbol @base = this.BaseTypeNoUseSiteDiagnostics;

            while ((object)@base != null)
            {
                if (@base.IsErrorType() && @base is NoPiaIllegalGenericInstantiationSymbol)
                {
                    return(@base.GetUseSiteDiagnostic());
                }

                @base = @base.BaseTypeNoUseSiteDiagnostics;
            }

            return(null);
        }
Esempio n. 7
0
        protected SubstitutedNamedTypeSymbol(Symbol newContainer, TypeMap map, NamedTypeSymbol originalDefinition, NamedTypeSymbol constructedFrom = null, bool unbound = false)
            : base(originalDefinition)
        {
            Debug.Assert(originalDefinition.IsDefinition);
            Debug.Assert(!originalDefinition.IsErrorType());
            _newContainer = newContainer;
            _inputMap     = map;
            _unbound      = unbound;

            // if we're substituting to create a new unconstructed type as a member of a constructed type,
            // then we must alpha rename the type parameters.
            if ((object)constructedFrom != null)
            {
                Debug.Assert(ReferenceEquals(constructedFrom.ConstructedFrom, constructedFrom));
                _lazyTypeParameters = constructedFrom.TypeParameters;
                _lazyMap            = map;
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Resolves <see cref="System.Type"/> to a <see cref="TypeSymbol"/> available in this assembly
        /// its referenced assemblies.
        /// </summary>
        /// <param name="type">The type to resolve.</param>
        /// <param name="includeReferences">Use referenced assemblies for resolution.</param>
        /// <returns>The resolved symbol if successful or null on failure.</returns>
        internal TypeSymbol GetTypeByReflectionType(Type type, bool includeReferences)
        {
            System.Reflection.TypeInfo typeInfo = type.GetTypeInfo();

            Debug.Assert(!typeInfo.IsByRef);

            // not supported rigth now (we don't accept open types as submission results nor host types):
            Debug.Assert(!typeInfo.ContainsGenericParameters);

            if (typeInfo.IsArray)
            {
                TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences);
                if ((object)symbol == null)
                {
                    return(null);
                }

                int rank = typeInfo.GetArrayRank();
                return(new ArrayTypeSymbol(this, symbol, ImmutableArray <CustomModifier> .Empty, rank));
            }
            else if (typeInfo.IsPointer)
            {
                TypeSymbol symbol = GetTypeByReflectionType(typeInfo.GetElementType(), includeReferences);
                if ((object)symbol == null)
                {
                    return(null);
                }

                return(new PointerTypeSymbol(symbol));
            }
            else if (typeInfo.DeclaringType != null)
            {
                Debug.Assert(!typeInfo.IsArray);

                // consolidated generic arguments (includes arguments of all declaring types):
                Type[] genericArguments  = typeInfo.GenericTypeArguments;
                int    typeArgumentIndex = 0;

                var currentTypeInfo = typeInfo.IsGenericType ? typeInfo.GetGenericTypeDefinition().GetTypeInfo() : typeInfo;
                var nestedTypes     = ArrayBuilder <System.Reflection.TypeInfo> .GetInstance();

                while (true)
                {
                    Debug.Assert(currentTypeInfo.IsGenericTypeDefinition || !currentTypeInfo.IsGenericType);

                    nestedTypes.Add(currentTypeInfo);
                    if (currentTypeInfo.DeclaringType == null)
                    {
                        break;
                    }

                    currentTypeInfo = currentTypeInfo.DeclaringType.GetTypeInfo();
                }

                int i      = nestedTypes.Count - 1;
                var symbol = (NamedTypeSymbol)GetTypeByReflectionType(nestedTypes[i].AsType(), includeReferences);
                if ((object)symbol == null)
                {
                    return(null);
                }

                while (--i >= 0)
                {
                    int forcedArity         = nestedTypes[i].GenericTypeParameters.Length - nestedTypes[i + 1].GenericTypeParameters.Length;
                    MetadataTypeName mdName = MetadataTypeName.FromTypeName(nestedTypes[i].Name, forcedArity: forcedArity);

                    symbol = symbol.LookupMetadataType(ref mdName);
                    if ((object)symbol == null || symbol.IsErrorType())
                    {
                        return(null);
                    }

                    symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences);
                    if ((object)symbol == null)
                    {
                        return(null);
                    }
                }

                nestedTypes.Free();
                Debug.Assert(typeArgumentIndex == genericArguments.Length);
                return(symbol);
            }
            else
            {
                AssemblyIdentity assemblyId = AssemblyIdentity.FromAssemblyDefinition(typeInfo.Assembly);

                MetadataTypeName mdName = MetadataTypeName.FromNamespaceAndTypeName(
                    typeInfo.Namespace ?? string.Empty,
                    typeInfo.Name,
                    forcedArity: typeInfo.GenericTypeArguments.Length);

                NamedTypeSymbol symbol = GetTopLevelTypeByMetadataName(ref mdName, assemblyId, includeReferences, isWellKnownType: false);

                if ((object)symbol == null || symbol.IsErrorType())
                {
                    return(null);
                }

                int    typeArgumentIndex = 0;
                Type[] genericArguments  = typeInfo.GenericTypeArguments;
                symbol = ApplyGenericArguments(symbol, genericArguments, ref typeArgumentIndex, includeReferences);
                Debug.Assert(typeArgumentIndex == genericArguments.Length);
                return(symbol);
            }
        }
Esempio n. 9
0
        protected virtual bool IsAttributeConditionallyOmitted(NamedTypeSymbol attributeType, SyntaxTree syntaxTree, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            // When early binding attributes, we don't want to determine if the attribute type is conditional and if so, must be emitted or not.
            // Invoking IsConditional property on attributeType can lead to a cycle, hence we delay this computation until after early binding.
            if (IsEarlyAttributeBinder)
            {
                return false;
            }

            Debug.Assert((object)attributeType != null);
            Debug.Assert(!attributeType.IsErrorType());

            if (attributeType.IsConditional)
            {
                ImmutableArray<string> conditionalSymbols = attributeType.GetAppliedConditionalSymbols();
                Debug.Assert(conditionalSymbols != null);
                if (syntaxTree.IsAnyPreprocessorSymbolDefined(conditionalSymbols))
                {
                    return false;
                }

                var baseType = attributeType.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics);
                if ((object)baseType != null && baseType.IsConditional)
                {
                    return IsAttributeConditionallyOmitted(baseType, syntaxTree, ref useSiteDiagnostics);
                }

                return true;
            }
            else
            {
                return false;
            }
        }
Esempio n. 10
0
        private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol attributeType, DiagnosticBag diagnostics)
        {
            Debug.Assert(this.SkipSemanticModelBinder() == this.GetBinder(node).SkipSemanticModelBinder());

            // If attribute name bound to an error type with a single named type
            // candidate symbol, we want to bind the attribute constructor
            // and arguments with that named type to generate better semantic info.

            // CONSIDER:    Do we need separate code paths for IDE and 
            // CONSIDER:    batch compilation scenarios? Above mentioned scenario
            // CONSIDER:    is not useful for batch compilation.

            NamedTypeSymbol attributeTypeForBinding = attributeType;
            LookupResultKind resultKind = LookupResultKind.Viable;
            if (attributeTypeForBinding.IsErrorType())
            {
                var errorType = (ErrorTypeSymbol)attributeTypeForBinding;
                resultKind = errorType.ResultKind;
                if (errorType.CandidateSymbols.Length == 1 && errorType.CandidateSymbols[0] is NamedTypeSymbol)
                {
                    attributeTypeForBinding = (NamedTypeSymbol)errorType.CandidateSymbols[0];
                }
            }

            // Bind constructor and named attribute arguments using the attribute binder
            var argumentListOpt = node.ArgumentList;
            Binder attributeArgumentBinder = this.WithAdditionalFlags(BinderFlags.AttributeArgument);
            AnalyzedAttributeArguments analyzedArguments = attributeArgumentBinder.BindAttributeArguments(argumentListOpt, attributeTypeForBinding, diagnostics);

            HashSet<DiagnosticInfo> useSiteDiagnostics = null;

            // Bind attributeType's constructor based on the bound constructor arguments
            MethodSymbol attributeConstructor = attributeTypeForBinding.IsErrorType() ?
                null :
                BindAttributeConstructor(node, attributeTypeForBinding, analyzedArguments.ConstructorArguments, diagnostics, ref resultKind, suppressErrors: attributeType.IsErrorType(), useSiteDiagnostics: ref useSiteDiagnostics);
            diagnostics.Add(node, useSiteDiagnostics);

            if ((object)attributeConstructor != null)
            {
                ReportDiagnosticsIfObsolete(diagnostics, attributeConstructor, node, hasBaseReceiver: false);
            }

            var constructorArguments = analyzedArguments.ConstructorArguments;
            ImmutableArray<BoundExpression> boundConstructorArguments = constructorArguments.Arguments.ToImmutableAndFree();
            ImmutableArray<string> boundConstructorArgumentNamesOpt = constructorArguments.GetNames();
            ImmutableArray<BoundExpression> boundNamedArguments = analyzedArguments.NamedArguments;
            constructorArguments.Free();

            return new BoundAttribute(node, attributeConstructor, boundConstructorArguments, boundConstructorArgumentNamesOpt,
                boundNamedArguments, resultKind, attributeType, hasErrors: resultKind != LookupResultKind.Viable);
        }
Esempio n. 11
0
        /// <summary>
        /// Lookup a top level type referenced from metadata, names should be
        /// compared case-sensitively.  Detect cycles during lookup.
        /// </summary>
        /// <param name="emittedName">
        /// Full type name, possibly with generic name mangling.
        /// </param>
        /// <param name="visitedAssemblies">
        /// List of assemblies lookup has already visited (since type forwarding can introduce cycles).
        /// </param>
        /// <param name="digThroughForwardedTypes">
        /// Take forwarded types into account.
        /// </param>
        internal sealed override NamedTypeSymbol LookupTopLevelMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList <AssemblySymbol> visitedAssemblies, bool digThroughForwardedTypes)
        {
            NamedTypeSymbol result = null;

            // This is a cache similar to the one used by MetaImport::GetTypeByName in native
            // compiler. The difference is that native compiler pre-populates the cache when it
            // loads types. Here we are populating the cache only with things we looked for, so that
            // next time we are looking for the same thing, the lookup is fast. This cache also
            // takes care of TypeForwarders. Gives about 8% win on subsequent lookups in some
            // scenarios.
            //
            // CONSIDER !!!
            //
            // However, it is questionable how often subsequent lookup by name  is going to happen.
            // Currently it doesn't happen for TypeDef tokens at all, for TypeRef tokens, the
            // lookup by name is done once and the result is cached. So, multiple lookups by name
            // for the same type are going to happen only in these cases:
            // 1) Resolving GetType() in attribute application, type is encoded by name.
            // 2) TypeRef token isn't reused within the same module, i.e. multiple TypeRefs point to
            //    the same type.
            // 3) Different Module refers to the same type, lookup once per Module (with exception of #2).
            // 4) Multitargeting - retargeting the type to a different version of assembly
            result = LookupTopLevelMetadataTypeInCache(ref emittedName);

            if ((object)result != null)
            {
                // We only cache result equivalent to digging through type forwarders, which
                // might produce an forwarder specific ErrorTypeSymbol. We don't want to
                // return that error symbol, unless digThroughForwardedTypes is true.
                if (digThroughForwardedTypes || (!result.IsErrorType() && (object)result.ContainingAssembly == (object)this))
                {
                    return(result);
                }

                // According to the cache, the type wasn't found, or isn't declared in this assembly (forwarded).
                return(new MissingMetadataTypeSymbol.TopLevel(this.Modules[0], ref emittedName));
            }
            else
            {
                // Now we will look for the type in each module of the assembly and pick the first type
                // we find, this is what native VB compiler does.

                var modules = this.Modules;
                var count   = modules.Length;
                var i       = 0;

                result = modules[i].LookupTopLevelMetadataType(ref emittedName);

                if (result is MissingMetadataTypeSymbol)
                {
                    for (i = 1; i < count; i++)
                    {
                        var newResult = modules[i].LookupTopLevelMetadataType(ref emittedName);

                        // Hold on to the first missing type result, unless we found the type.
                        if (!(newResult is MissingMetadataTypeSymbol))
                        {
                            result = newResult;
                            break;
                        }
                    }
                }

                bool foundMatchInThisAssembly = (i < count);

                Debug.Assert(!foundMatchInThisAssembly || (object)result.ContainingAssembly == (object)this);

                if (!foundMatchInThisAssembly && digThroughForwardedTypes)
                {
                    // We didn't find the type
                    System.Diagnostics.Debug.Assert(result is MissingMetadataTypeSymbol);

                    NamedTypeSymbol forwarded = TryLookupForwardedMetadataTypeWithCycleDetection(ref emittedName, visitedAssemblies);
                    if ((object)forwarded != null)
                    {
                        result = forwarded;
                    }
                }

                System.Diagnostics.Debug.Assert((object)result != null);

                // Add result of the lookup into the cache
                if (digThroughForwardedTypes || foundMatchInThisAssembly)
                {
                    CacheTopLevelMetadataType(ref emittedName, result);
                }

                return(result);
            }
        }
        internal override void EarlyDecodeWellKnownAttributeType(NamedTypeSymbol attributeType, AttributeSyntax attributeSyntax)
        {
            Debug.Assert(!attributeType.IsErrorType());

            // NOTE: OptionalAttribute is decoded specially before any of the other attributes and stored in the parameter
            // symbol (rather than in the EarlyWellKnownAttributeData) because it is needed during overload resolution.
            if (CSharpAttributeData.IsTargetEarlyAttribute(attributeType, attributeSyntax, AttributeDescription.OptionalAttribute))
            {
                _lazyHasOptionalAttribute = ThreeState.True;
            }
        }