Ejemplo n.º 1
0
 private static void AppendMethodSymbolInfo(this ICollection<SymbolMarkupToken> markup, MethodSymbol symbol)
 {
     markup.AppendType(symbol.AssociatedType);
     markup.AppendSpace();
     markup.AppendName(SymbolMarkupKind.MethodName, symbol.Name);
     markup.AppendParameters(symbol.Parameters);
 }
Ejemplo n.º 2
0
 public void defineMethod(string methodName, MethodSymbol methodSymbol)
 {
     if (methods.ContainsKey(methodName))
     {
         ReptileParser.manageException(new Exception("Metodo " + methodName + " ya ha sido declarado."));
     }
     else
     {
         methods.Add(methodName, methodSymbol);
     }
 }
Ejemplo n.º 3
0
 public StateMachineTypeSymbol(VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, MethodSymbol kickoffMethod, int kickoffMethodOrdinal)
     : base(MakeName(slotAllocatorOpt, compilationState, kickoffMethod, kickoffMethodOrdinal), kickoffMethod)
 {
     Debug.Assert(kickoffMethod != null);
     this.KickoffMethod = kickoffMethod;
 }
            // For switch statements, we have an option of completely rewriting the switch header
            // and switch sections into simpler constructs, i.e. we can rewrite the switch header
            // using bound conditional goto statements and the rewrite the switch sections into
            // bound labeled statements.
            //
            // However, all the logic for emitting the switch jump tables is language agnostic
            // and includes IL optimizations. Hence we delay the switch jump table generation
            // till the emit phase. This way we also get additional benefit of sharing this code
            // between both VB and C# compilers.
            //
            // For string switch statements, we need to determine if we are generating a hash
            // table based jump table or a non hash jump table, i.e. linear string comparisons
            // with each case label. We use the Dev10 Heuristic to determine this
            // (see SwitchStringJumpTableEmitter.ShouldGenerateHashTableSwitch() for details).
            // If we are generating a hash table based jump table, we use a simple
            // hash function to hash the string constants corresponding to the case labels.
            // See SwitchStringJumpTableEmitter.ComputeStringHash().
            // We need to emit this same function to compute the hash value into the compiler generated
            // <PrivateImplementationDetails> class.
            // If we have at least one string switch statement in a module that needs a
            // hash table based jump table, we generate a single public string hash synthesized method
            // that is shared across the module.
            private void LowerBasicSwitch(DecisionTree.ByValue byValue)
            {
                var switchSections = ArrayBuilder <BoundSwitchSection> .GetInstance();

                var noValueMatches       = _factory.GenerateLabel("noValueMatches");
                var underlyingSwitchType = byValue.Type.IsEnumType() ? byValue.Type.GetEnumUnderlyingType() : byValue.Type;

                foreach (var vd in byValue.ValueAndDecision)
                {
                    var value              = vd.Key;
                    var decision           = vd.Value;
                    var constantValue      = ConstantValue.Create(value, underlyingSwitchType.SpecialType);
                    var constantExpression = new BoundLiteral(_factory.Syntax, constantValue, underlyingSwitchType);
                    var label              = _factory.GenerateLabel("case+" + value);
                    var switchLabel        = new BoundSwitchLabel(_factory.Syntax, label, constantExpression, constantValue);
                    var forValue           = ArrayBuilder <BoundStatement> .GetInstance();

                    LowerDecisionTree(byValue.Expression, decision, forValue);
                    if (!decision.MatchIsComplete)
                    {
                        forValue.Add(_factory.Goto(noValueMatches));
                    }

                    var section = new BoundSwitchSection(_factory.Syntax, ImmutableArray.Create(switchLabel), forValue.ToImmutableAndFree());
                    switchSections.Add(section);
                }

                var          rewrittenSections = switchSections.ToImmutableAndFree();
                MethodSymbol stringEquality    = null;

                if (underlyingSwitchType.SpecialType == SpecialType.System_String)
                {
                    _localRewriter.EnsureStringHashFunction(rewrittenSections, _factory.Syntax);
                    stringEquality = _localRewriter.GetSpecialTypeMethod(_factory.Syntax, SpecialMember.System_String__op_Equality);
                }

                // The BoundSwitchStatement requires a constant target when there are no sections, so we accomodate that here.
                var constantTarget  = rewrittenSections.IsEmpty ? noValueMatches : null;
                var switchStatement = new BoundSwitchStatement(
                    _factory.Syntax, null, _factory.Convert(underlyingSwitchType, byValue.Expression),
                    constantTarget,
                    ImmutableArray <LocalSymbol> .Empty, ImmutableArray <LocalFunctionSymbol> .Empty,
                    rewrittenSections, noValueMatches, stringEquality);

                // The bound switch statement implicitly defines the label noValueMatches at the end, so we do not add it explicitly.

                switch (underlyingSwitchType.SpecialType)
                {
                case SpecialType.System_Boolean:
                    // boolean switch is handled in LowerBooleanSwitch, not here.
                    throw ExceptionUtilities.Unreachable;

                case SpecialType.System_String:
                case SpecialType.System_Byte:
                case SpecialType.System_Char:
                case SpecialType.System_Int16:
                case SpecialType.System_Int32:
                case SpecialType.System_Int64:
                case SpecialType.System_SByte:
                case SpecialType.System_UInt16:
                case SpecialType.System_UInt32:
                case SpecialType.System_UInt64:
                {
                    // emit knows how to efficiently generate code for these kinds of switches.
                    _loweredDecisionTree.Add(switchStatement);
                    break;
                }

                default:
                {
                    // other types, such as float, double, and decimal, are not currently
                    // handled by emit and must be lowered here.
                    _loweredDecisionTree.Add(LowerNonprimitiveSwitch(switchStatement));
                    break;
                }
                }

                LowerDecisionTree(byValue.Expression, byValue.Default);
            }
        private BoundExpression GetLiftedUnaryOperatorConsequence(UnaryOperatorKind kind, CSharpSyntaxNode syntax, MethodSymbol method, TypeSymbol type, BoundExpression nonNullOperand)
        {
            MethodSymbol ctor = GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);

            // OP(temp.GetValueOrDefault())
            BoundExpression unliftedOp = MakeUnaryOperator(
                oldNode: null,
                kind: kind.Unlifted(),
                syntax: syntax,
                method: method,
                loweredOperand: nonNullOperand,
                type: type.GetNullableUnderlyingType());

            // new R?(OP(temp.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(
                syntax,
                ctor,
                unliftedOp);

            return(consequence);
        }
        private BoundExpression MakeBuiltInIncrementOperator(BoundIncrementOperator node, BoundExpression rewrittenValueToIncrement)
        {
            BoundExpression result;
            // If we have a built-in increment or decrement then things get a bit trickier. Suppose for example we have
            // a user-defined conversion from X to short and from short to X, but no user-defined increment operator on
            // X.  The increment portion of "++x" is then: (X)(short)((int)(short)x + 1). That is, first x must be
            // converted to short via an implicit user- defined conversion, then to int via an implicit numeric
            // conversion, then the addition is performed in integers. The resulting integer is converted back to short,
            // and then the short is converted to X.

            // This is the input and output type of the unary increment operator we're going to call.
            // That is, "short" in the example above.
            TypeSymbol unaryOperandType = GetUnaryOperatorType(node);

            // This is the kind of binary operator that we're going to realize the unary operator
            // as. That is, "int + int --> int" in the example above.
            BinaryOperatorKind binaryOperatorKind = GetCorrespondingBinaryOperator(node);

            binaryOperatorKind |= IsIncrement(node) ? BinaryOperatorKind.Addition : BinaryOperatorKind.Subtraction;

            // The "1" in the example above.
            ConstantValue constantOne = GetConstantOneForBinOp(binaryOperatorKind);

            Debug.Assert(constantOne != null);
            Debug.Assert(constantOne.SpecialType != SpecialType.None);
            Debug.Assert(binaryOperatorKind.OperandTypes() != 0);

            // The input/output type of the binary operand. "int" in the example.
            TypeSymbol binaryOperandType = _compilation.GetSpecialType(constantOne.SpecialType);

            // 1
            BoundExpression boundOne = MakeLiteral(
                syntax: node.Syntax,
                constantValue: constantOne,
                type: binaryOperandType);

            if (binaryOperatorKind.IsLifted())
            {
                binaryOperandType = _compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(binaryOperandType);
                MethodSymbol ctor = GetNullableMethod(node.Syntax, binaryOperandType, SpecialMember.System_Nullable_T__ctor);
                boundOne = new BoundObjectCreationExpression(node.Syntax, ctor, boundOne);
            }

            // Now we construct the other operand to the binary addition. We start with just plain "x".
            BoundExpression binaryOperand = rewrittenValueToIncrement;

            bool @checked = node.OperatorKind.IsChecked();

            // If we need to make a conversion from the original operand type to the operand type of the
            // underlying increment operation, do it now.
            if (!node.OperandConversion.IsIdentity)
            {
                // (short)x
                binaryOperand = MakeConversion(
                    syntax: node.Syntax,
                    rewrittenOperand: binaryOperand,
                    conversion: node.OperandConversion,
                    rewrittenType: unaryOperandType,
                    @checked: @checked);
            }

            // Early-out for pointer increment - we don't need to convert the operands to a common type.
            if (node.OperatorKind.OperandTypes() == UnaryOperatorKind.Pointer)
            {
                Debug.Assert(binaryOperatorKind.OperandTypes() == BinaryOperatorKind.PointerAndInt);
                Debug.Assert(binaryOperand.Type.IsPointerType());
                Debug.Assert(boundOne.Type.SpecialType == SpecialType.System_Int32);
                return(MakeBinaryOperator(node.Syntax, binaryOperatorKind, binaryOperand, boundOne, binaryOperand.Type, method: null));
            }

            // If we need to make a conversion from the unary operator type to the binary operator type,
            // do it now.

            // (int)(short)x
            binaryOperand = MakeConversion(binaryOperand, binaryOperandType, @checked);

            // Perform the addition.

            // (int)(short)x + 1
            BoundExpression binOp;

            if (unaryOperandType.SpecialType == SpecialType.System_Decimal)
            {
                binOp = MakeDecimalIncDecOperator(node.Syntax, binaryOperatorKind, binaryOperand);
            }
            else if (unaryOperandType.IsNullableType() && unaryOperandType.GetNullableUnderlyingType().SpecialType == SpecialType.System_Decimal)
            {
                binOp = MakeLiftedDecimalIncDecOperator(node.Syntax, binaryOperatorKind, binaryOperand);
            }
            else
            {
                binOp = MakeBinaryOperator(node.Syntax, binaryOperatorKind, binaryOperand, boundOne, binaryOperandType, method: null);
            }

            // Generate the conversion back to the type of the unary operator.

            // (short)((int)(short)x + 1)
            result = MakeConversion(binOp, unaryOperandType, @checked);
            return(result);
        }
