public TypeSymbol InferredReturnType(ref HashSet<DiagnosticInfo> useSiteDiagnostics) { if (inferredReturnType == null) { HashSet<DiagnosticInfo> inferenceUseSiteDiagnostics = null; bool inferredFromSingleType; var inferredType = InferReturnType(ref inferenceUseSiteDiagnostics, out inferredFromSingleType); Debug.Assert(this.inferredFromSingleType == ThreeState.Unknown || this.inferredFromSingleType == inferredFromSingleType.ToThreeState(), "inferredFromSingleType cannot change"); this.inferredFromSingleType = inferredFromSingleType.ToThreeState(); Debug.Assert(inferredFromSingleType == false || inferenceUseSiteDiagnostics == null); // inferredReturnTypeUseSiteDiagnostics does not need to be unique, so we can just assign it. this.inferredReturnTypeUseSiteDiagnostics = inferenceUseSiteDiagnostics; // inferredReturnType must be observably unique, only one assignment must succeed Interlocked.CompareExchange(ref this.inferredReturnType, inferredType, null); } if (!this.inferredReturnTypeUseSiteDiagnostics.IsNullOrEmpty()) { if (useSiteDiagnostics == null) { useSiteDiagnostics = new HashSet<DiagnosticInfo>(); } foreach (var info in this.inferredReturnTypeUseSiteDiagnostics) { useSiteDiagnostics.Add(info); } } return this.inferredReturnType; }
protected bool IsEqual(ThreeState x, ThreeState y) { if (x == ThreeState.Unknown || y == ThreeState.Unknown) return false; //quick check return (x == y); }
public void Clear() { this.Arguments.Clear(); this.Names.Clear(); this.RefKinds.Clear(); this.IsExtensionMethodInvocation = false; this.lazyHasDynamicArgument = ThreeState.Unknown; }
protected string ThreeStateToString(ThreeState ts, string value) { switch (ts) { case ThreeState.False: return "false"; case ThreeState.True: return "true"; } return value; }
internal SourceNamedTypeSymbol(NamespaceOrTypeSymbol containingSymbol, MergedTypeDeclaration declaration, DiagnosticBag diagnostics) : base(containingSymbol, declaration, diagnostics) { Debug.Assert(declaration.Kind == DeclarationKind.Struct || declaration.Kind == DeclarationKind.Interface || declaration.Kind == DeclarationKind.Enum || declaration.Kind == DeclarationKind.Delegate || declaration.Kind == DeclarationKind.Class); if (containingSymbol.Kind == SymbolKind.NamedType) { // Nested types are never unified. _lazyIsExplicitDefinitionOfNoPiaLocalType = ThreeState.False; } }
internal SourceComplexParameterSymbol( Symbol owner, int ordinal, TypeSymbol parameterType, RefKind refKind, ImmutableArray<CustomModifier> customModifiers, bool hasByRefBeforeCustomModifiers, string name, ImmutableArray<Location> locations, SyntaxReference syntaxRef, ConstantValue defaultSyntaxValue, bool isParams, bool isExtensionMethodThis) : base(owner, parameterType, ordinal, refKind, name, locations) { Debug.Assert((syntaxRef == null) || (syntaxRef.GetSyntax().IsKind(SyntaxKind.Parameter))); Debug.Assert(!customModifiers.IsDefault); _lazyHasOptionalAttribute = ThreeState.Unknown; _syntaxRef = syntaxRef; if (isParams) { _parameterSyntaxKind |= ParameterSyntaxKind.ParamsParameter; } if (isExtensionMethodThis) { _parameterSyntaxKind |= ParameterSyntaxKind.ExtensionThisParameter; } var parameterSyntax = this.CSharpSyntaxNode; if (parameterSyntax != null && parameterSyntax.Default != null) { _parameterSyntaxKind |= ParameterSyntaxKind.DefaultParameter; } _lazyDefaultSyntaxValue = defaultSyntaxValue; _customModifiers = customModifiers; _hasByRefBeforeCustomModifiers = hasByRefBeforeCustomModifiers; }
private void EnsureClassAndConstructorSymbolsAreLoaded() { #pragma warning disable 0252 if ((object)_lazyAttributeClass == ErrorTypeSymbol.UnknownResultType) { TypeSymbol attributeClass; MethodSymbol attributeConstructor; if (!_decoder.GetCustomAttribute(_handle, out attributeClass, out attributeConstructor)) { // TODO: should we create CSErrorTypeSymbol for attribute class?? _lazyHasErrors = ThreeState.True; } else if ((object)attributeClass == null || attributeClass.IsErrorType() || (object)attributeConstructor == null) { _lazyHasErrors = ThreeState.True; } Interlocked.CompareExchange(ref _lazyAttributeConstructor, attributeConstructor, null); Interlocked.CompareExchange(ref _lazyAttributeClass, (NamedTypeSymbol)attributeClass, ErrorTypeSymbol.UnknownResultType); // Serves as a flag, so do it last. } #pragma warning restore 0252 }
private void InsertMissingOptionalArguments(SyntaxNode syntax, ImmutableArray<ParameterSymbol> parameters, BoundExpression[] arguments, ThreeState enableCallerInfo = ThreeState.Unknown) { for (int p = 0; p < arguments.Length; ++p) { if (arguments[p] == null) { ParameterSymbol parameter = parameters[p]; Debug.Assert(parameter.IsOptional); arguments[p] = GetDefaultParameterValue(syntax, parameter, enableCallerInfo); Debug.Assert(arguments[p].Type == parameter.Type); } } }
/// <summary> /// Rewrites arguments of an invocation according to the receiving method or indexer. /// It is assumed that each argument has already been lowered, but we may need /// additional rewriting for the arguments, such as generating a params array, re-ordering /// arguments based on <paramref name="argsToParamsOpt"/> map, inserting arguments for optional parameters, etc. /// <paramref name="optionalParametersMethod"/> is the method used for values of any optional parameters. /// For indexers, this method must be an accessor, and for methods it must be the method /// itself. <paramref name="optionalParametersMethod"/> is needed for indexers since getter and setter /// may have distinct optional parameter values. /// </summary> private ImmutableArray<BoundExpression> MakeArguments( SyntaxNode syntax, ImmutableArray<BoundExpression> rewrittenArguments, Symbol methodOrIndexer, MethodSymbol optionalParametersMethod, bool expanded, ImmutableArray<int> argsToParamsOpt, ref ImmutableArray<RefKind> argumentRefKindsOpt, out ImmutableArray<LocalSymbol> temps, bool invokedAsExtensionMethod = false, ThreeState enableCallerInfo = ThreeState.Unknown) { // Either the methodOrIndexer is a property, in which case the method used // for optional parameters is an accessor of that property (or an overridden // property), or the methodOrIndexer is used for optional parameters directly. Debug.Assert(((methodOrIndexer.Kind == SymbolKind.Property) && optionalParametersMethod.IsAccessor()) || ReferenceEquals(methodOrIndexer, optionalParametersMethod)); // We need to do a fancy rewrite under the following circumstances: // (1) a params array is being used; we need to generate the array. // (2) there were named arguments that reordered the arguments; we might // have to generate temporaries to ensure that the arguments are // evaluated in source code order, not the actual call order. // (3) there were optional parameters that had no corresponding arguments. // // If none of those are the case then we can just take an early out. // An applicable "vararg" method could not possibly be applicable in its expanded // form, and cannot possibly have named arguments or used optional parameters, // because the __arglist() argument has to be positional and in the last position. if (methodOrIndexer.GetIsVararg()) { Debug.Assert(rewrittenArguments.Length == methodOrIndexer.GetParameterCount() + 1); Debug.Assert(argsToParamsOpt.IsDefault); Debug.Assert(!expanded); temps = default(ImmutableArray<LocalSymbol>); return rewrittenArguments; } var receiverNamedType = invokedAsExtensionMethod ? ((MethodSymbol)methodOrIndexer).Parameters[0].Type as NamedTypeSymbol : methodOrIndexer.ContainingType; bool isComReceiver = (object)receiverNamedType != null && receiverNamedType.IsComImport; if (rewrittenArguments.Length == methodOrIndexer.GetParameterCount() && argsToParamsOpt.IsDefault && !expanded && !isComReceiver) { temps = default(ImmutableArray<LocalSymbol>); return rewrittenArguments; } // We have: // * a list of arguments, already converted to their proper types, // in source code order. Some optional arguments might be missing. // * a map showing which parameter each argument corresponds to. If // this is null, then the argument to parameter mapping is one-to-one. // * the ref kind of each argument, in source code order. That is, whether // the argument was marked as ref, out, or value (neither). // * a method symbol. // * whether the call is expanded or normal form. // We rewrite the call so that: // * if in its expanded form, we create the params array. // * if the call requires reordering of arguments because of named arguments, temporaries are generated as needed // Doing this transformation can move around refness in interesting ways. For example, consider // // A().M(y : ref B()[C()], x : out D()); // // This will be created as a call with receiver A(), symbol M, argument list ( B()[C()], D() ), // name list ( y, x ) and ref list ( ref, out ). We can rewrite this into temporaries: // // A().M( // seq ( ref int temp_y = ref B()[C()], out D() ), // temp_y ); // // Now we have a call with receiver A(), symbol M, argument list as shown, no name list, // and ref list ( out, value ). We do not want to pass a *ref* to temp_y; the temporary // storage is not the thing being ref'd! We want to pass the *value* of temp_y, which // *contains* a reference. // We attempt to minimize the number of temporaries required. Arguments which neither // produce nor observe a side effect can be placed into their proper position without // recourse to a temporary. For example: // // Where(predicate: x=>x.Length!=0, sequence: S()) // // can be rewritten without any temporaries because the conversion from lambda to // delegate does not produce any side effect that could be observed by S(). // // By contrast: // // Foo(z: this.p, y: this.Q(), x: (object)10) // // The boxing of 10 can be reordered, but the fetch of this.p has to happen before the // call to this.Q() because the call could change the value of this.p. // // We start by binding everything that is not obviously reorderable as a temporary, and // then run an optimizer to remove unnecessary temporaries. ImmutableArray<ParameterSymbol> parameters = methodOrIndexer.GetParameters(); BoundExpression[] actualArguments = new BoundExpression[parameters.Length]; // The actual arguments that will be passed; one actual argument per formal parameter. ArrayBuilder<BoundAssignmentOperator> storesToTemps = ArrayBuilder<BoundAssignmentOperator>.GetInstance(rewrittenArguments.Length); ArrayBuilder<RefKind> refKinds = ArrayBuilder<RefKind>.GetInstance(parameters.Length, RefKind.None); // Step one: Store everything that is non-trivial into a temporary; record the // stores in storesToTemps and make the actual argument a reference to the temp. // Do not yet attempt to deal with params arrays or optional arguments. BuildStoresToTemps(expanded, argsToParamsOpt, argumentRefKindsOpt, rewrittenArguments, actualArguments, refKinds, storesToTemps); // all the formal arguments, except missing optionals, are now in place. // Optimize away unnecessary temporaries. // Necessary temporaries have their store instructions merged into the appropriate // argument expression. ArrayBuilder<LocalSymbol> temporariesBuilder = ArrayBuilder<LocalSymbol>.GetInstance(); OptimizeTemporaries(actualArguments, refKinds, storesToTemps, temporariesBuilder); // Step two: If we have a params array, build the array and fill in the argument. if (expanded) { actualArguments[actualArguments.Length - 1] = BuildParamsArray(syntax, methodOrIndexer, argsToParamsOpt, rewrittenArguments, parameters, actualArguments[actualArguments.Length - 1]); } // Step three: Now fill in the optional arguments. InsertMissingOptionalArguments(syntax, optionalParametersMethod.Parameters, actualArguments, enableCallerInfo); if (isComReceiver) { RewriteArgumentsForComCall(parameters, actualArguments, refKinds, temporariesBuilder); } temps = temporariesBuilder.ToImmutableAndFree(); storesToTemps.Free(); // * The refkind map is now filled out to match the arguments. // * The list of parameter names is now null because the arguments have been reordered. // * The args-to-params map is now null because every argument exactly matches its parameter. // * The call is no longer in its expanded form. argumentRefKindsOpt = GetRefKindsOrNull(refKinds); refKinds.Free(); return actualArguments.AsImmutableOrNull(); }
private void EnsureAttributeArgumentsAreLoaded() { if (_lazyConstructorArguments.IsDefault || _lazyNamedArguments.IsDefault) { TypedConstant[] lazyConstructorArguments = null; KeyValuePair<string, TypedConstant>[] lazyNamedArguments = null; if (!_decoder.GetCustomAttribute(_handle, out lazyConstructorArguments, out lazyNamedArguments)) { _lazyHasErrors = ThreeState.True; } Debug.Assert(lazyConstructorArguments != null && lazyNamedArguments != null); ImmutableInterlocked.InterlockedInitialize(ref _lazyConstructorArguments, ImmutableArray.Create<TypedConstant>(lazyConstructorArguments)); ImmutableInterlocked.InterlockedInitialize(ref _lazyNamedArguments, ImmutableArray.Create<KeyValuePair<string, TypedConstant>>(lazyNamedArguments)); } }
public static bool Value(this ThreeState value) { Debug.Assert(value != ThreeState.Unknown); return(value == ThreeState.True); }
internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments) { Debug.Assert((object)arguments.AttributeSyntaxOpt != null); var attribute = arguments.Attribute; Debug.Assert(!attribute.HasErrors); Debug.Assert(arguments.SymbolPart == AttributeLocation.None); if (attribute.IsTargetAttribute(this, AttributeDescription.AttributeUsageAttribute)) { DecodeAttributeUsageAttribute(attribute, arguments.AttributeSyntaxOpt, diagnose: true, diagnosticsOpt: arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.DefaultMemberAttribute)) { arguments.GetOrCreateData<TypeWellKnownAttributeData>().HasDefaultMemberAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.CoClassAttribute)) { DecodeCoClassAttribute(ref arguments); } else if (attribute.IsTargetAttribute(this, AttributeDescription.ConditionalAttribute)) { ValidateConditionalAttribute(attribute, arguments.AttributeSyntaxOpt, arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.GuidAttribute)) { arguments.GetOrCreateData<TypeWellKnownAttributeData>().GuidString = attribute.DecodeGuidAttribute(arguments.AttributeSyntaxOpt, arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.SpecialNameAttribute)) { arguments.GetOrCreateData<TypeWellKnownAttributeData>().HasSpecialNameAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.SerializableAttribute)) { arguments.GetOrCreateData<TypeWellKnownAttributeData>().HasSerializableAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.StructLayoutAttribute)) { AttributeData.DecodeStructLayoutAttribute<TypeWellKnownAttributeData, AttributeSyntax, CSharpAttributeData, AttributeLocation>( ref arguments, this.DefaultMarshallingCharSet, defaultAutoLayoutSize: 0, messageProvider: MessageProvider.Instance); } else if (attribute.IsTargetAttribute(this, AttributeDescription.SuppressUnmanagedCodeSecurityAttribute)) { arguments.GetOrCreateData<TypeWellKnownAttributeData>().HasSuppressUnmanagedCodeSecurityAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.ClassInterfaceAttribute)) { attribute.DecodeClassInterfaceAttribute(arguments.AttributeSyntaxOpt, arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.InterfaceTypeAttribute)) { attribute.DecodeInterfaceTypeAttribute(arguments.AttributeSyntaxOpt, arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.WindowsRuntimeImportAttribute)) { arguments.GetOrCreateData<TypeWellKnownAttributeData>().HasWindowsRuntimeImportAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.RequiredAttributeAttribute)) { // CS1608: The Required attribute is not permitted on C# types arguments.Diagnostics.Add(ErrorCode.ERR_CantUseRequiredAttribute, arguments.AttributeSyntaxOpt.Name.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.CaseSensitiveExtensionAttribute)) { // ExtensionAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitExtension, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute)) { // DynamicAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.SecurityCriticalAttribute) || attribute.IsTargetAttribute(this, AttributeDescription.SecuritySafeCriticalAttribute)) { arguments.GetOrCreateData<TypeWellKnownAttributeData>().HasSecurityCriticalAttributes = true; } else if (_lazyIsExplicitDefinitionOfNoPiaLocalType == ThreeState.Unknown && attribute.IsTargetAttribute(this, AttributeDescription.TypeIdentifierAttribute)) { _lazyIsExplicitDefinitionOfNoPiaLocalType = ThreeState.True; } else { var compilation = this.DeclaringCompilation; if (attribute.IsSecurityAttribute(compilation)) { attribute.DecodeSecurityAttribute<TypeWellKnownAttributeData>(this, compilation, ref arguments); } } }
private PEParameterSymbol( PEModuleSymbol moduleSymbol, Symbol containingSymbol, int ordinal, bool isByRef, bool hasByRefBeforeCustomModifiers, TypeSymbol type, ParameterHandle handle, ImmutableArray<MetadataDecoder.ModifierInfo> customModifiers, out bool isBad) { Debug.Assert((object)moduleSymbol != null); Debug.Assert((object)containingSymbol != null); Debug.Assert(ordinal >= 0); Debug.Assert((object)type != null); isBad = false; this.moduleSymbol = moduleSymbol; this.containingSymbol = containingSymbol; this.customModifiers = CSharpCustomModifier.Convert(customModifiers); this.ordinal = (ushort)ordinal; this.handle = handle; RefKind refKind = RefKind.None; if (handle.IsNil) { refKind = isByRef ? RefKind.Ref : RefKind.None; this.type = type; this.lazyCustomAttributes = ImmutableArray<CSharpAttributeData>.Empty; this.lazyHiddenAttributes = ImmutableArray<CSharpAttributeData>.Empty; this.lazyWellKnownAttributeData = (int)WellKnownAttributeFlags.AllCompletedNoAttributes; this.lazyDefaultValue = ConstantValue.NotAvailable; this.lazyIsParams = ThreeState.False; } else { try { moduleSymbol.Module.GetParamPropsOrThrow(handle, out this.name, out this.flags); } catch (BadImageFormatException) { isBad = true; } if (isByRef) { ParameterAttributes inOutFlags = this.flags & (ParameterAttributes.Out | ParameterAttributes.In); refKind = (inOutFlags == ParameterAttributes.Out) ? RefKind.Out : RefKind.Ref; } // CONSIDER: Can we make parameter type computation lazy? this.type = DynamicTypeDecoder.TransformType(type, this.customModifiers.Length, handle, moduleSymbol, refKind); } if (string.IsNullOrEmpty(this.name)) { // As was done historically, if the parameter doesn't have a name, we give it the name "value". this.name = "value"; } this.packed = Pack(refKind, hasByRefBeforeCustomModifiers); Debug.Assert(refKind == this.RefKind); Debug.Assert(hasByRefBeforeCustomModifiers == this.HasByRefBeforeCustomModifiers); }
public override ImmutableArray <CSharpAttributeData> GetAttributes() { if (_lazyCustomAttributes.IsDefault) { Debug.Assert(!_handle.IsNil); var containingPEModuleSymbol = (PEModuleSymbol)this.ContainingModule; // Filter out ParamArrayAttributes if necessary and cache // the attribute handle for GetCustomAttributesToEmit bool filterOutParamArrayAttribute = (!_lazyIsParams.HasValue() || _lazyIsParams.Value()); ConstantValue defaultValue = this.ExplicitDefaultConstantValue; AttributeDescription filterOutConstantAttributeDescription = default(AttributeDescription); if ((object)defaultValue != null) { if (defaultValue.Discriminator == ConstantValueTypeDiscriminator.DateTime) { filterOutConstantAttributeDescription = AttributeDescription.DateTimeConstantAttribute; } else if (defaultValue.Discriminator == ConstantValueTypeDiscriminator.Decimal) { filterOutConstantAttributeDescription = AttributeDescription.DecimalConstantAttribute; } } if (filterOutParamArrayAttribute || filterOutConstantAttributeDescription.Signatures != null) { CustomAttributeHandle paramArrayAttribute; CustomAttributeHandle constantAttribute; ImmutableArray <CSharpAttributeData> attributes = containingPEModuleSymbol.GetCustomAttributesForToken( _handle, out paramArrayAttribute, filterOutParamArrayAttribute ? AttributeDescription.ParamArrayAttribute : default(AttributeDescription), out constantAttribute, filterOutConstantAttributeDescription); if (!paramArrayAttribute.IsNil || !constantAttribute.IsNil) { var builder = ArrayBuilder <CSharpAttributeData> .GetInstance(); if (!paramArrayAttribute.IsNil) { builder.Add(new PEAttributeData(containingPEModuleSymbol, paramArrayAttribute)); } if (!constantAttribute.IsNil) { builder.Add(new PEAttributeData(containingPEModuleSymbol, constantAttribute)); } ImmutableInterlocked.InterlockedInitialize(ref _lazyHiddenAttributes, builder.ToImmutableAndFree()); } else { ImmutableInterlocked.InterlockedInitialize(ref _lazyHiddenAttributes, ImmutableArray <CSharpAttributeData> .Empty); } if (!_lazyIsParams.HasValue()) { Debug.Assert(filterOutParamArrayAttribute); _lazyIsParams = (!paramArrayAttribute.IsNil).ToThreeState(); } ImmutableInterlocked.InterlockedInitialize( ref _lazyCustomAttributes, attributes); } else { ImmutableInterlocked.InterlockedInitialize(ref _lazyHiddenAttributes, ImmutableArray <CSharpAttributeData> .Empty); containingPEModuleSymbol.LoadCustomAttributes(_handle, ref _lazyCustomAttributes); } } Debug.Assert(!_lazyHiddenAttributes.IsDefault); return(_lazyCustomAttributes); }
private PEParameterSymbol( PEModuleSymbol moduleSymbol, Symbol containingSymbol, int ordinal, bool isByRef, TypeSymbol type, ParameterHandle handle, int countOfCustomModifiers, out bool isBad) { Debug.Assert((object)moduleSymbol != null); Debug.Assert((object)containingSymbol != null); Debug.Assert(ordinal >= 0); Debug.Assert((object)type != null); isBad = false; _moduleSymbol = moduleSymbol; _containingSymbol = containingSymbol; _ordinal = (ushort)ordinal; _handle = handle; RefKind refKind = RefKind.None; if (handle.IsNil) { refKind = isByRef ? RefKind.Ref : RefKind.None; type = TupleTypeSymbol.TransformToTupleIfCompatible(type); // temporary shallow unification _type = type; _lazyCustomAttributes = ImmutableArray<CSharpAttributeData>.Empty; _lazyHiddenAttributes = ImmutableArray<CSharpAttributeData>.Empty; _lazyDefaultValue = ConstantValue.NotAvailable; _lazyIsParams = ThreeState.False; } else { try { moduleSymbol.Module.GetParamPropsOrThrow(handle, out _name, out _flags); } catch (BadImageFormatException) { isBad = true; } if (isByRef) { ParameterAttributes inOutFlags = _flags & (ParameterAttributes.Out | ParameterAttributes.In); refKind = (inOutFlags == ParameterAttributes.Out) ? RefKind.Out : RefKind.Ref; } // CONSIDER: Can we make parameter type computation lazy? type = DynamicTypeDecoder.TransformType(type, countOfCustomModifiers, handle, moduleSymbol, refKind); _type = TupleTypeSymbol.TransformToTupleIfCompatible(type); // temporary shallow unification } bool hasNameInMetadata = !string.IsNullOrEmpty(_name); if (!hasNameInMetadata) { // As was done historically, if the parameter doesn't have a name, we give it the name "value". _name = "value"; } _packedFlags = new PackedFlags(refKind, attributesAreComplete: handle.IsNil, hasNameInMetadata: hasNameInMetadata); Debug.Assert(refKind == this.RefKind); Debug.Assert(hasNameInMetadata == this.HasNameInMetadata); }
private static bool IsViableSourceMethod(MethodSymbol candidateMethod, string desiredMethodName, ImmutableArray<TypeParameterSymbol> desiredTypeParameters, ThreeState isDesiredMethodStatic) { return !candidateMethod.IsAbstract && (isDesiredMethodStatic == ThreeState.Unknown || isDesiredMethodStatic.Value() == candidateMethod.IsStatic) && candidateMethod.Name == desiredMethodName && HaveSameConstraints(candidateMethod.TypeParameters, desiredTypeParameters); }
internal static void ReportDiagnosticsIfObsolete( DiagnosticBag diagnostics, Symbol symbol, SyntaxNodeOrToken node, bool hasBaseReceiver, Symbol containingMember, NamedTypeSymbol containingType, BinderFlags location) { Debug.Assert((object)symbol != null); Debug.Assert(symbol.Kind == SymbolKind.NamedType || symbol.Kind == SymbolKind.Field || symbol.Kind == SymbolKind.Method || symbol.Kind == SymbolKind.Event || symbol.Kind == SymbolKind.Property); // Dev11 also reports on the unconstructed method. It would be nice to report on // the constructed method, but then we wouldn't be able to walk the override chain. if (symbol.Kind == SymbolKind.Method) { symbol = ((MethodSymbol)symbol).ConstructedFrom; } // There are two reasons to walk up to the least-overridden member: // 1) That's the method to which we will actually emit a call. // 2) We don't know what virtual dispatch will do at runtime so an // overriding member is basically a shot in the dark. Better to // just be consistent and always use the least-overridden member. Symbol leastOverriddenSymbol = symbol.GetLeastOverriddenMember(containingType); bool checkOverridingSymbol = hasBaseReceiver && !ReferenceEquals(symbol, leastOverriddenSymbol); if (checkOverridingSymbol) { // If we have a base receiver, we must be done with declaration binding, so it should // be safe to decode diagnostics. We want to do this since reporting for the overriding // member is conditional on reporting for the overridden member (i.e. we need a definite // answer so we don't double-report). You might think that double reporting just results // in cascading diagnostics, but it's possible that the second diagnostic is an error // while the first is merely a warning. leastOverriddenSymbol.GetAttributes(); } ThreeState reportedOnOverridden = ReportDiagnosticsIfObsoleteInternal(diagnostics, leastOverriddenSymbol, node, containingMember, location); // CONSIDER: In place of hasBaseReceiver, dev11 also accepts cases where symbol.ContainingType is a "simple type" (e.g. int) // or a special by-ref type (e.g. ArgumentHandle). These cases are probably more important for other checks performed by // ExpressionBinder::PostBindMethod, but they do appear to ObsoleteAttribute as well. We're skipping them because they // don't make much sense for ObsoleteAttribute (e.g. this would seem to address the case where int.ToString has been made // obsolete but object.ToString has not). // If the overridden member was not definitely obsolete and this is a (non-virtual) base member // access, then check the overriding symbol as well. if (reportedOnOverridden != ThreeState.True && checkOverridingSymbol) { Debug.Assert(reportedOnOverridden != ThreeState.Unknown, "We forced attribute binding above."); ReportDiagnosticsIfObsoleteInternal(diagnostics, symbol, node, containingMember, location); } }
private ImmutableArray <TypeWithAnnotations> GetDeclaredConstraintTypes() { if (_lazyDeclaredConstraintTypes.IsDefault) { ImmutableArray <TypeWithAnnotations> declaredConstraintTypes; PEMethodSymbol containingMethod = null; PENamedTypeSymbol containingType; if (_containingSymbol.Kind == SymbolKind.Method) { containingMethod = (PEMethodSymbol)_containingSymbol; containingType = (PENamedTypeSymbol)containingMethod.ContainingSymbol; } else { containingType = (PENamedTypeSymbol)_containingSymbol; } var moduleSymbol = containingType.ContainingPEModule; PEModule peModule = moduleSymbol.Module; GenericParameterConstraintHandleCollection constraints = GetConstraintHandleCollection(peModule); bool hasUnmanagedModreqPattern = false; if (constraints.Count > 0) { var symbolsBuilder = ArrayBuilder <TypeWithAnnotations> .GetInstance(); MetadataDecoder tokenDecoder; if ((object)containingMethod != null) { tokenDecoder = new MetadataDecoder(moduleSymbol, containingMethod); } else { tokenDecoder = new MetadataDecoder(moduleSymbol, containingType); } var metadataReader = peModule.MetadataReader; foreach (var constraintHandle in constraints) { var constraint = metadataReader.GetGenericParameterConstraint(constraintHandle); var typeSymbol = tokenDecoder.DecodeGenericParameterConstraint(constraint.Type, out bool hasUnmanagedModreq); if (typeSymbol.SpecialType == SpecialType.System_ValueType) { // recognize "(class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType" pattern as "unmanaged" if (hasUnmanagedModreq) { hasUnmanagedModreqPattern = true; } // Drop 'System.ValueType' constraint type if the 'valuetype' constraint was also specified. if (((_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)) { continue; } } var type = TypeWithAnnotations.Create(typeSymbol); type = NullableTypeDecoder.TransformType(type, constraintHandle, moduleSymbol); // Drop 'System.Object?' constraint type. if (type.SpecialType == SpecialType.System_Object && type.NullableAnnotation.IsAnnotated()) { continue; } type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, constraintHandle, moduleSymbol); symbolsBuilder.Add(type); } declaredConstraintTypes = symbolsBuilder.ToImmutableAndFree(); } else { declaredConstraintTypes = ImmutableArray <TypeWithAnnotations> .Empty; } // - presence of unmanaged pattern has to be matched with `valuetype` // - IsUnmanagedAttribute is allowed iif there is an unmanaged pattern if (hasUnmanagedModreqPattern && (_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0 || hasUnmanagedModreqPattern != peModule.HasIsUnmanagedAttribute(_handle)) { // we do not recognize these combinations as "unmanaged" hasUnmanagedModreqPattern = false; Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); } _lazyHasIsUnmanagedConstraint = hasUnmanagedModreqPattern.ToThreeState(); ImmutableInterlocked.InterlockedInitialize(ref _lazyDeclaredConstraintTypes, declaredConstraintTypes); } return(_lazyDeclaredConstraintTypes); }
protected void SealTemplates() { templatesSealed = ThreeState.True; }
internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArguments <AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments) { Debug.Assert((object)arguments.AttributeSyntaxOpt != null); var attribute = arguments.Attribute; Debug.Assert(!attribute.HasErrors); Debug.Assert(arguments.SymbolPart == AttributeLocation.None); if (attribute.IsTargetAttribute(this, AttributeDescription.AttributeUsageAttribute)) { DecodeAttributeUsageAttribute(attribute, arguments.AttributeSyntaxOpt, diagnose: true, diagnosticsOpt: arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.DefaultMemberAttribute)) { arguments.GetOrCreateData <TypeWellKnownAttributeData>().HasDefaultMemberAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.CoClassAttribute)) { DecodeCoClassAttribute(ref arguments); } else if (attribute.IsTargetAttribute(this, AttributeDescription.ConditionalAttribute)) { ValidateConditionalAttribute(attribute, arguments.AttributeSyntaxOpt, arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.GuidAttribute)) { arguments.GetOrCreateData <TypeWellKnownAttributeData>().GuidString = attribute.DecodeGuidAttribute(arguments.AttributeSyntaxOpt, arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.SpecialNameAttribute)) { arguments.GetOrCreateData <TypeWellKnownAttributeData>().HasSpecialNameAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.SerializableAttribute)) { arguments.GetOrCreateData <TypeWellKnownAttributeData>().HasSerializableAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.StructLayoutAttribute)) { AttributeData.DecodeStructLayoutAttribute <TypeWellKnownAttributeData, AttributeSyntax, CSharpAttributeData, AttributeLocation>( ref arguments, this.DefaultMarshallingCharSet, defaultAutoLayoutSize: 0, messageProvider: MessageProvider.Instance); } else if (attribute.IsTargetAttribute(this, AttributeDescription.SuppressUnmanagedCodeSecurityAttribute)) { arguments.GetOrCreateData <TypeWellKnownAttributeData>().HasSuppressUnmanagedCodeSecurityAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.ClassInterfaceAttribute)) { attribute.DecodeClassInterfaceAttribute(arguments.AttributeSyntaxOpt, arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.InterfaceTypeAttribute)) { attribute.DecodeInterfaceTypeAttribute(arguments.AttributeSyntaxOpt, arguments.Diagnostics); } else if (attribute.IsTargetAttribute(this, AttributeDescription.WindowsRuntimeImportAttribute)) { arguments.GetOrCreateData <TypeWellKnownAttributeData>().HasWindowsRuntimeImportAttribute = true; } else if (attribute.IsTargetAttribute(this, AttributeDescription.RequiredAttributeAttribute)) { // CS1608: The Required attribute is not permitted on C# types arguments.Diagnostics.Add(ErrorCode.ERR_CantUseRequiredAttribute, arguments.AttributeSyntaxOpt.Name.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.CaseSensitiveExtensionAttribute)) { // ExtensionAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitExtension, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.DynamicAttribute)) { // DynamicAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } else if (attribute.IsTargetAttribute(this, AttributeDescription.SecurityCriticalAttribute) || attribute.IsTargetAttribute(this, AttributeDescription.SecuritySafeCriticalAttribute)) { arguments.GetOrCreateData <TypeWellKnownAttributeData>().HasSecurityCriticalAttributes = true; } else if (_lazyIsExplicitDefinitionOfNoPiaLocalType == ThreeState.Unknown && attribute.IsTargetAttribute(this, AttributeDescription.TypeIdentifierAttribute)) { _lazyIsExplicitDefinitionOfNoPiaLocalType = ThreeState.True; } else { var compilation = this.DeclaringCompilation; if (attribute.IsSecurityAttribute(compilation)) { attribute.DecodeSecurityAttribute <TypeWellKnownAttributeData>(this, compilation, ref arguments); } } }
private static SourceLocation GetCallerLocation(SyntaxNode syntax, ThreeState enableCallerInfo) { switch (enableCallerInfo) { case ThreeState.False: return null; case ThreeState.True: return new SourceLocation(syntax.GetFirstToken()); } Debug.Assert(enableCallerInfo == ThreeState.Unknown); switch (syntax.Kind()) { case SyntaxKind.InvocationExpression: return new SourceLocation(((InvocationExpressionSyntax)syntax).ArgumentList.OpenParenToken); case SyntaxKind.ObjectCreationExpression: return new SourceLocation(((ObjectCreationExpressionSyntax)syntax).NewKeyword); case SyntaxKind.BaseConstructorInitializer: case SyntaxKind.ThisConstructorInitializer: return new SourceLocation(((ConstructorInitializerSyntax)syntax).ArgumentList.OpenParenToken); case SyntaxKind.ElementAccessExpression: return new SourceLocation(((ElementAccessExpressionSyntax)syntax).ArgumentList.OpenBracketToken); case SyntaxKind.FromClause: case SyntaxKind.GroupClause: case SyntaxKind.JoinClause: case SyntaxKind.JoinIntoClause: case SyntaxKind.LetClause: case SyntaxKind.OrderByClause: case SyntaxKind.SelectClause: case SyntaxKind.WhereClause: return new SourceLocation(syntax.GetFirstToken()); default: return null; } }
private PEParameterSymbol( PEModuleSymbol moduleSymbol, Symbol containingSymbol, int ordinal, bool isByRef, TypeWithAnnotations typeWithAnnotations, ParameterHandle handle, Symbol nullableContext, int countOfCustomModifiers, out bool isBad) { Debug.Assert((object)moduleSymbol != null); Debug.Assert((object)containingSymbol != null); Debug.Assert(ordinal >= 0); Debug.Assert(typeWithAnnotations.HasType); isBad = false; _moduleSymbol = moduleSymbol; _containingSymbol = containingSymbol; _ordinal = (ushort)ordinal; _handle = handle; RefKind refKind = RefKind.None; if (handle.IsNil) { refKind = isByRef ? RefKind.Ref : RefKind.None; byte?value = nullableContext.GetNullableContextValue(); if (value.HasValue) { typeWithAnnotations = NullableTypeDecoder.TransformType(typeWithAnnotations, value.GetValueOrDefault(), default); } _lazyCustomAttributes = ImmutableArray <CSharpAttributeData> .Empty; _lazyHiddenAttributes = ImmutableArray <CSharpAttributeData> .Empty; _lazyDefaultValue = ConstantValue.NotAvailable; _lazyIsParams = ThreeState.False; } else { try { moduleSymbol.Module.GetParamPropsOrThrow(handle, out _name, out _flags); } catch (BadImageFormatException) { isBad = true; } if (isByRef) { ParameterAttributes inOutFlags = _flags & (ParameterAttributes.Out | ParameterAttributes.In); if (inOutFlags == ParameterAttributes.Out) { refKind = RefKind.Out; } else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle)) { refKind = RefKind.In; } else { refKind = RefKind.Ref; } } var typeSymbol = DynamicTypeDecoder.TransformType(typeWithAnnotations.Type, countOfCustomModifiers, handle, moduleSymbol, refKind); typeWithAnnotations = typeWithAnnotations.WithTypeAndModifiers(typeSymbol, typeWithAnnotations.CustomModifiers); // Decode nullable before tuple types to avoid converting between // NamedTypeSymbol and TupleTypeSymbol unnecessarily. // The containing type is passed to NullableTypeDecoder.TransformType to determine access // for property parameters because the property does not have explicit accessibility in metadata. var accessSymbol = containingSymbol.Kind == SymbolKind.Property ? containingSymbol.ContainingSymbol : containingSymbol; typeWithAnnotations = NullableTypeDecoder.TransformType(typeWithAnnotations, handle, moduleSymbol, accessSymbol: accessSymbol, nullableContext: nullableContext); typeWithAnnotations = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithAnnotations, handle, moduleSymbol); } _typeWithAnnotations = typeWithAnnotations; bool hasNameInMetadata = !string.IsNullOrEmpty(_name); if (!hasNameInMetadata) { // As was done historically, if the parameter doesn't have a name, we give it the name "value". _name = "value"; } _packedFlags = new PackedFlags(refKind, attributesAreComplete: handle.IsNil, hasNameInMetadata: hasNameInMetadata); Debug.Assert(refKind == this.RefKind); Debug.Assert(hasNameInMetadata == this.HasNameInMetadata); }
/// <summary> /// Gets the default value for the <paramref name="parameter"/>. /// </summary> /// <param name="syntax"> /// A syntax node corresponding to the invocation. /// </param> /// <param name="parameter"> /// A parameter to get the default value for. /// </param> /// <param name="enableCallerInfo"> /// Indicates if caller info is to be enabled when processing this optional parameter. /// The value <see cref="ThreeState.Unknown"/> means the decision is to be made based on the shape of the <paramref name="syntax"/> node. /// </param> /// <remarks> /// DELIBERATE SPEC VIOLATION: When processing an implicit invocation of an <c>Add</c> method generated /// for an element-initializer in a collection-initializer, the parameter <paramref name="enableCallerInfo"/> /// is set to <see cref="ThreeState.True"/>. It means that if the optional parameter is annotated with <see cref="CallerLineNumberAttribute"/>, /// <see cref="CallerFilePathAttribute"/> or <see cref="CallerMemberNameAttribute"/>, and there is no explicit argument corresponding to it, /// we will provide caller information as a value of this parameter. /// This is done to match the native compiler behavior and user requests (see http://roslyn.codeplex.com/workitem/171). This behavior /// does not match the C# spec that currently requires to provide caller information only in explicit invocations and query expressions. /// </remarks> private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSymbol parameter, ThreeState enableCallerInfo) { // TODO: Ideally, the enableCallerInfo parameter would be of just bool type with only 'true' and 'false' values, and all callers // explicitly provided one of those values, so that we do not rely on shape of syntax nodes in the rewriter. There are not many immediate callers, // but often the immediate caller does not have the required information, so all possible call chains should be analyzed and possibly updated // to pass this information, and this might be a big task. We should consider doing this when the time permits. TypeSymbol parameterType = parameter.Type; Debug.Assert(parameter.IsOptional); ConstantValue defaultConstantValue = parameter.ExplicitDefaultConstantValue; BoundExpression defaultValue; SourceLocation callerSourceLocation; // For compatibility with the native compiler we treat all bad imported constant // values as default(T). if (defaultConstantValue != null && defaultConstantValue.IsBad) { defaultConstantValue = ConstantValue.Null; } if (parameter.IsCallerLineNumber && ((callerSourceLocation = GetCallerLocation(syntax, enableCallerInfo)) != null)) { int line = callerSourceLocation.SourceTree.GetDisplayLineNumber(callerSourceLocation.SourceSpan); BoundExpression lineLiteral = MakeLiteral(syntax, ConstantValue.Create(line), _compilation.GetSpecialType(SpecialType.System_Int32)); if (parameterType.IsNullableType()) { defaultValue = MakeConversionNode(lineLiteral, parameterType.GetNullableUnderlyingType(), false); // wrap it in a nullable ctor. defaultValue = new BoundObjectCreationExpression( syntax, GetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor), defaultValue); } else { defaultValue = MakeConversionNode(lineLiteral, parameterType, false); } } else if (parameter.IsCallerFilePath && ((callerSourceLocation = GetCallerLocation(syntax, enableCallerInfo)) != null)) { string path = callerSourceLocation.SourceTree.GetDisplayPath(callerSourceLocation.SourceSpan, _compilation.Options.SourceReferenceResolver); BoundExpression memberNameLiteral = MakeLiteral(syntax, ConstantValue.Create(path), _compilation.GetSpecialType(SpecialType.System_String)); defaultValue = MakeConversionNode(memberNameLiteral, parameterType, false); } else if (parameter.IsCallerMemberName && ((callerSourceLocation = GetCallerLocation(syntax, enableCallerInfo)) != null)) { string memberName; switch (_factory.TopLevelMethod.MethodKind) { case MethodKind.Constructor: case MethodKind.StaticConstructor: // See if the code is actually part of a field, field-like event or property initializer and return the name of the corresponding member. var memberDecl = syntax.Ancestors().OfType<MemberDeclarationSyntax>().FirstOrDefault(); if (memberDecl != null) { BaseFieldDeclarationSyntax fieldDecl; if (memberDecl.Kind() == SyntaxKind.PropertyDeclaration) { var propDecl = (PropertyDeclarationSyntax)memberDecl; EqualsValueClauseSyntax initializer = propDecl.Initializer; if (initializer != null && initializer.Span.Contains(syntax.Span)) { memberName = propDecl.Identifier.ValueText; break; } } else if ((fieldDecl = memberDecl as BaseFieldDeclarationSyntax) != null) { memberName = null; foreach (VariableDeclaratorSyntax varDecl in fieldDecl.Declaration.Variables) { EqualsValueClauseSyntax initializer = varDecl.Initializer; if (initializer != null && initializer.Span.Contains(syntax.Span)) { memberName = varDecl.Identifier.ValueText; break; } } if (memberName != null) { break; } } } goto default; default: memberName = _factory.TopLevelMethod.GetMemberCallerName(); break; } BoundExpression memberNameLiteral = MakeLiteral(syntax, ConstantValue.Create(memberName), _compilation.GetSpecialType(SpecialType.System_String)); defaultValue = MakeConversionNode(memberNameLiteral, parameterType, false); } else if (defaultConstantValue == ConstantValue.NotAvailable) { // There is no constant value given for the parameter in source/metadata. if (parameterType.IsDynamic() || parameterType.SpecialType == SpecialType.System_Object) { // We have something like M([Optional] object x). We have special handling for such situations. defaultValue = GetDefaultParameterSpecial(syntax, parameter); } else { // The argument to M([Optional] int x) becomes default(int) defaultValue = new BoundDefaultOperator(syntax, parameterType); } } else if (defaultConstantValue.IsNull && parameterType.IsValueType) { // We have something like M(int? x = null) or M(S x = default(S)), // so replace the argument with default(int?). defaultValue = new BoundDefaultOperator(syntax, parameterType); } else if (parameterType.IsNullableType()) { // We have something like M(double? x = 1.23), so replace the argument // with new double?(1.23). TypeSymbol constantType = _compilation.GetSpecialType(defaultConstantValue.SpecialType); defaultValue = MakeLiteral(syntax, defaultConstantValue, constantType); // The parameter's underlying type might not match the constant type. For example, we might have // a default value of 5 (an integer) but a parameter type of decimal?. defaultValue = MakeConversionNode(defaultValue, parameterType.GetNullableUnderlyingType(), @checked: false, acceptFailingConversion: true); // Finally, wrap it in a nullable ctor. defaultValue = new BoundObjectCreationExpression( syntax, GetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor), defaultValue); } else if (defaultConstantValue.IsNull || defaultConstantValue.IsBad) { defaultValue = MakeLiteral(syntax, defaultConstantValue, parameterType); } else { // We have something like M(double x = 1.23), so replace the argument with 1.23. TypeSymbol constantType = _compilation.GetSpecialType(defaultConstantValue.SpecialType); defaultValue = MakeLiteral(syntax, defaultConstantValue, constantType); // The parameter type might not match the constant type. defaultValue = MakeConversionNode(defaultValue, parameterType, @checked: false, acceptFailingConversion: true); } return defaultValue; }
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; } }
private PEParameterSymbol( PEModuleSymbol moduleSymbol, Symbol containingSymbol, int ordinal, bool isByRef, bool hasByRefBeforeCustomModifiers, TypeSymbol type, ParameterHandle handle, ImmutableArray <ModifierInfo <TypeSymbol> > customModifiers, out bool isBad) { Debug.Assert((object)moduleSymbol != null); Debug.Assert((object)containingSymbol != null); Debug.Assert(ordinal >= 0); Debug.Assert((object)type != null); isBad = false; _moduleSymbol = moduleSymbol; _containingSymbol = containingSymbol; _customModifiers = CSharpCustomModifier.Convert(customModifiers); _ordinal = (ushort)ordinal; _handle = handle; RefKind refKind = RefKind.None; if (handle.IsNil) { refKind = isByRef ? RefKind.Ref : RefKind.None; _type = type; _lazyCustomAttributes = ImmutableArray <CSharpAttributeData> .Empty; _lazyHiddenAttributes = ImmutableArray <CSharpAttributeData> .Empty; _lazyDefaultValue = ConstantValue.NotAvailable; _lazyIsParams = ThreeState.False; } else { try { moduleSymbol.Module.GetParamPropsOrThrow(handle, out _name, out _flags); } catch (BadImageFormatException) { isBad = true; } if (isByRef) { ParameterAttributes inOutFlags = _flags & (ParameterAttributes.Out | ParameterAttributes.In); refKind = (inOutFlags == ParameterAttributes.Out) ? RefKind.Out : RefKind.Ref; } // CONSIDER: Can we make parameter type computation lazy? _type = DynamicTypeDecoder.TransformType(type, _customModifiers.Length, handle, moduleSymbol, refKind); } if (string.IsNullOrEmpty(_name)) { // As was done historically, if the parameter doesn't have a name, we give it the name "value". _name = "value"; } _packedFlags = new PackedFlags(refKind, hasByRefBeforeCustomModifiers, attributesAreComplete: handle.IsNil); Debug.Assert(refKind == this.RefKind); Debug.Assert(hasByRefBeforeCustomModifiers == this.HasByRefBeforeCustomModifiers); }
internal override void PostEarlyDecodeWellKnownAttributeTypes() { if (_lazyHasOptionalAttribute == ThreeState.Unknown) { _lazyHasOptionalAttribute = ThreeState.False; } base.PostEarlyDecodeWellKnownAttributeTypes(); }
internal bool ContainsNoPiaLocalTypes() { if (this.lazyContainsNoPiaLocalTypes == ThreeState.Unknown) { foreach (PEModule module in Modules) { if (module.ContainsNoPiaLocalTypes()) { this.lazyContainsNoPiaLocalTypes = ThreeState.True; return true; } } this.lazyContainsNoPiaLocalTypes = ThreeState.False; } return this.lazyContainsNoPiaLocalTypes == ThreeState.True; }
public static bool HasValue(this ThreeState value) { return(value != ThreeState.Unknown); }
public override ImmutableArray<CSharpAttributeData> GetAttributes() { if (_lazyCustomAttributes.IsDefault) { Debug.Assert(!_handle.IsNil); var containingPEModuleSymbol = (PEModuleSymbol)this.ContainingModule; // Filter out ParamArrayAttributes if necessary and cache // the attribute handle for GetCustomAttributesToEmit bool filterOutParamArrayAttribute = (!_lazyIsParams.HasValue() || _lazyIsParams.Value()); ConstantValue defaultValue = this.ExplicitDefaultConstantValue; AttributeDescription filterOutConstantAttributeDescription = default(AttributeDescription); if ((object)defaultValue != null) { if (defaultValue.Discriminator == ConstantValueTypeDiscriminator.DateTime) { filterOutConstantAttributeDescription = AttributeDescription.DateTimeConstantAttribute; } else if (defaultValue.Discriminator == ConstantValueTypeDiscriminator.Decimal) { filterOutConstantAttributeDescription = AttributeDescription.DecimalConstantAttribute; } } if (filterOutParamArrayAttribute || filterOutConstantAttributeDescription.Signatures != null) { CustomAttributeHandle paramArrayAttribute; CustomAttributeHandle constantAttribute; ImmutableArray<CSharpAttributeData> attributes = containingPEModuleSymbol.GetCustomAttributesForToken( _handle, out paramArrayAttribute, filterOutParamArrayAttribute ? AttributeDescription.ParamArrayAttribute : default(AttributeDescription), out constantAttribute, filterOutConstantAttributeDescription); if (!paramArrayAttribute.IsNil || !constantAttribute.IsNil) { var builder = ArrayBuilder<CSharpAttributeData>.GetInstance(); if (!paramArrayAttribute.IsNil) { builder.Add(new PEAttributeData(containingPEModuleSymbol, paramArrayAttribute)); } if (!constantAttribute.IsNil) { builder.Add(new PEAttributeData(containingPEModuleSymbol, constantAttribute)); } ImmutableInterlocked.InterlockedInitialize(ref _lazyHiddenAttributes, builder.ToImmutableAndFree()); } else { ImmutableInterlocked.InterlockedInitialize(ref _lazyHiddenAttributes, ImmutableArray<CSharpAttributeData>.Empty); } if (!_lazyIsParams.HasValue()) { Debug.Assert(filterOutParamArrayAttribute); _lazyIsParams = (!paramArrayAttribute.IsNil).ToThreeState(); } ImmutableInterlocked.InterlockedInitialize( ref _lazyCustomAttributes, attributes); } else { ImmutableInterlocked.InterlockedInitialize(ref _lazyHiddenAttributes, ImmutableArray<CSharpAttributeData>.Empty); containingPEModuleSymbol.LoadCustomAttributes(_handle, ref _lazyCustomAttributes); } } Debug.Assert(!_lazyHiddenAttributes.IsDefault); return _lazyCustomAttributes; }
protected void SealTemplates() { _templatesSealed = ThreeState.True; }