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); }
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); } }
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); }
public ResolveOverloadsResult(MethodSymbol exactMatch, MethodSymbol bestMatch) : this() { this.ExactMatch = exactMatch; this.BestMatch = bestMatch; }
protected static void AddMethod(int inlet, MethodSymbol m) { AddMethod(inlet, _symbol, m); }
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; }
private AwaitExpressionSpiller(MethodSymbol method, CSharpSyntaxNode syntaxNode, TypeCompilationState compilationState, PooledDictionary <LocalSymbol, LocalSymbol> tempSubstitution, DiagnosticBag diagnostics) { _F = new SyntheticBoundNodeFactory(method, syntaxNode, compilationState, diagnostics); _tempSubstitution = tempSubstitution; }
/// <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); }
public MethodDefinition(Module moduleBeingBuilt, MethodSymbol underlyingMethod) : base(moduleBeingBuilt, underlyingMethod) { }
protected static void AddMethod(int inlet, string sel, MethodSymbol m) { AddMethod(inlet, new Symbol(sel), m); }
protected static void AddMethod(MethodSymbol m) { AddMethod(0, m); }
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); } } }
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); } }
/// <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()); }
private DiagnosticsPass(CSharpCompilation compilation, DiagnosticBag diagnostics, MethodSymbol containingSymbol) { Debug.Assert(diagnostics != null); Debug.Assert((object)containingSymbol != null); _compilation = compilation; _diagnostics = diagnostics; _containingSymbol = containingSymbol; }
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; }
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<T>, 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; }
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); }
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); }
private void CheckReducedExtensionMethods(MethodSymbol source, MethodSymbol retargeting) { CheckMethods(source.ReducedFrom, retargeting.ReducedFrom); }
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)); }
private static MethodGroupResolution ResolveDelegateOrFunctionPointerMethodGroup(Binder binder, BoundMethodGroup source, MethodSymbol delegateInvokeMethodOpt, bool isFunctionPointer, in CallingConventionInfo callingConventionInfo, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo)
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)); }
public GenericMethodInstanceReference(MethodSymbol underlyingMethod) : base(underlyingMethod) { }
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); }
public override void VisitMethod(MethodSymbol symbol) { throw ExceptionUtilities.Unreachable; }
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; }
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; }
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); }
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; }
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); }
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; }
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); }
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); }
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); }
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); }