Ejemplo n.º 7
0
 public ResolveOverloadsResult(MethodSymbol exactMatch, MethodSymbol bestMatch)
     : this()
 {
     this.ExactMatch = exactMatch;
     this.BestMatch = bestMatch;
 }
Ejemplo n.º 8
0
 protected static void AddMethod(int inlet, MethodSymbol m) { AddMethod(inlet, _symbol, m); }
Ejemplo n.º 9
0
 internal static bool IsFunction(MethodSymbol method)
 {
     return(method.IsStatic && method.DeclaredAccessibility == Accessibility.Public && method.MethodKind == MethodKind.Ordinary && !method.IsPhpHidden());
 }
 public SynthesizedExplicitImplementationForwardingMethod(MethodSymbol interfaceMethod, MethodSymbol implementingMethod, NamedTypeSymbol implementingType) 
     : base(interfaceMethod, implementingType, generateDebugInfo: false)
 {
     this.implementingMethod = implementingMethod;
 }
Ejemplo n.º 11
0
 private AwaitExpressionSpiller(MethodSymbol method, CSharpSyntaxNode syntaxNode, TypeCompilationState compilationState, PooledDictionary <LocalSymbol, LocalSymbol> tempSubstitution, DiagnosticBag diagnostics)
 {
     _F = new SyntheticBoundNodeFactory(method, syntaxNode, compilationState, diagnostics);
     _tempSubstitution = tempSubstitution;
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Generate the body for <c>MoveNext()</c>.
        /// </summary>
        internal void GenerateMoveNext(BoundStatement body, MethodSymbol moveNextMethod)
        {
            F.CurrentFunction = moveNextMethod;
            BoundStatement rewrittenBody = VisitBody(body);

            ImmutableArray <StateMachineFieldSymbol> rootScopeHoistedLocals;

            TryUnwrapBoundStateMachineScope(ref rewrittenBody, out rootScopeHoistedLocals);

            var bodyBuilder = ArrayBuilder <BoundStatement> .GetInstance();

            bodyBuilder.Add(F.HiddenSequencePoint());
            bodyBuilder.Add(F.Assignment(F.Local(cachedState), F.Field(F.This(), stateField)));
            bodyBuilder.Add(CacheThisIfNeeded());

            var exceptionLocal = F.SynthesizedLocal(F.WellKnownType(WellKnownType.core_Exception));

            bodyBuilder.Add(
                GenerateTopLevelTry(
                    F.Block(ImmutableArray <LocalSymbol> .Empty,
                            // switch (state) ...
                            F.HiddenSequencePoint(),
                            Dispatch(),
                            // [body]
                            rewrittenBody
                            ),
                    F.CatchBlocks(GenerateExceptionHandling(exceptionLocal)))
                );

            // ReturnLabel (for the rewritten return expressions in the user's method body)
            bodyBuilder.Add(F.Label(_exprReturnLabel));

            // this.state = finishedState
            var stateDone = F.Assignment(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedStateMachine));
            var block     = body.Syntax as BlockSyntax;

            if (block == null)
            {
                // this happens, for example, in (async () => await e) where there is no block syntax
                bodyBuilder.Add(stateDone);
            }
            else
            {
                bodyBuilder.Add(F.SequencePointWithSpan(block, block.CloseBraceToken.Span, stateDone));
                bodyBuilder.Add(F.HiddenSequencePoint());
                // The remaining code is hidden to hide the fact that it can run concurrently with the task's continuation
            }

            bodyBuilder.Add(GenerateSetResultCall());

            // this code is hidden behind a hidden sequence point.
            bodyBuilder.Add(F.Label(_exitLabel));
            bodyBuilder.Add(F.Return());

            var newStatements = bodyBuilder.ToImmutableAndFree();

            var locals = ArrayBuilder <LocalSymbol> .GetInstance();

            locals.Add(cachedState);
            if ((object)cachedThis != null)
            {
                locals.Add(cachedThis);
            }
            if ((object)_exprRetValue != null)
            {
                locals.Add(_exprRetValue);
            }

            var newBody =
                F.SequencePoint(
                    body.Syntax,
                    F.Block(
                        locals.ToImmutableAndFree(),
                        newStatements));

            if (rootScopeHoistedLocals.Length > 0)
            {
                newBody = MakeStateMachineScope(rootScopeHoistedLocals, newBody);
            }

            F.CloseMethod(newBody);
        }
Ejemplo n.º 13
0
 public MethodDefinition(Module moduleBeingBuilt, MethodSymbol underlyingMethod)
     : base(moduleBeingBuilt, underlyingMethod)
 { }
Ejemplo n.º 14
0
 protected static void AddMethod(int inlet, string sel, MethodSymbol m) { AddMethod(inlet, new Symbol(sel), m); }
Ejemplo n.º 15
0
 protected static void AddMethod(MethodSymbol m) { AddMethod(0, m); }
Ejemplo n.º 16
0
        public void MemberDeclaringSyntax()
        {
            var text =
                @"
using System;
using System.Collections.Generic;

namespace N1 {
    enum E1 {Red, Blue = 5, Green };
    class C1<T> {
        C1<int> t, w, x;
        const int q = 4, r = 7;
        C1(int i) {}
        static C1() {}
        int m(T t, int y = 3) { return 3; }
        int P {get { return 0; } set {}}
        abstract int Prop2 {get; set; }
        int Prop3 {get; set; }
        string this[int i] {get { return ""; } set {}}
        abstract string this[int i, int j] {get; set;}
        event EventHandler ev1;
        event EventHandler ev2 { add {} remove {} }
    }
    class C2<U>
    {
         static int x = 7;
    }
}
";
            var comp   = CreateCompilation(text);
            var global = comp.GlobalNamespace;
            var n1     = global.GetMembers("N1").Single() as NamespaceSymbol;
            var c1     = n1.GetTypeMembers("C1").Single() as NamedTypeSymbol;
            var c2     = n1.GetTypeMembers("C2").Single() as NamedTypeSymbol;
            var e1     = n1.GetTypeMembers("E1").Single() as NamedTypeSymbol;

            foreach (Symbol memb in e1.GetMembers())
            {
                if (memb.Kind == SymbolKind.Method && ((MethodSymbol)memb).MethodKind == MethodKind.Constructor)
                {
                    CheckDeclaringSyntaxNodesIncludingParameters(comp, memb, 0);  // implicit constructor
                }
                else
                {
                    CheckDeclaringSyntaxNodesIncludingParameters(comp, memb, 1);
                }
            }

            var ev1   = c1.GetMembers("ev1").Single() as EventSymbol;
            var prop3 = c1.GetMembers("Prop3").Single() as PropertySymbol;

            foreach (Symbol memb in c1.GetMembers())
            {
                int expectedDeclaringNodes = 1;

                if (memb is MethodSymbol)
                {
                    MethodSymbol meth = (MethodSymbol)memb;
                    if (meth.AssociatedSymbol != null && meth.AssociatedSymbol.OriginalDefinition.Equals(ev1))
                    {
                        expectedDeclaringNodes = 0;  // implicit accessor.
                    }
                }
                if (memb is FieldSymbol)
                {
                    FieldSymbol fld = (FieldSymbol)memb;
                    if (fld.AssociatedSymbol != null && fld.AssociatedSymbol.OriginalDefinition.Equals(prop3))
                    {
                        expectedDeclaringNodes = 0;  // auto-prop backing field.
                    }
                }

                CheckDeclaringSyntaxNodesIncludingParameters(comp, memb, expectedDeclaringNodes);
            }

            var fieldT        = c1.GetMembers("t").Single() as FieldSymbol;
            var constructedC1 = fieldT.Type;

            foreach (Symbol memb in constructedC1.GetMembers())
            {
                int expectedDeclaringNodes = 1;

                if (memb is MethodSymbol)
                {
                    MethodSymbol meth = (MethodSymbol)memb;
                    if (meth.AssociatedSymbol != null && meth.AssociatedSymbol.OriginalDefinition.Equals(ev1))
                    {
                        expectedDeclaringNodes = 0;  // implicit accessor.
                    }
                }
                if (memb is FieldSymbol)
                {
                    FieldSymbol fld = (FieldSymbol)memb;
                    if (fld.AssociatedSymbol != null && fld.AssociatedSymbol.OriginalDefinition.Equals(prop3))
                    {
                        expectedDeclaringNodes = 0;  // auto-prop backing field.
                    }
                }

                CheckDeclaringSyntaxNodesIncludingParameters(comp, memb, expectedDeclaringNodes);
            }

            foreach (Symbol memb in c2.GetMembers())
            {
                if (memb.Kind == SymbolKind.Method)
                {
                    CheckDeclaringSyntaxNodesIncludingParameters(comp, memb, 0);
                }
            }
        }
