public MultiplicationMemoryOp(int offset, int scalar, ConstantValue constant, ConstantValue multiplicationConstant) { Offset = offset; Scalar = scalar; Constant = constant; MultiplicationConstant = multiplicationConstant; }
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 }
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); } }
public CriteriaOperator PrepareCriteria(CriteriaOperator op) { if (op is FunctionOperator) { var funcOp = new FunctionOperator(); for (int i = 0; i < (op as FunctionOperator).Operands.Count; i++) funcOp.Operands.Add(PrepareCriteria((op as FunctionOperator).Operands[i])); return funcOp; } else if (op is ConstantValue) { var cnst = new ConstantValue((op as ConstantValue).Value); if (String.Concat((op as ConstantValue).Value).ToLower().IndexOf("@this") > -1) { IMemberInfo info; cnst.Value = ObjectFormatValues.GetValueRecursive((op as ConstantValue).Value.ToString().Replace("@This.", "").Replace("@This", "").Replace("@this.", "").Replace("@this", ""), CurrentObject, out info); } return cnst; } else if (op is BinaryOperator) { var binary = new BinaryOperator(); binary.LeftOperand = PrepareCriteria((op as BinaryOperator).LeftOperand); binary.RightOperand = PrepareCriteria((op as BinaryOperator).RightOperand); return binary; } else { return op; } }
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; }
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 SourceLabelSymbol( MethodSymbol containingMethod, ConstantValue switchCaseLabelConstant) { _containingMethod = containingMethod; _identifierNodeOrToken = default(SyntaxToken); _switchCaseLabelConstant = switchCaseLabelConstant; }
public SourceLabelSymbol( MethodSymbol containingMethod, ConstantValue switchCaseLabelConstant = null) : base(switchCaseLabelConstant.ToString()) { this.containingMethod = containingMethod; this.identifierNodeOrToken = default(SyntaxToken); this.switchCaseLabelConstant = switchCaseLabelConstant; }
public FieldVariable(ChelaModule module) : base(module) { this.flags = MemberFlags.Default; this.slot = -1; this.initializer = null; this.parentScope = null; this.position = null; }
public BoundFieldAccess( CSharpSyntaxNode syntax, BoundExpression receiver, FieldSymbol fieldSymbol, ConstantValue constantValueOpt, bool hasErrors = false) : this(syntax, receiver, fieldSymbol, constantValueOpt, LookupResultKind.Viable, fieldSymbol.Type, hasErrors) { }
public SourceLabelSymbol( MethodSymbol containingMethod, SyntaxNodeOrToken identifierNodeOrToken, ConstantValue switchCaseLabelConstant = null) { _containingMethod = containingMethod; _identifierNodeOrToken = identifierNodeOrToken; _switchCaseLabelConstant = switchCaseLabelConstant; }
public BoundFieldAccess Update( BoundExpression receiver, FieldSymbol fieldSymbol, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol typeSymbol) { return this.Update(receiver, fieldSymbol, constantValueOpt, resultKind, this.IsByValue, typeSymbol); }
public SourceLabelSymbol( MethodSymbol containingMethod, SyntaxNodeOrToken identifierNodeOrToken, ConstantValue switchCaseLabelConstant = null) : base(identifierNodeOrToken.IsToken ? identifierNodeOrToken.AsToken().ValueText : identifierNodeOrToken.ToString()) { this.containingMethod = containingMethod; this.identifierNodeOrToken = identifierNodeOrToken; this.switchCaseLabelConstant = switchCaseLabelConstant; }
public SynthesizedFieldSymbol( NamedTypeSymbol containing, TypeSymbol type, string name, Accessibility accessibility, ConstantValue constant) :this(containing, type, name, accessibility, true) { _const = constant; }
public FieldVariable(string name, MemberFlags flags, IChelaType type, Scope parentScope) : base(type, parentScope.GetModule()) { SetName(name); this.flags = flags; this.parentScope = parentScope; this.slot = -1; this.initializer = null; this.position = null; }
public BoundFieldAccess( CSharpSyntaxNode syntax, BoundExpression receiver, FieldSymbol fieldSymbol, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type, bool hasErrors = false) : this(syntax, receiver, fieldSymbol, constantValueOpt, resultKind, NeedsByValueFieldAccess(receiver, fieldSymbol), type, hasErrors) { }
public EELocalConstantSymbol( MethodSymbol method, string name, TypeSymbol type, ConstantValue value) { _method = method; _name = name; _type = type; _value = value; }
public static ITypeRef Create(ConstantValue c) { Contract.ThrowIfNull(c); switch (c.SpecialType) { 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; default: throw new NotImplementedException(); } }
/// <summary> /// Converts access to a tuple instance into access into the underlying ValueTuple(s). /// /// For instance, tuple.Item8 /// produces fieldAccess(field=Item1, receiver=fieldAccess(field=Rest, receiver=ValueTuple for tuple)) /// </summary> private BoundExpression MakeTupleFieldAccess( CSharpSyntaxNode syntax, FieldSymbol tupleField, BoundExpression rewrittenReceiver, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type) { var tupleType = tupleField.ContainingType; NamedTypeSymbol currentLinkType = tupleType.TupleUnderlyingType; FieldSymbol underlyingField = tupleField.TupleUnderlyingField; if ((object)underlyingField == null) { // Use-site error must have been reported elsewhere. return new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type, hasErrors: true); } if (underlyingField.ContainingType != currentLinkType) { WellKnownMember wellKnownTupleRest = TupleTypeSymbol.GetTupleTypeMember(TupleTypeSymbol.RestPosition, TupleTypeSymbol.RestPosition); var tupleRestField = (FieldSymbol)TupleTypeSymbol.GetWellKnownMemberInType(currentLinkType.OriginalDefinition, wellKnownTupleRest, _diagnostics, syntax); if ((object)tupleRestField == null) { // error tolerance for cases when Rest is missing return new BoundFieldAccess(syntax, rewrittenReceiver, tupleField, constantValueOpt, resultKind, type, hasErrors: true); } // make nested field accesses to Rest do { FieldSymbol nestedFieldSymbol = tupleRestField.AsMember(currentLinkType); currentLinkType = currentLinkType.TypeArgumentsNoUseSiteDiagnostics[TupleTypeSymbol.RestPosition - 1].TupleUnderlyingType; rewrittenReceiver = new BoundFieldAccess(syntax, rewrittenReceiver, nestedFieldSymbol, ConstantValue.NotAvailable, LookupResultKind.Viable, currentLinkType); } while (underlyingField.ContainingType != currentLinkType); } // make a field access for the most local access return new BoundFieldAccess(syntax, rewrittenReceiver, underlyingField, constantValueOpt, resultKind, type); }
internal SourcePrimaryConstructorParameterSymbolWithBackingField( Symbol owner, int ordinal, TypeSymbol parameterType, RefKind refKind, string name, ImmutableArray<Location> locations, ParameterSyntax syntax, ConstantValue defaultSyntaxValue, bool isParams, bool isExtensionMethodThis, DiagnosticBag diagnostics ) : base(owner, ordinal, parameterType, refKind, ImmutableArray<CustomModifier>.Empty, false, name, locations, syntax.GetReference(), defaultSyntaxValue, isParams, isExtensionMethodThis) { bool modifierErrors; var modifiers = SourceMemberFieldSymbol.MakeModifiers(owner.ContainingType, syntax.Identifier, syntax.Modifiers, diagnostics, out modifierErrors, ignoreParameterModifiers: true); backingField = new BackingField(this, modifiers, modifierErrors, diagnostics); }
protected override Action<ITextControl> ExecutePsiTransaction(ISolution solution, IProgressIndicator progress) { var methodDeclaration = _highlighting.MethodDeclaration; methodDeclaration.SetStatic(true); var factory = CSharpElementFactory.GetInstance(methodDeclaration.GetPsiModule()); var type = TypeFactory.CreateTypeByCLRName(DllImportMissingAnalyzer.DllImportAttribute, methodDeclaration.GetPsiModule()); var constantValue = new ConstantValue("name.dll", methodDeclaration.GetPsiModule()); var attributeValue = new AttributeValue(constantValue); var attribute = factory.CreateAttribute(type.GetTypeElement(), new[] { attributeValue }, new Pair<string, AttributeValue>[0]); var addedAttribute = methodDeclaration.AddAttributeAfter(attribute, null); var firstParameter = addedAttribute.ConstructorArgumentExpressions.FirstOrDefault(); if (firstParameter == null) { return null; } var documentRange = firstParameter.GetDocumentRange(); documentRange = documentRange.TrimLeft(1).TrimRight(1); var rangeMarker = documentRange.CreateRangeMarker(DocumentManager.GetInstance(solution)); return control => control.Selection.SetRange(rangeMarker.Range); }
private static ulong GetBucketSize(ConstantValue startConstant, ConstantValue endConstant) { Debug.Assert(!BucketOverflowUInt64Limit(startConstant, endConstant)); Debug.Assert(endConstant.Discriminator == startConstant.Discriminator); ulong bucketSize; if (startConstant.IsNegativeNumeric || endConstant.IsNegativeNumeric) { Debug.Assert(endConstant.Int64Value >= startConstant.Int64Value); bucketSize = unchecked((ulong)(endConstant.Int64Value - startConstant.Int64Value + 1)); } else { Debug.Assert(endConstant.UInt64Value >= startConstant.UInt64Value); bucketSize = endConstant.UInt64Value - startConstant.UInt64Value + 1; } return bucketSize; }
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; }
/// <summary> /// Add a registry requirement to an existing deployment type /// </summary> public static void AddRequirement(string applicationName, string authoringScopeId, string logicalName, string settingLogicalName, string value, string dataType, string expressionOperator, string server) { Application app = CMApplication.GetApplicationByName(applicationName, server); DeploymentType deploymentType = app.DeploymentTypes[0]; CustomCollection<ExpressionBase> settingsOperands = new CustomCollection<ExpressionBase>(); GlobalSettingReference settingReferences = null; ConstantValue constant = null; switch (dataType) { case "Version": settingReferences = new GlobalSettingReference(authoringScopeId, logicalName, DataType.Version, settingLogicalName, ConfigurationItemSettingSourceType.Registry); constant = new ConstantValue(value, DataType.Version); break; default: break; } settingsOperands.Add(settingReferences); settingsOperands.Add(constant); Expression expression = null; switch (expressionOperator) { case "IsEquals": expression = new Expression(ExpressionOperator.IsEquals, settingsOperands); break; case "LessEquals": expression = new Expression(ExpressionOperator.LessEquals, settingsOperands); break; default: break; } Rule rule = new Rule(Guid.NewGuid().ToString("N"), NoncomplianceSeverity.Critical, null, expression); deploymentType.Requirements.Add(rule); CMApplication.Save(app, server); }
public void Returns_a_warning_when_tag_is_zero() { var mockPsiModule = new Mock<IPsiModule>(); var mockName = new Mock<IReferenceName>(); mockName.Setup(n => n.ShortName).Returns("ProtoMember"); var mockConstructorExpression = new Mock<ICSharpExpression>(); mockConstructorExpression.Setup(e => e.IsConstantValue()).Returns(true); var constantValue = new ConstantValue(0, mockPsiModule.Object, DiagnosticResolveContext.Instance); mockConstructorExpression.Setup(e => e.ConstantValue).Returns(constantValue); var mockAttributeElement = new Mock<IAttribute>(); mockAttributeElement.Setup(a => a.Name).Returns(mockName.Object); var expressionTree = new TreeNodeCollection<ICSharpExpression>(new[] {mockConstructorExpression.Object}); mockAttributeElement.Setup(a => a.ConstructorArgumentExpressions).Returns(expressionTree); var mockConsumer = new Mock<IHighlightingConsumer>(); var analyzer = new TagValueAnalyzer(); analyzer.Analyze(mockAttributeElement.Object, mockConsumer.Object); mockConsumer.Verify(v => v.ConsumeHighlighting(It.IsAny<HighlightingInfo>())); }
public SynthesizedParameterSymbol( MethodSymbol container, TypeSymbol type, int ordinal, RefKind refKind, string name = "", ImmutableArray<CustomModifier> customModifiers = default(ImmutableArray<CustomModifier>), ushort countOfCustomModifiersPrecedingByRef = 0, ConstantValue explicitDefaultConstantValue = null) { Debug.Assert((object)type != null); Debug.Assert(name != null); Debug.Assert(ordinal >= 0); _container = container; _type = type; _ordinal = ordinal; _refKind = refKind; _name = name; _customModifiers = customModifiers.NullToEmpty(); _countOfCustomModifiersPrecedingByRef = countOfCustomModifiersPrecedingByRef; _explicitDefaultConstantValue = explicitDefaultConstantValue; }
public IEnumerable <GaugeValueSource> SetupGauges() { var gauge = new GaugeValueSource("test_gauge", ConstantValue.Provider(0.5), Unit.Calls, Tags); return(new[] { gauge }); }
private void CheckForBitwiseOrSignExtend(BoundExpression node, BinaryOperatorKind operatorKind, BoundExpression leftOperand, BoundExpression rightOperand) { // We wish to give a warning for situations where an unexpected sign extension wipes // out some bits. For example: // // int x = 0x0ABC0000; // short y = -2; // 0xFFFE // int z = x | y; // // The user might naively expect the result to be 0x0ABCFFFE. But the short is sign-extended // when it is converted to int before the bitwise or, so this is in fact the same as: // // int x = 0x0ABC0000; // short y = -2; // 0xFFFE // int ytemp = y; // 0xFFFFFFFE // int z = x | ytemp; // // Which gives 0xFFFFFFFE, not 0x0ABCFFFE. // // However, we wish to suppress the warning if: // // * The sign extension is "expected" -- for instance, because there was an explicit cast // from short to int: "int z = x | (int)y;" should not produce the warning. // Note that "uint z = (uint)x | (uint)y;" should still produce the warning because // the user might not realize that converting y to uint does a sign extension. // // * There is the same amount of sign extension on both sides. For example, when // doing "short | sbyte", both sides are sign extended. The left creates two FF bytes // and the right creates three, so we are potentially wiping out information from the // left side. But "short | short" adds two FF bytes on both sides, so no information is lost. // // The native compiler also suppresses this warning in a bizarre and inconsistent way. If // the side whose bits are going to be wiped out by sign extension is a *constant*, then the // warning is suppressed *if the constant, when converted to a signed long, fits into the // range of the type that is being sign-extended.* // // Consider the effects of this rule: // // (uint)0xFFFF0000 | y -- gives the warning because 0xFFFF0000 as a long is not in the range of a short, // *even though the result will not be affected by the sign extension*. // (ulong)0xFFFFFFFFFFFFFFFF | y -- suppresses the warning, because 0xFFFFFFFFFFFFFFFF as a signed long fits into a short. // (int)0x0000ABCD | y -- suppresses the warning, even though the 0000 is going to be wiped out by the sign extension. // // It seems clear that the intention of the heuristic is to *suppress the warning when the bits being hammered // on are either all zero, or all one.* Therefore that is the heuristic we will *actually* implement here. // switch (operatorKind) { case BinaryOperatorKind.LiftedUInt32Or: case BinaryOperatorKind.LiftedInt32Or: case BinaryOperatorKind.LiftedUInt64Or: case BinaryOperatorKind.LiftedInt64Or: case BinaryOperatorKind.UInt32Or: case BinaryOperatorKind.Int32Or: case BinaryOperatorKind.UInt64Or: case BinaryOperatorKind.Int64Or: break; default: return; } // The native compiler skips this warning if both sides of the operator are constants. // // CONSIDER: Is that sensible? It seems reasonable that if we would warn on int | short // when they are non-constants, or when one is a constant, that we would similarly warn // when both are constants. if (node.ConstantValue != null) { return; } // Start by determining *which bits on each side are going to be unexpectedly turned on*. ulong left = FindSurprisingSignExtensionBits(leftOperand); ulong right = FindSurprisingSignExtensionBits(rightOperand); // If they are all the same then there's no warning to give. if (left == right) { return; } // Suppress the warning if one side is a constant, and either all the unexpected // bits are already off, or all the unexpected bits are already on. ConstantValue constVal = GetConstantValueForBitwiseOrCheck(leftOperand); if (constVal != null) { ulong val = constVal.UInt64Value; if ((val & right) == right || (~val & right) == right) { return; } } constVal = GetConstantValueForBitwiseOrCheck(rightOperand); if (constVal != null) { ulong val = constVal.UInt64Value; if ((val & left) == left || (~val & left) == left) { return; } } // CS0675: Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first Error(ErrorCode.WRN_BitwiseOrSignExtend, node); }
public Literal(ConstantValue value, ITypeSymbol resultType, SyntaxNode syntax) { _value = value; this.ResultType = resultType; this.Syntax = syntax; }
public BoundObjectCreationExpression(SyntaxNode syntax, MethodSymbol constructor, ImmutableArray <BoundExpression> arguments, ImmutableArray <string> argumentNamesOpt, ImmutableArray <RefKind> argumentRefKindsOpt, bool expanded, ImmutableArray <int> argsToParamsOpt, ConstantValue constantValueOpt, BoundObjectInitializerExpressionBase initializerExpressionOpt, Binder binderOpt, TypeSymbol type, bool hasErrors = false) : this(syntax, constructor, ImmutableArray <MethodSymbol> .Empty, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, binderOpt, type, hasErrors) { }
private BoundExpression MakeDecimalLiteral(CSharpSyntaxNode syntax, ConstantValue constantValue) { Debug.Assert(constantValue != null); Debug.Assert(constantValue.IsDecimal); var value = constantValue.DecimalValue; var parts = new ConstantValueUtils.DecimalValue(value); var scale = parts.Scale; var arguments = new ArrayBuilder <BoundExpression>(); SpecialMember member; // check if we can call a simpler constructor, or use a predefined constant if (scale == 0 && int.MinValue <= value && value <= int.MaxValue) { // If we are building static constructor of System.Decimal, accessing static fields // would be bad. var curMethod = _factory.CurrentMethod; if ((curMethod.MethodKind != MethodKind.SharedConstructor || curMethod.ContainingType.SpecialType != SpecialType.System_Decimal) && !_inExpressionLambda) { Symbol useField = null; if (value == decimal.Zero) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__Zero); } else if (value == decimal.One) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__One); } else if (value == decimal.MinusOne) { useField = _compilation.GetSpecialTypeMember(SpecialMember.System_Decimal__MinusOne); } if ((object)useField != null && !useField.HasUseSiteError && !useField.ContainingType.HasUseSiteError) { var fieldSymbol = (FieldSymbol)useField; return(new BoundFieldAccess(syntax, null, fieldSymbol, constantValue)); } } //new decimal(int); member = SpecialMember.System_Decimal__CtorInt32; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((int)value), _compilation.GetSpecialType(SpecialType.System_Int32))); } else if (scale == 0 && uint.MinValue <= value && value <= uint.MaxValue) { //new decimal(uint); member = SpecialMember.System_Decimal__CtorUInt32; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((uint)value), _compilation.GetSpecialType(SpecialType.System_UInt32))); } else if (scale == 0 && long.MinValue <= value && value <= long.MaxValue) { //new decimal(long); member = SpecialMember.System_Decimal__CtorInt64; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((long)value), _compilation.GetSpecialType(SpecialType.System_Int64))); } else if (scale == 0 && ulong.MinValue <= value && value <= ulong.MaxValue) { //new decimal(ulong); member = SpecialMember.System_Decimal__CtorUInt64; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create((ulong)value), _compilation.GetSpecialType(SpecialType.System_UInt64))); } else { //new decimal(int low, int mid, int high, bool isNegative, byte scale); member = SpecialMember.System_Decimal__CtorInt32Int32Int32BooleanByte; arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(parts.Low), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(parts.Mid), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(parts.High), _compilation.GetSpecialType(SpecialType.System_Int32))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(parts.IsNegative), _compilation.GetSpecialType(SpecialType.System_Boolean))); arguments.Add(new BoundLiteral(syntax, ConstantValue.Create(parts.Scale), _compilation.GetSpecialType(SpecialType.System_Byte))); } var ctor = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(member); Debug.Assert((object)ctor != null); Debug.Assert(ctor.ContainingType.SpecialType == SpecialType.System_Decimal); return(new BoundObjectCreationExpression( syntax, ctor, arguments.ToImmutableAndFree(), default(ImmutableArray <string>), default(ImmutableArray <RefKind>), false, default(ImmutableArray <int>), constantValue, null, ctor.ContainingType)); }
/// <summary> /// Tries to convert <paramref name="value"/> to a <see cref="ConstantValue"/> if possible. /// Argument that doesn't have value or values which cannot be represented as <see cref="ConstantValue"/> causes a <c>null</c> reference to be returned. /// </summary> /// <param name="value">Optional boced value.</param> /// <returns><see cref="ConstantValue"/> instance if possible. Otherwise a <c>null</c> reference.</returns> public static ConstantValue ToConstantValueOrNull(this Optional <object> value) { if (value.HasValue) { var obj = value.Value; if (obj == null) { return(ConstantValue.Null); } if (obj is int) { return(ConstantValue.Create((int)obj)); } if (obj is long) { return(ConstantValue.Create((long)obj)); } if (obj is string) { return(ConstantValue.Create((string)obj)); } if (obj is bool) { return(ConstantValue.Create((bool)obj)); } if (obj is double) { return(ConstantValue.Create((double)obj)); } if (obj is float) { return(ConstantValue.Create((float)obj)); } if (obj is decimal) { return(ConstantValue.Create((decimal)obj)); } if (obj is ulong) { return(ConstantValue.Create((ulong)obj)); } if (obj is uint) { return(ConstantValue.Create((uint)obj)); } if (obj is sbyte) { return(ConstantValue.Create((sbyte)obj)); } if (obj is short) { return(ConstantValue.Create((short)obj)); } if (obj is DateTime) { return(ConstantValue.Create((DateTime)obj)); } } return(null); }
protected static object KeyForConstant(ConstantValue constantValue) { Debug.Assert((object)constantValue != null); return(constantValue.IsNull ? s_nullKey : constantValue.Value); }
float INumericTC <float> .FromConstantValue(ConstantValue constantValue) => constantValue.IsBad ? 0.0F : constantValue.SingleValue;
ConstantValue INumericTC <float> .ToConstantValue(float value) => ConstantValue.Create(value);
/// <summary> /// Write Code-Entry into C# Code /// </summary> /// <param name="inOutput"></param> /// <param name="inCodeEntry"></param> private TypeContainer CodeEntryHandling(ICodeEntry inCodeEntry, FieldNameFinder inNameFinder, TypeContainer inReturnType = null) { if (inCodeEntry == null) { return(null); } TypeContainer tmpReturnType = null; if (inCodeEntry is VariableDeclaration) { var tmpVarDecl = inCodeEntry as VariableDeclaration; inNameFinder.VariableList.Add(tmpVarDecl); var tmpConstant = new ConstantValue() { Type = tmpVarDecl.Type }; GetGlobalTypeForType(new FieldNameFinder(inNameFinder), tmpConstant, tmpVarDecl.Type.Name); tmpVarDecl.Type = tmpConstant.Type; } else if (inCodeEntry is ConstantValue) { var tmpConstant = (inCodeEntry as ConstantValue); var tmpVal = tmpConstant.Value?.ToString() ?? tmpConstant.Type.Name; if (tmpConstant.Value is FieldContainer) { tmpVal = (tmpConstant.Value as FieldContainer).Name; } else if (tmpConstant.Value is VariableDeclaration) { tmpVal = (tmpConstant.Value as VariableDeclaration).Name; } else if (tmpVal.EndsWith("\"")) { //It's a number, nothing to do tmpReturnType = ProjectInformation.GetAliasType("string")?.Type ?? tmpReturnType; } else if (RegexHelper.NumberCheck.IsMatch(tmpVal)) { //It's a number, nothing to do tmpReturnType = ProjectInformation.GetAliasType("int")?.Type ?? tmpReturnType; } else { //Access to Variable, Field, Param or static Class, so we need to do a lot here for Code-link if (tmpVal == "this") { inNameFinder.VariableList = new List <VariableDeclaration>(); tmpConstant.Type = inNameFinder.MethodeParentClass.Type; } else if (tmpVal == "base") { inNameFinder.Class = inNameFinder.Class.InterfaceList .Select(inItem => ProjectInformation.GetClassForType(inItem.Type.Name, new List <string> { inItem.Type.Namespace })) .FirstOrDefault(inItem => !inItem.IsInterface()); inNameFinder.VariableList = new List <VariableDeclaration>(); tmpConstant.Type = inNameFinder.Class.GetParentClass().Type; } else if (tmpVal.StartsWith("\"") && tmpVal.EndsWith("\"")) { //GetGlobalTypeForType(inNameFinder, tmpConstant, "String"); } else if (new Regex("^\\-?[0-9]*(\\.[0-9]*)?(S|D|F|L)?$").IsMatch(tmpVal)) { var tmpConstValue = tmpConstant.Value; if (tmpVal.EndsWith("L")) { GetGlobalTypeForType(inNameFinder, tmpConstant, "long"); } else if (tmpVal.EndsWith("D")) { GetGlobalTypeForType(inNameFinder, tmpConstant, "double"); } else if (tmpVal.EndsWith("S")) { GetGlobalTypeForType(inNameFinder, tmpConstant, "short"); } else if (tmpVal.EndsWith("F")) { GetGlobalTypeForType(inNameFinder, tmpConstant, "float"); } else { GetGlobalTypeForType(inNameFinder, tmpConstant, "int"); } tmpConstant.Value = tmpConstValue; } else { GetGlobalTypeForType(inNameFinder, tmpConstant, tmpVal); } tmpReturnType = tmpConstant.Type; } } else if (inCodeEntry is StatementCode) { var tmpStatement = inCodeEntry as StatementCode; if (tmpStatement.StatementType == Enum.StatementTypeEnum.If || tmpStatement.StatementType == Enum.StatementTypeEnum.Else || tmpStatement.StatementType == Enum.StatementTypeEnum.For || tmpStatement.StatementType == Enum.StatementTypeEnum.While) { if (tmpStatement.InnerContent != null) { foreach (var tmpEntry in tmpStatement.InnerContent.CodeEntries) { CodeEntryHandling(tmpEntry, new FieldNameFinder(inNameFinder)); } } if (tmpStatement.StatementCodeBlocks != null) { foreach (var tmpEntry in tmpStatement.StatementCodeBlocks.SelectMany(inItem => inItem.CodeEntries)) { CodeEntryHandling(tmpEntry, new FieldNameFinder(inNameFinder)); } } } else if (tmpStatement.StatementType == Enum.StatementTypeEnum.Assert || tmpStatement.StatementType == Enum.StatementTypeEnum.Elvis) { foreach (var tmpCodeBlock in tmpStatement.StatementCodeBlocks) { foreach (var tmpEntry in tmpCodeBlock.CodeEntries) { CodeEntryHandling(tmpEntry, new FieldNameFinder(inNameFinder)); } } } else { throw new NotImplementedException("CodeEntryHandling: StatementCode Handling not Implemented"); } } else if (inCodeEntry is SetFieldWithValue) { var tmpFieldVal = inCodeEntry as SetFieldWithValue; foreach (var tmpEntry in tmpFieldVal.VariableToAccess.CodeEntries) { CodeEntryHandling(tmpEntry, new FieldNameFinder(inNameFinder)); } foreach (var tmpEntry in tmpFieldVal.ValueToSet.CodeEntries) { CodeEntryHandling(tmpEntry, new FieldNameFinder(inNameFinder)); } } else if (inCodeEntry is VariableAccess) { var tmpVarAccess = inCodeEntry as VariableAccess; inNameFinder.StackVariables(true, true); ClassContainer tmpPrevClass = null; if (!(tmpVarAccess.Access is VariableDeclaration)) { tmpReturnType = CodeEntryHandling(tmpVarAccess.Access, inNameFinder); tmpPrevClass = inNameFinder.Class; if (tmpReturnType != null) { inNameFinder.Class = ProjectInformation.ClassFromBaseType(tmpReturnType); } else { inNameFinder.Class = null; } } if (tmpVarAccess.Child != null) { tmpReturnType = CodeEntryHandling(tmpVarAccess.Child, inNameFinder, inReturnType); } inNameFinder.Class = tmpPrevClass; inNameFinder.UnstackVariableList(); if (tmpVarAccess.BaseDataSource != null) { CodeEntryHandling(tmpVarAccess.BaseDataSource, inNameFinder, inReturnType); } } else if (inCodeEntry is ReturnCodeEntry) { foreach (var tmpEntry in (inCodeEntry as ReturnCodeEntry).CodeEntries) { CodeEntryHandling(tmpEntry, inNameFinder); } } else if (inCodeEntry is NewObjectDeclaration) { var tmpObjectDecl = (inCodeEntry as NewObjectDeclaration); CodeEntryHandling(tmpObjectDecl.InnerCode, inNameFinder); if (tmpObjectDecl.ArgumentList != null) { foreach (var tmpArgument in tmpObjectDecl.ArgumentList) { foreach (var tmpEntry in tmpArgument.CodeEntries) { CodeEntryHandling(tmpEntry, inNameFinder); } } } } else if (inCodeEntry is MethodeCall) { var tmpMethodeCall = inCodeEntry as MethodeCall; var tmpParentClass = inNameFinder.Class; while (tmpParentClass != null) { tmpMethodeCall.MethodeLink = tmpParentClass.MethodeList.FirstOrDefault(inItem => inItem.Name == tmpMethodeCall.Name); if (tmpMethodeCall.MethodeLink != null) { break; } tmpParentClass = tmpParentClass.GetParentClass(); foreach (var tmpParam in tmpMethodeCall.Parameter) { foreach (var tmpEntry in tmpParam.CodeEntries) { CodeEntryHandling(tmpEntry, new FieldNameFinder() { VariableList = inNameFinder.GetMethodeVariableList(), Class = inNameFinder.MethodeParentClass ?? inNameFinder.Class, MethodeParentClass = inNameFinder.MethodeParentClass }); } } } if (tmpMethodeCall.MethodeLink == null) { //TODO Implement Extension Methode finding if (inNameFinder.Class is UnknownTypeClass || inNameFinder.Class is ClassContainer) { if (tmpMethodeCall.Parameter.Count > 0) { foreach (var tmpParam in tmpMethodeCall.Parameter) { for (var tmpI = 0; tmpI < tmpParam.CodeEntries.Count; tmpI++) { var tmpCodeBlock = tmpParam.CodeEntries[tmpI]; CodeEntryHandling(tmpCodeBlock, new FieldNameFinder() { VariableList = inNameFinder.GetMethodeVariableList(), Class = inNameFinder.MethodeParentClass ?? inNameFinder.Class, MethodeParentClass = inNameFinder.MethodeParentClass }); } } } var tmpMethode = Create.AddMethode(inNameFinder.Class, tmpMethodeCall.Name, inReturnType ?? TypeContainer.Void); tmpMethode.ReturnType = /*inReturnType ??*/ TypeContainer.Void; tmpReturnType = tmpMethode.ReturnType; } else if (inNameFinder.Class == null) { } else { throw new NotImplementedException("Unknown Methode on Class"); } } else { if (tmpMethodeCall.Parameter.Count > 0) { foreach (var tmpParam in tmpMethodeCall.Parameter) { for (var tmpI = 0; tmpI < tmpParam.CodeEntries.Count; tmpI++) { var tmpCodeBlock = tmpParam.CodeEntries[tmpI]; CodeEntryHandling(tmpCodeBlock, new FieldNameFinder() { VariableList = inNameFinder.GetMethodeVariableList(), Class = inNameFinder.MethodeParentClass ?? inNameFinder.Class, MethodeParentClass = inNameFinder.MethodeParentClass }); } } } tmpReturnType = tmpMethodeCall.MethodeLink.ReturnType; } } else if (inCodeEntry is CodeExpression) { var tmpExpr = inCodeEntry as CodeExpression; tmpReturnType = inReturnType; foreach (var tmpSubClause in tmpExpr.SubClauseEntries) { foreach (var tmpCodeEntry in tmpSubClause.CodeEntries) { tmpReturnType = CodeEntryHandling(tmpCodeEntry, inNameFinder, tmpReturnType); } } } else if (inCodeEntry is CodeBlockContainer) { var tmpExpr = inCodeEntry as CodeBlockContainer; tmpReturnType = inReturnType; foreach (var tmpEntry in tmpExpr.InnerBlock.CodeEntries) { tmpReturnType = CodeEntryHandling(tmpEntry, inNameFinder); } } else if (inCodeEntry is TypeConversion) { var tmpExpr = inCodeEntry as TypeConversion; tmpReturnType = tmpExpr.Type; foreach (var tmpEntry in tmpExpr.PreconversionValue.CodeEntries) { CodeEntryHandling(tmpEntry, inNameFinder); } } else { throw new NotImplementedException("Code Entry Type not Implement"); } return(tmpReturnType); }
public BoundDecisionDag SimplifyDecisionDagIfConstantInput(BoundExpression input) { if (input.ConstantValue == null) { return(this); } else { ConstantValue inputConstant = input.ConstantValue; return(Rewrite(makeReplacement)); // Make a replacement for a given node, using the precomputed replacements for its successors. BoundDecisionDagNode makeReplacement(BoundDecisionDagNode dag, Func <BoundDecisionDagNode, BoundDecisionDagNode> replacement) { if (dag is BoundTestDecisionDagNode p) { // This is the key to the optimization. The result of a top-level test might be known if the input is constant. switch (knownResult(p.Test)) { case true: return(replacement(p.WhenTrue)); case false: return(replacement(p.WhenFalse)); } } return(TrivialReplacement(dag, replacement)); } // Is the decision's result known because the input is a constant? bool?knownResult(BoundDagTest choice) { if (!choice.Input.IsOriginalInput) { // This is a test of something other than the main input; result unknown return(null); } switch (choice) { case BoundDagExplicitNullTest d: return(inputConstant.IsNull); case BoundDagNonNullTest d: return(!inputConstant.IsNull); case BoundDagValueTest d: return(d.Value == inputConstant); case BoundDagTypeTest d: return(inputConstant.IsNull ? (bool?)false : null); case BoundDagRelationalTest d: var f = ValueSetFactory.ForType(input.Type); if (f is null) { return(null); } return(f.Related(d.Relation.Operator(), inputConstant, d.Value)); default: throw ExceptionUtilities.UnexpectedValue(choice); } } } }
protected BoundExpression ConvertCaseExpression(CSharpSyntaxNode node, BoundExpression caseExpression, Binder sectionBinder, out ConstantValue constantValueOpt, DiagnosticBag diagnostics, bool isGotoCaseExpr = false) { bool hasErrors = false; if (isGotoCaseExpr) { // SPEC VIOLATION for Dev10 COMPATIBILITY: // Dev10 compiler violates the SPEC comment below: // "if the constant-expression is not implicitly convertible (§6.1) to // the governing type of the nearest enclosing switch statement, // a compile-time error occurs" // If there is no implicit conversion from gotoCaseExpression to switchGoverningType, // but there exists an explicit conversion, Dev10 compiler generates a warning "WRN_GotoCaseShouldConvert" // instead of an error. See test "CS0469_NoImplicitConversionWarning". HashSet <DiagnosticInfo> useSiteDiagnostics = null; Conversion conversion = Conversions.ClassifyConversionFromExpression(caseExpression, SwitchGoverningType, ref useSiteDiagnostics); diagnostics.Add(node, useSiteDiagnostics); if (!conversion.IsValid) { GenerateImplicitConversionError(diagnostics, node, conversion, caseExpression, SwitchGoverningType); hasErrors = true; } else if (!conversion.IsImplicit) { diagnostics.Add(ErrorCode.WRN_GotoCaseShouldConvert, node.Location, SwitchGoverningType); hasErrors = true; } caseExpression = CreateConversion(caseExpression, conversion, SwitchGoverningType, diagnostics); } return(ConvertPatternExpression(SwitchGoverningType, node, caseExpression, out constantValueOpt, hasErrors, diagnostics)); }
private static void ReportAsOperatorConstantWarnings( CSharpSyntaxNode node, DiagnosticBag diagnostics, TypeSymbol operandType, TypeSymbol targetType, ConversionKind conversionKind, ConstantValue operandConstantValue) { // NOTE: Even though BoundIsOperator and BoundAsOperator will always have no ConstantValue // NOTE: (they are non-constant expressions according to Section 7.19 of the specification), // NOTE: we want to perform constant analysis of is/as expressions to generate warnings if the // NOTE: expression will always be true/false/null. ConstantValue constantValue = GetAsOperatorConstantResult(operandType, targetType, conversionKind, operandConstantValue); if (constantValue != null) { Debug.Assert(constantValue.IsNull); Error(diagnostics, ErrorCode.WRN_AlwaysNull, node, targetType); } }
internal static ConstantValue GetIsOperatorConstantResult(TypeSymbol operandType, TypeSymbol targetType, ConversionKind conversionKind, ConstantValue operandConstantValue) { Debug.Assert((object)targetType != null); // SPEC: The result of the operation depends on D and T as follows: // SPEC: 1) If T is a reference type, the result is true if D and T are the same type, if D is a reference type and // SPEC: an implicit reference conversion from D to T exists, or if D is a value type and a boxing conversion from D to T exists. // SPEC: 2) If T is a nullable type, the result is true if D is the underlying type of T. // SPEC: 3) If T is a non-nullable value type, the result is true if D and T are the same type. // SPEC: 4) Otherwise, the result is false. // NOTE: The language specification talks about the runtime evaluation of the is operation. // NOTE: However, we are interested in computing the compile time constant value for the expression. // NOTE: Even though BoundIsOperator and BoundAsOperator will always have no ConstantValue // NOTE: (they are non-constant expressions according to Section 7.19 of the specification), // NOTE: we want to perform constant analysis of is/as expressions during binding to generate warnings (always true/false/null) // NOTE: and during rewriting for optimized codegen. // NOTE: // NOTE: Because the heuristic presented here is used to change codegen, it must be conservative. It is acceptable // NOTE: for us to fail to report a warning in cases where humans could logically deduce that the operator will // NOTE: always return false. It is not acceptable to inaccurately warn that the operator will always return false // NOTE: if there are cases where it might succeed. // // To begin our heuristic: if the operand is literal null then we automatically return that the // result is false. You might think that we can simply check to see if the conversion is // ConversionKind.NullConversion, but "null is T" for a type parameter T is actually classified // as an implicit reference conversion if T is constrained to reference types. Rather // than deal with all those special cases we can simply bail out here. if (operandConstantValue == ConstantValue.Null) { return ConstantValue.False; } Debug.Assert((object)operandType != null); switch (conversionKind) { case ConversionKind.NoConversion: // Oddly enough, "x is T" can be true even if there is no conversion from x to T! // // Scenario 1: Type parameter compared to System.Enum. // // bool M1<X>(X x) where X : struct { return x is Enum; } // // There is no conversion from X to Enum, not even an explicit conversion. But // nevertheless, X could be constructed as an enumerated type. // However, we can sometimes know that the result will be false. // // Scenario 2: Constrained type parameter compared to reference type. // // bool M2<X>(X x) where X : struct { return x is string; } // // We know that X, constrained to struct, will never be string. // // Scenario 3: Value type compared to type parameter. // // bool M3<T>(int x) { return x is T; } // // There is no conversion from int to T, but T could nevertheless be int. // // Scenario 4: Constructed type compared to open type // // bool M4<T>(C<int> x) { return x is C<T>; } // // There is no conversion from C<int> to C<T>, but nevertheless, T might be int. // // Scenario 5: Open type compared to constructed type: // // bool M5<X>(C<X> x) { return x is C<int>); // // Again, X could be int. // // We could then go on to get more complicated. For example, // // bool M6<X>(C<X> x) where X : struct { return x is C<string>; } // // We know that C<X> is never convertible to C<string> no matter what // X is. Or: // // bool M7<T>(Dictionary<int, int> x) { return x is List<T>; } // // We know that no matter what T is, the conversion will never succeed. // // As noted above, we must be conservative. We follow the lead of the native compiler, // which uses the following algorithm: // // * If neither type is open and there is no conversion then the result is always false: if (!operandType.ContainsTypeParameter() && !targetType.ContainsTypeParameter()) { return ConstantValue.False; } // * Otherwise, at least one of them is of an open type. If the operand is of value type // and the target is a class type other than System.Enum, then we are in scenario 2, // not scenario 1, and can correctly deduce that the result is false. if (operandType.IsValueType && targetType.IsClassType() && targetType.SpecialType != SpecialType.System_Enum) { return ConstantValue.False; } // * Otherwise, we give up. Though there are other situations in which we can deduce that // the result will always be false, such as scenarios 6 and 7, but we do not attempt // to deduce this. // CONSIDER: we could use TypeUnification.CanUnify to do additional compile-time checking. return null; case ConversionKind.ImplicitNumeric: case ConversionKind.ExplicitNumeric: case ConversionKind.ImplicitEnumeration: // case ConversionKind.ExplicitEnumeration: // Handled separately below. case ConversionKind.ImplicitConstant: case ConversionKind.ImplicitUserDefined: case ConversionKind.ExplicitUserDefined: case ConversionKind.IntPtr: // Consider all the cases where we know that "x is T" must be false just from // the conversion classification. // // If we have "x is T" and the conversion from x to T is numeric or enum then the result must be false. // // If we have "null is T" then obviously that must be false. // // If we have "1 is long" then that must be false. (If we have "1 is int" then it is an identity conversion, // not an implicit constant conversion. // // User-defined and IntPtr conversions are always false for "is". return ConstantValue.False; case ConversionKind.ExplicitEnumeration: // Enum-to-enum conversions should be treated the same as unsuccessful struct-to-struct // conversions (i.e. make allowances for type unification, etc) if (operandType.IsEnumType() && targetType.IsEnumType()) { goto case ConversionKind.NoConversion; } return ConstantValue.False; case ConversionKind.ExplicitNullable: // An explicit nullable conversion is a conversion of one of the following forms: // // 1) X? --> Y?, where X --> Y is an explicit conversion. (If X --> Y is an implicit // conversion then X? --> Y? is an implicit nullable conversion.) In this case we // know that "X? is Y?" must be false because either X? is null, or we have an // explicit conversion from struct type X to struct type Y, and so X is never of type Y.) // // 2) X --> Y?, where again, X --> Y is an explicit conversion. By the same reasoning // as in case 1, this must be false. if (targetType.IsNullableType()) { return ConstantValue.False; } Debug.Assert(operandType.IsNullableType()); // 3) X? --> X. In this case, this is just a different way of writing "x != null". // We do not know what the result will be. // CONSIDER: If we know statically that the operand is going to be null or non-null // CONSIDER: then we could give a better result here. if (Conversions.HasIdentityConversion(operandType.GetNullableUnderlyingType(), targetType)) { return null; } // 4) X? --> Y where the conversion X --> Y is an implicit or explicit value type conversion. // "X? is Y" again must be false. return ConstantValue.False; case ConversionKind.ImplicitReference: case ConversionKind.ExplicitReference: case ConversionKind.Unboxing: // In these three cases, the expression type must be a reference type. Therefore, // the result cannot be determined. The expression could be null, resulting // in false, or it could be a non-null reference to the appropriate type, // resulting in true. return null; case ConversionKind.Identity: // The result of "x is T" can be statically determined to be true if x is an expression // of non-nullable value type T. If x is of reference or nullable value type then // we cannot know, because again, the expression value could be null or it could be good. // If it is of pointer type then we have already given an error. return (operandType.IsValueType && !operandType.IsNullableType()) ? ConstantValue.True : null; case ConversionKind.Boxing: // A boxing conversion might be a conversion: // // * From a non-nullable value type to a reference type // * From a nullable value type to a reference type // * From a type parameter that *could* be a value type under construction // to a reference type // // In the first case we know that the conversion will always succeed and that the // operand is never null, and therefore "is" will always result in true. // // In the second two cases we do not know; either the nullable value type could be // null, or the type parameter could be constructed with a reference type, and it // could be null. return operandType.IsValueType && !operandType.IsNullableType() ? ConstantValue.True : null; case ConversionKind.ImplicitNullable: // We have "x is T" in one of the following situations: // 1) x is of type X and T is X?. The value is always true. // 2) x is of type X and T is Y? where X is convertible to Y via an implicit numeric conversion. Eg, // x is of type int and T is decimal?. The value is always false. // 3) x is of type X? and T is Y? where X is convertible to Y via an implicit numeric conversion. // The value is always false. Debug.Assert(targetType.IsNullableType()); return (operandType == targetType.GetNullableUnderlyingType()) ? ConstantValue.True : ConstantValue.False; default: case ConversionKind.ImplicitDynamic: case ConversionKind.ExplicitDynamic: case ConversionKind.PointerToInteger: case ConversionKind.PointerToPointer: case ConversionKind.PointerToVoid: case ConversionKind.IntegerToPointer: case ConversionKind.NullToPointer: case ConversionKind.AnonymousFunction: case ConversionKind.NullLiteral: case ConversionKind.MethodGroup: // We've either replaced Dynamic with Object, or already bailed out with an error. throw ExceptionUtilities.UnexpectedValue(conversionKind); } }
private BoundExpression ConvertCaseExpression(TypeSymbol switchGoverningType, CSharpSyntaxNode node, BoundExpression caseExpression, ref ConstantValue constantValueOpt, DiagnosticBag diagnostics, bool isGotoCaseExpr = false) { BoundExpression convertedCaseExpression; if (!isGotoCaseExpr) { // NOTE: This will allow user-defined conversions, even though they're not allowed here. This is acceptable // because the result of a user-defined conversion does not have a ConstantValue and we'll report a diagnostic // to that effect below (same error code as Dev10). convertedCaseExpression = GenerateConversionForAssignment(switchGoverningType, caseExpression, diagnostics); } else { // SPEC VIOLATION for Dev10 COMPATIBILITY: // Dev10 compiler violates the SPEC comment below: // "if the constant-expression is not implicitly convertible (§6.1) to // the governing type of the nearest enclosing switch statement, // a compile-time error occurs" // If there is no implicit conversion from gotoCaseExpression to switchGoverningType, // but there exists an explicit conversion, Dev10 compiler generates a warning "WRN_GotoCaseShouldConvert" // instead of an error. See test "CS0469_NoImplicitConversionWarning". // CONSIDER: Should we introduce a breaking change and violate Dev10 compatibility and follow the spec? HashSet <DiagnosticInfo> useSiteDiagnostics = null; Conversion conversion = Conversions.ClassifyConversionFromExpression(caseExpression, switchGoverningType, ref useSiteDiagnostics); diagnostics.Add(node, useSiteDiagnostics); if (!conversion.IsValid) { GenerateImplicitConversionError(diagnostics, node, conversion, caseExpression, switchGoverningType); } else if (!conversion.IsImplicit) { diagnostics.Add(ErrorCode.WRN_GotoCaseShouldConvert, node.Location, switchGoverningType); } convertedCaseExpression = this.CreateConversion(caseExpression, conversion, switchGoverningType, diagnostics); } if (switchGoverningType.IsNullableType() && convertedCaseExpression.Kind == BoundKind.Conversion) { constantValueOpt = ((BoundConversion)convertedCaseExpression).Operand.ConstantValue; } else { constantValueOpt = convertedCaseExpression.ConstantValue; } return(convertedCaseExpression); }
private ConstantValue DecodeDefaultParameterValueAttribute(CSharpAttributeData attribute, AttributeSyntax node, bool diagnose, DiagnosticBag diagnosticsOpt) { Debug.Assert(!diagnose || diagnosticsOpt != null); if (HasDefaultArgumentSyntax) { // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute if (diagnose) { diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueUsedWithAttributes, node.Name.Location); } return(ConstantValue.Bad); } // BREAK: In dev10, DefaultParameterValueAttribute could not be applied to System.Type or array parameters. // When this was attempted, dev10 produced CS1909, ERR_DefaultValueBadParamType. Roslyn takes a different // approach: instead of looking at the parameter type, we look at the argument type. There's nothing wrong // with providing a default value for a System.Type or array parameter, as long as the default parameter // is not a System.Type or an array (i.e. null is fine). Since we are no longer interested in the type of // the parameter, all occurrences of CS1909 have been replaced with CS1910, ERR_DefaultValueBadValueType, // to indicate that the argument type, rather than the parameter type, is the source of the problem. Debug.Assert(attribute.CommonConstructorArguments.Length == 1); // the type of the value is the type of the expression in the attribute: var arg = attribute.CommonConstructorArguments[0]; SpecialType specialType = arg.Kind == TypedConstantKind.Enum ? ((INamedTypeSymbol)arg.Type).EnumUnderlyingType.SpecialType : arg.Type.SpecialType; var compilation = this.DeclaringCompilation; var constantValueDiscriminator = ConstantValue.GetDiscriminator(specialType); HashSet <DiagnosticInfo> useSiteDiagnostics = null; if (constantValueDiscriminator == ConstantValueTypeDiscriminator.Bad) { if (arg.Kind != TypedConstantKind.Array && arg.Value == null) { if (this.Type.IsReferenceType) { constantValueDiscriminator = ConstantValueTypeDiscriminator.Null; } else { // error CS1908: The type of the argument to the DefaultParameterValue attribute must match the parameter type if (diagnose) { diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueTypeMustMatch, node.Name.Location); } return(ConstantValue.Bad); } } else { // error CS1910: Argument of type '{0}' is not applicable for the DefaultParameterValue attribute if (diagnose) { diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueBadValueType, node.Name.Location, arg.Type); } return(ConstantValue.Bad); } } else if (!compilation.Conversions.ClassifyConversion((TypeSymbol)arg.Type, this.Type, ref useSiteDiagnostics).Kind.IsImplicitConversion()) { // error CS1908: The type of the argument to the DefaultParameterValue attribute must match the parameter type if (diagnose) { diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueTypeMustMatch, node.Name.Location); diagnosticsOpt.Add(node.Name.Location, useSiteDiagnostics); } return(ConstantValue.Bad); } if (diagnose) { diagnosticsOpt.Add(node.Name.Location, useSiteDiagnostics); } return(ConstantValue.Create(arg.Value, constantValueDiscriminator)); }
public int FromConstantValue(ConstantValue constantValue) { // We could have a negate value in source, but it won't get past NonNegativeIntValueSetFactory.Related return(constantValue.IsBad ? 0 : constantValue.Int32Value); }
private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSyntax node, DiagnosticBag diagnostics) { var builder = ArrayBuilder <BoundExpression> .GetInstance(); var stringType = GetSpecialType(SpecialType.System_String, diagnostics, node); var objectType = GetSpecialType(SpecialType.System_Object, diagnostics, node); var intType = GetSpecialType(SpecialType.System_Int32, diagnostics, node); foreach (var content in node.Contents) { switch (content.Kind()) { case SyntaxKind.Interpolation: { var interpolation = (InterpolationSyntax)content; var value = BindValue(interpolation.Expression, diagnostics, Binder.BindValueKind.RValue); // We need to ensure the argument is not a lambda, method group, etc. It isn't nice to wait until lowering, // when we perform overload resolution, to report a problem. So we do that check by calling // GenerateConversionForAssignment with objectType. However we want to preserve the original expression's // natural type so that overload resolution may select a specialized implementation of string.Format, // so we discard the result of that call and only preserve its diagnostics. var discarded = GenerateConversionForAssignment(objectType, value, diagnostics); BoundExpression alignment = null, format = null; if (interpolation.AlignmentClause != null) { alignment = GenerateConversionForAssignment(intType, BindValue(interpolation.AlignmentClause.Value, diagnostics, Binder.BindValueKind.RValue), diagnostics); var alignmentConstant = alignment.ConstantValue; if (alignmentConstant != null && !alignmentConstant.IsBad) { const int magnitudeLimit = 32767; // check that the magnitude of the alignment is "in range". int alignmentValue = alignmentConstant.Int32Value; // We do the arithmetic using negative numbers because the largest negative int has no corresponding positive (absolute) value. alignmentValue = (alignmentValue > 0) ? -alignmentValue : alignmentValue; if (alignmentValue < -magnitudeLimit) { diagnostics.Add(ErrorCode.WRN_AlignmentMagnitude, alignment.Syntax.Location, alignmentConstant.Int32Value, magnitudeLimit); } } else if (!alignment.HasErrors) { diagnostics.Add(ErrorCode.ERR_ConstantExpected, interpolation.AlignmentClause.Value.Location); } } if (interpolation.FormatClause != null) { var text = interpolation.FormatClause.FormatStringToken.ValueText; char lastChar; bool hasErrors = false; if (text.Length == 0) { diagnostics.Add(ErrorCode.ERR_EmptyFormatSpecifier, interpolation.FormatClause.Location); hasErrors = true; } else if (SyntaxFacts.IsWhitespace(lastChar = text[text.Length - 1]) || SyntaxFacts.IsNewLine(lastChar)) { diagnostics.Add(ErrorCode.ERR_TrailingWhitespaceInFormatSpecifier, interpolation.FormatClause.Location); hasErrors = true; } format = new BoundLiteral(interpolation.FormatClause, ConstantValue.Create(text), stringType, hasErrors); } builder.Add(new BoundStringInsert(interpolation, value, alignment, format, null)); continue; } case SyntaxKind.InterpolatedStringText: { var text = ((InterpolatedStringTextSyntax)content).TextToken.ValueText; builder.Add(new BoundLiteral(node, ConstantValue.Create(text, SpecialType.System_String), stringType)); continue; } default: throw ExceptionUtilities.Unreachable; } } return(new BoundInterpolatedString(node, builder.ToImmutableAndFree(), stringType)); }
/// <summary> /// TBD ?!? /// </summary> public object ParseItem(XmlReader reader) { switch (reader.NodeType) { case XmlNodeType.Element: if (reader.Name.ToLower() == "filter") { reader.Read(); return(ParseItem(reader)); } if (reader.Name.ToLower() == "propertyisequalto") { reader.Read(); FieldValue fieldValue = (FieldValue)ParseItem(reader); reader.Read(); FixedValue fixedValue = (FixedValue)ParseItem(reader); reader.Read(); return(new BinaryComparisionOperation(fieldValue, fixedValue, WFSBinaryComparisionOperator.EqualTo)); } if (reader.Name.ToLower() == "propertyisgreaterthan") { reader.Read(); FieldValue fieldValue = (FieldValue)ParseItem(reader); reader.Read(); FixedValue fixedValue = (FixedValue)ParseItem(reader); reader.Read(); return(new BinaryComparisionOperation(fieldValue, fixedValue, WFSBinaryComparisionOperator.GreaterThan)); } if (reader.Name.ToLower() == "propertyisgreaterthanorequalto") { reader.Read(); FieldValue fieldValue = (FieldValue)ParseItem(reader); reader.Read(); FixedValue fixedValue = (FixedValue)ParseItem(reader); reader.Read(); return(new BinaryComparisionOperation(fieldValue, fixedValue, WFSBinaryComparisionOperator.GreaterOrEqualTo)); } if (reader.Name.ToLower() == "propertyislessthanorequalto") { reader.Read(); FieldValue fieldValue = (FieldValue)ParseItem(reader); reader.Read(); FixedValue fixedValue = (FixedValue)ParseItem(reader); reader.Read(); return(new BinaryComparisionOperation(fieldValue, fixedValue, WFSBinaryComparisionOperator.LessOrEqualTo)); } if (reader.Name.ToLower() == "propertyislessthan") { reader.Read(); FieldValue fieldValue = (FieldValue)ParseItem(reader); reader.Read(); FixedValue fixedValue = (FixedValue)ParseItem(reader); reader.Read(); return(new BinaryComparisionOperation(fieldValue, fixedValue, WFSBinaryComparisionOperator.LessThan)); } if (reader.Name.ToLower() == "propertyislike") { reader.Read(); FieldValue fieldValue = (FieldValue)ParseItem(reader); reader.Read(); FixedValue fixedValue = (FixedValue)ParseItem(reader); reader.Read(); return(new BinaryComparisionOperation(fieldValue, fixedValue, WFSBinaryComparisionOperator.Like)); } if (reader.Name.ToLower() == "propertyisnotequalto") { reader.Read(); FieldValue fieldValue = (FieldValue)ParseItem(reader); reader.Read(); FixedValue fixedValue = (FixedValue)ParseItem(reader); reader.Read(); return(new BinaryComparisionOperation(fieldValue, fixedValue, WFSBinaryComparisionOperator.NotEqualTo)); } if (reader.Name.ToLower() == "propertyisnull") { reader.Read(); FieldValue fieldValue = (FieldValue)ParseItem(reader); reader.Read(); return(new UnaryComparisionOperation(fieldValue, WFSUnaryComparisionOperator.IsNull)); } if (reader.Name.ToLower() == "or") { reader.Read(); FormulaOperation leftOperand = (FormulaOperation)ParseItem(reader); reader.Read(); FormulaOperation rightOperand = (FormulaOperation)ParseItem(reader); reader.Read(); return(new BinaryLogicalOperation(leftOperand, rightOperand, WFSBinaryLogicalOperator.Or)); } if (reader.Name.ToLower() == "and") { reader.Read(); FormulaOperation leftOperand = (FormulaOperation)ParseItem(reader); reader.Read(); FormulaOperation rightOperand = (FormulaOperation)ParseItem(reader); reader.Read(); return(new BinaryLogicalOperation(leftOperand, rightOperand, WFSBinaryLogicalOperator.And)); } if (reader.Name.ToLower() == "not") { reader.Read(); FormulaOperation operand = (FormulaOperation)ParseItem(reader); reader.Read(); return(new UnaryLogicalOperation(operand, WFSUnaryLogicalOperator.Not)); } if (reader.Name.ToLower() == "propertyname") // leaf { reader.Read(); FieldValue fieldValue = new FieldValue(reader.Value); reader.Read(); return(fieldValue); } if (reader.Name.ToLower() == "literal") // leaf { reader.Read(); ConstantValue constantValue = new ConstantValue(reader.Value); reader.Read(); return(constantValue); } break; } reader.Read(); return(null); }
private BoundExpression MakeEventAccess( CSharpSyntaxNode syntax, BoundExpression rewrittenReceiver, EventSymbol eventSymbol, ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type) { Debug.Assert(eventSymbol.HasAssociatedField); FieldSymbol fieldSymbol = eventSymbol.AssociatedField; Debug.Assert((object)fieldSymbol != null); if (!eventSymbol.IsWindowsRuntimeEvent) { return(MakeFieldAccess(syntax, rewrittenReceiver, fieldSymbol, constantValueOpt, resultKind, type)); } NamedTypeSymbol fieldType = (NamedTypeSymbol)fieldSymbol.Type; Debug.Assert(fieldType.Name == "EventRegistrationTokenTable"); // _tokenTable BoundFieldAccess fieldAccess = new BoundFieldAccess( syntax, fieldSymbol.IsStatic ? null : rewrittenReceiver, fieldSymbol, constantValueOpt: null) { WasCompilerGenerated = true }; BoundExpression getOrCreateCall; MethodSymbol getOrCreateMethod; if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable, out getOrCreateMethod)) { getOrCreateMethod = getOrCreateMethod.AsMember(fieldType); // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable) getOrCreateCall = BoundCall.Synthesized( syntax, receiverOpt: null, method: getOrCreateMethod, arguments: fieldAccess); } else { getOrCreateCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(fieldAccess), ErrorTypeSymbol.UnknownResultType); } PropertySymbol invocationListProperty; if (TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__InvocationList, out invocationListProperty)) { MethodSymbol invocationListAccessor = invocationListProperty.GetMethod; if ((object)invocationListAccessor == null) { string accessorName = SourcePropertyAccessorSymbol.GetAccessorName(invocationListProperty.Name, getNotSet: true, isWinMdOutput: invocationListProperty.IsCompilationOutputWinMdObj()); diagnostics.Add(new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember, invocationListProperty.ContainingType, accessorName), syntax.Location); } else { invocationListAccessor = invocationListAccessor.AsMember(fieldType); return(factory.Call(getOrCreateCall, invocationListAccessor)); } } return(new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(getOrCreateCall), ErrorTypeSymbol.UnknownResultType)); }
public BoundObjectCreationExpression Update(MethodSymbol constructor, ImmutableArray <BoundExpression> arguments, ImmutableArray <string> argumentNamesOpt, ImmutableArray <RefKind> argumentRefKindsOpt, bool expanded, ImmutableArray <int> argsToParamsOpt, ConstantValue constantValueOpt, BoundObjectInitializerExpressionBase initializerExpressionOpt, Binder binderOpt, TypeSymbol type) { return(this.Update(constructor, ImmutableArray <MethodSymbol> .Empty, arguments, argumentNamesOpt, argumentRefKindsOpt, expanded, argsToParamsOpt, constantValueOpt, initializerExpressionOpt, binderOpt, type)); }
ConstantValue INumericTC <char> .ToConstantValue(char value) => ConstantValue.Create(value);
/// <summary> /// Translates the value of a constant returned by <see cref="ISymUnmanagedConstant.GetValue(out object)"/> to a <see cref="ConstantValue"/>. /// </summary> public static ConstantValue GetSymConstantValue(ITypeSymbolInternal type, object symValue) { if (type.TypeKind == TypeKind.Enum) { type = ((INamedTypeSymbolInternal)type).EnumUnderlyingType; } return((type.SpecialType, symValue) switch { (SpecialType.System_Boolean, short shortVal) => ConstantValue.Create(shortVal != 0), (SpecialType.System_Byte, short shortVal)when unchecked ((byte)shortVal) == shortVal => ConstantValue.Create((byte)shortVal), (SpecialType.System_SByte, short shortVal)when unchecked ((sbyte)shortVal) == shortVal => ConstantValue.Create((sbyte)shortVal), (SpecialType.System_Int16, short shortVal) => ConstantValue.Create(shortVal), (SpecialType.System_Char, ushort ushortVal) => ConstantValue.Create((char)ushortVal), (SpecialType.System_UInt16, ushort ushortVal) => ConstantValue.Create(ushortVal), (SpecialType.System_Int32, int intVal) => ConstantValue.Create(intVal), (SpecialType.System_UInt32, uint uintVal) => ConstantValue.Create(uintVal), (SpecialType.System_Int64, long longVal) => ConstantValue.Create(longVal), (SpecialType.System_UInt64, ulong ulongVal) => ConstantValue.Create(ulongVal), (SpecialType.System_Single, float floatVal) => ConstantValue.Create(floatVal), (SpecialType.System_Double, double doubleVal) => ConstantValue.Create(doubleVal), (SpecialType.System_String, 0) => ConstantValue.Null, (SpecialType.System_String, null) => ConstantValue.Create(string.Empty), (SpecialType.System_String, string str) => ConstantValue.Create(str), (SpecialType.System_Object, 0) => ConstantValue.Null, (SpecialType.System_Decimal, decimal decimalValue) => ConstantValue.Create(decimalValue), (SpecialType.System_DateTime, double doubleVal) => ConstantValue.Create(DateTimeUtilities.ToDateTime(doubleVal)), (SpecialType.None, 0)when type.IsReferenceType => ConstantValue.Null, _ => ConstantValue.Bad, });
/// <summary> /// Generates a submission initialization part of a Script type constructor that represents an interactive submission. /// </summary> /// <remarks> /// The constructor takes a parameter of type Microsoft.CodeAnalysis.Scripting.Session - the session reference. /// It adds the object being constructed into the session by calling Microsoft.CSharp.RuntimeHelpers.SessionHelpers.SetSubmission, /// and retrieves strongly typed references on all previous submission script classes whose members are referenced by this submission. /// The references are stored to fields of the submission (<paramref name="synthesizedFields"/>). /// </remarks> private static void MakeSubmissionInitialization( ArrayBuilder <BoundStatement> statements, SyntaxNode syntax, MethodSymbol submissionConstructor, SynthesizedSubmissionFields synthesizedFields, CSharpCompilation compilation) { Debug.Assert(submissionConstructor.ParameterCount == 1); var submissionArrayReference = new BoundParameter(syntax, submissionConstructor.Parameters[0]) { WasCompilerGenerated = true }; var intType = compilation.GetSpecialType(SpecialType.System_Int32); var objectType = compilation.GetSpecialType(SpecialType.System_Object); var thisReference = new BoundThisReference(syntax, submissionConstructor.ContainingType) { WasCompilerGenerated = true }; var slotIndex = compilation.GetSubmissionSlotIndex(); Debug.Assert(slotIndex >= 0); // <submission_array>[<slot_index] = this; statements.Add(new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundArrayAccess(syntax, submissionArrayReference, ImmutableArray.Create <BoundExpression>(new BoundLiteral(syntax, ConstantValue.Create(slotIndex), intType) { WasCompilerGenerated = true }), objectType) { WasCompilerGenerated = true }, thisReference, RefKind.None, thisReference.Type) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }); var hostObjectField = synthesizedFields.GetHostObjectField(); if ((object)hostObjectField != null) { // <host_object> = (<host_object_type>)<submission_array>[0] statements.Add( new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, thisReference, hostObjectField, ConstantValue.NotAvailable) { WasCompilerGenerated = true }, BoundConversion.Synthesized(syntax, new BoundArrayAccess(syntax, submissionArrayReference, ImmutableArray.Create <BoundExpression>(new BoundLiteral(syntax, ConstantValue.Create(0), intType) { WasCompilerGenerated = true }), objectType), Conversion.ExplicitReference, false, true, ConstantValue.NotAvailable, hostObjectField.Type ), hostObjectField.Type) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }); } foreach (var field in synthesizedFields.FieldSymbols) { var targetScriptType = (ImplicitNamedTypeSymbol)field.Type; var targetSubmissionIndex = targetScriptType.DeclaringCompilation.GetSubmissionSlotIndex(); Debug.Assert(targetSubmissionIndex >= 0); // this.<field> = (<target_script_type>)<submission_array>[<target_submission_index>]; statements.Add( new BoundExpressionStatement(syntax, new BoundAssignmentOperator(syntax, new BoundFieldAccess(syntax, thisReference, field, ConstantValue.NotAvailable) { WasCompilerGenerated = true }, BoundConversion.Synthesized(syntax, new BoundArrayAccess(syntax, submissionArrayReference, ImmutableArray.Create <BoundExpression>(new BoundLiteral(syntax, ConstantValue.Create(targetSubmissionIndex), intType) { WasCompilerGenerated = true }), objectType) { WasCompilerGenerated = true }, Conversion.ExplicitReference, false, true, ConstantValue.NotAvailable, targetScriptType ), targetScriptType ) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }); } }
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); _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); if (inOutFlags == ParameterAttributes.Out) { refKind = RefKind.Out; } else if (moduleSymbol.Module.HasIsReadOnlyAttribute(handle)) { refKind = RefKind.In; } else { refKind = RefKind.Ref; } } // CONSIDER: Can we make parameter type computation lazy? type = DynamicTypeDecoder.TransformType(type, countOfCustomModifiers, handle, moduleSymbol, refKind); _type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, handle, moduleSymbol); } 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 void CheckVacuousComparisons(BoundBinaryOperator tree, ConstantValue constantValue, BoundNode operand) { Debug.Assert(tree != null); Debug.Assert(constantValue != null); Debug.Assert(operand != null); // We wish to detect comparisons between integers and constants which are likely to be wrong // because we know at compile time whether they will be true or false. For example: // // const short s = 1000; // byte b = whatever; // if (b < s) // // We know that this will always be true because when b and s are both converted to int for // the comparison, the left side will always be less than the right side. // // We only give the warning if there is no explicit conversion involved on the operand. // For example, if we had: // // const uint s = 1000; // sbyte b = whatever; // if ((byte)b < s) // // Then we do not give a warning. // // Note that the native compiler has what looks to be some dead code. It checks to see // if the conversion on the operand is from an enum type. But this is unnecessary if // we are rejecting cases with explicit conversions. The only possible cases are: // // enum == enumConstant -- enum types must be the same, so it must be in range. // enum == integralConstant -- not legal unless the constant is zero, which is in range. // enum == (ENUM)anyConstant -- if the constant is out of range then this is not legal in the first place // unless we're in an unchecked context, in which case, the user probably does // not want the warning. // integral == enumConstant -- never legal in the first place // // Since it seems pointless to try to check enums, we simply look for vacuous comparisons of // integral types here. for (BoundConversion conversion = operand as BoundConversion; conversion != null; conversion = conversion.Operand as BoundConversion) { if (conversion.ConversionKind != ConversionKind.ImplicitNumeric && conversion.ConversionKind != ConversionKind.ImplicitConstant) { return; } // As in dev11, we don't dig through explicit casts (see ExpressionBinder::WarnAboutBadRelationals). if (conversion.ExplicitCastInCode) { return; } if (!conversion.Operand.Type.SpecialType.IsIntegralType() || !conversion.Type.SpecialType.IsIntegralType()) { return; } if (!Binder.CheckConstantBounds(conversion.Operand.Type.SpecialType, constantValue)) { Error(ErrorCode.WRN_VacuousIntegralComp, tree, conversion.Operand.Type); return; } } }
public EvaluatedConstant(ConstantValue value, ImmutableArray <Diagnostic> diagnostics) { this.Value = value; this.Diagnostics = diagnostics.NullToEmpty(); }
char INumericTC <char> .FromConstantValue(ConstantValue constantValue) => constantValue.IsBad ? (char)0 : constantValue.CharValue;
public ReadOp(int offset, int repeated, ConstantValue constant) { Offset = offset; Constant = constant; Repeated = repeated; }
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); typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, handle, moduleSymbol); 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); }
private static bool ReportAsOperatorConversionDiagnostics( CSharpSyntaxNode node, DiagnosticBag diagnostics, Compilation compilation, TypeSymbol operandType, TypeSymbol targetType, ConversionKind conversionKind, ConstantValue operandConstantValue) { // SPEC: In an operation of the form E as T, E must be an expression and T must be a reference type, // SPEC: a type parameter known to be a reference type, or a nullable type. // SPEC: Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs: // SPEC: • An identity (§6.1.1), implicit nullable (§6.1.4), implicit reference (§6.1.6), boxing (§6.1.7), // SPEC: explicit nullable (§6.2.3), explicit reference (§6.2.4), or unboxing (§6.2.5) conversion exists // SPEC: from E to T. // SPEC: • The type of E or T is an open type. // SPEC: • E is the null literal. // SPEC VIOLATION: The specification contains an error in the list of legal conversions above. // SPEC VIOLATION: If we have "class C<T, U> where T : U where U : class" then there is // SPEC VIOLATION: an implicit conversion from T to U, but it is not an identity, reference or // SPEC VIOLATION: boxing conversion. It will be one of those at runtime, but at compile time // SPEC VIOLATION: we do not know which, and therefore cannot classify it as any of those. // SPEC VIOLATION: See Microsoft.CodeAnalysis.CSharp.UnitTests.SyntaxBinderTests.TestAsOperator_SpecErrorCase() test for an example. // SPEC VIOLATION: The specification also unintentionally allows the case where requirement 2 above: // SPEC VIOLATION: "The type of E or T is an open type" is true, but type of E is void type, i.e. T is an open type. // SPEC VIOLATION: Dev10 compiler correctly generates an error for this case and we will maintain compatibility. bool hasErrors = false; switch (conversionKind) { case ConversionKind.ImplicitReference: case ConversionKind.Boxing: case ConversionKind.ImplicitNullable: case ConversionKind.Identity: case ConversionKind.ExplicitNullable: case ConversionKind.ExplicitReference: case ConversionKind.Unboxing: break; default: // Generate an error if there is no possible legal conversion and both the operandType // and the targetType are closed types OR operandType is void type, otherwise we need a runtime check if (!operandType.ContainsTypeParameter() && !targetType.ContainsTypeParameter() || operandType.SpecialType == SpecialType.System_Void) { SymbolDistinguisher distinguisher = new SymbolDistinguisher(compilation, operandType, targetType); Error(diagnostics, ErrorCode.ERR_NoExplicitBuiltinConv, node, distinguisher.First, distinguisher.Second); hasErrors = true; } break; } if (!hasErrors) { ReportAsOperatorConstantWarnings(node, diagnostics, operandType, targetType, conversionKind, operandConstantValue); } return hasErrors; }
/// <exception cref="BadImageFormatException"></exception> /// <exception cref="UnsupportedSignatureContent"></exception> public override void DecodeLocalConstant(ref BlobReader reader, out TypeSymbol type, out ConstantValue value) { _metadataDecoder.DecodeLocalConstantBlobOrThrow(ref reader, out type, out value); }
internal static ConstantValue GetAsOperatorConstantResult(TypeSymbol operandType, TypeSymbol targetType, ConversionKind conversionKind, ConstantValue operandConstantValue) { // NOTE: Even though BoundIsOperator and BoundAsOperator will always have no ConstantValue // NOTE: (they are non-constant expressions according to Section 7.19 of the specification), // NOTE: we want to perform constant analysis of is/as expressions during binding to generate warnings (always true/false/null) // NOTE: and during rewriting for optimized codegen. ConstantValue isOperatorConstantResult = GetIsOperatorConstantResult(operandType, targetType, conversionKind, operandConstantValue); if (isOperatorConstantResult != null && !isOperatorConstantResult.BooleanValue) { return ConstantValue.Null; } return null; }
private void AppendConstantValue([NotNull] ConstantValue constantValue, bool treatEnumAsIntegral) { if (constantValue.IsBadValue()) { AppendText("bad value", null); return; } IEnum enumType = constantValue.Type.GetEnumType(); if (enumType != null) { if (treatEnumAsIntegral) { AppendText(constantValue.Value?.ToString() ?? String.Empty, _highlighterIdProvider.Number); return; } if (AppendEnumValue(constantValue, enumType)) { return; } } string presentation = constantValue.GetPresentation(CSharpLanguage.Instance); if (CSharpLexer.IsKeyword(presentation)) { AppendText(presentation, _highlighterIdProvider.Keyword); return; } IType type = constantValue.Type; if (type.IsNullable()) { type = type.GetNullableUnderlyingType(); } if (type == null) { AppendText(presentation, null); return; } if (type.IsString()) { AppendText(presentation, _highlighterIdProvider.String); } else if (type.IsChar()) { AppendText(presentation, _highlighterIdProvider.String); } else if (type.IsPredefinedNumeric()) { AppendText(presentation, _highlighterIdProvider.Number); } else { AppendText(presentation, null); } }