internal SynthesizedEntryPointSymbol(NamedTypeSymbol containingType, TypeSymbol returnType, DiagnosticBag diagnostics) { Debug.Assert((object)containingType != null); _containingType = containingType; if (containingType.ContainingAssembly.IsInteractive) { var submissionArrayType = this.DeclaringCompilation.CreateArrayTypeSymbol(this.DeclaringCompilation.GetSpecialType(SpecialType.System_Object)); var useSiteDiagnostic = submissionArrayType.GetUseSiteDiagnostic(); if (useSiteDiagnostic != null) { Symbol.ReportUseSiteDiagnostic(useSiteDiagnostic, diagnostics, NoLocation.Singleton); } _parameters = ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(this, submissionArrayType, 0, RefKind.None, "submissionArray")); _name = "<Factory>"; } else { _parameters = ImmutableArray<ParameterSymbol>.Empty; _name = "<Main>"; } if (this.DeclaringCompilation.IsSubmission) { returnType = this.DeclaringCompilation.GetSpecialType(SpecialType.System_Object); } _returnType = returnType; }
public SynthesizedImplementationMethod( MethodSymbol interfaceMethod, NamedTypeSymbol implementingType, string name = null, bool generateDebugInfo = true, PropertySymbol associatedProperty = null) { //it does not make sense to add methods to substituted types Debug.Assert(implementingType.IsDefinition); _name = name ?? ExplicitInterfaceHelpers.GetMemberName(interfaceMethod.Name, interfaceMethod.ContainingType, aliasQualifierOpt: null); _interfaceMethod = interfaceMethod; _implementingType = implementingType; _generateDebugInfo = generateDebugInfo; _associatedProperty = associatedProperty; _explicitInterfaceImplementations = ImmutableArray.Create<MethodSymbol>(interfaceMethod); // alpha-rename to get the implementation's type parameters var typeMap = interfaceMethod.ContainingType.TypeSubstitution ?? TypeMap.Empty; typeMap.WithAlphaRename(interfaceMethod, this, out _typeParameters); var substitutedInterfaceMethod = interfaceMethod.ConstructIfGeneric(_typeParameters.Cast<TypeParameterSymbol, TypeSymbol>()); _returnType = substitutedInterfaceMethod.ReturnType; _parameters = SynthesizedParameterSymbol.DeriveParameters(substitutedInterfaceMethod, this); }
public SynthesizedIntrinsicOperatorSymbol(TypeSymbol leftType, string name, TypeSymbol rightType, TypeSymbol returnType, bool isCheckedBuiltin) { if (leftType.Equals(rightType, ignoreCustomModifiers: true)) { this.containingType = leftType; } else if (rightType.Equals(returnType, ignoreCustomModifiers: true)) { this.containingType = rightType; } else { Debug.Assert(leftType.Equals(returnType, ignoreCustomModifiers: true)); this.containingType = leftType; } this.name = name; this.returnType = returnType; Debug.Assert((leftType.IsDynamic() || rightType.IsDynamic()) == returnType.IsDynamic()); Debug.Assert(containingType.IsDynamic() == returnType.IsDynamic()); this.parameters = (new ParameterSymbol[] {new SynthesizedOperatorParameterSymbol(this, leftType, 0, "left"), new SynthesizedOperatorParameterSymbol(this, rightType, 1, "right")}).AsImmutableOrNull(); this.isCheckedBuiltin = isCheckedBuiltin; }
public BoundLocal SetInferredType(TypeSymbol type, bool success) { Debug.Assert(type != null); var syntaxNode = (SingleVariableDesignationSyntax)this.Syntax; Binder.DeclareLocalVariable((SourceLocalSymbol)this.LocalSymbol, syntaxNode.Identifier, type); return new BoundLocal(syntaxNode, this.LocalSymbol, constantValueOpt: null, type: type, hasErrors: this.HasErrors || !success); }
public Conversion ClassifyConversionFromExpression(TypeSymbol source, TypeSymbol destination, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { Debug.Assert((object)source != null); Debug.Assert((object)destination != null); return ClassifyConversionFromExpression(null, source, destination, ref useSiteDiagnostics); }
// take a type of the form Something<X> and return the type X. private TypeSymbol TypeArg(TypeSymbol t) { var nts = t as NamedTypeSymbol; Assert.NotEqual(null, nts); Assert.Equal(1, nts.Arity); return nts.TypeArguments[0]; }
private static void StructDependsClosure(TypeSymbol type, HashSet<Symbol> partialClosure, NamedTypeSymbol on) { if ((object)type == null) { return; } var nt = type as NamedTypeSymbol; if ((object)nt != null && ReferenceEquals(nt.OriginalDefinition, on)) { // found a possibly expanding cycle, for example // struct X<T> { public T t; } // struct W<T> { X<W<W<T>>> x; } // while not explicitly forbidden by the spec, it should be. partialClosure.Add(on); return; } if ((object)nt != null && partialClosure.Add(nt)) { foreach (var member in type.GetMembersUnordered()) { var field = member as FieldSymbol; if ((object)field == null || field.Type.TypeKind != TypeKind.Struct || field.IsStatic) { continue; } StructDependsClosure(field.Type, partialClosure, on); } } }
/// <summary> /// Converts CLR type symbol to TypeRef used by flow analysis. /// </summary> public static ITypeRef CreateTypeRef(TypeRefContext ctx, TypeSymbol t) { Contract.ThrowIfNull(t); switch (t.SpecialType) { case SpecialType.System_Void: throw new ArgumentException(); case SpecialType.System_Int32: case SpecialType.System_Int64: return LongTypeRef; case SpecialType.System_String: return StringTypeRef; case SpecialType.System_Double: return DoubleTypeRef; case SpecialType.System_Boolean: return BoolTypeRef; case SpecialType.System_Object: return new ClassTypeRef(NameUtils.SpecialNames.System_Object); case SpecialType.System_DateTime: return new ClassTypeRef(new QualifiedName(new Name("DateTime"), new[] { new Name("System") })); default: if (t is NamedTypeSymbol) { return new ClassTypeRef(((NamedTypeSymbol)t).MakeQualifiedName()); } else if (t is ArrayTypeSymbol) { var arr = (ArrayTypeSymbol)t; if (!arr.IsSZArray) { throw new NotImplementedException(); } return new ArrayTypeRef(null, CreateMask(ctx, arr.ElementType)); } else { throw Roslyn.Utilities.ExceptionUtilities.UnexpectedValue(t); } } }
public static TypeRefMask CreateMask(TypeRefContext ctx, TypeSymbol t) { Contract.ThrowIfNull(t); switch (t.SpecialType) { case SpecialType.System_Void: return 0; case SpecialType.System_Int64: return ctx.GetLongTypeMask(); case SpecialType.System_String: return ctx.GetStringTypeMask(); case SpecialType.System_Double: return ctx.GetDoubleTypeMask(); case SpecialType.System_Boolean: return ctx.GetBooleanTypeMask(); case SpecialType.None: var containing = t.ContainingAssembly; if (containing != null && containing.IsPchpCorLibrary) { if (t.Name == "PhpValue") return TypeRefMask.AnyType; if (t.Name == "PhpAlias") return TypeRefMask.AnyType.WithRefFlag; if (t.Name == "PhpNumber") return ctx.GetNumberTypeMask(); if (t.Name == "PhpString") return ctx.GetWritableStringTypeMask(); if (t.Name == "PhpArray") return ctx.GetArrayTypeMask(); if (t.Name == "IPhpCallable") return ctx.GetCallableTypeMask(); } break; } return CreateMask(ctx, CreateTypeRef(ctx, t)); }
public DelegateConstructor(NamedTypeSymbol containingType, TypeSymbol objectType, TypeSymbol intPtrType) : base(containingType) { _parameters = ImmutableArray.Create<ParameterSymbol>( new SynthesizedParameterSymbol(this, objectType, 0, RefKind.None, "object"), new SynthesizedParameterSymbol(this, intPtrType, 1, RefKind.None, "method")); }
internal TempLocalSymbol(TypeSymbol type, RefKind refKind, MethodSymbol containingMethod) : base(containingMethod, type, null) { this.refKind = refKind; #if TEMPNAMES this.name = "_" + Interlocked.Increment(ref nextName); #endif }
private static BoundExpression RewriteConditionalOperator( CSharpSyntaxNode syntax, BoundExpression rewrittenCondition, BoundExpression rewrittenConsequence, BoundExpression rewrittenAlternative, ConstantValue constantValueOpt, TypeSymbol rewrittenType) { // NOTE: This optimization assumes that a constant has no side effects. In the future we // might wish to represent nodes that are known to the optimizer as having constant // values as a sequence of side effects and a constant value; in that case the result // of this should be a sequence containing the side effect and the consequence or alternative. ConstantValue conditionConstantValue = rewrittenCondition.ConstantValue; if (conditionConstantValue == ConstantValue.True) { return rewrittenConsequence; } else if (conditionConstantValue == ConstantValue.False) { return rewrittenAlternative; } else { return new BoundConditionalOperator( syntax, rewrittenCondition, rewrittenConsequence, rewrittenAlternative, constantValueOpt, rewrittenType); } }
public EELocalSymbol( MethodSymbol method, ImmutableArray<Location> locations, string nameOpt, int ordinal, LocalDeclarationKind declarationKind, TypeSymbol type, RefKind refKind, bool isPinned, bool isCompilerGenerated, bool canScheduleToStack) { Debug.Assert(method != null); Debug.Assert(ordinal >= -1); Debug.Assert(!locations.IsDefault); Debug.Assert(type != null); _method = method; _locations = locations; _nameOpt = nameOpt; _ordinal = ordinal; _declarationKind = declarationKind; _type = type; _refKind = refKind; _isPinned = isPinned; _isCompilerGenerated = isCompilerGenerated; _canScheduleToStack = canScheduleToStack; }
/// <summary> /// Return the extension method in reduced form if the extension method /// is applicable, and satisfies type parameter constraints, based on the /// "this" argument type. Otherwise, returns null. /// </summary> public static MethodSymbol Create(MethodSymbol method, TypeSymbol receiverType, Compilation compilation) { Debug.Assert(method.IsExtensionMethod && method.MethodKind != MethodKind.ReducedExtension); Debug.Assert(method.ParameterCount > 0); Debug.Assert((object)receiverType != null); HashSet<DiagnosticInfo> useSiteDiagnostics = null; method = method.InferExtensionMethodTypeArguments(receiverType, compilation, ref useSiteDiagnostics); if ((object)method == null) { return null; } var conversions = new TypeConversions(method.ContainingAssembly.CorLibrary); var conversion = conversions.ConvertExtensionMethodThisArg(method.Parameters[0].Type, receiverType, ref useSiteDiagnostics); if (!conversion.Exists) { return null; } if (useSiteDiagnostics != null) { foreach (var diag in useSiteDiagnostics) { if (diag.Severity == DiagnosticSeverity.Error) { return null; } } } return Create(method); }
/// <summary> /// Logical equality on anonymous types that ignores custom modifiers and/or the object/dynamic distinction. /// Differs from IsSameType for arrays, pointers, and generic instantiations. /// </summary> internal static bool IsSameType(TypeSymbol type1, TypeSymbol type2, bool ignoreCustomModifiers, bool ignoreDynamic) { Debug.Assert(type1.IsAnonymousType); Debug.Assert(type2.IsAnonymousType); if (ignoreCustomModifiers || ignoreDynamic) { AnonymousTypeDescriptor left = ((AnonymousTypePublicSymbol)type1).TypeDescriptor; AnonymousTypeDescriptor right = ((AnonymousTypePublicSymbol)type2).TypeDescriptor; if (left.Key != right.Key) { return false; } int count = left.Fields.Length; Debug.Assert(right.Fields.Length == count); for (int i = 0; i < count; i++) { if (!left.Fields[i].Type.Equals(right.Fields[i].Type, ignoreCustomModifiers, ignoreDynamic)) { return false; } } return true; } else { return type1 == type2; } }
internal IndexerSymbol(string name, string documentation, TypeSymbol parent, TypeSymbol indexType, TypeSymbol valueType, bool readOnly = true) : base(SymbolKind.Indexer, name, documentation, parent, valueType) { IndexType = indexType; ValueType = valueType; ReadOnly = readOnly; }
public SynthesizedImplementationMethod( MethodSymbol interfaceMethod, NamedTypeSymbol implementingType, string name = null, bool debuggerHidden = false, PropertySymbol associatedProperty = null, MethodSymbol asyncKickoffMethod = null) { //it does not make sense to add methods to substituted types Debug.Assert(implementingType.IsDefinition); this.name = name ?? ExplicitInterfaceHelpers.GetMemberName(interfaceMethod.Name, interfaceMethod.ContainingType, aliasQualifierOpt: null); this.interfaceMethod = interfaceMethod; this.implementingType = implementingType; this.debuggerHidden = debuggerHidden; this.associatedProperty = associatedProperty; this.explicitInterfaceImplementations = ImmutableArray.Create<MethodSymbol>(interfaceMethod); this.asyncKickoffMethod = asyncKickoffMethod; // alpha-rename to get the implementation's type parameters var typeMap = interfaceMethod.ContainingType.TypeSubstitution ?? TypeMap.Empty; typeMap.WithAlphaRename(interfaceMethod, this, out this.typeParameters); var substitutedInterfaceMethod = interfaceMethod.ConstructIfGeneric(this.typeParameters.Cast<TypeParameterSymbol, TypeSymbol>()); this.returnType = substitutedInterfaceMethod.ReturnType; this.parameters = SynthesizedParameterSymbol.DeriveParameters(substitutedInterfaceMethod, this); }
private ForEachEnumeratorInfo( TypeSymbol collectionType, TypeSymbol elementType, MethodSymbol getEnumeratorMethod, MethodSymbol currentPropertyGetter, MethodSymbol moveNextMethod, bool needsDisposeMethod, Conversion collectionConversion, Conversion currentConversion, Conversion enumeratorConversion, BinderFlags location) { Debug.Assert((object)collectionType != null, "Field 'collectionType' cannot be null"); Debug.Assert((object)elementType != null, "Field 'elementType' cannot be null"); Debug.Assert((object)getEnumeratorMethod != null, "Field 'getEnumeratorMethod' cannot be null"); Debug.Assert((object)currentPropertyGetter != null, "Field 'currentPropertyGetter' cannot be null"); Debug.Assert((object)moveNextMethod != null, "Field 'moveNextMethod' cannot be null"); this.CollectionType = collectionType; this.ElementType = elementType; this.GetEnumeratorMethod = getEnumeratorMethod; this.CurrentPropertyGetter = currentPropertyGetter; this.MoveNextMethod = moveNextMethod; this.NeedsDisposeMethod = needsDisposeMethod; this.CollectionConversion = collectionConversion; this.CurrentConversion = currentConversion; this.EnumeratorConversion = enumeratorConversion; this.Location = location; }
/// <param name="sourceType">Type that already has custom modifiers.</param> /// <param name="destinationType">Same as <paramref name="sourceType"/>, but without custom modifiers. May differ in object/dynamic.</param> /// <param name="refKind"><see cref="RefKind"/> of the parameter of which this is the type (or <see cref="RefKind.None"/> for a return type.</param> /// <param name="containingAssembly">The assembly containing the signature referring to the destination type.</param> /// <returns><paramref name="destinationType"/> with custom modifiers copied from <paramref name="sourceType"/>.</returns> internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, RefKind refKind, AssemblySymbol containingAssembly) { Debug.Assert(sourceType.Equals(destinationType, ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: true)); if (sourceType.ContainsTuple()) { // TODO(https://github.com/dotnet/roslyn/issues/12389): // Need to save/restore tupleness as well if (sourceType.IsTupleType) { Debug.Assert(destinationType.IsTupleType); return destinationType; } ImmutableArray<bool> flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind); TypeSymbol resultType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags); Debug.Assert(resultType.Equals(sourceType, ignoreCustomModifiersAndArraySizesAndLowerBounds: false, ignoreDynamic: true)); // Same custom modifiers as source type. return resultType; } else { // NOTE: overrides can differ by object/dynamic. If they do, we'll need to tweak newType before // we can use it in place of this.Type. We do so by computing the dynamic transform flags that // code gen uses and then passing them to the dynamic type decoder that metadata reading uses. ImmutableArray<bool> flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind); TypeSymbol resultType = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags); Debug.Assert(resultType.Equals(sourceType, ignoreCustomModifiersAndArraySizesAndLowerBounds: false, ignoreDynamic: true)); // Same custom modifiers as source type. Debug.Assert(resultType.Equals(destinationType, ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: false)); // Same object/dynamic as destination type. return resultType; } }
public BoundLambda(CSharpSyntaxNode syntax, BoundBlock body, ImmutableArray<Diagnostic> diagnostics, Binder binder, TypeSymbol delegateType, bool inferReturnType) : this(syntax, (LambdaSymbol)binder.ContainingMemberOrLambda, body, diagnostics, binder, delegateType) { if (inferReturnType) { this._inferredReturnType = InferReturnType( this.Body, this.Binder, delegateType, this.Symbol.IsAsync, ref this._inferredReturnTypeUseSiteDiagnostics, out this._refKind, out this._inferredFromSingleType); #if DEBUG _hasInferredReturnType = true; #endif } Debug.Assert( syntax.IsAnonymousFunction() || // lambda expressions syntax is ExpressionSyntax && LambdaUtilities.IsLambdaBody(syntax, allowReducedLambdas: true) || // query lambdas LambdaUtilities.IsQueryPairLambda(syntax) // "pair" lambdas in queries ); }
protected override void MethodChecks(DiagnosticBag diagnostics) { var syntax = GetSyntax(); var binderFactory = this.DeclaringCompilation.GetBinderFactory(syntax.SyntaxTree); ParameterListSyntax parameterList = syntax.ParameterList; // NOTE: if we asked for the binder for the body of the constructor, we'd risk a stack overflow because // we might still be constructing the member list of the containing type. However, getting the binder // for the parameters should be safe. var bodyBinder = binderFactory.GetBinder(parameterList).WithContainingMemberOrLambda(this); SyntaxToken arglistToken; _lazyParameters = ParameterHelpers.MakeParameters(bodyBinder, this, parameterList, true, out arglistToken, diagnostics); _lazyIsVararg = (arglistToken.Kind() == SyntaxKind.ArgListKeyword); _lazyReturnType = bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax); var location = this.Locations[0]; if (MethodKind == MethodKind.StaticConstructor && (_lazyParameters.Length != 0)) { diagnostics.Add(ErrorCode.ERR_StaticConstParam, location, this); } this.CheckEffectiveAccessibility(_lazyReturnType, _lazyParameters, diagnostics); if (_lazyIsVararg && (IsGenericMethod || ContainingType.IsGenericType || _lazyParameters.Length > 0 && _lazyParameters[_lazyParameters.Length - 1].IsParams)) { diagnostics.Add(ErrorCode.ERR_BadVarargs, location); } }
public UnaryOperatorSignature(UnaryOperatorKind kind, TypeSymbol operandType, TypeSymbol returnType, MethodSymbol method = null) { this.Kind = kind; this.OperandType = operandType; this.ReturnType = returnType; this.Method = method; }
/// <param name="sourceType">Type that already has custom modifiers.</param> /// <param name="destinationType">Same as <paramref name="sourceType"/>, but without custom modifiers. May differ in object/dynamic.</param> /// <param name="refKind"><see cref="RefKind"/> of the parameter of which this is the type (or <see cref="RefKind.None"/> for a return type.</param> /// <param name="containingAssembly">The assembly containing the signature referring to the destination type.</param> /// <returns><paramref name="destinationType"/> with custom modifiers copied from <paramref name="sourceType"/>.</returns> internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, RefKind refKind, AssemblySymbol containingAssembly) { Debug.Assert(sourceType.Equals(destinationType, TypeCompareKind.AllIgnoreOptions)); // NOTE: overrides can differ by object/dynamic. If they do, we'll need to tweak newType before // we can use it in place of this.Type. We do so by computing the dynamic transform flags that // code gen uses and then passing them to the dynamic type decoder that metadata reading uses. ImmutableArray<bool> flags = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind); TypeSymbol typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags); TypeSymbol resultType; if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic)) { // We also preserve tuple names, if present and different ImmutableArray<string> names = CSharpCompilation.TupleNamesEncoder.Encode(destinationType); resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithDynamic, containingAssembly, names); } else { resultType = typeWithDynamic; } Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames)); // Same custom modifiers as source type. Debug.Assert(resultType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); // Same object/dynamic and tuple names as destination type. return resultType; }
/// <summary> /// </summary> /// <param name="typeDef"> /// </param> /// <param name="isByRef"> /// </param> internal MetadataTypeAdapter(TypeSymbol typeDef, bool isByRef = false, bool isPinned = false) { Debug.Assert(typeDef != null); this.typeDef = typeDef; this.IsByRef = isByRef; this.IsPinned = isPinned; var def = typeDef as ByRefReturnErrorTypeSymbol; if (def != null) { this.typeDef = def.ReferencedType; this.IsByRef = true; } Debug.Assert(this.typeDef.TypeKind != TypeKind.Error); this.lazyName = new Lazy<string>(this.CalculateName); this.lazyFullName = new Lazy<string>(this.CalculateFullName); this.lazyMetadataName = new Lazy<string>(this.CalculateMetadataName); this.lazyMetadataFullName = new Lazy<string>(this.CalculateMetadataFullName); this.lazyNamespace = new Lazy<string>(this.CalculateNamespace); this.lazyBaseType = new Lazy<IType>(this.CalculateBaseType); this.lazyAssemblyQualifiedName = new Lazy<string>(this.CalculateAssemblyQualifiedName); this.lazyToString = new Lazy<string>(this.CalculateToString); }
private BoundExpression MakeFieldAccess( CSharpSyntaxNode syntax, BoundExpression rewrittenReceiver, FieldSymbol fieldSymbol, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type, BoundFieldAccess oldNodeOpt = null) { if (fieldSymbol.IsTupleField) { return MakeTupleFieldAccess(syntax, fieldSymbol, rewrittenReceiver, constantValueOpt, resultKind); } BoundExpression result = oldNodeOpt != null ? oldNodeOpt.Update(rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type) : new BoundFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type); if (fieldSymbol.IsFixed) { // a reference to a fixed buffer is translated into its address result = new BoundConversion(syntax, new BoundAddressOfOperator(syntax, result, syntax != null && SyntaxFacts.IsFixedStatementExpression(syntax), type, false), new Conversion(ConversionKind.PointerToPointer), false, false, default(ConstantValue), type, false); } return result; }
internal SynthesizedEntryPointSymbol(NamedTypeSymbol containingType, TypeSymbol returnType, DiagnosticBag diagnostics) { Debug.Assert((object)containingType != null); this.containingType = containingType; if (containingType.ContainingAssembly.IsInteractive) { var interactiveSessionType = this.DeclaringCompilation.GetWellKnownType(WellKnownType.Microsoft_CSharp_RuntimeHelpers_Session); var useSiteDiagnostic = interactiveSessionType.GetUseSiteDiagnostic(); if (useSiteDiagnostic != null) { Symbol.ReportUseSiteDiagnostic(useSiteDiagnostic, diagnostics, NoLocation.Singleton); } this.parameters = ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(this, interactiveSessionType, 0, RefKind.None, "session")); this.name = "<Factory>"; } else { this.parameters = ImmutableArray<ParameterSymbol>.Empty; this.name = "<Main>"; } this.returnType = returnType; }
protected override Conversion GetImplicitTupleLiteralConversion(BoundTupleLiteral source, TypeSymbol destination, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { var arguments = source.Arguments; // check if the type is actually compatible type for a tuple of given cardinality if (!destination.IsTupleOrCompatibleWithTupleOfCardinality(arguments.Length)) { return Conversion.NoConversion; } ImmutableArray<TypeSymbol> targetElementTypes = destination.GetElementTypesOfTupleOrCompatible(); Debug.Assert(arguments.Length == targetElementTypes.Length); // check arguments against flattened list of target element types var argumentConversions = ArrayBuilder<Conversion>.GetInstance(arguments.Length); for (int i = 0; i < arguments.Length; i++) { var argument = arguments[i]; var result = ClassifyImplicitConversionFromExpression(argument, targetElementTypes[i], ref useSiteDiagnostics); if (!result.Exists) { argumentConversions.Free(); return Conversion.NoConversion; } argumentConversions.Add(result); } return new Conversion(ConversionKind.ImplicitTupleLiteral, argumentConversions.ToImmutableAndFree()); }
private BoundExpression MakeLiteral(CSharpSyntaxNode syntax, ConstantValue constantValue, TypeSymbol type, BoundLiteral oldNodeOpt = null) { Debug.Assert(constantValue != null); if (constantValue.IsDecimal) { // Rewrite decimal literal Debug.Assert((object)type != null); Debug.Assert(type.SpecialType == SpecialType.System_Decimal); return MakeDecimalLiteral(syntax, constantValue); } else if (constantValue.IsDateTime) { // C# does not support DateTime constants but VB does; we might have obtained a // DateTime constant by calling a method with an optional parameter with a DateTime // for its default value. Debug.Assert((object)type != null); Debug.Assert(type.SpecialType == SpecialType.System_DateTime); return MakeDateTimeLiteral(syntax, constantValue); } else if (oldNodeOpt != null) { return oldNodeOpt.Update(constantValue, type); } else { return new BoundLiteral(syntax, constantValue, type, hasErrors: constantValue.IsBad); } }
internal SourceStrictComplexParameterSymbol( DiagnosticBag diagnostics, Binder binder, Symbol owner, int ordinal, TypeSymbol parameterType, RefKind refKind, string name, ImmutableArray<Location> locations, SyntaxReference syntaxRef, ConstantValue defaultSyntaxValue, bool isParams, bool isExtensionMethodThis) : base( owner: owner, ordinal: ordinal, parameterType: parameterType, refKind: refKind, name: name, locations: locations, syntaxRef: syntaxRef, defaultSyntaxValue: defaultSyntaxValue, isParams: isParams, isExtensionMethodThis: isExtensionMethodThis) { _tempBinder = binder; var unused = GetAttributesBag(diagnostics); _lazyDefaultSyntaxValue = MakeDefaultExpression(diagnostics, binder); _tempBinder = null; // no need to keep it around anymore, just uses up a lot of memory }
public BoundDeconstructValuePlaceholder SetInferredType(TypeSymbol type, bool success) { Debug.Assert((object)Placeholder == null); Placeholder = new BoundDeconstructValuePlaceholder(this.Syntax, type, hasErrors: this.HasErrors || !success); return Placeholder; }
public override Conversion GetMethodGroupConversion(BoundMethodGroup source, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { // Conversions involving method groups require a Binder. throw ExceptionUtilities.Unreachable; }
internal static void GetTypeOrReturnType(this Symbol member, out RefKind refKind, out TypeSymbol returnType, out ImmutableArray <CustomModifier> returnTypeCustomModifiers) { switch (member.Kind) { case SymbolKind.Field: FieldSymbol field = (FieldSymbol)member; refKind = RefKind.None; returnType = field.Type; returnTypeCustomModifiers = field.CustomModifiers; break; case SymbolKind.Method: MethodSymbol method = (MethodSymbol)member; refKind = method.RefKind; returnType = method.ReturnType; returnTypeCustomModifiers = method.ReturnTypeCustomModifiers; break; case SymbolKind.Property: PropertySymbol property = (PropertySymbol)member; refKind = property.RefKind; returnType = property.Type; returnTypeCustomModifiers = property.TypeCustomModifiers; break; case SymbolKind.Event: EventSymbol @event = (EventSymbol)member; refKind = RefKind.None; returnType = @event.Type; returnTypeCustomModifiers = ImmutableArray <CustomModifier> .Empty; break; default: throw ExceptionUtilities.UnexpectedValue(member.Kind); } }
/// <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 (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; } }
/// <summary> /// Does an expression of type <paramref name="expressionType"/> "match" a pattern that looks for /// type <paramref name="patternType"/>? /// 'true' if the matched type catches all of them, 'false' if it catches none of them, and /// 'null' if it might catch some of them. For this test we assume the expression's value /// isn't null. /// </summary> internal bool?ExpressionOfTypeMatchesPatternType(TypeSymbol expressionType, TypeSymbol patternType, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { return(Binder.ExpressionOfTypeMatchesPatternType(this._conversions, expressionType, patternType, ref _useSiteDiagnostics, out Conversion conversion, null, false)); }
public void ReadOnlyStructApiMetadata() { var text1 = @" class Program { readonly struct S1 { public S1(int dummy) { } public string M1() { return ""1""; } public override string ToString() { return ""2""; } } readonly struct S1<T> { public S1(int dummy) { } public string M1() { return ""1""; } public override string ToString() { return ""2""; } } struct S2 { public S2(int dummy) { } public string M1() { return ""1""; } public override string ToString() { return ""2""; } } class C1 { public C1(int dummy) { } public string M1() { return ""1""; } public override string ToString() { return ""2""; } } delegate int D1(); } "; var comp1 = CreateStandardCompilation(text1, assemblyName: "A"); var ref1 = comp1.EmitToImageReference(); var comp = CreateStandardCompilation("//NO CODE HERE", new[] { ValueTupleRef, SystemRuntimeFacadeRef, ref1 }, parseOptions: TestOptions.Regular); // S1 NamedTypeSymbol namedType = comp.GetTypeByMetadataName("Program+S1"); Assert.True(namedType.IsReadOnly); Assert.Equal(RefKind.Out, namedType.Constructors[0].ThisParameter.RefKind); Assert.Equal(RefKind.In, namedType.GetMethod("M1").ThisParameter.RefKind); Assert.Equal(RefKind.In, namedType.GetMethod("ToString").ThisParameter.RefKind); // S1<T> namedType = comp.GetTypeByMetadataName("Program+S1`1"); Assert.True(namedType.IsReadOnly); Assert.Equal(RefKind.Out, namedType.Constructors[0].ThisParameter.RefKind); Assert.Equal(RefKind.In, namedType.GetMethod("M1").ThisParameter.RefKind); Assert.Equal(RefKind.In, namedType.GetMethod("ToString").ThisParameter.RefKind); // T TypeSymbol type = namedType.TypeParameters[0]; Assert.True(namedType.IsReadOnly); Assert.Equal(RefKind.Out, namedType.Constructors[0].ThisParameter.RefKind); Assert.Equal(RefKind.In, namedType.GetMethod("M1").ThisParameter.RefKind); Assert.Equal(RefKind.In, namedType.GetMethod("ToString").ThisParameter.RefKind); // S1<object> namedType = namedType.Construct(comp.ObjectType); Assert.True(namedType.IsReadOnly); Assert.Equal(RefKind.Out, namedType.Constructors[0].ThisParameter.RefKind); Assert.Equal(RefKind.In, namedType.GetMethod("M1").ThisParameter.RefKind); Assert.Equal(RefKind.In, namedType.GetMethod("ToString").ThisParameter.RefKind); // S2 namedType = comp.GetTypeByMetadataName("Program+S2"); Assert.False(namedType.IsReadOnly); Assert.Equal(RefKind.Out, namedType.Constructors[0].ThisParameter.RefKind); Assert.Equal(RefKind.Ref, namedType.GetMethod("M1").ThisParameter.RefKind); Assert.Equal(RefKind.Ref, namedType.GetMethod("ToString").ThisParameter.RefKind); // C1 namedType = comp.GetTypeByMetadataName("Program+C1"); Assert.False(namedType.IsReadOnly); Assert.Equal(RefKind.None, namedType.Constructors[0].ThisParameter.RefKind); Assert.Equal(RefKind.None, namedType.GetMethod("M1").ThisParameter.RefKind); Assert.Equal(RefKind.None, namedType.GetMethod("ToString").ThisParameter.RefKind); // D1 namedType = comp.GetTypeByMetadataName("Program+D1"); Assert.False(namedType.IsReadOnly); Assert.Equal(RefKind.None, namedType.Constructors[0].ThisParameter.RefKind); Assert.Equal(RefKind.None, namedType.GetMethod("Invoke").ThisParameter.RefKind); // object[] type = comp.CreateArrayTypeSymbol(comp.ObjectType); Assert.False(type.IsReadOnly); // dynamic type = comp.DynamicType; Assert.False(type.IsReadOnly); // object type = comp.ObjectType; Assert.False(type.IsReadOnly); // anonymous type type = (TypeSymbol)comp.CreateAnonymousTypeSymbol(ImmutableArray.Create <ITypeSymbol>(comp.ObjectType), ImmutableArray.Create("qq")); Assert.False(type.IsReadOnly); // pointer type type = (TypeSymbol)comp.CreatePointerTypeSymbol(comp.ObjectType); Assert.False(type.IsReadOnly); // tuple type type = (TypeSymbol)comp.CreateTupleTypeSymbol(ImmutableArray.Create <ITypeSymbol>(comp.ObjectType, comp.ObjectType)); Assert.False(type.IsReadOnly); }
public static LiteralExpression GetDefaultValueExpression(TypeSymbol type, SymbolSet symbolSet) { return(new LiteralExpression(symbolSet.ResolveIntrinsicType(IntrinsicType.Object), GetDefaultValue(type, symbolSet))); }
private void EmitSymbolToken(TypeSymbol symbol, SyntaxNode syntaxNode) { EmitTypeReferenceToken(_module.Translate(symbol, syntaxNode, _diagnostics), syntaxNode); }
public DynamicTypeEraser(TypeSymbol objectType) { Debug.Assert((object)objectType != null); _objectType = objectType; }
// Used to increment integer index into an array or string. private BoundStatement MakePositionIncrement(CSharpSyntaxNode syntax, BoundLocal boundPositionVar, TypeSymbol intType) { // A normal for-loop would have a sequence point on the increment. We don't want that since the code is synthesized, // but we add a hidden sequence point to avoid disrupting the stepping experience. return(new BoundSequencePoint(null, statementOpt: new BoundExpressionStatement(syntax, expression: new BoundAssignmentOperator(syntax, left: boundPositionVar, right: new BoundBinaryOperator(syntax, operatorKind: BinaryOperatorKind.IntAddition, // unchecked, never overflows since array/string index can't be >= Int32.MaxValue left: boundPositionVar, right: MakeLiteral(syntax, constantValue: ConstantValue.Create(1), type: intType), constantValueOpt: null, methodOpt: null, resultKind: LookupResultKind.Viable, type: intType), type: intType)))); }
public TypeSymbol EraseDynamic(TypeSymbol type) { return(SubstituteType(type).AsTypeSymbolOnly()); }
/// <summary> /// Lower a foreach loop that will enumerate a collection using an enumerator. /// /// E e = ((C)(x)).GetEnumerator() /// try { /// while (e.MoveNext()) { /// V v = (V)(T)e.Current; /// // body /// } /// } /// finally { /// // clean up e /// } /// </summary> private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement node) { ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax; ForEachEnumeratorInfo enumeratorInfo = node.EnumeratorInfoOpt; Debug.Assert(enumeratorInfo != null); BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node); BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression); BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body); TypeSymbol enumeratorType = enumeratorInfo.GetEnumeratorMethod.ReturnType; TypeSymbol elementType = enumeratorInfo.ElementType; // E e LocalSymbol enumeratorVar = factory.SynthesizedLocal(enumeratorType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachEnumerator); // Reference to e. BoundLocal boundEnumeratorVar = MakeBoundLocal(forEachSyntax, enumeratorVar, enumeratorType); // ((C)(x)).GetEnumerator() or (x).GetEnumerator(); BoundExpression enumeratorVarInitValue = SynthesizeCall(forEachSyntax, rewrittenExpression, enumeratorInfo.GetEnumeratorMethod, enumeratorInfo.CollectionConversion, enumeratorInfo.CollectionType); // E e = ((C)(x)).GetEnumerator(); BoundStatement enumeratorVarDecl = MakeLocalDeclaration(forEachSyntax, enumeratorVar, enumeratorVarInitValue); AddForEachExpressionSequencePoint(forEachSyntax, ref enumeratorVarDecl); // V v LocalSymbol iterationVar = node.IterationVariable; //(V)(T)e.Current BoundExpression iterationVarAssignValue = MakeConversion( syntax: forEachSyntax, rewrittenOperand: MakeConversion( syntax: forEachSyntax, rewrittenOperand: BoundCall.Synthesized( syntax: forEachSyntax, receiverOpt: boundEnumeratorVar, method: enumeratorInfo.CurrentPropertyGetter), conversion: enumeratorInfo.CurrentConversion, rewrittenType: elementType, @checked: node.Checked), conversion: node.ElementConversion, rewrittenType: iterationVar.Type, @checked: node.Checked); // V v = (V)(T)e.Current; BoundStatement iterationVarDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarAssignValue); AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVarDecl); // while (e.MoveNext()) { // V v = (V)(T)e.Current; // /* node.Body */ // } BoundStatement whileLoop = RewriteWhileStatement( syntax: forEachSyntax, rewrittenCondition: BoundCall.Synthesized( syntax: forEachSyntax, receiverOpt: boundEnumeratorVar, method: enumeratorInfo.MoveNextMethod), conditionSequencePointSpan: forEachSyntax.InKeyword.Span, rewrittenBody: new BoundBlock(rewrittenBody.Syntax, statements: ImmutableArray.Create <BoundStatement>(iterationVarDecl, rewrittenBody), locals: ImmutableArray.Create <LocalSymbol>(iterationVar)), breakLabel: node.BreakLabel, continueLabel: node.ContinueLabel, hasErrors: false); BoundStatement result; MethodSymbol disposeMethod; if (enumeratorInfo.NeedsDisposeMethod && TryGetSpecialTypeMember(forEachSyntax, SpecialMember.System_IDisposable__Dispose, out disposeMethod)) { Binder.ReportDiagnosticsIfObsolete(diagnostics, disposeMethod, forEachSyntax, hasBaseReceiver: false, containingMember: this.factory.CurrentMethod, containingType: this.factory.CurrentClass, location: enumeratorInfo.Location); BoundBlock finallyBlockOpt; var idisposableTypeSymbol = disposeMethod.ContainingType; var conversions = new TypeConversions(this.factory.CurrentMethod.ContainingAssembly.CorLibrary); HashSet <DiagnosticInfo> useSiteDiagnostics = null; var isImplicit = conversions.ClassifyImplicitConversion(enumeratorType, idisposableTypeSymbol, ref useSiteDiagnostics).IsImplicit; diagnostics.Add(forEachSyntax, useSiteDiagnostics); if (isImplicit) { Debug.Assert(enumeratorInfo.NeedsDisposeMethod); Conversion receiverConversion = enumeratorType.IsStructType() ? Conversion.Boxing : Conversion.ImplicitReference; // ((IDisposable)e).Dispose(); or e.Dispose(); BoundStatement disposeCall = new BoundExpressionStatement(forEachSyntax, expression: SynthesizeCall(forEachSyntax, boundEnumeratorVar, disposeMethod, receiverConversion, idisposableTypeSymbol)); BoundStatement disposeStmt; if (enumeratorType.IsValueType) { // No way for the struct to be nullable and disposable. Debug.Assert(((TypeSymbol)enumeratorType.OriginalDefinition).SpecialType != SpecialType.System_Nullable_T); // For non-nullable structs, no null check is required. disposeStmt = disposeCall; } else { // NB: cast to object missing from spec. Needed to ignore user-defined operators and box type parameters. // if ((object)e != null) ((IDisposable)e).Dispose(); disposeStmt = RewriteIfStatement( syntax: forEachSyntax, rewrittenCondition: new BoundBinaryOperator(forEachSyntax, operatorKind: BinaryOperatorKind.NotEqual, left: MakeConversion( syntax: forEachSyntax, rewrittenOperand: boundEnumeratorVar, conversion: enumeratorInfo.EnumeratorConversion, rewrittenType: this.compilation.GetSpecialType(SpecialType.System_Object), @checked: false), right: MakeLiteral(forEachSyntax, constantValue: ConstantValue.Null, type: null), constantValueOpt: null, methodOpt: null, resultKind: LookupResultKind.Viable, type: this.compilation.GetSpecialType(SpecialType.System_Boolean)), rewrittenConsequence: disposeCall, rewrittenAlternativeOpt: null, hasErrors: false); } finallyBlockOpt = new BoundBlock(forEachSyntax, locals: ImmutableArray <LocalSymbol> .Empty, statements: ImmutableArray.Create <BoundStatement>(disposeStmt)); } else { Debug.Assert(!enumeratorType.IsSealed); // IDisposable d LocalSymbol disposableVar = factory.SynthesizedLocal(idisposableTypeSymbol); // Reference to d. BoundLocal boundDisposableVar = MakeBoundLocal(forEachSyntax, disposableVar, idisposableTypeSymbol); BoundTypeExpression boundIDisposableTypeExpr = new BoundTypeExpression(forEachSyntax, aliasOpt: null, type: idisposableTypeSymbol); // e as IDisposable BoundExpression disposableVarInitValue = new BoundAsOperator(forEachSyntax, operand: boundEnumeratorVar, targetType: boundIDisposableTypeExpr, conversion: Conversion.ExplicitReference, // Explicit so the emitter won't optimize it away. type: idisposableTypeSymbol); // IDisposable d = e as IDisposable; BoundStatement disposableVarDecl = MakeLocalDeclaration(forEachSyntax, disposableVar, disposableVarInitValue); // if (d != null) d.Dispose(); BoundStatement ifStmt = RewriteIfStatement( syntax: forEachSyntax, rewrittenCondition: new BoundBinaryOperator(forEachSyntax, operatorKind: BinaryOperatorKind.NotEqual, // reference equality left: boundDisposableVar, right: MakeLiteral(forEachSyntax, constantValue: ConstantValue.Null, type: null), constantValueOpt: null, methodOpt: null, resultKind: LookupResultKind.Viable, type: this.compilation.GetSpecialType(SpecialType.System_Boolean)), rewrittenConsequence: new BoundExpressionStatement(forEachSyntax, expression: BoundCall.Synthesized( syntax: forEachSyntax, receiverOpt: boundDisposableVar, method: disposeMethod)), rewrittenAlternativeOpt: null, hasErrors: false); // IDisposable d = e as IDisposable; // if (d != null) d.Dispose(); finallyBlockOpt = new BoundBlock(forEachSyntax, locals: ImmutableArray.Create <LocalSymbol>(disposableVar), statements: ImmutableArray.Create <BoundStatement>(disposableVarDecl, ifStmt)); } // try { // while (e.MoveNext()) { // V v = (V)(T)e.Current; // /* loop body */ // } // } // finally { // /* dispose of e */ // } BoundStatement tryFinally = new BoundTryStatement(forEachSyntax, tryBlock: new BoundBlock(forEachSyntax, locals: ImmutableArray <LocalSymbol> .Empty, statements: ImmutableArray.Create <BoundStatement>(whileLoop)), catchBlocks: ImmutableArray <BoundCatchBlock> .Empty, finallyBlockOpt: finallyBlockOpt); // E e = ((C)(x)).GetEnumerator(); // try { // /* as above */ result = new BoundBlock( syntax: forEachSyntax, locals: ImmutableArray.Create(enumeratorVar), statements: ImmutableArray.Create <BoundStatement>(enumeratorVarDecl, tryFinally)); } else { // E e = ((C)(x)).GetEnumerator(); // while (e.MoveNext()) { // V v = (V)(T)e.Current; // /* loop body */ // } result = new BoundBlock( syntax: forEachSyntax, locals: ImmutableArray.Create(enumeratorVar), statements: ImmutableArray.Create <BoundStatement>(enumeratorVarDecl, whileLoop)); } AddForEachKeywordSequencePoint(forEachSyntax, ref result); return(result); }
internal SynthesizedGlobalMethodSymbol(ModuleSymbol containingModule, PrivateImplementationDetails privateImplType, TypeSymbol returnType, string name) { Debug.Assert((object)containingModule != null); Debug.Assert(privateImplType != null); Debug.Assert((object)returnType != null); Debug.Assert(name != null); _containingModule = containingModule; _privateImplType = privateImplType; _returnType = returnType; _name = name; }
/// <summary> /// Lower a foreach loop that will enumerate a single-dimensional array. /// /// A[] a = x; /// for (int p = 0; p < a.Length; p = p + 1) { /// V v = (V)a[p]; /// // body /// } /// </summary> /// <remarks> /// We will follow Dev10 in diverging from the C# 4 spec by ignoring Array's /// implementation of IEnumerable and just indexing into its elements. /// /// NOTE: We're assuming that sequence points have already been generated. /// Otherwise, lowering to for-loops would generated spurious ones. /// </remarks> private BoundStatement RewriteSingleDimensionalArrayForEachStatement(BoundForEachStatement node) { ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax; BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node); Debug.Assert(collectionExpression.Type.IsArray()); ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type; Debug.Assert(arrayType.Rank == 1); TypeSymbol intType = compilation.GetSpecialType(SpecialType.System_Int32); TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean); BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression); BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body); // A[] a LocalSymbol arrayVar = factory.SynthesizedLocal(arrayType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArray); // A[] a = /*node.Expression*/; BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression); AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl); // Reference to a. BoundLocal boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType); // int p LocalSymbol positionVar = factory.SynthesizedLocal(intType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArrayIndex0); // Reference to p. BoundLocal boundPositionVar = MakeBoundLocal(forEachSyntax, positionVar, intType); // int p = 0; BoundStatement positionVarDecl = MakeLocalDeclaration(forEachSyntax, positionVar, MakeLiteral(forEachSyntax, ConstantValue.Default(SpecialType.System_Int32), intType)); // V v LocalSymbol iterationVar = node.IterationVariable; TypeSymbol iterationVarType = iterationVar.Type; // (V)a[p] BoundExpression iterationVarInitValue = MakeConversion( syntax: forEachSyntax, rewrittenOperand: new BoundArrayAccess( syntax: forEachSyntax, expression: boundArrayVar, indices: ImmutableArray.Create <BoundExpression>(boundPositionVar), type: arrayType.ElementType), conversion: node.ElementConversion, rewrittenType: iterationVarType, @checked: node.Checked); // V v = (V)a[p]; BoundStatement iterationVariableDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue); AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVariableDecl); BoundStatement initializer = new BoundStatementList(forEachSyntax, statements: ImmutableArray.Create <BoundStatement>(arrayVarDecl, positionVarDecl)); // a.Length BoundExpression arrayLength = new BoundArrayLength( syntax: forEachSyntax, expression: boundArrayVar, type: intType); // p < a.Length BoundExpression exitCondition = new BoundBinaryOperator( syntax: forEachSyntax, operatorKind: BinaryOperatorKind.IntLessThan, left: boundPositionVar, right: arrayLength, constantValueOpt: null, methodOpt: null, resultKind: LookupResultKind.Viable, type: boolType); // p = p + 1; BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar, intType); // { V v = (V)a[p]; /* node.Body */ } BoundStatement loopBody = new BoundBlock(forEachSyntax, locals: ImmutableArray.Create <LocalSymbol>(iterationVar), statements: ImmutableArray.Create <BoundStatement>(iterationVariableDecl, rewrittenBody)); // for (A[] a = /*node.Expression*/, int p = 0; p < a.Length; p = p + 1) { // V v = (V)a[p]; // /*node.Body*/ // } BoundStatement result = RewriteForStatement( syntax: node.Syntax, outerLocals: ImmutableArray.Create <LocalSymbol>(arrayVar, positionVar), rewrittenInitializer: initializer, rewrittenCondition: exitCondition, conditionSyntaxOpt: null, conditionSpanOpt: forEachSyntax.InKeyword.Span, rewrittenIncrement: positionIncrement, rewrittenBody: loopBody, breakLabel: node.BreakLabel, continueLabel: node.ContinueLabel, hasErrors: node.HasErrors); AddForEachKeywordSequencePoint(forEachSyntax, ref result); return(result); }
private static BoundLocal MakeBoundLocal(CSharpSyntaxNode syntax, LocalSymbol local, TypeSymbol type) { return(new BoundLocal(syntax, localSymbol: local, constantValueOpt: null, type: type)); }
/// <summary> /// Synthesize a no-argument call to a given method, possibly applying a conversion to the receiver. /// /// If the receiver is of struct type and the method is an interface method, then skip the conversion /// and just call the interface method directly - the code generator will detect this and generate a /// constrained virtual call. /// </summary> /// <param name="syntax">A syntax node to attach to the synthesized bound node.</param> /// <param name="receiver">Receiver of method call.</param> /// <param name="method">Method to invoke.</param> /// <param name="receiverConversion">Conversion to be applied to the receiver if not calling an interface method on a struct.</param> /// <param name="convertedReceiverType">Type of the receiver after applying the conversion.</param> /// <returns>A BoundExpression representing the call.</returns> private BoundExpression SynthesizeCall(CSharpSyntaxNode syntax, BoundExpression receiver, MethodSymbol method, Conversion receiverConversion, TypeSymbol convertedReceiverType) { if (receiver.Type.TypeKind == TypeKind.Struct && method.ContainingType.IsInterface) { Debug.Assert(receiverConversion.IsBoxing); // NOTE: The spec says that disposing of a struct enumerator won't cause any // unnecessary boxing to occur. However, Dev10 extends this improvement to the // GetEnumerator call as well. // We're going to let the emitter take care of avoiding the extra boxing. // When it sees an interface call to a struct, it will generate a constrained // virtual call, which will skip boxing, if possible. // CONSIDER: In cases where the struct implicitly implements the interface method // (i.e. with a public method), we could save a few bytes of IL by creating a // BoundCall to the struct method rather than the interface method (so that the // emitter wouldn't need to create a constrained virtual call). It is not clear // what effect this would have on back compat. // NOTE: This call does not correspond to anything that can be written in C# source. // We're invoking the interface method directly on the struct (which may have a private // explicit implementation). The code generator knows how to handle it though. // receiver.InterfaceMethod() return(BoundCall.Synthesized(syntax, receiver, method)); } else { // ((Interface)receiver).InterfaceMethod() Debug.Assert(!receiverConversion.IsNumeric); return(BoundCall.Synthesized( syntax: syntax, receiverOpt: MakeConversion( syntax: syntax, rewrittenOperand: receiver, conversion: receiverConversion, @checked: false, rewrittenType: convertedReceiverType), method: method)); } }
/// <summary> /// Lower a foreach loop that will enumerate a multi-dimensional array. /// /// A[...] a = x; /// int q_0 = a.GetUpperBound(0), q_1 = a.GetUpperBound(1), ...; /// for (int p_0 = a.GetLowerBound(0); p_0 <= q_0; p_0 = p_0 + 1) /// for (int p_1 = a.GetLowerBound(1); p_1 <= q_1; p_1 = p_1 + 1) /// ... /// { V v = (V)a[p_0, p_1, ...]; /* body */ } /// </summary> /// <remarks> /// We will follow Dev10 in diverging from the C# 4 spec by ignoring Array's /// implementation of IEnumerable and just indexing into its elements. /// /// NOTE: We're assuming that sequence points have already been generated. /// Otherwise, lowering to nested for-loops would generated spurious ones. /// </remarks> private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEachStatement node) { ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax; BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node); Debug.Assert(collectionExpression.Type.IsArray()); ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type; int rank = arrayType.Rank; Debug.Assert(rank > 1); TypeSymbol intType = compilation.GetSpecialType(SpecialType.System_Int32); TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean); // Values we'll use every iteration MethodSymbol getLowerBoundMethod = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetLowerBound); MethodSymbol getUpperBoundMethod = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_Array__GetUpperBound); BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression); BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body); // A[...] a LocalSymbol arrayVar = factory.SynthesizedLocal(arrayType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArray); BoundLocal boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType); // A[...] a = /*node.Expression*/; BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression); AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl); // NOTE: dev10 initializes all of the upper bound temps before entering the loop (as opposed to // initializing each one at the corresponding level of nesting). Doing it at the same time as // the lower bound would make this code a bit simpler, but it would make it harder to compare // the roslyn and dev10 IL. // int q_0, q_1, ... LocalSymbol[] upperVar = new LocalSymbol[rank]; BoundLocal[] boundUpperVar = new BoundLocal[rank]; BoundStatement[] upperVarDecl = new BoundStatement[rank]; for (int dimension = 0; dimension < rank; dimension++) { // int q_/*dimension*/ upperVar[dimension] = factory.SynthesizedLocal( intType, syntax: forEachSyntax, kind: (SynthesizedLocalKind)((int)SynthesizedLocalKind.ForEachArrayLimit0 + dimension)); boundUpperVar[dimension] = MakeBoundLocal(forEachSyntax, upperVar[dimension], intType); ImmutableArray <BoundExpression> dimensionArgument = ImmutableArray.Create <BoundExpression>( MakeLiteral(forEachSyntax, constantValue: ConstantValue.Create(dimension, ConstantValueTypeDiscriminator.Int32), type: intType)); // a.GetUpperBound(/*dimension*/) BoundExpression currentDimensionUpperBound = BoundCall.Synthesized(forEachSyntax, boundArrayVar, getUpperBoundMethod, dimensionArgument); // int q_/*dimension*/ = a.GetUpperBound(/*dimension*/); upperVarDecl[dimension] = MakeLocalDeclaration(forEachSyntax, upperVar[dimension], currentDimensionUpperBound); } // int p_0, p_1, ... LocalSymbol[] positionVar = new LocalSymbol[rank]; BoundLocal[] boundPositionVar = new BoundLocal[rank]; for (int dimension = 0; dimension < rank; dimension++) { positionVar[dimension] = factory.SynthesizedLocal( intType, syntax: forEachSyntax, kind: (SynthesizedLocalKind)((int)SynthesizedLocalKind.ForEachArrayIndex0 + dimension)); boundPositionVar[dimension] = MakeBoundLocal(forEachSyntax, positionVar[dimension], intType); } // V v LocalSymbol iterationVar = node.IterationVariable; TypeSymbol iterationVarType = iterationVar.Type; // (V)a[p_0, p_1, ...] BoundExpression iterationVarInitValue = MakeConversion( syntax: forEachSyntax, rewrittenOperand: new BoundArrayAccess(forEachSyntax, expression: boundArrayVar, indices: ImmutableArray.Create <BoundExpression>((BoundExpression[])boundPositionVar), type: arrayType.ElementType), conversion: node.ElementConversion, rewrittenType: iterationVarType, @checked: node.Checked); // V v = (V)a[p_0, p_1, ...]; BoundStatement iterationVarDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue); AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVarDecl); // { V v = (V)a[p_0, p_1, ...]; /* node.Body */ } BoundStatement innermostLoopBody = new BoundBlock(forEachSyntax, locals: ImmutableArray.Create <LocalSymbol>(iterationVar), statements: ImmutableArray.Create <BoundStatement>(iterationVarDecl, rewrittenBody)); // work from most-nested to least-nested // for (int p_0 = a.GetLowerBound(0); p_0 <= q_0; p_0 = p_0 + 1) // for (int p_1 = a.GetLowerBound(0); p_1 <= q_1; p_1 = p_1 + 1) // ... // { V v = (V)a[p_0, p_1, ...]; /* node.Body */ } BoundStatement forLoop = null; for (int dimension = rank - 1; dimension >= 0; dimension--) { ImmutableArray <BoundExpression> dimensionArgument = ImmutableArray.Create <BoundExpression>( MakeLiteral(forEachSyntax, constantValue: ConstantValue.Create(dimension, ConstantValueTypeDiscriminator.Int32), type: intType)); // a.GetLowerBound(/*dimension*/) BoundExpression currentDimensionLowerBound = BoundCall.Synthesized(forEachSyntax, boundArrayVar, getLowerBoundMethod, dimensionArgument); // int p_/*dimension*/ = a.GetLowerBound(/*dimension*/); BoundStatement positionVarDecl = MakeLocalDeclaration(forEachSyntax, positionVar[dimension], currentDimensionLowerBound); GeneratedLabelSymbol breakLabel = dimension == 0 // outermost for-loop ? node.BreakLabel // i.e. the one that break statements will jump to : new GeneratedLabelSymbol("break"); // Should not affect emitted code since unused // p_/*dimension*/ <= q_/*dimension*/ //NB: OrEqual BoundExpression exitCondition = new BoundBinaryOperator( syntax: forEachSyntax, operatorKind: BinaryOperatorKind.IntLessThanOrEqual, left: boundPositionVar[dimension], right: boundUpperVar[dimension], constantValueOpt: null, methodOpt: null, resultKind: LookupResultKind.Viable, type: boolType); // p_/*dimension*/ = p_/*dimension*/ + 1; BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar[dimension], intType); BoundStatement body; GeneratedLabelSymbol continueLabel; if (forLoop == null) { // innermost for-loop body = innermostLoopBody; continueLabel = node.ContinueLabel; //i.e. the one continue statements will actually jump to } else { body = forLoop; continueLabel = new GeneratedLabelSymbol("continue"); // Should not affect emitted code since unused } forLoop = RewriteForStatement( syntax: forEachSyntax, outerLocals: ImmutableArray.Create(positionVar[dimension]), rewrittenInitializer: positionVarDecl, rewrittenCondition: exitCondition, conditionSyntaxOpt: null, conditionSpanOpt: forEachSyntax.InKeyword.Span, rewrittenIncrement: positionIncrement, rewrittenBody: body, breakLabel: breakLabel, continueLabel: continueLabel, hasErrors: node.HasErrors); } Debug.Assert(forLoop != null); BoundStatement result = new BoundBlock( forEachSyntax, ImmutableArray.Create <LocalSymbol>(arrayVar).Concat(upperVar.AsImmutableOrNull()), ImmutableArray.Create <BoundStatement>(arrayVarDecl).Concat(upperVarDecl.AsImmutableOrNull()).Add(forLoop)); AddForEachKeywordSequencePoint(forEachSyntax, ref result); return(result); }
internal ReturnValueLocalSymbol(MethodSymbol method, string name, string displayName, TypeSymbol type, int index) : base(method, name, displayName, type) { _index = index; }
/// <summary> /// Lower a foreach loop that will enumerate the characters of a string. /// /// string s = x; /// for (int p = 0; p < s.Length; p = p + 1) { /// V v = (V)s.Chars[p]; /// // body /// } /// </summary> /// <remarks> /// We will follow Dev10 in diverging from the C# 4 spec by ignoring string's /// implementation of IEnumerable and just indexing into its characters. /// /// NOTE: We're assuming that sequence points have already been generated. /// Otherwise, lowering to for-loops would generated spurious ones. /// </remarks> private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node) { ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax; BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node); TypeSymbol stringType = collectionExpression.Type; Debug.Assert(stringType.SpecialType == SpecialType.System_String); TypeSymbol intType = compilation.GetSpecialType(SpecialType.System_Int32); TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean); BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression); BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body); // string s; LocalSymbol stringVar = factory.SynthesizedLocal(stringType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArray); // int p; LocalSymbol positionVar = factory.SynthesizedLocal(intType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArrayIndex0); // Reference to s. BoundLocal boundStringVar = MakeBoundLocal(forEachSyntax, stringVar, stringType); // Reference to p. BoundLocal boundPositionVar = MakeBoundLocal(forEachSyntax, positionVar, intType); // string s = /*expr*/; BoundStatement stringVarDecl = MakeLocalDeclaration(forEachSyntax, stringVar, rewrittenExpression); AddForEachExpressionSequencePoint(forEachSyntax, ref stringVarDecl); // int p = 0; BoundStatement positionVariableDecl = MakeLocalDeclaration(forEachSyntax, positionVar, MakeLiteral(forEachSyntax, ConstantValue.Default(SpecialType.System_Int32), intType)); // string s = /*node.Expression*/; int p = 0; BoundStatement initializer = new BoundStatementList(forEachSyntax, statements: ImmutableArray.Create <BoundStatement>(stringVarDecl, positionVariableDecl)); MethodSymbol method = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Length); BoundExpression stringLength = BoundCall.Synthesized( syntax: forEachSyntax, receiverOpt: boundStringVar, method: method, arguments: ImmutableArray <BoundExpression> .Empty); // p < s.Length BoundExpression exitCondition = new BoundBinaryOperator( syntax: forEachSyntax, operatorKind: BinaryOperatorKind.IntLessThan, left: boundPositionVar, right: stringLength, constantValueOpt: null, methodOpt: null, resultKind: LookupResultKind.Viable, type: boolType); // p = p + 1; BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar, intType); LocalSymbol iterationVar = node.IterationVariable; TypeSymbol iterationVarType = iterationVar.Type; Debug.Assert(node.ElementConversion.IsValid); // (V)s.Chars[p] MethodSymbol chars = GetSpecialTypeMethod(forEachSyntax, SpecialMember.System_String__Chars); BoundExpression iterationVarInitValue = MakeConversion( syntax: forEachSyntax, rewrittenOperand: BoundCall.Synthesized( syntax: forEachSyntax, receiverOpt: boundStringVar, method: chars, arguments: ImmutableArray.Create <BoundExpression>(boundPositionVar)), conversion: node.ElementConversion, rewrittenType: iterationVarType, @checked: node.Checked); // V v = (V)s.Chars[p]; BoundStatement iterationVarDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue); AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVarDecl); // { V v = (V)s.Chars[p]; /*node.Body*/ } BoundStatement loopBody = new BoundBlock(forEachSyntax, locals: ImmutableArray.Create <LocalSymbol>(iterationVar), statements: ImmutableArray.Create <BoundStatement>(iterationVarDecl, rewrittenBody)); // for (string s = /*node.Expression*/, int p = 0; p < s.Length; p = p + 1) { // V v = (V)s.Chars[p]; // /*node.Body*/ // } BoundStatement result = RewriteForStatement( syntax: forEachSyntax, outerLocals: ImmutableArray.Create(stringVar, positionVar), rewrittenInitializer: initializer, rewrittenCondition: exitCondition, conditionSyntaxOpt: null, conditionSpanOpt: forEachSyntax.InKeyword.Span, rewrittenIncrement: positionIncrement, rewrittenBody: loopBody, breakLabel: node.BreakLabel, continueLabel: node.ContinueLabel, hasErrors: node.HasErrors); AddForEachKeywordSequencePoint(forEachSyntax, ref result); return(result); }
/// <summary> /// This method finds an attribute by metadata name and signature. The algorithm for signature matching is similar to the one /// in Module.GetTargetAttributeSignatureIndex. Note, the signature matching is limited to primitive types /// and System.Type. It will not match an arbitrary signature but it is sufficient to match the signatures of the current set of /// well known attributes. /// </summary> /// <param name="targetSymbol">The symbol which is the target of the attribute</param> /// <param name="description">The attribute to match.</param> internal override int GetTargetAttributeSignatureIndex(Symbol targetSymbol, AttributeDescription description) { if (!IsTargetAttribute(description.Namespace, description.Name)) { return(-1); } var ctor = this.AttributeConstructor; // Ensure that the attribute data really has a constructor before comparing the signature. if ((object)ctor == null) { return(-1); } // Lazily loaded System.Type type symbol TypeSymbol lazySystemType = null; ImmutableArray <ParameterSymbol> parameters = ctor.Parameters; bool foundMatch = false; for (int i = 0; i < description.Signatures.Length; i++) { byte[] targetSignature = description.Signatures[i]; if (targetSignature[0] != (byte)SignatureAttributes.Instance) { continue; } byte parameterCount = targetSignature[1]; if (parameterCount != parameters.Length) { continue; } if ((SignatureTypeCode)targetSignature[2] != SignatureTypeCode.Void) { continue; } foundMatch = (targetSignature.Length == 3); int k = 0; for (int j = 3; j < targetSignature.Length; j++) { if (k >= parameters.Length) { break; } TypeSymbol parameterType = parameters[k].Type; SpecialType specType = parameterType.SpecialType; byte targetType = targetSignature[j]; if (targetType == (byte)SignatureTypeCode.TypeHandle) { j++; if (parameterType.Kind != SymbolKind.NamedType && parameterType.Kind != SymbolKind.ErrorType) { foundMatch = false; break; } var namedType = (NamedTypeSymbol)parameterType; AttributeDescription.TypeHandleTargetInfo targetInfo = AttributeDescription.TypeHandleTargets[targetSignature[j]]; // Compare name and containing symbol name. Uses HasNameQualifier // extension method to avoid string allocations. if (!string.Equals(namedType.MetadataName, targetInfo.Name, System.StringComparison.Ordinal) || !namedType.HasNameQualifier(targetInfo.Namespace)) { foundMatch = false; break; } targetType = (byte)targetInfo.Underlying; if (parameterType.IsEnumType()) { specType = parameterType.GetEnumUnderlyingType().SpecialType; } } else if (parameterType.IsArray()) { specType = ((ArrayTypeSymbol)parameterType).ElementType.SpecialType; } switch (targetType) { case (byte)SignatureTypeCode.Boolean: foundMatch = specType == SpecialType.System_Boolean; k += 1; break; case (byte)SignatureTypeCode.Char: foundMatch = specType == SpecialType.System_Char; k += 1; break; case (byte)SignatureTypeCode.SByte: foundMatch = specType == SpecialType.System_SByte; k += 1; break; case (byte)SignatureTypeCode.Byte: foundMatch = specType == SpecialType.System_Byte; k += 1; break; case (byte)SignatureTypeCode.Int16: foundMatch = specType == SpecialType.System_Int16; k += 1; break; case (byte)SignatureTypeCode.UInt16: foundMatch = specType == SpecialType.System_UInt16; k += 1; break; case (byte)SignatureTypeCode.Int32: foundMatch = specType == SpecialType.System_Int32; k += 1; break; case (byte)SignatureTypeCode.UInt32: foundMatch = specType == SpecialType.System_UInt32; k += 1; break; case (byte)SignatureTypeCode.Int64: foundMatch = specType == SpecialType.System_Int64; k += 1; break; case (byte)SignatureTypeCode.UInt64: foundMatch = specType == SpecialType.System_UInt64; k += 1; break; case (byte)SignatureTypeCode.Single: foundMatch = specType == SpecialType.System_Single; k += 1; break; case (byte)SignatureTypeCode.Double: foundMatch = specType == SpecialType.System_Double; k += 1; break; case (byte)SignatureTypeCode.String: foundMatch = specType == SpecialType.System_String; k += 1; break; case (byte)SignatureTypeCode.Object: foundMatch = specType == SpecialType.System_Object; k += 1; break; case (byte)SerializationTypeCode.Type: if ((object)lazySystemType == null) { lazySystemType = GetSystemType(targetSymbol); } foundMatch = TypeSymbol.Equals(parameterType, lazySystemType, TypeCompareKind.ConsiderEverything2); k += 1; break; case (byte)SignatureTypeCode.SZArray: // Skip over and check the next byte foundMatch = parameterType.IsArray(); break; default: return(-1); } if (!foundMatch) { break; } } if (foundMatch) { return(i); } } Debug.Assert(!foundMatch); return(-1); }
private LiteralExpressionNode(Token literal, object value, TypeSymbol type) { Literal = literal ?? throw new ArgumentNullException(nameof(literal)); Value = value ?? throw new ArgumentNullException(nameof(value)); Type = type ?? throw new ArgumentNullException(nameof(type)); }
public virtual void VisitTypeSymbol(TypeSymbol symbol) { VisitDescendants(symbol); }
private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpressionSyntax node, DiagnosticBag diagnostics) { // prepare var initializers = node.Initializers; int fieldCount = initializers.Count; bool hasError = false; // bind field initializers BoundExpression[] boundExpressions = new BoundExpression[fieldCount]; AnonymousTypeField[] fields = new AnonymousTypeField[fieldCount]; CSharpSyntaxNode[] fieldSyntaxNodes = new CSharpSyntaxNode[fieldCount]; // WARNING: Note that SemanticModel.GetDeclaredSymbol for field initializer node relies on // the fact that the order of properties in anonymous type template corresponds // 1-to-1 to the appropriate filed initializer syntax nodes; This means such // correspondence must be preserved all the time including erroneos scenarios // set of names already used HashSet <string> uniqueFieldNames = new HashSet <string>(); for (int i = 0; i < fieldCount; i++) { AnonymousObjectMemberDeclaratorSyntax fieldInitializer = initializers[i]; NameEqualsSyntax nameEquals = fieldInitializer.NameEquals; ExpressionSyntax expression = fieldInitializer.Expression; SyntaxToken nameToken = default(SyntaxToken); if (nameEquals != null) { nameToken = nameEquals.Name.Identifier; } else { nameToken = expression.ExtractAnonymousTypeMemberName(); } hasError = hasError || expression.HasErrors; boundExpressions[i] = this.BindValue(expression, diagnostics, BindValueKind.RValue); // check the name to be unique string fieldName = null; if (nameToken.Kind() == SyntaxKind.IdentifierToken) { fieldName = nameToken.ValueText; if (uniqueFieldNames.Contains(fieldName)) { // name duplication Error(diagnostics, ErrorCode.ERR_AnonymousTypeDuplicatePropertyName, fieldInitializer); hasError = true; fieldName = null; } else { uniqueFieldNames.Add(fieldName); } } else { // there is something wrong with field's name hasError = true; } // calculate the expression's type and report errors if needed TypeSymbol fieldType = GetAnonymousTypeFieldType(boundExpressions[i], fieldInitializer, diagnostics, ref hasError); // build anonymous type field descriptor fieldSyntaxNodes[i] = (nameToken.Kind() == SyntaxKind.IdentifierToken) ? (CSharpSyntaxNode)nameToken.Parent : fieldInitializer; fields[i] = new AnonymousTypeField(fieldName == null ? '$' + i.ToString() : fieldName, fieldSyntaxNodes[i].Location, fieldType); // NOTE: ERR_InvalidAnonymousTypeMemberDeclarator (CS0746) would be generated by parser if needed } // Create anonymous type AnonymousTypeManager manager = this.Compilation.AnonymousTypeManager; AnonymousTypeDescriptor descriptor = new AnonymousTypeDescriptor(fields.AsImmutableOrNull(), node.NewKeyword.GetLocation()); NamedTypeSymbol anonymousType = manager.ConstructAnonymousTypeSymbol(descriptor); // declarators - bound nodes created for providing semantic info // on anonymous type fields having explicitly specified name ArrayBuilder <BoundAnonymousPropertyDeclaration> declarators = ArrayBuilder <BoundAnonymousPropertyDeclaration> .GetInstance(); for (int i = 0; i < fieldCount; i++) { NameEqualsSyntax explicitName = initializers[i].NameEquals; if (explicitName != null) { AnonymousTypeField field = fields[i]; if (field.Name != null) { // get property symbol and create a bound property declaration node foreach (var symbol in anonymousType.GetMembers(field.Name)) { if (symbol.Kind == SymbolKind.Property) { declarators.Add(new BoundAnonymousPropertyDeclaration(fieldSyntaxNodes[i], (PropertySymbol)symbol, field.Type)); break; } } } } } // check if anonymous object creation is allowed in this context if (!this.IsAnonymousTypesAllowed()) { Error(diagnostics, ErrorCode.ERR_AnonymousTypeNotAvailable, node.NewKeyword); hasError = true; } // Finally create a bound node return(new BoundAnonymousObjectCreationExpression( node, anonymousType.InstanceConstructors[0], boundExpressions.AsImmutableOrNull(), declarators.ToImmutableAndFree(), anonymousType, hasError)); }
private BoundExpression MakeConversionLambda(Conversion conversion, TypeSymbol fromType, TypeSymbol toType) { string parameterName = "p"; ParameterSymbol lambdaParameter = _bound.SynthesizedParameter(fromType, parameterName); var param = _bound.SynthesizedLocal(ParameterExpressionType); var parameterReference = _bound.Local(param); var parameter = ExprFactory("Parameter", _bound.Typeof(fromType), _bound.Literal(parameterName)); _parameterMap[lambdaParameter] = parameterReference; var convertedValue = Visit(_bound.Convert(toType, _bound.Parameter(lambdaParameter), conversion)); _parameterMap.Remove(lambdaParameter); var result = _bound.Sequence( ImmutableArray.Create(param), ImmutableArray.Create <BoundExpression>(_bound.AssignmentExpression(parameterReference, parameter)), ExprFactory( "Lambda", convertedValue, _bound.ArrayOrEmpty(ParameterExpressionType, ImmutableArray.Create <BoundExpression>(parameterReference)))); return(result); }
private static Symbol FindExplicitlyImplementedMember( Symbol implementingMember, TypeSymbol explicitInterfaceType, string interfaceMemberName, ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifierSyntax, DiagnosticBag diagnostics) { if ((object)explicitInterfaceType == null) { return(null); } var memberLocation = implementingMember.Locations[0]; var containingType = implementingMember.ContainingType; switch (containingType.TypeKind) { case TypeKind.Class: case TypeKind.Struct: case TypeKind.Interface: break; default: diagnostics.Add(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, memberLocation, implementingMember); return(null); } if (!explicitInterfaceType.IsInterfaceType()) { //we'd like to highlight just the type part of the name var explicitInterfaceSyntax = explicitInterfaceSpecifierSyntax.Name; var location = new SourceLocation(explicitInterfaceSyntax); diagnostics.Add(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, location, explicitInterfaceType); return(null); } var explicitInterfaceNamedType = (NamedTypeSymbol)explicitInterfaceType; // 13.4.1: "For an explicit interface member implementation to be valid, the class or struct must name an // interface in its base class list that contains a member ..." MultiDictionary <NamedTypeSymbol, NamedTypeSymbol> .ValueSet set = containingType.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics[explicitInterfaceNamedType]; int setCount = set.Count; if (setCount == 0 || !set.Contains(explicitInterfaceNamedType, Symbols.SymbolEqualityComparer.ObliviousNullableModifierMatchesAny)) { //we'd like to highlight just the type part of the name var explicitInterfaceSyntax = explicitInterfaceSpecifierSyntax.Name; var location = new SourceLocation(explicitInterfaceSyntax); if (setCount > 0 && set.Contains(explicitInterfaceNamedType, Symbols.SymbolEqualityComparer.IgnoringNullable)) { diagnostics.Add(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, location); } else { diagnostics.Add(ErrorCode.ERR_ClassDoesntImplementInterface, location, implementingMember, explicitInterfaceNamedType); } //do a lookup anyway } // Do not look in itself if (containingType == (object)explicitInterfaceNamedType.OriginalDefinition) { // An error will be reported elsewhere. // Either the interface is not implemented, or it causes a cycle in the interface hierarchy. return(null); } var hasParamsParam = implementingMember.HasParamsParameter(); // Setting this flag to true does not imply that an interface member has been successfully implemented. // It just indicates that a corresponding interface member has been found (there may still be errors). var foundMatchingMember = false; Symbol implementedMember = null; foreach (Symbol interfaceMember in explicitInterfaceNamedType.GetMembers(interfaceMemberName)) { // At this point, we know that explicitInterfaceNamedType is an interface. // However, metadata interface members can be static - we ignore them, as does Dev10. if (interfaceMember.Kind != implementingMember.Kind || !interfaceMember.IsImplementableInterfaceMember()) { continue; } if (MemberSignatureComparer.ExplicitImplementationComparer.Equals(implementingMember, interfaceMember)) { foundMatchingMember = true; // Cannot implement accessor directly unless // the accessor is from an indexed property. if (interfaceMember.IsAccessor() && !((MethodSymbol)interfaceMember).IsIndexedPropertyAccessor()) { diagnostics.Add(ErrorCode.ERR_ExplicitMethodImplAccessor, memberLocation, implementingMember, interfaceMember); } else { if (interfaceMember.MustCallMethodsDirectly()) { diagnostics.Add(ErrorCode.ERR_BogusExplicitImpl, memberLocation, implementingMember, interfaceMember); } else if (hasParamsParam && !interfaceMember.HasParamsParameter()) { // Note: no error for !hasParamsParam && interfaceMethod.HasParamsParameter() // Still counts as an implementation. diagnostics.Add(ErrorCode.ERR_ExplicitImplParams, memberLocation, implementingMember, interfaceMember); } implementedMember = interfaceMember; break; } } } if (!foundMatchingMember) { // CONSIDER: we may wish to suppress this error in the event that another error // has been reported about the signature. diagnostics.Add(ErrorCode.ERR_InterfaceMemberNotFound, memberLocation, implementingMember); } // Make sure implemented member is accessible if ((object)implementedMember != null) { HashSet <DiagnosticInfo> useSiteDiagnostics = null; if (!AccessCheck.IsSymbolAccessible(implementedMember, implementingMember.ContainingType, ref useSiteDiagnostics, throughTypeOpt: null)) { diagnostics.Add(ErrorCode.ERR_BadAccess, memberLocation, implementedMember); } else { switch (implementedMember.Kind) { case SymbolKind.Property: var propertySymbol = (PropertySymbol)implementedMember; checkAccessorIsAccessibleIfImplementable(propertySymbol.GetMethod); checkAccessorIsAccessibleIfImplementable(propertySymbol.SetMethod); break; case SymbolKind.Event: var eventSymbol = (EventSymbol)implementedMember; checkAccessorIsAccessibleIfImplementable(eventSymbol.AddMethod); checkAccessorIsAccessibleIfImplementable(eventSymbol.RemoveMethod); break; } void checkAccessorIsAccessibleIfImplementable(MethodSymbol accessor) { if (accessor.IsImplementable() && !AccessCheck.IsSymbolAccessible(accessor, implementingMember.ContainingType, ref useSiteDiagnostics, throughTypeOpt: null)) { diagnostics.Add(ErrorCode.ERR_BadAccess, memberLocation, accessor); } } } diagnostics.Add(memberLocation, useSiteDiagnostics); } return(implementedMember); }
private BoundExpression Convert(BoundExpression expr, TypeSymbol type, bool isChecked) { return(ExprFactory(isChecked ? "ConvertChecked" : "Convert", expr, _bound.Typeof(type))); }
internal override bool GetUnificationUseSiteDiagnostic(ref DiagnosticInfo result, TypeSymbol dependentType) { throw ExceptionUtilities.Unreachable; }
private BoundExpression ConvertIndex(BoundExpression expr, TypeSymbol oldType, TypeSymbol newType) { HashSet <DiagnosticInfo> useSiteDiagnostics = null; var kind = _bound.Compilation.Conversions.ClassifyConversionFromType(oldType, newType, ref useSiteDiagnostics).Kind; Debug.Assert(useSiteDiagnostics.IsNullOrEmpty()); switch (kind) { case ConversionKind.Identity: return(expr); case ConversionKind.ExplicitNumeric: return(Convert(expr, newType, true)); default: return(Convert(expr, _int32Type, false)); } }
private BoundExpression DelegateCreation(BoundExpression receiver, MethodSymbol method, TypeSymbol delegateType, bool staticMember) { var nullObject = _bound.Null(_objectType); receiver = staticMember ? nullObject : receiver.Type.IsReferenceType ? receiver : _bound.Convert(_objectType, receiver); var createDelegate = _bound.WellKnownMethod(WellKnownMember.System_Reflection_MethodInfo__CreateDelegate, isOptional: true); BoundExpression unquoted; if ((object)createDelegate != null) { // beginning in 4.5, we do it this way unquoted = _bound.Call(_bound.MethodInfo(method), createDelegate, _bound.Typeof(delegateType), receiver); } else { // 4.0 and earlier we do it this way //createDelegate = (MethodSymbol)Bound.WellKnownMember(WellKnownMember.System_Delegate__CreateDelegate); //operand = Bound.Call(nullObject, createDelegate, Bound.Typeof(node.Type), receiver, Bound.MethodInfo(method)); unquoted = _bound.StaticCall(_bound.SpecialType(SpecialType.System_Delegate), "CreateDelegate", _bound.Typeof(delegateType), receiver, _bound.MethodInfo(method)); } // NOTE: we visit the just-built node, which has not yet been visited. This is not the usual order // of operations. The above code represents Dev10's pre-expression-tree lowering, and producing // the expanded lowering by hand is very cumbersome. return(Convert(Visit(unquoted), delegateType, false)); }
private BoundExpression VisitBinaryOperator(BinaryOperatorKind opKind, MethodSymbol methodOpt, TypeSymbol type, BoundExpression left, BoundExpression right) { bool isChecked, isLifted, requiresLifted; string opName = GetBinaryOperatorName(opKind, out isChecked, out isLifted, out requiresLifted); // Fix up the null value for a nullable comparison vs null if ((object)left.Type == null && left.IsLiteralNull()) { left = _bound.Default(right.Type); } if ((object)right.Type == null && right.IsLiteralNull()) { right = _bound.Default(left.Type); } // Enums are handled as per their promoted underlying type switch (opKind.OperandTypes()) { case BinaryOperatorKind.EnumAndUnderlying: case BinaryOperatorKind.UnderlyingAndEnum: case BinaryOperatorKind.Enum: { var enumOperand = (opKind.OperandTypes() == BinaryOperatorKind.UnderlyingAndEnum) ? right : left; var promotedType = PromotedType(enumOperand.Type.StrippedType().GetEnumUnderlyingType()); if (opKind.IsLifted()) { promotedType = _nullableType.Construct(promotedType); } var loweredLeft = VisitAndPromoteEnumOperand(left, promotedType, isChecked); var loweredRight = VisitAndPromoteEnumOperand(right, promotedType, isChecked); var result = MakeBinary(methodOpt, type, isLifted, requiresLifted, opName, loweredLeft, loweredRight); return(Demote(result, type, isChecked)); } default: { var loweredLeft = Visit(left); var loweredRight = Visit(right); return(MakeBinary(methodOpt, type, isLifted, requiresLifted, opName, loweredLeft, loweredRight)); } } }
private BoundExpression Convert(BoundExpression operand, TypeSymbol oldType, TypeSymbol newType, bool isChecked, bool isExplicit) { return((oldType == newType && !isExplicit) ? operand : Convert(operand, newType, isChecked)); }