Ejemplo n.º 17
0
        public static void IssueDiagnostics(CSharpCompilation compilation, BoundNode node, DiagnosticBag diagnostics, MethodSymbol containingSymbol)
        {
            Debug.Assert(node != null);
            Debug.Assert((object)containingSymbol != null);

            ExecutableCodeBinder.ValidateIteratorMethod(compilation, containingSymbol, diagnostics);

            try
            {
                var diagnosticPass = new DiagnosticsPass(compilation, diagnostics, containingSymbol);
                diagnosticPass.Visit(node);
            }
            catch (CancelledByStackGuardException ex)
            {
                ex.AddAnError(diagnostics);
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Given a list of method and/or property candidates, choose the first one (if any) with a signature
        /// that matches the parameter list in the cref.  Return null if there isn't one.
        /// </summary>
        /// <remarks>
        /// Produces a diagnostic for ambiguous matches, but not for unresolved members - WRN_BadXMLRef is
        /// handled in BindMemberCref.
        /// </remarks>
        private static ImmutableArray <Symbol> PerformCrefOverloadResolution(ArrayBuilder <Symbol> candidates, ImmutableArray <ParameterSymbol> parameterSymbols, int arity, MemberCrefSyntax memberSyntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
        {
            ArrayBuilder <Symbol> viable = null;

            foreach (Symbol candidate in candidates)
            {
                // BREAK: In dev11, any candidate with the type "dynamic" anywhere in its parameter list would be skipped
                // (see XmlDocCommentBinder::bindXmlReference).  Apparently, this was because "the params that the xml doc
                // comments produce never will."  This does not appear to have made sense in dev11 (skipping dropping the
                // candidate doesn't cause anything to blow up and may cause resolution to start succeeding) and it almost
                // certainly does not in roslyn (the signature comparer ignores the object-dynamic distiction anyway).

                Symbol signatureMember;
                switch (candidate.Kind)
                {
                case SymbolKind.Method:
                {
                    MethodSymbol candidateMethod         = (MethodSymbol)candidate;
                    MethodKind   candidateMethodKind     = candidateMethod.MethodKind;
                    bool         candidateMethodIsVararg = candidateMethod.IsVararg;

                    // If the arity from the cref is zero, then we accept methods of any arity.
                    int signatureMemberArity = candidateMethodKind == MethodKind.Constructor
                                ? 0
                                : (arity == 0 ? candidateMethod.Arity : arity);

                    // CONSIDER: we might want to reuse this method symbol (as long as the MethodKind and Vararg-ness match).
                    signatureMember = new SignatureOnlyMethodSymbol(
                        methodKind: candidateMethodKind,
                        typeParameters: IndexedTypeParameterSymbol.Take(signatureMemberArity),
                        parameters: parameterSymbols,
                        // This specific comparer only looks for varargs.
                        callingConvention: candidateMethodIsVararg ? Microsoft.Cci.CallingConvention.ExtraArguments : Microsoft.Cci.CallingConvention.HasThis,
                        // These are ignored by this specific MemberSignatureComparer.
                        containingType: null,
                        name: null,
                        returnType: null,
                        returnTypeCustomModifiers: ImmutableArray <CustomModifier> .Empty,
                        explicitInterfaceImplementations: ImmutableArray <MethodSymbol> .Empty);
                    break;
                }

                case SymbolKind.Property:
                {
                    // CONSIDER: we might want to reuse this property symbol.
                    signatureMember = new SignatureOnlyPropertySymbol(
                        parameters: parameterSymbols,
                        // These are ignored by this specific MemberSignatureComparer.
                        containingType: null,
                        name: null,
                        type: null,
                        typeCustomModifiers: ImmutableArray <CustomModifier> .Empty,
                        isStatic: false,
                        explicitInterfaceImplementations: ImmutableArray <PropertySymbol> .Empty);
                    break;
                }

                case SymbolKind.NamedType:
                    // Because we replaced them with constructors when we built the candidate list.
                    throw ExceptionUtilities.UnexpectedValue(candidate.Kind);

                default:
                    continue;
                }

                if (MemberSignatureComparer.CrefComparer.Equals(signatureMember, candidate))
                {
                    Debug.Assert(candidate.GetMemberArity() != 0 || candidate.Name == WellKnownMemberNames.InstanceConstructorName || arity == 0,
                                 "Can only have a 0-arity, non-constructor candidate if the desired arity is 0.");

                    if (viable == null)
                    {
                        viable = ArrayBuilder <Symbol> .GetInstance();

                        viable.Add(candidate);
                    }
                    else
                    {
                        bool oldArityIsZero = viable[0].GetMemberArity() == 0;
                        bool newArityIsZero = candidate.GetMemberArity() == 0;

                        // If the cref specified arity 0 and the current candidate has arity 0 but the previous
                        // match did not, then the current candidate is the unambiguous winner (unless there's
                        // another match with arity 0 in a subsequent iteration).
                        if (!oldArityIsZero || newArityIsZero)
                        {
                            if (!oldArityIsZero && newArityIsZero)
                            {
                                viable.Clear();
                            }

                            viable.Add(candidate);
                        }
                    }
                }
            }

            if (viable == null)
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            if (viable.Count > 1)
            {
                ambiguityWinner = viable[0];
                CrefSyntax crefSyntax = GetRootCrefSyntax(memberSyntax);
                diagnostics.Add(ErrorCode.WRN_AmbiguousXMLReference, crefSyntax.Location, crefSyntax.ToString(), ambiguityWinner, viable[1]);
            }
            else
            {
                ambiguityWinner = null;
            }

            return(viable.ToImmutableAndFree());
        }
Ejemplo n.º 19
0
        private DiagnosticsPass(CSharpCompilation compilation, DiagnosticBag diagnostics, MethodSymbol containingSymbol)
        {
            Debug.Assert(diagnostics != null);
            Debug.Assert((object)containingSymbol != null);

            _compilation      = compilation;
            _diagnostics      = diagnostics;
            _containingSymbol = containingSymbol;
        }
Ejemplo n.º 20
0
        private static bool MethodSymbolMatchesParamInfo(MethodSymbol candidateMethod, ParamInfo<TypeSymbol>[] targetParamInfo)
        {
            int numParams = targetParamInfo.Length - 1; //don't count return type

            if (candidateMethod.ParameterCount != numParams)
            {
                return false;
            }

            // IndexedTypeParameterSymbol is not going to be exposed anywhere,
            // so we'll cheat and use it here for comparison purposes.
            TypeMap candidateMethodTypeMap = new TypeMap(
                candidateMethod.TypeParameters,
                IndexedTypeParameterSymbol.Take(candidateMethod.Arity), true);

            if (!ReturnTypesMatch(candidateMethod, candidateMethodTypeMap, ref targetParamInfo[0]))
            {
                return false;
            }

            for (int i = 0; i < numParams; i++)
            {
                if (!ParametersMatch(candidateMethod.Parameters[i], candidateMethodTypeMap, ref targetParamInfo[i + 1 /*for return type*/]))
                {
                    return false;
                }
            }

            return true;
        }
Ejemplo n.º 21
0
        private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
        {
            var returnType = DelegateReturnType(delegateType);

            LambdaSymbol lambdaSymbol;
            Binder       lambdaBodyBinder;
            BoundBlock   block;

            var diagnostics = DiagnosticBag.GetInstance();

            // when binding for real (not for return inference), there is still
            // a good chance that we could reuse a body of a lambda previously bound for
            // return type inference.
            MethodSymbol cacheKey = GetCacheKey(delegateType);

            BoundLambda returnInferenceLambda;

            if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType)
            {
                var lambdaSym     = returnInferenceLambda.Symbol;
                var lambdaRetType = lambdaSym.ReturnType;
                if (lambdaRetType == returnType)
                {
                    lambdaSymbol     = lambdaSym;
                    lambdaBodyBinder = returnInferenceLambda.Binder;
                    block            = returnInferenceLambda.Body;
                    diagnostics.AddRange(returnInferenceLambda.Diagnostics);

                    goto haveLambdaBodyAndBinders;
                }
            }

            var parameters = DelegateParameters(delegateType);

            lambdaSymbol     = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, parameters, returnType);
            lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            block            = BindLambdaBody(lambdaSymbol, ref lambdaBodyBinder, diagnostics);
            ValidateUnsafeParameters(diagnostics, parameters);

haveLambdaBodyAndBinders:

            bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics);

            if (reachableEndpoint)
            {
                if (DelegateNeedsReturn(delegateType))
                {
                    // Not all code paths return a value in {0} of type '{1}'
                    diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.Locations[0], this.MessageID.Localize(), delegateType);
                }
                else
                {
                    block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol, _unboundLambda.Syntax);
                }
            }

            if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics))
            {
                if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type.
                    returnType.SpecialType != SpecialType.System_Void &&
                    returnType != binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task) &&
                    returnType.OriginalDefinition != binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T))
                {
                    // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task&lt;T&gt;, none of which are convertible to '{1}'.
                    diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.Locations[0], lambdaSymbol.MessageID.Localize(), delegateType);
                }
            }

            if (IsAsync)
            {
                Debug.Assert(lambdaSymbol.IsAsync);
                SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol, diagnostics, lambdaSymbol.Locations[0]);
            }

            var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false)
            {
                WasCompilerGenerated = _unboundLambda.WasCompilerGenerated
            };

            return(result);
        }
        protected internal override object VisitMethod(MethodSymbol symbol, ArrayBuilder<SymbolDescriptionPart> builder)
        {
            AddAccessibilityIfRequired(symbol, builder);

            AddMemberModifiersIfRequired(symbol, builder);

            if (format.MemberFlags.HasFlag(MemberFlags.IncludeType))
            {
                switch (symbol.MethodKind)
                {
                    case MethodKind.Constructor:
                    case MethodKind.StaticConstructor:
                    case MethodKind.Destructor:
                        break;
                    default:
                        VisitType(symbol.ReturnType, builder);
                        AddSpace(builder);
                        break;
                }
            }

            switch (symbol.MethodKind)
            {
                case MethodKind.Ordinary:
                    builder.Add(new SymbolDescriptionPart
                    {
                        Kind = SymbolDescriptionPartKind.MethodName,
                        Text = symbol.Name,
                    });
                    break;
                case MethodKind.Constructor:
                    builder.Add(new SymbolDescriptionPart
                    {
                        Kind = SymbolDescriptionPartKind.MethodName,
                        Text = symbol.ContainingType.Name,
                    });
                    break;
                case MethodKind.StaticConstructor:
                    AddKeyword(SyntaxKind.StaticKeyword, builder);
                    AddSpace(builder);
                    builder.Add(new SymbolDescriptionPart
                    {
                        Kind = SymbolDescriptionPartKind.MethodName,
                        Text = symbol.ContainingType.Name,
                    });
                    break;
                case MethodKind.Destructor:
                    AddPunctuation(SyntaxKind.TildeToken, builder);
                    builder.Add(new SymbolDescriptionPart
                    {
                        Kind = SymbolDescriptionPartKind.MethodName,
                        Text = symbol.ContainingType.Name,
                    });
                    break;
                case MethodKind.ExplicitInterfaceImplementation:
                    if (format.MemberFlags.HasFlag(MemberFlags.IncludeExplicitInterface))
                    {
                        var implementedMethods = symbol.ExplicitInterfaceImplementation;
                        if (implementedMethods.Any())
                        {
                            if (implementedMethods.Skip(1).Any())
                            {
                                throw new NotImplementedException(); //TODO: multiple implemented methods?
                            }

                            var implementedMethod = implementedMethods.First();

                            VisitType(implementedMethod.ContainingType, builder);
                            AddPunctuation(SyntaxKind.DotToken, builder);
                        }
                    }
                    builder.Add(new SymbolDescriptionPart
                    {
                        Kind = SymbolDescriptionPartKind.MethodName,
                        Text = symbol.Name,
                    });
                    break;
                default:
                    throw new NotImplementedException(); //TODO
            }

            bool hasContraints = false;
            if (symbol.Arity > 0 && format.GenericsFlags.HasFlag(GenericsFlags.IncludeTypeParameters))
            {
                hasContraints = AddTypeArguments(symbol.TypeArguments, builder);
            }

            if (format.MemberFlags.HasFlag(MemberFlags.IncludeParameters))
            {
                AddPunctuation(SyntaxKind.OpenParenToken, builder);
                AddParameters(symbol.IsExtensionMethod, symbol.Parameters, builder);
                AddPunctuation(SyntaxKind.CloseParenToken, builder);
            }

            if (hasContraints && format.GenericsFlags.HasFlag(GenericsFlags.IncludeTypeConstraints))
            {
                AddTypeParameterConstraints(symbol.TypeArguments, builder);
            }

            return null;
        }
Ejemplo n.º 23
0
        public IteratorStateMachine(VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, MethodSymbol iteratorMethod, int iteratorMethodOrdinal, bool isEnumerable, TypeSymbol elementType)
            : base(slotAllocatorOpt, compilationState, iteratorMethod, iteratorMethodOrdinal)
        {
            this.ElementType = TypeMap.SubstituteType(elementType);

            var interfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance();

            if (isEnumerable)
            {
                interfaces.Add(ContainingAssembly.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T).Construct(ElementType));
                interfaces.Add(ContainingAssembly.GetSpecialType(SpecialType.System_Collections_IEnumerable));
            }

            interfaces.Add(ContainingAssembly.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerator_T).Construct(ElementType));
            interfaces.Add(ContainingAssembly.GetSpecialType(SpecialType.System_IDisposable));
            interfaces.Add(ContainingAssembly.GetSpecialType(SpecialType.System_Collections_IEnumerator));
            _interfaces = interfaces.ToImmutableAndFree();

            _constructor = new IteratorConstructor(this);
        }
Ejemplo n.º 24
0
 public void AddMethod(int inlet, Symbol sel, MethodSymbol d)
 {
     DynamicMethodSymbol dyn = DynamicMethods.Create(d);
     if (inlet == 0 && sel == _symbol)
     {
         m_symbol = dyn;
         methodflags |= MethodFlags.f_symbol;
     }
     else
         AddMethodIntern(inlet, sel, Kind.k_symbol, dyn);
 }
Ejemplo n.º 25
0
 private void CheckReducedExtensionMethods(MethodSymbol source, MethodSymbol retargeting)
 {
     CheckMethods(source.ReducedFrom, retargeting.ReducedFrom);
 }
Ejemplo n.º 26
0
        private BoundExpression MakeUserDefinedIncrementOperator(BoundIncrementOperator node, BoundExpression rewrittenValueToIncrement)
        {
            Debug.Assert((object)node.MethodOpt != null);
            Debug.Assert(node.MethodOpt.ParameterCount == 1);

            bool isLifted = node.OperatorKind.IsLifted();
            bool @checked = node.OperatorKind.IsChecked();

            BoundExpression  rewrittenArgument = rewrittenValueToIncrement;
            CSharpSyntaxNode syntax            = node.Syntax;

            TypeSymbol type = node.MethodOpt.ParameterTypes[0];

            if (isLifted)
            {
                type = _compilation.GetSpecialType(SpecialType.System_Nullable_T).Construct(type);
                Debug.Assert(node.MethodOpt.ParameterTypes[0] == node.MethodOpt.ReturnType);
            }

            if (!node.OperandConversion.IsIdentity)
            {
                rewrittenArgument = MakeConversion(
                    syntax: syntax,
                    rewrittenOperand: rewrittenValueToIncrement,
                    conversion: node.OperandConversion,
                    rewrittenType: type,
                    @checked: @checked);
            }

            if (!isLifted)
            {
                return(BoundCall.Synthesized(syntax, null, node.MethodOpt, rewrittenArgument));
            }

            // S? temp = operand;
            // S? r = temp.HasValue ?
            //        new S?(op_Increment(temp.GetValueOrDefault())) :
            //        default(S?);

            // Unlike the other unary operators, we do not attempt to optimize nullable user-defined
            // increment or decrement. The operand is a variable (or property), and so we do not know if
            // it is always null/never null.

            BoundAssignmentOperator tempAssignment;
            BoundLocal boundTemp = _factory.StoreToTemp(rewrittenArgument, out tempAssignment);

            MethodSymbol getValueOrDefault = GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T_GetValueOrDefault);
            MethodSymbol ctor = GetNullableMethod(syntax, type, SpecialMember.System_Nullable_T__ctor);

            // temp.HasValue
            BoundExpression condition = MakeNullableHasValue(node.Syntax, boundTemp);

            // temp.GetValueOrDefault()
            BoundExpression call_GetValueOrDefault = BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault);

            // op_Increment(temp.GetValueOrDefault())
            BoundExpression userDefinedCall = BoundCall.Synthesized(syntax, null, node.MethodOpt, call_GetValueOrDefault);

            // new S?(op_Increment(temp.GetValueOrDefault()))
            BoundExpression consequence = new BoundObjectCreationExpression(syntax, ctor, userDefinedCall);

            // default(S?)
            BoundExpression alternative = new BoundDefaultOperator(syntax, null, type);

            // temp.HasValue ?
            //          new S?(op_Increment(temp.GetValueOrDefault())) :
            //          default(S?);
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: type);

            // temp = operand;
            // temp.HasValue ?
            //          new S?(op_Increment(temp.GetValueOrDefault())) :
            //          default(S?);
            return(new BoundSequence(
                       syntax: syntax,
                       locals: ImmutableArray.Create <LocalSymbol>(boundTemp.LocalSymbol),
                       sideEffects: ImmutableArray.Create <BoundExpression>(tempAssignment),
                       value: conditionalExpression,
                       type: type));
        }
Ejemplo n.º 27
0
 private static MethodGroupResolution ResolveDelegateOrFunctionPointerMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, bool isFunctionPointer, in CallingConventionInfo callingConventionInfo, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo)
Ejemplo n.º 28
0
        private BoundExpression MakeUnaryOperator(
            BoundUnaryOperator oldNode,
            UnaryOperatorKind kind,
            CSharpSyntaxNode syntax,
            MethodSymbol method,
            BoundExpression loweredOperand,
            TypeSymbol type)
        {
            if (kind.IsDynamic())
            {
                Debug.Assert(kind == UnaryOperatorKind.DynamicTrue && type.SpecialType == SpecialType.System_Boolean || type.IsDynamic());
                Debug.Assert((object)method == null);

                // Logical operators on boxed Boolean constants:
                var constant = UnboxConstant(loweredOperand);
                if (constant == ConstantValue.True || constant == ConstantValue.False)
                {
                    if (kind == UnaryOperatorKind.DynamicTrue)
                    {
                        return(_factory.Literal(constant.BooleanValue));
                    }
                    else if (kind == UnaryOperatorKind.DynamicLogicalNegation)
                    {
                        return(MakeConversion(_factory.Literal(!constant.BooleanValue), type, @checked: false));
                    }
                }

                return(_dynamicFactory.MakeDynamicUnaryOperator(kind, loweredOperand, type).ToExpression());
            }
            else if (kind.IsLifted())
            {
                if (!_inExpressionLambda)
                {
                    return(LowerLiftedUnaryOperator(kind, syntax, method, loweredOperand, type));
                }
            }
            else if (kind.IsUserDefined())
            {
                Debug.Assert((object)method != null);
                Debug.Assert(type == method.ReturnType);
                if (!_inExpressionLambda || kind == UnaryOperatorKind.UserDefinedTrue || kind == UnaryOperatorKind.UserDefinedFalse)
                {
                    return(BoundCall.Synthesized(syntax, null, method, loweredOperand));
                }
            }
            else if (kind.Operator() == UnaryOperatorKind.UnaryPlus)
            {
                // We do not call the operator even for decimal; we simply optimize it away entirely.
                return(loweredOperand);
            }

            if (kind == UnaryOperatorKind.EnumBitwiseComplement)
            {
                var underlyingType       = loweredOperand.Type.GetEnumUnderlyingType();
                var upconvertSpecialType = Binder.GetEnumPromotedType(underlyingType.SpecialType);
                var upconvertType        = upconvertSpecialType == underlyingType.SpecialType ?
                                           underlyingType :
                                           _compilation.GetSpecialType(upconvertSpecialType);


                var newOperand            = MakeConversion(loweredOperand, upconvertType, false);
                UnaryOperatorKind newKind = kind.Operator().WithType(upconvertSpecialType);

                var newNode = (oldNode != null) ?
                              oldNode.Update(
                    newKind,
                    newOperand,
                    oldNode.ConstantValueOpt,
                    method,
                    newOperand.ResultKind,
                    upconvertType) :
                              new BoundUnaryOperator(
                    syntax,
                    newKind,
                    newOperand,
                    null,
                    method,
                    LookupResultKind.Viable,
                    upconvertType);

                return(MakeConversion(newNode.Syntax, newNode, ConversionKind.ExplicitEnumeration, type, @checked: false));
            }

            if (kind == UnaryOperatorKind.DecimalUnaryMinus)
            {
                method = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(SpecialMember.System_Decimal__op_UnaryNegation);
                if (!_inExpressionLambda)
                {
                    return(BoundCall.Synthesized(syntax, null, method, loweredOperand));
                }
            }

            return((oldNode != null) ?
                   oldNode.Update(kind, loweredOperand, oldNode.ConstantValueOpt, method, oldNode.ResultKind, type) :
                   new BoundUnaryOperator(syntax, kind, loweredOperand, null, method, LookupResultKind.Viable, type));
        }
Ejemplo n.º 29
0
 public GenericMethodInstanceReference(MethodSymbol underlyingMethod)
     : base(underlyingMethod)
 {
 }
Ejemplo n.º 30
0
 private static string MakeName(VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, MethodSymbol kickoffMethod, int kickoffMethodOrdinal)
 {
     return(slotAllocatorOpt?.PreviousStateMachineTypeName ??
            GeneratedNames.MakeStateMachineTypeName(kickoffMethod.Name, kickoffMethodOrdinal, compilationState.ModuleBuilderOpt.CurrentGenerationOrdinal));
 }
        private BoundStatement RewriteUsingStatementTryFinally(CSharpSyntaxNode syntax, BoundBlock tryBlock, BoundLocal local)
        {
            // SPEC: When ResourceType is a non-nullable value type, the expansion is:
            // SPEC:
            // SPEC: {
            // SPEC:   ResourceType resource = expr;
            // SPEC:   try { statement; }
            // SPEC:   finally { ((IDisposable)resource).Dispose(); }
            // SPEC: }
            // SPEC:
            // SPEC: Otherwise, when Resource type is a nullable value type or
            // SPEC: a reference type other than dynamic, the expansion is:
            // SPEC:
            // SPEC: {
            // SPEC:   ResourceType resource = expr;
            // SPEC:   try { statement; }
            // SPEC:   finally { if (resource != null) ((IDisposable)resource).Dispose(); }
            // SPEC: }
            // SPEC:
            // SPEC: Otherwise, when ResourceType is dynamic, the expansion is:
            // SPEC: {
            // SPEC:   dynamic resource = expr;
            // SPEC:   IDisposable d = (IDisposable)resource;
            // SPEC:   try { statement; }
            // SPEC:   finally { if (d != null) d.Dispose(); }
            // SPEC: }
            // SPEC:
            // SPEC: An implementation is permitted to implement a given using statement
            // SPEC: differently -- for example, for performance reasons -- as long as the
            // SPEC: behavior is consistent with the above expansion.
            //
            // And we do in fact generate the code slightly differently than precisely how it is
            // described above.
            //
            // First: if the type is a non-nullable value type then we do not do the
            // *boxing conversion* from the resource to IDisposable. Rather, we do
            // a *constrained virtual call* that elides the boxing if possible.
            //
            // Now, you might wonder if that is legal; isn't skipping the boxing producing
            // an observable difference? Because if the value type is mutable and the Dispose
            // mutates it, then skipping the boxing means that we are now mutating the original,
            // not the boxed copy. But this is never observable. Either (1) we have "using(R r = x){}"
            // and r is out of scope after the finally, so it is not possible to observe the mutation,
            // or (2) we have "using(x) {}". But that has the semantics of "using(R temp = x){}",
            // so again, we are not mutating x to begin with; we're always mutating a copy. Therefore
            // it doesn't matter if we skip making *a copy of the copy*.
            //
            // This is what the dev10 compiler does, and we do so as well.
            //
            // Second: if the type is a nullable value type then we can similarly elide the boxing.
            // We can generate
            //
            // {
            //   ResourceType resource = expr;
            //   try { statement; }
            //   finally { if (resource.HasValue) resource.GetValueOrDefault().Dispose(); }
            // }
            //
            // Where again we do a constrained virtual call to Dispose, rather than boxing
            // the value to IDisposable.
            //
            // Note that this optimization is *not* what the native compiler does; in this case
            // the native compiler behavior is to test for HasValue, then *box* and convert
            // the boxed value to IDisposable. There's no need to do that.
            //
            // Third: if we have "using(x)" and x is dynamic then obviously we need not generate
            // "{ dynamic temp1 = x; IDisposable temp2 = (IDisposable) temp1; ... }". Rather, we elide
            // the completely unnecessary first temporary.

            BoundExpression disposedExpression;
            bool            isNullableValueType = local.Type.IsNullableType();

            if (isNullableValueType)
            {
                MethodSymbol getValueOrDefault = GetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);
                // local.GetValueOrDefault()
                disposedExpression = BoundCall.Synthesized(syntax, local, getValueOrDefault);
            }
            else
            {
                // local
                disposedExpression = local;
            }

            // local.Dispose()
            BoundExpression disposeCall;

            MethodSymbol disposeMethodSymbol;

            if (TryGetSpecialTypeMember(syntax, SpecialMember.System_IDisposable__Dispose, out disposeMethodSymbol))
            {
                disposeCall = BoundCall.Synthesized(syntax, disposedExpression, disposeMethodSymbol);
            }
            else
            {
                disposeCall = new BoundBadExpression(syntax, LookupResultKind.NotInvocable, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(disposedExpression), ErrorTypeSymbol.UnknownResultType);
            }

            // local.Dispose();
            BoundStatement disposeStatement = new BoundExpressionStatement(syntax, disposeCall);

            BoundExpression ifCondition;

            if (isNullableValueType)
            {
                MethodSymbol hasValue = GetNullableMethod(syntax, local.Type, SpecialMember.System_Nullable_T_get_HasValue);
                // local.HasValue
                ifCondition = BoundCall.Synthesized(syntax, local, hasValue);
            }
            else if (local.Type.IsValueType)
            {
                ifCondition = null;
            }
            else
            {
                // local != null
                ifCondition = MakeNullCheck(syntax, local, BinaryOperatorKind.NotEqual);
            }

            BoundStatement finallyStatement;

            if (ifCondition == null)
            {
                // local.Dispose();
                finallyStatement = disposeStatement;
            }
            else
            {
                // if (local != null) local.Dispose();
                // or
                // if (local.HasValue) local.GetValueOrDefault().Dispose();
                finallyStatement = RewriteIfStatement(
                    syntax: syntax,
                    rewrittenCondition: ifCondition,
                    rewrittenConsequence: disposeStatement,
                    rewrittenAlternativeOpt: null,
                    hasErrors: false);
            }

            // try { ... } finally { if (local != null) local.Dispose(); }
            BoundStatement tryFinally = new BoundTryStatement(
                syntax: syntax,
                tryBlock: tryBlock,
                catchBlocks: ImmutableArray <BoundCatchBlock> .Empty,
                finallyBlockOpt: BoundBlock.SynthesizedNoLocals(syntax, finallyStatement));

            return(tryFinally);
        }
Ejemplo n.º 32
0
 public override void VisitMethod(MethodSymbol symbol)
 {
     throw ExceptionUtilities.Unreachable;
 }
Ejemplo n.º 33
0
        protected SynthesizedImplementationMethod GenerateIteratorGetEnumerator(MethodSymbol getEnumeratorMethod, ref BoundExpression managedThreadId, int initialState)
        {
            // Produces:
            //    {StateMachineType} result;
            //    if (this.initialThreadId == {managedThreadId} && this.state == -2)
            //    {
            //        this.state = {initialState};
            //        extraReset
            //        result = this;
            //    }
            //    else
            //    {
            //        result = new {StateMachineType}({initialState});
            //    }
            //
            //    result.parameter = this.parameterProxy; // OR more complex initialization for async-iterator parameter marked with [EnumeratorCancellation]

            // The implementation doesn't depend on the method body of the iterator method.
            // Only on its parameters and staticness.
            var getEnumerator = OpenMethodImplementation(
                getEnumeratorMethod,
                hasMethodBodyDependency: false);

            var bodyBuilder = ArrayBuilder <BoundStatement> .GetInstance();

            // {StateMachineType} result;
            var resultVariable = F.SynthesizedLocal(stateMachineType, null);
            // result = new {StateMachineType}({initialState})
            BoundStatement makeIterator = F.Assignment(F.Local(resultVariable), F.New(stateMachineType.Constructor, F.Literal(initialState)));

            var thisInitialized = F.GenerateLabel("thisInitialized");

            if ((object)initialThreadIdField != null)
            {
                managedThreadId = MakeCurrentThreadId();

                var thenBuilder = ArrayBuilder <BoundStatement> .GetInstance(4);

                GenerateResetInstance(thenBuilder, initialState);

                thenBuilder.Add(
                    // result = this;
                    F.Assignment(F.Local(resultVariable), F.This()));

                if (method.IsStatic || method.ThisParameter.Type.IsReferenceType)
                {
                    // if this is a reference type, no need to copy it since it is not assignable
                    thenBuilder.Add(
                        // goto thisInitialized;
                        F.Goto(thisInitialized));
                }

                makeIterator = F.If(
                    // if (this.state == -2 && this.initialThreadId == Thread.CurrentThread.ManagedThreadId)
                    condition: F.LogicalAnd(
                        F.IntEqual(F.Field(F.This(), stateField), F.Literal(StateMachineStates.FinishedStateMachine)),
                        F.IntEqual(F.Field(F.This(), initialThreadIdField), managedThreadId)),
                    thenClause: F.Block(thenBuilder.ToImmutableAndFree()),
                    elseClauseOpt: makeIterator);
            }

            bodyBuilder.Add(makeIterator);

            // Initialize all the parameter copies
            var copySrc  = initialParameters;
            var copyDest = nonReusableLocalProxies;

            if (!method.IsStatic)
            {
                // starting with "this"
                CapturedSymbolReplacement proxy;
                if (copyDest.TryGetValue(method.ThisParameter, out proxy))
                {
                    bodyBuilder.Add(
                        F.Assignment(
                            proxy.Replacement(F.Syntax, stateMachineType => F.Local(resultVariable)),
                            copySrc[method.ThisParameter].Replacement(F.Syntax, stateMachineType => F.This())));
                }
            }

            bodyBuilder.Add(F.Label(thisInitialized));

            foreach (var parameter in method.Parameters)
            {
                CapturedSymbolReplacement proxy;
                if (copyDest.TryGetValue(parameter, out proxy))
                {
                    // result.parameter
                    BoundExpression resultParameter = proxy.Replacement(F.Syntax, stateMachineType => F.Local(resultVariable));
                    // this.parameterProxy
                    BoundExpression parameterProxy = copySrc[parameter].Replacement(F.Syntax, stateMachineType => F.This());
                    BoundStatement  copy           = InitializeParameterField(getEnumeratorMethod, parameter, resultParameter, parameterProxy);

                    bodyBuilder.Add(copy);
                }
            }

            bodyBuilder.Add(F.Return(F.Local(resultVariable)));
            F.CloseMethod(F.Block(ImmutableArray.Create(resultVariable), bodyBuilder.ToImmutableAndFree()));
            return(getEnumerator);
        }
 public OutsideVariablesUsedInside(IteratorAndAsyncCaptureWalker analyzer, MethodSymbol topLevelMethod, IteratorAndAsyncCaptureWalker parent)
     : base(parent._recursionDepth)
 {
     _analyzer       = analyzer;
     _topLevelMethod = topLevelMethod;
     _localsInScope  = new HashSet <Symbol>();
     _parent         = parent;
 }
Ejemplo n.º 35
0
        internal EEMethodSymbol(
            EENamedTypeSymbol container,
            string name,
            Location location,
            MethodSymbol sourceMethod,
            ImmutableArray <LocalSymbol> sourceLocals,
            ImmutableArray <LocalSymbol> sourceLocalsForBinding,
            ImmutableDictionary <string, DisplayClassVariable> sourceDisplayClassVariables,
            GenerateMethodBody generateMethodBody)
        {
            Debug.Assert(sourceMethod.IsDefinition);
            Debug.Assert(TypeSymbol.Equals((TypeSymbol)sourceMethod.ContainingSymbol, container.SubstitutedSourceType.OriginalDefinition, TypeCompareKind.ConsiderEverything2));
            Debug.Assert(sourceLocals.All(l => l.ContainingSymbol == sourceMethod));

            _container = container;
            _name      = name;
            _locations = ImmutableArray.Create(location);

            // What we want is to map all original type parameters to the corresponding new type parameters
            // (since the old ones have the wrong owners).  Unfortunately, we have a circular dependency:
            //   1) Each new type parameter requires the entire map in order to be able to construct its constraint list.
            //   2) The map cannot be constructed until all new type parameters exist.
            // Our solution is to pass each new type parameter a lazy reference to the type map.  We then
            // initialize the map as soon as the new type parameters are available - and before they are
            // handed out - so that there is never a period where they can require the type map and find
            // it uninitialized.

            var sourceMethodTypeParameters = sourceMethod.TypeParameters;
            var allSourceTypeParameters    = container.SourceTypeParameters.Concat(sourceMethodTypeParameters);

            var getTypeMap = new Func <TypeMap>(() => this.TypeMap);

            _typeParameters = sourceMethodTypeParameters.SelectAsArray(
                (tp, i, arg) => (TypeParameterSymbol) new EETypeParameterSymbol(this, tp, i, getTypeMap),
                (object)null);
            _allTypeParameters = container.TypeParameters.Concat(_typeParameters);
            this.TypeMap       = new TypeMap(allSourceTypeParameters, _allTypeParameters);

            EENamedTypeSymbol.VerifyTypeParameters(this, _typeParameters);

            var substitutedSourceType = container.SubstitutedSourceType;

            this.SubstitutedSourceMethod = sourceMethod.AsMember(substitutedSourceType);
            if (sourceMethod.Arity > 0)
            {
                this.SubstitutedSourceMethod = this.SubstitutedSourceMethod.Construct(_typeParameters.As <TypeSymbol>());
            }
            TypeParameterChecker.Check(this.SubstitutedSourceMethod, _allTypeParameters);

            // Create a map from original parameter to target parameter.
            var parameterBuilder = ArrayBuilder <ParameterSymbol> .GetInstance();

            var substitutedSourceThisParameter    = this.SubstitutedSourceMethod.ThisParameter;
            var substitutedSourceHasThisParameter = (object)substitutedSourceThisParameter != null;

            if (substitutedSourceHasThisParameter)
            {
                _thisParameter = MakeParameterSymbol(0, GeneratedNames.ThisProxyFieldName(), substitutedSourceThisParameter);
                Debug.Assert(TypeSymbol.Equals(_thisParameter.Type, this.SubstitutedSourceMethod.ContainingType, TypeCompareKind.ConsiderEverything2));
                parameterBuilder.Add(_thisParameter);
            }

            var ordinalOffset = (substitutedSourceHasThisParameter ? 1 : 0);

            foreach (var substitutedSourceParameter in this.SubstitutedSourceMethod.Parameters)
            {
                var ordinal = substitutedSourceParameter.Ordinal + ordinalOffset;
                Debug.Assert(ordinal == parameterBuilder.Count);
                var parameter = MakeParameterSymbol(ordinal, substitutedSourceParameter.Name, substitutedSourceParameter);
                parameterBuilder.Add(parameter);
            }

            _parameters = parameterBuilder.ToImmutableAndFree();

            var localsBuilder = ArrayBuilder <LocalSymbol> .GetInstance();

            var localsMap = PooledDictionary <LocalSymbol, LocalSymbol> .GetInstance();

            foreach (var sourceLocal in sourceLocals)
            {
                var local = sourceLocal.ToOtherMethod(this, this.TypeMap);
                localsMap.Add(sourceLocal, local);
                localsBuilder.Add(local);
            }
            this.Locals   = localsBuilder.ToImmutableAndFree();
            localsBuilder = ArrayBuilder <LocalSymbol> .GetInstance();

            foreach (var sourceLocal in sourceLocalsForBinding)
            {
                LocalSymbol local;
                if (!localsMap.TryGetValue(sourceLocal, out local))
                {
                    local = sourceLocal.ToOtherMethod(this, this.TypeMap);
                    localsMap.Add(sourceLocal, local);
                }
                localsBuilder.Add(local);
            }
            this.LocalsForBinding = localsBuilder.ToImmutableAndFree();

            // Create a map from variable name to display class field.
            var displayClassVariables = PooledDictionary <string, DisplayClassVariable> .GetInstance();

            foreach (var pair in sourceDisplayClassVariables)
            {
                var variable = pair.Value;
                var oldDisplayClassInstance = variable.DisplayClassInstance;

                // Note: we don't call ToOtherMethod in the local case because doing so would produce
                // a new LocalSymbol that would not be ReferenceEquals to the one in this.LocalsForBinding.
                var oldDisplayClassInstanceFromLocal = oldDisplayClassInstance as DisplayClassInstanceFromLocal;
                var newDisplayClassInstance          = (oldDisplayClassInstanceFromLocal == null) ?
                                                       oldDisplayClassInstance.ToOtherMethod(this, this.TypeMap) :
                                                       new DisplayClassInstanceFromLocal((EELocalSymbol)localsMap[oldDisplayClassInstanceFromLocal.Local]);

                variable = variable.SubstituteFields(newDisplayClassInstance, this.TypeMap);
                displayClassVariables.Add(pair.Key, variable);
            }

            _displayClassVariables = displayClassVariables.ToImmutableDictionary();
            displayClassVariables.Free();
            localsMap.Free();

            _generateMethodBody = generateMethodBody;
        }
Ejemplo n.º 36
0
        protected override void PropertySetter(BoundExpression node, BoundExpression receiver, MethodSymbol setter, BoundExpression value = null)
        {
            base.PropertySetter(node, receiver, setter, value);

            if (receiver is null || receiver is BoundThisReference)
            {
                ApplyMemberPostConditions(setter.ContainingType, setter.NotNullMembers, notNullWhenTrueMembers: default, notNullWhenFalseMembers: default);
            // NOTE: We're not sharing code with the BinderFactory visitor, because we already have the
            // member symbol in hand, which makes things much easier.
            private static Binder MakeNameBinder(bool isParameter, Symbol memberSymbol, CSharpCompilation compilation)
            {
                Binder binder = new BuckStopsHereBinder(compilation);

                // All binders should have a containing symbol.
                Symbol containingSymbol = memberSymbol.ContainingSymbol;

                Debug.Assert((object)containingSymbol != null);
                binder = binder.WithContainingMemberOrLambda(containingSymbol);

                if (isParameter)
                {
                    ImmutableArray <ParameterSymbol> parameters = ImmutableArray <ParameterSymbol> .Empty;

                    switch (memberSymbol.Kind)
                    {
                    case SymbolKind.Method:
                        parameters = ((MethodSymbol)memberSymbol).Parameters;
                        break;

                    case SymbolKind.Property:
                        parameters = ((PropertySymbol)memberSymbol).Parameters;
                        break;

                    case SymbolKind.NamedType:
                    case SymbolKind.ErrorType:
                        NamedTypeSymbol typeSymbol = (NamedTypeSymbol)memberSymbol;
                        if (typeSymbol.IsDelegateType())
                        {
                            parameters = typeSymbol.DelegateInvokeMethod.Parameters;
                        }
                        break;
                    }

                    if (parameters.Length > 0)
                    {
                        binder = new WithParametersBinder(parameters, binder);
                    }
                }
                else
                {
                    switch (memberSymbol.Kind)
                    {
                    case SymbolKind.NamedType:     // Includes delegates.
                    case SymbolKind.ErrorType:
                        NamedTypeSymbol typeSymbol = (NamedTypeSymbol)memberSymbol;
                        if (typeSymbol.Arity > 0)
                        {
                            binder = new WithClassTypeParametersBinder(typeSymbol, binder);
                        }
                        break;

                    case SymbolKind.Method:
                        MethodSymbol methodSymbol = (MethodSymbol)memberSymbol;
                        if (methodSymbol.Arity > 0)
                        {
                            binder = new WithMethodTypeParametersBinder(methodSymbol, binder);
                        }
                        break;
                    }
                }

                return(binder);
            }
Ejemplo n.º 38
0
        private static bool ReturnTypesMatch(MethodSymbol candidateMethod, TypeMap candidateMethodTypeMap, ref ParamInfo targetReturnParam)
        {
            TypeSymbol candidateReturnType = candidateMethod.ReturnType;
            TypeSymbol targetReturnType = targetReturnParam.Type;

            // CONSIDER: Do we want to add special handling for error types?  Right now, we expect they'll just fail to match.
            if (candidateMethodTypeMap.SubstituteType(candidateReturnType) != targetReturnType)
            {
                return false;
            }

            if (!CustomModifiersMatch(candidateMethod.ReturnTypeCustomModifiers, targetReturnParam.CustomModifiers))
            {
                return false;
            }

            return true;
        }
Ejemplo n.º 39
0
        internal static bool TryCreate(SyntheticBoundNodeFactory F, MethodSymbol method, TypeMap typeMap, out AsyncMethodBuilderMemberCollection collection)
        {
            if (method.IsVoidReturningAsync())
            {
                var builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncVoidMethodBuilder);
                Debug.Assert((object)builderType != null);
                MethodSymbol createBuilderMethod;
                bool         customBuilder = false;
                TryGetBuilderMember <MethodSymbol>(
                    F,
                    WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Create,
                    builderType,
                    customBuilder,
                    out createBuilderMethod);
                if ((object)createBuilderMethod == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: F.SpecialType(SpecialType.System_Void),
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: null,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncVoidMethodBuilder__SetStateMachine,
                           collection: out collection));
            }

            if (method.IsTaskReturningAsync(F.Compilation))
            {
                var             returnType = (NamedTypeSymbol)method.ReturnType;
                NamedTypeSymbol builderType;
                MethodSymbol    createBuilderMethod = null;
                PropertySymbol  taskProperty        = null;

                object builderArgument;
                bool   customBuilder = returnType.IsCustomTaskType(out builderArgument);
                if (customBuilder)
                {
                    builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: false);
                    if ((object)builderType != null)
                    {
                        taskProperty        = GetCustomTaskProperty(F, builderType, returnType);
                        createBuilderMethod = GetCustomCreateMethod(F, builderType);
                    }
                }
                else
                {
                    builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder);
                    Debug.Assert((object)builderType != null);
                    TryGetBuilderMember <MethodSymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Create,
                        builderType,
                        customBuilder,
                        out createBuilderMethod);
                    TryGetBuilderMember <PropertySymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Task,
                        builderType,
                        customBuilder,
                        out taskProperty);
                }
                if ((object)builderType == null ||
                    (object)createBuilderMethod == null ||
                    (object)taskProperty == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: F.SpecialType(SpecialType.System_Void),
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: taskProperty,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder__SetStateMachine,
                           collection: out collection));
            }

            if (method.IsGenericTaskReturningAsync(F.Compilation))
            {
                var returnType = (NamedTypeSymbol)method.ReturnType;
                var resultType = returnType.TypeArgumentsNoUseSiteDiagnostics.Single();
                if (resultType.IsDynamic())
                {
                    resultType = F.SpecialType(SpecialType.System_Object);
                }
                if (typeMap != null)
                {
                    resultType = typeMap.SubstituteType(resultType).Type;
                }
                returnType = returnType.ConstructedFrom.Construct(resultType);
                NamedTypeSymbol builderType;
                MethodSymbol    createBuilderMethod = null;
                PropertySymbol  taskProperty        = null;

                object builderArgument;
                bool   customBuilder = returnType.IsCustomTaskType(out builderArgument);
                if (customBuilder)
                {
                    builderType = ValidateBuilderType(F, builderArgument, returnType.DeclaredAccessibility, isGeneric: true);
                    if ((object)builderType != null)
                    {
                        builderType         = builderType.ConstructedFrom.Construct(resultType);
                        taskProperty        = GetCustomTaskProperty(F, builderType, returnType);
                        createBuilderMethod = GetCustomCreateMethod(F, builderType);
                    }
                }
                else
                {
                    builderType = F.WellKnownType(WellKnownType.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T);
                    Debug.Assert((object)builderType != null);
                    builderType = builderType.Construct(resultType);
                    TryGetBuilderMember <MethodSymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Create,
                        builderType,
                        customBuilder,
                        out createBuilderMethod);
                    TryGetBuilderMember <PropertySymbol>(
                        F,
                        WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Task,
                        builderType,
                        customBuilder,
                        out taskProperty);
                }
                if ((object)builderType == null ||
                    (object)taskProperty == null ||
                    (object)createBuilderMethod == null)
                {
                    collection = default(AsyncMethodBuilderMemberCollection);
                    return(false);
                }
                return(TryCreate(
                           F,
                           customBuilder: customBuilder,
                           builderType: builderType,
                           resultType: resultType,
                           createBuilderMethod: createBuilderMethod,
                           taskProperty: taskProperty,
                           setException: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetException,
                           setResult: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetResult,
                           awaitOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitOnCompleted,
                           awaitUnsafeOnCompleted: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__AwaitUnsafeOnCompleted,
                           start: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__Start_T,
                           setStateMachine: WellKnownMember.System_Runtime_CompilerServices_AsyncTaskMethodBuilder_T__SetStateMachine,
                           collection: out collection));
            }

            throw ExceptionUtilities.UnexpectedValue(method);
        }
Ejemplo n.º 40
0
        private static bool ReturnTypesMatch(MethodSymbol candidateMethod, TypeMap candidateMethodTypeMap, ref ParamInfo<TypeSymbol> targetReturnParam)
        {
            Debug.Assert(candidateMethodTypeMap != null);

            if (candidateMethod.ReturnsByRef != targetReturnParam.IsByRef)
            {
                return false;
            }

            TypeSymbol candidateReturnType = candidateMethod.ReturnType;
            TypeSymbol targetReturnType = targetReturnParam.Type;

            // CONSIDER: Do we want to add special handling for error types?  Right now, we expect they'll just fail to match.
            var substituted = new TypeWithModifiers(candidateReturnType, candidateMethod.ReturnTypeCustomModifiers).SubstituteType(candidateMethodTypeMap);
            if (substituted.Type != targetReturnType)
            {
                return false;
            }

            if (!CustomModifiersMatch(substituted.CustomModifiers, targetReturnParam.CustomModifiers) ||
                !CustomModifiersMatch(candidateMethodTypeMap.SubstituteCustomModifiers(candidateMethod.RefCustomModifiers), targetReturnParam.RefCustomModifiers))
            {
                return false;
            }

            return true;
        }
        internal Microsoft.Cci.IMethodReference Translate(MethodSymbol methodSymbol, bool needDeclaration)
        {
            object reference;
            Microsoft.Cci.IMethodReference methodRef;
            NamedTypeSymbol container = methodSymbol.ContainingType;

            System.Diagnostics.Debug.Assert(ReferenceEquals(methodSymbol, methodSymbol.OriginalDefinition) ||
                !methodSymbol.Equals(methodSymbol.OriginalDefinition));

            if (!ReferenceEquals(methodSymbol.OriginalDefinition, methodSymbol))
            {
                System.Diagnostics.Debug.Assert(!needDeclaration);

                return methodSymbol;
            }
            else if (!needDeclaration)
            {
                bool methodIsGeneric = methodSymbol.IsGeneric;
                bool typeIsGeneric = IsGenericType(container);

                if (methodIsGeneric || typeIsGeneric)
                {
                    if (genericInstanceMap.TryGetValue(methodSymbol, out reference))
                    {
                        return (Microsoft.Cci.IMethodReference)reference;
                    }

                    if (methodIsGeneric)
                    {
                        if (typeIsGeneric)
                        {
                            // Specialized and generic instance at the same time.
                            throw new NotImplementedException();
                        }
                        else
                        {
                            methodRef = new GenericMethodInstanceReference(methodSymbol);
                        }
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(typeIsGeneric);
                        methodRef = new SpecializedMethodReference(methodSymbol);
                    }

                    genericInstanceMap.Add(methodSymbol, methodRef);

                    return methodRef;
                }
            }

            return methodSymbol;
        }
 private void AddGetOrSet(PropertySymbol property, MethodSymbol method, SyntaxKind keyword, ArrayBuilder<SymbolDescriptionPart> builder)
 {
     if (method != null)
     {
         AddSpace(builder);
         if (method.DeclaredAccessibility != property.DeclaredAccessibility)
         {
             AddAccessibilityIfRequired(method, builder);
         }
         AddKeyword(keyword, builder);
         AddPunctuation(SyntaxKind.SemicolonToken, builder);
     }
 }
        public Microsoft.Cci.IMethodBody GetMethodBody(MethodSymbol methodSymbol)
        {
            System.Diagnostics.Debug.Assert(methodSymbol.ContainingModule == this.SourceModule &&
                ReferenceEquals(methodSymbol, methodSymbol.OriginalDefinition)); 

            Microsoft.Cci.IMethodBody body;

            if (methodBodyMap.TryGetValue(methodSymbol, out body))
            {
                return body;
            }

            return null;
        }
Ejemplo n.º 44
0
        internal static Symbol GetRuntimeMember(NamedTypeSymbol declaringType, ref MemberDescriptor descriptor, SignatureComparer <MethodSymbol, FieldSymbol, PropertySymbol, TypeSymbol, ParameterSymbol> comparer, AssemblySymbol accessWithinOpt)
        {
            Symbol     result = null;
            SymbolKind targetSymbolKind;
            MethodKind targetMethodKind = MethodKind.Ordinary;
            bool       isStatic         = (descriptor.Flags & MemberFlags.Static) != 0;

            switch (descriptor.Flags & MemberFlags.KindMask)
            {
            case MemberFlags.Constructor:
                targetSymbolKind = SymbolKind.Method;
                targetMethodKind = MethodKind.Constructor;
                //  static constructors are never called explicitly
                Debug.Assert(!isStatic);
                break;

            case MemberFlags.Method:
                targetSymbolKind = SymbolKind.Method;
                break;

            case MemberFlags.PropertyGet:
                targetSymbolKind = SymbolKind.Method;
                targetMethodKind = MethodKind.PropertyGet;
                break;

            case MemberFlags.Field:
                targetSymbolKind = SymbolKind.Field;
                break;

            case MemberFlags.Property:
                targetSymbolKind = SymbolKind.Property;
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(descriptor.Flags);
            }

            foreach (var member in declaringType.GetMembers(descriptor.Name))
            {
                Debug.Assert(member.Name.Equals(descriptor.Name));

                if (member.Kind != targetSymbolKind || member.IsStatic != isStatic ||
                    !(member.DeclaredAccessibility == Accessibility.Public || ((object)accessWithinOpt != null && Symbol.IsSymbolAccessible(member, accessWithinOpt))))
                {
                    continue;
                }

                switch (targetSymbolKind)
                {
                case SymbolKind.Method:
                {
                    MethodSymbol method     = (MethodSymbol)member;
                    MethodKind   methodKind = method.MethodKind;
                    // Treat user-defined conversions and operators as ordinary methods for the purpose
                    // of matching them here.
                    if (methodKind == MethodKind.Conversion || methodKind == MethodKind.UserDefinedOperator)
                    {
                        methodKind = MethodKind.Ordinary;
                    }

                    if (method.Arity != descriptor.Arity || methodKind != targetMethodKind ||
                        ((descriptor.Flags & MemberFlags.Virtual) != 0) != (method.IsVirtual || method.IsOverride || method.IsAbstract))
                    {
                        continue;
                    }

                    if (!comparer.MatchMethodSignature(method, descriptor.Signature))
                    {
                        continue;
                    }
                }

                break;

                case SymbolKind.Property:
                {
                    PropertySymbol property = (PropertySymbol)member;
                    if (((descriptor.Flags & MemberFlags.Virtual) != 0) != (property.IsVirtual || property.IsOverride || property.IsAbstract))
                    {
                        continue;
                    }

                    if (!comparer.MatchPropertySignature(property, descriptor.Signature))
                    {
                        continue;
                    }
                }

                break;

                case SymbolKind.Field:
                    if (!comparer.MatchFieldSignature((FieldSymbol)member, descriptor.Signature))
                    {
                        continue;
                    }

                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(targetSymbolKind);
                }

                // ambiguity
                if ((object)result != null)
                {
                    result = null;
                    break;
                }

                result = member;
            }
            return(result);
        }
Ejemplo n.º 45
0
 protected static void AddMethod(int inlet, Symbol sel, MethodSymbol m) { ((External)m.Target).klass.AddMethod(inlet, sel, m); }
        public void SetMethodBody(MethodSymbol methodSymbol, Microsoft.Cci.IMethodBody body)
        {
            Contract.ThrowIfFalse(methodSymbol.ContainingModule == this.SourceModule &&
                ReferenceEquals(methodSymbol, methodSymbol.OriginalDefinition));

            methodBodyMap.Add(methodSymbol, body);
        }
Ejemplo n.º 47
0
        private BoundExpression LowerLiftedUnaryOperator(
            UnaryOperatorKind kind,
            CSharpSyntaxNode syntax,
            MethodSymbol method,
            BoundExpression loweredOperand,
            TypeSymbol type)
        {
            // First, an optimization. If we know that the operand is always null then
            // we can simply lower to the alternative.

            BoundExpression optimized = OptimizeLiftedUnaryOperator(kind, syntax, method, loweredOperand, type);

            if (optimized != null)
            {
                return(optimized);
            }

            // We do not know whether the operand is null or non-null, so we generate:
            //
            // S? temp = operand;
            // R? r = temp.HasValue ?
            //        new R?(OP(temp.GetValueOrDefault())) :
            //        default(R?);

            BoundAssignmentOperator tempAssignment;
            BoundLocal   boundTemp         = _factory.StoreToTemp(loweredOperand, out tempAssignment);
            MethodSymbol getValueOrDefault = GetNullableMethod(syntax, boundTemp.Type, SpecialMember.System_Nullable_T_GetValueOrDefault);

            // temp.HasValue
            BoundExpression condition = MakeNullableHasValue(syntax, boundTemp);

            // temp.GetValueOrDefault()
            BoundExpression call_GetValueOrDefault = BoundCall.Synthesized(syntax, boundTemp, getValueOrDefault);

            // new R?(temp.GetValueOrDefault())
            BoundExpression consequence = GetLiftedUnaryOperatorConsequence(kind, syntax, method, type, call_GetValueOrDefault);

            // default(R?)
            BoundExpression alternative = new BoundDefaultOperator(syntax, null, type);

            // temp.HasValue ?
            //          new R?(OP(temp.GetValueOrDefault())) :
            //          default(R?);
            BoundExpression conditionalExpression = RewriteConditionalOperator(
                syntax: syntax,
                rewrittenCondition: condition,
                rewrittenConsequence: consequence,
                rewrittenAlternative: alternative,
                constantValueOpt: null,
                rewrittenType: type);

            // temp = operand;
            // temp.HasValue ?
            //          new R?(OP(temp.GetValueOrDefault())) :
            //          default(R?);
            return(new BoundSequence(
                       syntax: syntax,
                       locals: ImmutableArray.Create <LocalSymbol>(boundTemp.LocalSymbol),
                       sideEffects: ImmutableArray.Create <BoundExpression>(tempAssignment),
                       value: conditionalExpression,
                       type: type));
        }
 public override Microsoft.Cci.IReference VisitMethod(MethodSymbol symbol, bool a)
 {
     return Translate(symbol, false);
 }
Ejemplo n.º 49
0
        private BoundExpression OptimizeLiftedUnaryOperator(
            UnaryOperatorKind operatorKind,
            CSharpSyntaxNode syntax,
            MethodSymbol method,
            BoundExpression loweredOperand,
            TypeSymbol type)
        {
            if (NullableNeverHasValue(loweredOperand))
            {
                return(new BoundDefaultOperator(syntax, null, type));
            }

            // Second, another simple optimization. If we know that the operand is never null
            // then we can obtain the non-null value and skip generating the temporary. That is,
            // "~(new int?(M()))" is the same as "new int?(~M())".

            BoundExpression neverNull = NullableAlwaysHasValue(loweredOperand);

            if (neverNull != null)
            {
                return(GetLiftedUnaryOperatorConsequence(operatorKind, syntax, method, type, neverNull));
            }

            var conditionalLeft = loweredOperand as BoundLoweredConditionalAccess;

            // NOTE: we could in theory handle sideeffecting loweredRight here too
            //       by including it as a part of whenNull, but there is a concern
            //       that it can lead to code duplication
            var optimize = conditionalLeft != null &&
                           (conditionalLeft.WhenNullOpt == null || conditionalLeft.WhenNullOpt.IsDefaultValue());

            if (optimize)
            {
                var result = LowerLiftedUnaryOperator(operatorKind, syntax, method, conditionalLeft.WhenNotNull, type);

                return(conditionalLeft.Update(
                           conditionalLeft.Receiver,
                           conditionalLeft.HasValueMethodOpt,
                           whenNotNull: result,
                           whenNullOpt: null,
                           id: conditionalLeft.Id,
                           type: result.Type
                           ));
            }

            // This optimization is analogous to DistributeLiftedConversionIntoLiftedOperand.

            // Suppose we have a lifted unary conversion whose operand is itself a lifted operation.
            // That is, we have something like:
            //
            // int? r = - (M() + N());
            //
            // where M() and N() return nullable ints. We would simply codegen this as first
            // creating the nullable int result of M() + N(), then checking it for nullity,
            // and then doing the unary minus. That is:
            //
            // int? m = M();
            // int? n = N();
            // int? t = m.HasValue && n.HasValue ? new int?(m.Value + n.Value) : new int?();
            // int? r = t.HasValue ? new int?(-t.Value) : new int?();
            //
            // However, we also observe that we can distribute the unary minus into both branches of
            // the conditional:
            //
            // int? m = M();
            // int? n = N();
            // int? r = m.HasValue && n.HasValue ? - (new int?(m.Value + n.Value))) : - new int?();
            //
            // And we already optimize those! So we could reduce this to:
            //
            // int? m = M();
            // int? n = N();
            // int? r = m.HasValue && n.HasValue ? new int?(- (m.Value + n.Value)) : new int?());
            //
            // which avoids entirely the creation of the unnecessary nullable int and the unnecessary
            // extra null check.

            if (loweredOperand.Kind == BoundKind.Sequence)
            {
                BoundSequence seq = (BoundSequence)loweredOperand;
                if (seq.Value.Kind == BoundKind.ConditionalOperator)
                {
                    BoundConditionalOperator conditional = (BoundConditionalOperator)seq.Value;
                    Debug.Assert(seq.Type == conditional.Type);
                    Debug.Assert(conditional.Type == conditional.Consequence.Type);
                    Debug.Assert(conditional.Type == conditional.Alternative.Type);

                    if (NullableAlwaysHasValue(conditional.Consequence) != null && NullableNeverHasValue(conditional.Alternative))
                    {
                        return(new BoundSequence(
                                   syntax,
                                   seq.Locals,
                                   seq.SideEffects,
                                   RewriteConditionalOperator(
                                       syntax,
                                       conditional.Condition,
                                       MakeUnaryOperator(operatorKind, syntax, method, conditional.Consequence, type),
                                       MakeUnaryOperator(operatorKind, syntax, method, conditional.Alternative, type),
                                       ConstantValue.NotAvailable,
                                       type),
                                   type));
                    }
                }
            }

            return(null);
        }