提交 8f4befcc 编写于 作者: E Evan Hauck

Add local functions to BoundBlock

上级 bd2fa007
...@@ -157,6 +157,14 @@ internal virtual ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSyn ...@@ -157,6 +157,14 @@ internal virtual ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSyn
return this.Next.GetDeclaredLocalsForScope(node); return this.Next.GetDeclaredLocalsForScope(node);
} }
/// <summary>
/// Get local functions declared immediately in scope represented by the node.
/// </summary>
internal virtual ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode node)
{
return this.Next.GetDeclaredLocalFunctionsForScope(node);
}
/// <summary> /// <summary>
/// The member containing the binding context. Note that for the purposes of the compiler, /// The member containing the binding context. Note that for the purposes of the compiler,
/// a lambda expression is considered a "member" of its enclosing method, field, or lambda. /// a lambda expression is considered a "member" of its enclosing method, field, or lambda.
......
...@@ -2132,7 +2132,11 @@ internal static BoundBlock BindBlock(BlockSyntax node, DiagnosticBag diagnostics ...@@ -2132,7 +2132,11 @@ internal static BoundBlock BindBlock(BlockSyntax node, DiagnosticBag diagnostics
} }
} }
return new BoundBlock(node, blockBinder.GetDeclaredLocalsForScope(node), boundStatements.ToImmutableAndFree()); return new BoundBlock(
node,
blockBinder.GetDeclaredLocalsForScope(node),
blockBinder.GetDeclaredLocalFunctionsForScope(node),
boundStatements.ToImmutableAndFree());
} }
internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType, BoundExpression expression, DiagnosticBag diagnostics, bool isDefaultParameter = false) internal BoundExpression GenerateConversionForAssignment(TypeSymbol targetType, BoundExpression expression, DiagnosticBag diagnostics, bool isDefaultParameter = false)
...@@ -3271,7 +3275,7 @@ internal BoundBlock CreateBlockFromExpression(CSharpSyntaxNode node, ImmutableAr ...@@ -3271,7 +3275,7 @@ internal BoundBlock CreateBlockFromExpression(CSharpSyntaxNode node, ImmutableAr
} }
// Need to attach the tree for when we generate sequence points. // Need to attach the tree for when we generate sequence points.
return new BoundBlock(node, locals, ImmutableArray.Create(statement)) { WasCompilerGenerated = node.Kind() != SyntaxKind.ArrowExpressionClause }; return new BoundBlock(node, locals, ImmutableArray<LocalFunctionSymbol>.Empty, ImmutableArray.Create(statement)) { WasCompilerGenerated = node.Kind() != SyntaxKind.ArrowExpressionClause };
} }
/// <summary> /// <summary>
......
...@@ -56,5 +56,22 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy ...@@ -56,5 +56,22 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy
throw ExceptionUtilities.Unreachable; throw ExceptionUtilities.Unreachable;
} }
internal override ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode node)
{
if (node.Kind() == SyntaxKind.Block)
{
if (((BlockSyntax)node).Statements == _statements)
{
return this.LocalFunctions;
}
}
else if (_statements.Count == 1 && _statements.First() == node)
{
return this.LocalFunctions;
}
throw ExceptionUtilities.Unreachable;
}
} }
} }
...@@ -154,6 +154,11 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy ...@@ -154,6 +154,11 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy
throw ExceptionUtilities.Unreachable; throw ExceptionUtilities.Unreachable;
} }
internal override ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode node)
{
throw ExceptionUtilities.Unreachable;
}
internal override BoundSwitchStatement BindSwitchExpressionAndSections(SwitchStatementSyntax node, Binder originalBinder, DiagnosticBag diagnostics) internal override BoundSwitchStatement BindSwitchExpressionAndSections(SwitchStatementSyntax node, Binder originalBinder, DiagnosticBag diagnostics)
{ {
// There's supposed to be a SwitchBinder (or other overrider of this method) in the chain. // There's supposed to be a SwitchBinder (or other overrider of this method) in the chain.
......
...@@ -46,5 +46,15 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy ...@@ -46,5 +46,15 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy
throw ExceptionUtilities.Unreachable; throw ExceptionUtilities.Unreachable;
} }
internal override ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode node)
{
if (node == _syntax)
{
return ImmutableArray<LocalFunctionSymbol>.Empty;
}
throw ExceptionUtilities.Unreachable;
}
} }
} }
...@@ -46,5 +46,15 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy ...@@ -46,5 +46,15 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy
throw ExceptionUtilities.Unreachable; throw ExceptionUtilities.Unreachable;
} }
internal override ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode node)
{
if (node == _syntax)
{
return ImmutableArray<LocalFunctionSymbol>.Empty;
}
throw ExceptionUtilities.Unreachable;
}
} }
} }
...@@ -444,5 +444,10 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy ...@@ -444,5 +444,10 @@ internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(CSharpSy
{ {
throw ExceptionUtilities.Unreachable; throw ExceptionUtilities.Unreachable;
} }
internal override ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode node)
{
throw ExceptionUtilities.Unreachable;
}
} }
} }
...@@ -549,6 +549,7 @@ ...@@ -549,6 +549,7 @@
--> -->
<Node Name="BoundBlock" Base="BoundStatementList"> <Node Name="BoundBlock" Base="BoundStatementList">
<Field Name="Locals" Type="ImmutableArray&lt;LocalSymbol&gt;"/> <Field Name="Locals" Type="ImmutableArray&lt;LocalSymbol&gt;"/>
<Field Name="LocalFunctions" Type="ImmutableArray&lt;LocalFunctionSymbol&gt;"/>
</Node> </Node>
<!-- <!--
......
...@@ -525,21 +525,19 @@ internal partial class BoundBlock ...@@ -525,21 +525,19 @@ internal partial class BoundBlock
{ {
public static BoundBlock SynthesizedNoLocals(CSharpSyntaxNode syntax, BoundStatement statement) public static BoundBlock SynthesizedNoLocals(CSharpSyntaxNode syntax, BoundStatement statement)
{ {
return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create(statement)) ImmutableArray.Create(statement))
{ WasCompilerGenerated = true }; { WasCompilerGenerated = true };
} }
public static BoundBlock SynthesizedNoLocals(CSharpSyntaxNode syntax, ImmutableArray<BoundStatement> statements) public static BoundBlock SynthesizedNoLocals(CSharpSyntaxNode syntax, ImmutableArray<BoundStatement> statements)
{ {
Debug.Assert(statements.Length > 0); return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalFunctionSymbol>.Empty, statements) { WasCompilerGenerated = true };
return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, statements) { WasCompilerGenerated = true };
} }
public static BoundBlock SynthesizedNoLocals(CSharpSyntaxNode syntax, params BoundStatement[] statements) public static BoundBlock SynthesizedNoLocals(CSharpSyntaxNode syntax, params BoundStatement[] statements)
{ {
Debug.Assert(statements.Length > 0); return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalFunctionSymbol>.Empty, statements.AsImmutableOrNull()) { WasCompilerGenerated = true };
return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, statements.AsImmutableOrNull()) { WasCompilerGenerated = true };
} }
} }
......
...@@ -145,7 +145,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, ...@@ -145,7 +145,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
BoundStatement retStatement = F.Return(retExpression); BoundStatement retStatement = F.Return(retExpression);
// Create a bound block // Create a bound block
F.CloseMethod(F.Block(ImmutableArray.Create<LocalSymbol>(boundLocal.LocalSymbol), assignment, retStatement)); F.CloseMethod(F.Block(ImmutableArray.Create<LocalSymbol>(boundLocal.LocalSymbol), ImmutableArray<LocalFunctionSymbol>.Empty, assignment, retStatement));
} }
internal override bool HasSpecialName internal override bool HasSpecialName
......
...@@ -81,6 +81,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, ...@@ -81,6 +81,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
var body = F.Block( var body = F.Block(
ImmutableArray.Create<LocalSymbol>(hashCode, i), ImmutableArray.Create<LocalSymbol>(hashCode, i),
ImmutableArray<LocalFunctionSymbol>.Empty,
F.If( F.If(
F.Binary(BinaryOperatorKind.ObjectNotEqual, F.SpecialType(SpecialType.System_Boolean), F.Binary(BinaryOperatorKind.ObjectNotEqual, F.SpecialType(SpecialType.System_Boolean),
F.Parameter(text), F.Parameter(text),
......
...@@ -200,7 +200,7 @@ internal static BoundBlock ConstructAutoPropertyAccessorBody(SourceMethodSymbol ...@@ -200,7 +200,7 @@ internal static BoundBlock ConstructAutoPropertyAccessorBody(SourceMethodSymbol
statement = new BoundSequencePoint(accessor.SyntaxNode, statement) { WasCompilerGenerated = true }; statement = new BoundSequencePoint(accessor.SyntaxNode, statement) { WasCompilerGenerated = true };
return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create<BoundStatement>(statement)) { WasCompilerGenerated = true }; return BoundBlock.SynthesizedNoLocals(syntax, statement);
} }
/// <summary> /// <summary>
...@@ -358,10 +358,7 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEve ...@@ -358,10 +358,7 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEve
memberDescriptor.Name), memberDescriptor.Name),
syntax.Location)); syntax.Location));
return new BoundBlock(syntax, return BoundBlock.SynthesizedNoLocals(syntax, @return);
locals: ImmutableArray<LocalSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>(@return))
{ WasCompilerGenerated = true };
} }
Binder.ReportUseSiteDiagnostics(updateMethod, diagnostics, syntax); Binder.ReportUseSiteDiagnostics(updateMethod, diagnostics, syntax);
...@@ -404,12 +401,10 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEve ...@@ -404,12 +401,10 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEve
{ WasCompilerGenerated = true }) { WasCompilerGenerated = true })
{ WasCompilerGenerated = true }; { WasCompilerGenerated = true };
return new BoundBlock(syntax, return BoundBlock.SynthesizedNoLocals(syntax,
locals: ImmutableArray<LocalSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>( statements: ImmutableArray.Create<BoundStatement>(
eventUpdate, eventUpdate,
@return)) @return));
{ WasCompilerGenerated = true };
} }
compareExchangeMethod = compareExchangeMethod.Construct(ImmutableArray.Create<TypeSymbol>(delegateType)); compareExchangeMethod = compareExchangeMethod.Construct(ImmutableArray.Create<TypeSymbol>(delegateType));
...@@ -505,6 +500,7 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEve ...@@ -505,6 +500,7 @@ internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEve
return new BoundBlock(syntax, return new BoundBlock(syntax,
locals: tmps.AsImmutable(), locals: tmps.AsImmutable(),
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>( statements: ImmutableArray.Create<BoundStatement>(
tmp0Init, tmp0Init,
loopStart, loopStart,
...@@ -548,6 +544,7 @@ internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlo ...@@ -548,6 +544,7 @@ internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlo
return new BoundBlock( return new BoundBlock(
syntax, syntax,
ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalSymbol>.Empty,
ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create<BoundStatement>( ImmutableArray.Create<BoundStatement>(
new BoundTryStatement( new BoundTryStatement(
syntax, syntax,
...@@ -556,6 +553,7 @@ internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlo ...@@ -556,6 +553,7 @@ internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlo
new BoundBlock( new BoundBlock(
syntax, syntax,
ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalSymbol>.Empty,
ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create<BoundStatement>( ImmutableArray.Create<BoundStatement>(
baseFinalizeCall) baseFinalizeCall)
) )
......
...@@ -847,7 +847,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum ...@@ -847,7 +847,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
if (methodSymbol.IsScriptConstructor) if (methodSymbol.IsScriptConstructor)
{ {
body = new BoundBlock(methodSymbol.GetNonNullSyntaxNode(), ImmutableArray<LocalSymbol>.Empty, ImmutableArray<BoundStatement>.Empty) { WasCompilerGenerated = true }; body = BoundBlock.SynthesizedNoLocals(methodSymbol.GetNonNullSyntaxNode(), ImmutableArray<BoundStatement>.Empty);
includeInitializersInBody = false; includeInitializersInBody = false;
importChain = null; importChain = null;
} }
...@@ -858,7 +858,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum ...@@ -858,7 +858,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
BoundTypeOrInstanceInitializers initializerStatements = InitializerRewriter.Rewrite(processedInitializers.BoundInitializers, methodSymbol, submissionResultType); BoundTypeOrInstanceInitializers initializerStatements = InitializerRewriter.Rewrite(processedInitializers.BoundInitializers, methodSymbol, submissionResultType);
// the lowered script initializers should not be treated as initializers anymore but as a method body: // the lowered script initializers should not be treated as initializers anymore but as a method body:
body = new BoundBlock(initializerStatements.Syntax, ImmutableArray<LocalSymbol>.Empty, initializerStatements.Statements) { WasCompilerGenerated = true }; body = BoundBlock.SynthesizedNoLocals(initializerStatements.Syntax, initializerStatements.Statements);
includeInitializersInBody = false; includeInitializersInBody = false;
importChain = null; importChain = null;
...@@ -883,7 +883,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum ...@@ -883,7 +883,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
if (body != null && methodSymbol.ContainingType.IsStructType() && !methodSymbol.IsImplicitConstructor) if (body != null && methodSymbol.ContainingType.IsStructType() && !methodSymbol.IsImplicitConstructor)
{ {
// In order to get correct diagnostics, we need to analyze initializers and the body together. // In order to get correct diagnostics, we need to analyze initializers and the body together.
body = body.Update(body.Locals, body.Statements.Insert(0, analyzedInitializers)); body = body.Update(body.Locals, body.LocalFunctions, body.Statements.Insert(0, analyzedInitializers));
includeInitializersInBody = false; includeInitializersInBody = false;
analyzedInitializers = null; analyzedInitializers = null;
} }
...@@ -1592,7 +1592,7 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta ...@@ -1592,7 +1592,7 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
statements = ImmutableArray.Create(constructorInitializer, body); statements = ImmutableArray.Create(constructorInitializer, body);
} }
return new BoundBlock(method.GetNonNullSyntaxNode(), ImmutableArray<LocalSymbol>.Empty, statements) { WasCompilerGenerated = true }; return BoundBlock.SynthesizedNoLocals(method.GetNonNullSyntaxNode(), statements);
} }
/// <summary> /// <summary>
......
...@@ -26,6 +26,12 @@ internal partial class DataFlowPass : AbstractFlowPass<DataFlowPass.LocalState> ...@@ -26,6 +26,12 @@ internal partial class DataFlowPass : AbstractFlowPass<DataFlowPass.LocalState>
/// </summary> /// </summary>
private readonly PooledHashSet<LocalSymbol> _usedVariables = PooledHashSet<LocalSymbol>.GetInstance(); private readonly PooledHashSet<LocalSymbol> _usedVariables = PooledHashSet<LocalSymbol>.GetInstance();
/// <summary>
/// Variables that were used anywhere, in the sense required to suppress warnings about
/// unused variables.
/// </summary>
private readonly PooledHashSet<LocalFunctionSymbol> _usedLocalFunctions = PooledHashSet<LocalFunctionSymbol>.GetInstance();
/// <summary> /// <summary>
/// Variables that were initialized or written anywhere. /// Variables that were initialized or written anywhere.
/// </summary> /// </summary>
...@@ -102,6 +108,7 @@ internal partial class DataFlowPass : AbstractFlowPass<DataFlowPass.LocalState> ...@@ -102,6 +108,7 @@ internal partial class DataFlowPass : AbstractFlowPass<DataFlowPass.LocalState>
protected override void Free() protected override void Free()
{ {
_usedVariables.Free(); _usedVariables.Free();
_usedLocalFunctions.Free();
_writtenVariables.Free(); _writtenVariables.Free();
_capturedVariables.Free(); _capturedVariables.Free();
_unsafeAddressTakenVariables.Free(); _unsafeAddressTakenVariables.Free();
...@@ -394,6 +401,11 @@ protected virtual void NoteRead(Symbol variable, ParameterSymbol rangeVariableUn ...@@ -394,6 +401,11 @@ protected virtual void NoteRead(Symbol variable, ParameterSymbol rangeVariableUn
{ {
_usedVariables.Add(local); _usedVariables.Add(local);
} }
var localFunction = variable as LocalFunctionSymbol;
if ((object)localFunction != null)
{
_usedLocalFunctions.Add(localFunction);
}
if ((object)variable != null) if ((object)variable != null)
{ {
...@@ -1281,6 +1293,7 @@ public override BoundNode VisitBlock(BoundBlock node) ...@@ -1281,6 +1293,7 @@ public override BoundNode VisitBlock(BoundBlock node)
DeclareVariables(node.Locals); DeclareVariables(node.Locals);
var result = base.VisitBlock(node); var result = base.VisitBlock(node);
ReportUnusedVariables(node.Locals); ReportUnusedVariables(node.Locals);
ReportUnusedVariables(node.LocalFunctions);
return result; return result;
} }
...@@ -1455,6 +1468,25 @@ private void ReportIfUnused(LocalSymbol symbol, bool assigned) ...@@ -1455,6 +1468,25 @@ private void ReportIfUnused(LocalSymbol symbol, bool assigned)
} }
} }
private void ReportUnusedVariables(ImmutableArray<LocalFunctionSymbol> locals)
{
foreach (var symbol in locals)
{
ReportIfUnused(symbol, assigned: true);
}
}
private void ReportIfUnused(LocalFunctionSymbol symbol, bool assigned)
{
if (!_usedLocalFunctions.Contains(symbol))
{
if (!string.IsNullOrEmpty(symbol.Name)) // avoid diagnostics for parser-inserted names
{
Diagnostics.Add(assigned && _writtenVariables.Contains(symbol) ? ErrorCode.WRN_UnreferencedVarAssg : ErrorCode.WRN_UnreferencedVar, symbol.Locations[0], symbol.Name);
}
}
}
public override BoundNode VisitLocal(BoundLocal node) public override BoundNode VisitLocal(BoundLocal node)
{ {
// Note: the caller should avoid allowing this to be called for the left-hand-side of // Note: the caller should avoid allowing this to be called for the left-hand-side of
...@@ -1494,7 +1526,7 @@ public override BoundNode VisitCall(BoundCall node) ...@@ -1494,7 +1526,7 @@ public override BoundNode VisitCall(BoundCall node)
{ {
if (node.Method.MethodKind == MethodKind.LocalFunction) if (node.Method.MethodKind == MethodKind.LocalFunction)
{ {
CheckAssigned(node.Method, node.Syntax); CheckAssigned(node.Method.OriginalDefinition, node.Syntax);
} }
return base.VisitCall(node); return base.VisitCall(node);
} }
...@@ -1503,7 +1535,7 @@ public override BoundNode VisitConversion(BoundConversion node) ...@@ -1503,7 +1535,7 @@ public override BoundNode VisitConversion(BoundConversion node)
{ {
if (node.ConversionKind == ConversionKind.MethodGroup && node.SymbolOpt?.MethodKind == MethodKind.LocalFunction) if (node.ConversionKind == ConversionKind.MethodGroup && node.SymbolOpt?.MethodKind == MethodKind.LocalFunction)
{ {
CheckAssigned(node.SymbolOpt, node.Syntax); CheckAssigned(node.SymbolOpt.OriginalDefinition, node.Syntax);
} }
return base.VisitConversion(node); return base.VisitConversion(node);
} }
...@@ -1512,11 +1544,23 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE ...@@ -1512,11 +1544,23 @@ public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationE
{ {
if (node.MethodOpt?.MethodKind == MethodKind.LocalFunction) if (node.MethodOpt?.MethodKind == MethodKind.LocalFunction)
{ {
CheckAssigned(node.MethodOpt, node.Syntax); CheckAssigned(node.MethodOpt.OriginalDefinition, node.Syntax);
} }
return base.VisitDelegateCreationExpression(node); return base.VisitDelegateCreationExpression(node);
} }
public override BoundNode VisitMethodGroup(BoundMethodGroup node)
{
foreach (var method in node.Methods)
{
if (method.MethodKind == MethodKind.LocalFunction)
{
CheckAssigned(method, node.Syntax);
}
}
return base.VisitMethodGroup(node);
}
public override BoundNode VisitLambda(BoundLambda node) public override BoundNode VisitLambda(BoundLambda node)
{ {
return VisitLambdaOrLocalFunction(node); return VisitLambdaOrLocalFunction(node);
......
...@@ -88,10 +88,10 @@ internal static BoundBlock AppendImplicitReturn(BoundStatement node, MethodSymbo ...@@ -88,10 +88,10 @@ internal static BoundBlock AppendImplicitReturn(BoundStatement node, MethodSymbo
{ {
case BoundKind.Block: case BoundKind.Block:
var block = (BoundBlock)node; var block = (BoundBlock)node;
return block.Update(block.Locals, block.Statements.Add(ret)); return block.Update(block.Locals, block.LocalFunctions, block.Statements.Add(ret));
default: default:
return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create(ret, node)); return new BoundBlock(syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalFunctionSymbol>.Empty, ImmutableArray.Create(ret, node));
} }
} }
......
...@@ -226,6 +226,7 @@ public override BoundNode VisitTryStatement(BoundTryStatement node) ...@@ -226,6 +226,7 @@ public override BoundNode VisitTryStatement(BoundTryStatement node)
var completeTry = _F.Block( var completeTry = _F.Block(
locals.ToImmutableAndFree(), locals.ToImmutableAndFree(),
ImmutableArray<LocalFunctionSymbol>.Empty,
statements.ToImmutableAndFree()); statements.ToImmutableAndFree());
return completeTry; return completeTry;
...@@ -402,6 +403,7 @@ private BoundStatement UnpendException(LocalSymbol pendingExceptionLocal) ...@@ -402,6 +403,7 @@ private BoundStatement UnpendException(LocalSymbol pendingExceptionLocal)
return _F.Block( return _F.Block(
ImmutableArray.Create<LocalSymbol>(obj), ImmutableArray.Create<LocalSymbol>(obj),
ImmutableArray<LocalFunctionSymbol>.Empty,
objInit, objInit,
_F.If( _F.If(
_F.ObjectNotEqual( _F.ObjectNotEqual(
...@@ -430,6 +432,7 @@ private BoundStatement Rethrow(LocalSymbol obj) ...@@ -430,6 +432,7 @@ private BoundStatement Rethrow(LocalSymbol obj)
// better rethrow // better rethrow
rethrow = _F.Block( rethrow = _F.Block(
ImmutableArray.Create(ex), ImmutableArray.Create(ex),
ImmutableArray<LocalFunctionSymbol>.Empty,
assignment, assignment,
_F.If(_F.ObjectEqual(_F.Local(ex), _F.Null(ex.Type)), rethrow), _F.If(_F.ObjectEqual(_F.Local(ex), _F.Null(ex.Type)), rethrow),
// ExceptionDispatchInfo.Capture(pendingExceptionLocal).Throw(); // ExceptionDispatchInfo.Capture(pendingExceptionLocal).Throw();
...@@ -484,6 +487,7 @@ private BoundStatement RewriteFinalizedRegion(BoundTryStatement node) ...@@ -484,6 +487,7 @@ private BoundStatement RewriteFinalizedRegion(BoundTryStatement node)
currentAwaitCatchFrame.pendingCaughtException, currentAwaitCatchFrame.pendingCaughtException,
currentAwaitCatchFrame.pendingCatch). currentAwaitCatchFrame.pendingCatch).
AddRange(currentAwaitCatchFrame.GetHoistedLocals()), AddRange(currentAwaitCatchFrame.GetHoistedLocals()),
ImmutableArray<LocalFunctionSymbol>.Empty,
_F.HiddenSequencePoint(), _F.HiddenSequencePoint(),
_F.Assignment( _F.Assignment(
_F.Local(currentAwaitCatchFrame.pendingCatch), _F.Local(currentAwaitCatchFrame.pendingCatch),
...@@ -616,6 +620,7 @@ public override BoundNode VisitCatchBlock(BoundCatchBlock node) ...@@ -616,6 +620,7 @@ public override BoundNode VisitCatchBlock(BoundCatchBlock node)
var handler = _F.Block( var handler = _F.Block(
handlerLocals, handlerLocals,
ImmutableArray<LocalFunctionSymbol>.Empty,
handlerStatements.ToImmutableAndFree() handlerStatements.ToImmutableAndFree()
); );
......
...@@ -130,6 +130,7 @@ internal void GenerateMoveNext(BoundStatement body, MethodSymbol moveNextMethod) ...@@ -130,6 +130,7 @@ internal void GenerateMoveNext(BoundStatement body, MethodSymbol moveNextMethod)
bodyBuilder.Add( bodyBuilder.Add(
F.Try( F.Try(
F.Block(ImmutableArray<LocalSymbol>.Empty, F.Block(ImmutableArray<LocalSymbol>.Empty,
ImmutableArray<LocalFunctionSymbol>.Empty,
// switch (state) ... // switch (state) ...
F.HiddenSequencePoint(), F.HiddenSequencePoint(),
Dispatch(), Dispatch(),
...@@ -201,6 +202,7 @@ internal void GenerateMoveNext(BoundStatement body, MethodSymbol moveNextMethod) ...@@ -201,6 +202,7 @@ internal void GenerateMoveNext(BoundStatement body, MethodSymbol moveNextMethod)
body.Syntax, body.Syntax,
F.Block( F.Block(
locals.ToImmutableAndFree(), locals.ToImmutableAndFree(),
ImmutableArray<LocalFunctionSymbol>.Empty,
newStatements)); newStatements));
if (rootScopeHoistedLocals.Length > 0) if (rootScopeHoistedLocals.Length > 0)
...@@ -301,6 +303,7 @@ private BoundBlock VisitAwaitExpression(BoundAwaitExpression node, BoundExpressi ...@@ -301,6 +303,7 @@ private BoundBlock VisitAwaitExpression(BoundAwaitExpression node, BoundExpressi
LocalSymbol resultTemp = F.SynthesizedLocal(type); LocalSymbol resultTemp = F.SynthesizedLocal(type);
return F.Block( return F.Block(
ImmutableArray.Create(awaiterTemp, resultTemp), ImmutableArray.Create(awaiterTemp, resultTemp),
ImmutableArray<LocalFunctionSymbol>.Empty,
awaitIfIncomplete, awaitIfIncomplete,
F.Assignment(F.Local(resultTemp), getResultCall), F.Assignment(F.Local(resultTemp), getResultCall),
F.ExpressionStatement(nullAwaiter), F.ExpressionStatement(nullAwaiter),
...@@ -312,6 +315,7 @@ private BoundBlock VisitAwaitExpression(BoundAwaitExpression node, BoundExpressi ...@@ -312,6 +315,7 @@ private BoundBlock VisitAwaitExpression(BoundAwaitExpression node, BoundExpressi
// $awaiterTemp = null; // $awaiterTemp = null;
return F.Block( return F.Block(
ImmutableArray.Create(awaiterTemp), ImmutableArray.Create(awaiterTemp),
ImmutableArray<LocalFunctionSymbol>.Empty,
awaitIfIncomplete, awaitIfIncomplete,
F.ExpressionStatement(getResultCall), F.ExpressionStatement(getResultCall),
F.ExpressionStatement(nullAwaiter)); F.ExpressionStatement(nullAwaiter));
...@@ -474,6 +478,7 @@ private BoundStatement GenerateAwaitOnCompletedDynamic(LocalSymbol awaiterTemp) ...@@ -474,6 +478,7 @@ private BoundStatement GenerateAwaitOnCompletedDynamic(LocalSymbol awaiterTemp)
thenClause: F.Block( thenClause: F.Block(
ImmutableArray.Create(notifyCompletionTemp), ImmutableArray.Create(notifyCompletionTemp),
ImmutableArray<LocalFunctionSymbol>.Empty,
F.Assignment( F.Assignment(
F.Local(notifyCompletionTemp), F.Local(notifyCompletionTemp),
// Use reference conversion rather than dynamic conversion: // Use reference conversion rather than dynamic conversion:
...@@ -505,6 +510,7 @@ private BoundStatement GenerateAwaitOnCompletedDynamic(LocalSymbol awaiterTemp) ...@@ -505,6 +510,7 @@ private BoundStatement GenerateAwaitOnCompletedDynamic(LocalSymbol awaiterTemp)
return F.Block( return F.Block(
SingletonOrPair(criticalNotifyCompletedTemp, thisTemp), SingletonOrPair(criticalNotifyCompletedTemp, thisTemp),
ImmutableArray<LocalFunctionSymbol>.Empty,
blockBuilder.ToImmutableAndFree()); blockBuilder.ToImmutableAndFree());
} }
......
...@@ -193,6 +193,7 @@ protected override BoundStatement GenerateStateMachineCreation(LocalSymbol state ...@@ -193,6 +193,7 @@ protected override BoundStatement GenerateStateMachineCreation(LocalSymbol state
return F.Block( return F.Block(
ImmutableArray.Create(builderVariable), ImmutableArray.Create(builderVariable),
ImmutableArray<LocalFunctionSymbol>.Empty,
bodyBuilder.ToImmutableAndFree()); bodyBuilder.ToImmutableAndFree());
} }
catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
......
...@@ -302,7 +302,7 @@ private BoundStatement UpdateStatement(BoundSpillSequenceBuilder builder, BoundS ...@@ -302,7 +302,7 @@ private BoundStatement UpdateStatement(BoundSpillSequenceBuilder builder, BoundS
} }
var substituterOpt = (substituteTemps && _tempSubstitution.Count > 0) ? new LocalSubstituter(_tempSubstitution) : null; var substituterOpt = (substituteTemps && _tempSubstitution.Count > 0) ? new LocalSubstituter(_tempSubstitution) : null;
var result = _F.Block(builder.GetLocals(), builder.GetStatements(substituterOpt)); var result = _F.Block(builder.GetLocals(), ImmutableArray<LocalFunctionSymbol>.Empty, builder.GetStatements(substituterOpt));
builder.Free(); builder.Free();
return result; return result;
......
...@@ -95,7 +95,7 @@ internal void GenerateMoveNextAndDispose(BoundStatement body, SynthesizedImpleme ...@@ -95,7 +95,7 @@ internal void GenerateMoveNextAndDispose(BoundStatement body, SynthesizedImpleme
// state_0: // state_0:
// state = -1; // state = -1;
// [[rewritten body]] // [[rewritten body]]
newBody = F.Block(ImmutableArray.Create(cachedState), newBody = F.Block(ImmutableArray.Create(cachedState), ImmutableArray<LocalFunctionSymbol>.Empty,
F.Block( F.Block(
F.HiddenSequencePoint(), F.HiddenSequencePoint(),
F.Assignment(F.Local(cachedState), F.Field(F.This(), stateField)) F.Assignment(F.Local(cachedState), F.Field(F.This(), stateField))
...@@ -153,6 +153,7 @@ internal void GenerateMoveNextAndDispose(BoundStatement body, SynthesizedImpleme ...@@ -153,6 +153,7 @@ internal void GenerateMoveNextAndDispose(BoundStatement body, SynthesizedImpleme
var disposeBody = F.Block( var disposeBody = F.Block(
ImmutableArray.Create<LocalSymbol>(stateLocal), ImmutableArray.Create<LocalSymbol>(stateLocal),
ImmutableArray<LocalFunctionSymbol>.Empty,
F.Assignment(F.Local(stateLocal), F.Field(F.This(), stateField)), F.Assignment(F.Local(stateLocal), F.Field(F.This(), stateField)),
EmitFinallyFrame(rootFrame, state), EmitFinallyFrame(rootFrame, state),
F.Return()); F.Return());
...@@ -179,6 +180,7 @@ private BoundStatement HandleReturn(BoundStatement newBody) ...@@ -179,6 +180,7 @@ private BoundStatement HandleReturn(BoundStatement newBody)
// return methodValue; // return methodValue;
newBody = F.Block( newBody = F.Block(
ImmutableArray.Create<LocalSymbol>(_methodValue), ImmutableArray.Create<LocalSymbol>(_methodValue),
ImmutableArray<LocalFunctionSymbol>.Empty,
newBody, newBody,
F.Assignment(this.F.Local(_methodValue), this.F.Literal(true)), F.Assignment(this.F.Local(_methodValue), this.F.Literal(true)),
F.Label(_exitLabel), F.Label(_exitLabel),
......
...@@ -267,7 +267,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI ...@@ -267,7 +267,7 @@ private void GenerateEnumerableImplementation(ref BoundExpression managedThreadI
} }
bodyBuilder.Add(F.Return(F.Local(resultVariable))); bodyBuilder.Add(F.Return(F.Local(resultVariable)));
F.CloseMethod(F.Block(ImmutableArray.Create(resultVariable), bodyBuilder.ToImmutableAndFree())); F.CloseMethod(F.Block(ImmutableArray.Create(resultVariable), ImmutableArray<LocalFunctionSymbol>.Empty, bodyBuilder.ToImmutableAndFree()));
// Generate IEnumerable.GetEnumerator // Generate IEnumerable.GetEnumerator
var getEnumerator = OpenMethodImplementation(IEnumerable_GetEnumerator); var getEnumerator = OpenMethodImplementation(IEnumerable_GetEnumerator);
......
...@@ -248,7 +248,7 @@ private BoundStatement AddStatementsIfNeeded(BoundStatement body) ...@@ -248,7 +248,7 @@ private BoundStatement AddStatementsIfNeeded(BoundStatement body)
if (_addedLocals != null) if (_addedLocals != null)
{ {
_addedStatements.Add(body); _addedStatements.Add(body);
body = new BoundBlock(body.Syntax, _addedLocals.ToImmutableAndFree(), _addedStatements.ToImmutableAndFree()) { WasCompilerGenerated = true }; body = new BoundBlock(body.Syntax, _addedLocals.ToImmutableAndFree(), ImmutableArray<LocalFunctionSymbol>.Empty, _addedStatements.ToImmutableAndFree()) { WasCompilerGenerated = true };
_addedLocals = null; _addedLocals = null;
_addedStatements = null; _addedStatements = null;
} }
...@@ -839,7 +839,7 @@ private BoundBlock RewriteBlock(BoundBlock node, ArrayBuilder<BoundExpression> p ...@@ -839,7 +839,7 @@ private BoundBlock RewriteBlock(BoundBlock node, ArrayBuilder<BoundExpression> p
} }
// TODO: we may not need to update if there was nothing to rewrite. // TODO: we may not need to update if there was nothing to rewrite.
return node.Update(newLocals.ToImmutableAndFree(), newStatements.ToImmutableAndFree()); return node.Update(newLocals.ToImmutableAndFree(), node.LocalFunctions, newStatements.ToImmutableAndFree());
} }
public override BoundNode VisitCatchBlock(BoundCatchBlock node) public override BoundNode VisitCatchBlock(BoundCatchBlock node)
...@@ -965,7 +965,7 @@ public override BoundNode VisitStatementList(BoundStatementList node) ...@@ -965,7 +965,7 @@ public override BoundNode VisitStatementList(BoundStatementList node)
newStatements.Add((BoundStatement)this.Visit(s)); newStatements.Add((BoundStatement)this.Visit(s));
} }
return new BoundBlock(node.Syntax, newLocals.ToImmutableAndFree(), newStatements.ToImmutableAndFree(), node.HasErrors); return new BoundBlock(node.Syntax, newLocals.ToImmutableAndFree(), ImmutableArray<LocalFunctionSymbol>.Empty, newStatements.ToImmutableAndFree(), node.HasErrors);
}); });
} }
else else
...@@ -986,7 +986,7 @@ public override BoundNode VisitSwitchStatement(BoundSwitchStatement node) ...@@ -986,7 +986,7 @@ public override BoundNode VisitSwitchStatement(BoundSwitchStatement node)
InsertAndFreePrologue(newStatements, prologue); InsertAndFreePrologue(newStatements, prologue);
newStatements.Add((BoundStatement)base.VisitSwitchStatement(node)); newStatements.Add((BoundStatement)base.VisitSwitchStatement(node));
return new BoundBlock(node.Syntax, newLocals.ToImmutableAndFree(), newStatements.ToImmutableAndFree(), node.HasErrors); return new BoundBlock(node.Syntax, newLocals.ToImmutableAndFree(), ImmutableArray<LocalFunctionSymbol>.Empty, newStatements.ToImmutableAndFree(), node.HasErrors);
}); });
} }
else else
......
...@@ -14,7 +14,7 @@ public override BoundNode VisitBlock(BoundBlock node) ...@@ -14,7 +14,7 @@ public override BoundNode VisitBlock(BoundBlock node)
{ {
if (node.WasCompilerGenerated || !this.GenerateDebugInfo || node.Syntax.Kind() == SyntaxKind.ArrowExpressionClause) if (node.WasCompilerGenerated || !this.GenerateDebugInfo || node.Syntax.Kind() == SyntaxKind.ArrowExpressionClause)
{ {
return node.Update(node.Locals, VisitList(node.Statements)); return node.Update(node.Locals, node.LocalFunctions, VisitList(node.Statements));
} }
BlockSyntax syntax = node.Syntax as BlockSyntax; BlockSyntax syntax = node.Syntax as BlockSyntax;
...@@ -39,13 +39,13 @@ public override BoundNode VisitBlock(BoundBlock node) ...@@ -39,13 +39,13 @@ public override BoundNode VisitBlock(BoundBlock node)
builder.Add(new BoundSequencePointWithSpan(syntax, null, cBspan)); builder.Add(new BoundSequencePointWithSpan(syntax, null, cBspan));
} }
return new BoundBlock(syntax, node.Locals, builder.ToImmutableAndFree(), node.HasErrors); return new BoundBlock(syntax, node.Locals, node.LocalFunctions, builder.ToImmutableAndFree(), node.HasErrors);
} }
public override BoundNode VisitNoOpStatement(BoundNoOpStatement node) public override BoundNode VisitNoOpStatement(BoundNoOpStatement node)
{ {
return (node.WasCompilerGenerated || !this.GenerateDebugInfo) return (node.WasCompilerGenerated || !this.GenerateDebugInfo)
? new BoundBlock(node.Syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray<BoundStatement>.Empty) ? new BoundBlock(node.Syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalFunctionSymbol>.Empty, ImmutableArray<BoundStatement>.Empty)
: AddSequencePoint(node); : AddSequencePoint(node);
} }
} }
......
...@@ -55,6 +55,7 @@ public override BoundNode VisitFixedStatement(BoundFixedStatement node) ...@@ -55,6 +55,7 @@ public override BoundNode VisitFixedStatement(BoundFixedStatement node)
{ {
return _factory.Block( return _factory.Block(
localBuilder.ToImmutableAndFree(), localBuilder.ToImmutableAndFree(),
ImmutableArray<LocalFunctionSymbol>.Empty,
new BoundTryStatement( new BoundTryStatement(
_factory.Syntax, _factory.Syntax,
_factory.Block(statementBuilder.ToImmutableAndFree()), _factory.Block(statementBuilder.ToImmutableAndFree()),
...@@ -64,7 +65,7 @@ public override BoundNode VisitFixedStatement(BoundFixedStatement node) ...@@ -64,7 +65,7 @@ public override BoundNode VisitFixedStatement(BoundFixedStatement node)
else else
{ {
statementBuilder.AddRange(cleanup); statementBuilder.AddRange(cleanup);
return _factory.Block(localBuilder.ToImmutableAndFree(), statementBuilder.ToImmutableAndFree()); return _factory.Block(localBuilder.ToImmutableAndFree(), ImmutableArray<LocalFunctionSymbol>.Empty, statementBuilder.ToImmutableAndFree());
} }
} }
......
...@@ -208,6 +208,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n ...@@ -208,6 +208,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n
finallyBlockOpt = new BoundBlock(forEachSyntax, finallyBlockOpt = new BoundBlock(forEachSyntax,
locals: ImmutableArray<LocalSymbol>.Empty, locals: ImmutableArray<LocalSymbol>.Empty,
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>(disposeStmt)); statements: ImmutableArray.Create<BoundStatement>(disposeStmt));
} }
else else
...@@ -259,6 +260,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n ...@@ -259,6 +260,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n
// if (d != null) d.Dispose(); // if (d != null) d.Dispose();
finallyBlockOpt = new BoundBlock(forEachSyntax, finallyBlockOpt = new BoundBlock(forEachSyntax,
locals: ImmutableArray.Create<LocalSymbol>(disposableVar), locals: ImmutableArray.Create<LocalSymbol>(disposableVar),
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>(disposableVarDecl, ifStmt)); statements: ImmutableArray.Create<BoundStatement>(disposableVarDecl, ifStmt));
} }
...@@ -274,6 +276,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n ...@@ -274,6 +276,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n
BoundStatement tryFinally = new BoundTryStatement(forEachSyntax, BoundStatement tryFinally = new BoundTryStatement(forEachSyntax,
tryBlock: new BoundBlock(forEachSyntax, tryBlock: new BoundBlock(forEachSyntax,
locals: ImmutableArray<LocalSymbol>.Empty, locals: ImmutableArray<LocalSymbol>.Empty,
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>(whileLoop)), statements: ImmutableArray.Create<BoundStatement>(whileLoop)),
catchBlocks: ImmutableArray<BoundCatchBlock>.Empty, catchBlocks: ImmutableArray<BoundCatchBlock>.Empty,
finallyBlockOpt: finallyBlockOpt); finallyBlockOpt: finallyBlockOpt);
...@@ -284,6 +287,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n ...@@ -284,6 +287,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n
result = new BoundBlock( result = new BoundBlock(
syntax: forEachSyntax, syntax: forEachSyntax,
locals: ImmutableArray.Create(enumeratorVar), locals: ImmutableArray.Create(enumeratorVar),
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>(enumeratorVarDecl, tryFinally)); statements: ImmutableArray.Create<BoundStatement>(enumeratorVarDecl, tryFinally));
} }
else else
...@@ -296,6 +300,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n ...@@ -296,6 +300,7 @@ private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement n
result = new BoundBlock( result = new BoundBlock(
syntax: forEachSyntax, syntax: forEachSyntax,
locals: ImmutableArray.Create(enumeratorVar), locals: ImmutableArray.Create(enumeratorVar),
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>(enumeratorVarDecl, whileLoop)); statements: ImmutableArray.Create<BoundStatement>(enumeratorVarDecl, whileLoop));
} }
...@@ -502,6 +507,7 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node) ...@@ -502,6 +507,7 @@ private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
return new BoundBlock( return new BoundBlock(
forEachSyntax, forEachSyntax,
locals: ImmutableArray.Create(iterationVariable), locals: ImmutableArray.Create(iterationVariable),
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create(iteratorVariableInitialization, rewrittenBody)); statements: ImmutableArray.Create(iteratorVariableInitialization, rewrittenBody));
} }
...@@ -808,6 +814,7 @@ private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEach ...@@ -808,6 +814,7 @@ private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEach
BoundStatement result = new BoundBlock( BoundStatement result = new BoundBlock(
forEachSyntax, forEachSyntax,
ImmutableArray.Create(arrayVar).Concat(upperVar.AsImmutableOrNull()), ImmutableArray.Create(arrayVar).Concat(upperVar.AsImmutableOrNull()),
ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create(arrayVarDecl).Concat(upperVarDecl.AsImmutableOrNull()).Add(forLoop)); ImmutableArray.Create(arrayVarDecl).Concat(upperVarDecl.AsImmutableOrNull()).Add(forLoop));
AddForEachKeywordSequencePoint(forEachSyntax, ref result); AddForEachKeywordSequencePoint(forEachSyntax, ref result);
......
...@@ -150,7 +150,7 @@ public override BoundNode VisitForStatement(BoundForStatement node) ...@@ -150,7 +150,7 @@ public override BoundNode VisitForStatement(BoundForStatement node)
statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel)); statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel));
var statements = statementBuilder.ToImmutableAndFree(); var statements = statementBuilder.ToImmutableAndFree();
return new BoundBlock(syntax, outerLocals, statements, hasErrors); return new BoundBlock(syntax, outerLocals, ImmutableArray<LocalFunctionSymbol>.Empty, statements, hasErrors);
} }
} }
} }
...@@ -120,6 +120,7 @@ public override BoundNode VisitLockStatement(BoundLockStatement node) ...@@ -120,6 +120,7 @@ public override BoundNode VisitLockStatement(BoundLockStatement node)
return new BoundBlock( return new BoundBlock(
lockSyntax, lockSyntax,
ImmutableArray.Create(boundLockTemp.LocalSymbol, boundLockTakenTemp.LocalSymbol), ImmutableArray.Create(boundLockTemp.LocalSymbol, boundLockTakenTemp.LocalSymbol),
ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create( ImmutableArray.Create(
MakeInitialLockSequencePoint(boundLockTempInit, lockSyntax), MakeInitialLockSequencePoint(boundLockTempInit, lockSyntax),
boundLockTakenTempInit, boundLockTakenTempInit,
...@@ -170,6 +171,7 @@ public override BoundNode VisitLockStatement(BoundLockStatement node) ...@@ -170,6 +171,7 @@ public override BoundNode VisitLockStatement(BoundLockStatement node)
return new BoundBlock( return new BoundBlock(
lockSyntax, lockSyntax,
ImmutableArray.Create(boundLockTemp.LocalSymbol), ImmutableArray.Create(boundLockTemp.LocalSymbol),
ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create( ImmutableArray.Create(
MakeInitialLockSequencePoint(boundLockTempInit, lockSyntax), MakeInitialLockSequencePoint(boundLockTempInit, lockSyntax),
enterCall, enterCall,
......
...@@ -172,7 +172,11 @@ public override BoundNode VisitSwitchStatement(BoundSwitchStatement node) ...@@ -172,7 +172,11 @@ public override BoundNode VisitSwitchStatement(BoundSwitchStatement node)
statementBuilder.Add(rewrittenSwitchStatement); statementBuilder.Add(rewrittenSwitchStatement);
return new BoundBlock(syntax, locals: (object)tempLocal == null ? ImmutableArray<LocalSymbol>.Empty : ImmutableArray.Create<LocalSymbol>(tempLocal), statements: statementBuilder.ToImmutableAndFree()); return new BoundBlock(
syntax,
locals: (object)tempLocal == null ? ImmutableArray<LocalSymbol>.Empty : ImmutableArray.Create<LocalSymbol>(tempLocal),
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: statementBuilder.ToImmutableAndFree());
} }
private static LabelSymbol GetNullValueTargetSwitchLabel(ImmutableArray<BoundSwitchSection> sections, GeneratedLabelSymbol breakLabel) private static LabelSymbol GetNullValueTargetSwitchLabel(ImmutableArray<BoundSwitchSection> sections, GeneratedLabelSymbol breakLabel)
......
...@@ -56,6 +56,7 @@ public override BoundNode VisitUsingStatement(BoundUsingStatement node) ...@@ -56,6 +56,7 @@ public override BoundNode VisitUsingStatement(BoundUsingStatement node)
return new BoundBlock( return new BoundBlock(
usingSyntax, usingSyntax,
node.Locals, node.Locals,
ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create<BoundStatement>(result)); ImmutableArray.Create<BoundStatement>(result));
} }
} }
...@@ -141,6 +142,7 @@ private BoundBlock RewriteExpressionUsingStatement(BoundUsingStatement node, Bou ...@@ -141,6 +142,7 @@ private BoundBlock RewriteExpressionUsingStatement(BoundUsingStatement node, Bou
return new BoundBlock( return new BoundBlock(
syntax: usingSyntax, syntax: usingSyntax,
locals: node.Locals.Add(boundTemp.LocalSymbol), locals: node.Locals.Add(boundTemp.LocalSymbol),
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>(expressionStatement, tryFinally)); statements: ImmutableArray.Create<BoundStatement>(expressionStatement, tryFinally));
} }
...@@ -190,6 +192,7 @@ private BoundBlock RewriteDeclarationUsingStatement(CSharpSyntaxNode usingSyntax ...@@ -190,6 +192,7 @@ private BoundBlock RewriteDeclarationUsingStatement(CSharpSyntaxNode usingSyntax
return new BoundBlock( return new BoundBlock(
syntax: usingSyntax, syntax: usingSyntax,
locals: ImmutableArray.Create<LocalSymbol>(boundTemp.LocalSymbol), //localSymbol will be declared by an enclosing block locals: ImmutableArray.Create<LocalSymbol>(boundTemp.LocalSymbol), //localSymbol will be declared by an enclosing block
localFunctions: ImmutableArray<LocalFunctionSymbol>.Empty,
statements: ImmutableArray.Create<BoundStatement>( statements: ImmutableArray.Create<BoundStatement>(
rewrittenDeclaration, rewrittenDeclaration,
new BoundExpressionStatement(declarationSyntax, tempAssignment), new BoundExpressionStatement(declarationSyntax, tempAssignment),
......
...@@ -131,8 +131,9 @@ public override BoundNode VisitCatchBlock(BoundCatchBlock node) ...@@ -131,8 +131,9 @@ public override BoundNode VisitCatchBlock(BoundCatchBlock node)
public override BoundNode VisitBlock(BoundBlock node) public override BoundNode VisitBlock(BoundBlock node)
{ {
var newLocals = RewriteLocals(node.Locals); var newLocals = RewriteLocals(node.Locals);
var newLocalFunctions = node.LocalFunctions;
var newStatements = VisitList(node.Statements); var newStatements = VisitList(node.Statements);
return node.Update(newLocals, newStatements); return node.Update(newLocals, newLocalFunctions, newStatements);
} }
public override BoundNode VisitSequence(BoundSequence node) public override BoundNode VisitSequence(BoundSequence node)
......
...@@ -269,6 +269,7 @@ private BoundStatement GenerateKickoffMethodBody() ...@@ -269,6 +269,7 @@ private BoundStatement GenerateKickoffMethodBody()
bodyBuilder.Add(GenerateStateMachineCreation(stateMachineVariable, frameType)); bodyBuilder.Add(GenerateStateMachineCreation(stateMachineVariable, frameType));
return F.Block( return F.Block(
ImmutableArray.Create(stateMachineVariable), ImmutableArray.Create(stateMachineVariable),
ImmutableArray<LocalFunctionSymbol>.Empty,
bodyBuilder.ToImmutableAndFree()); bodyBuilder.ToImmutableAndFree());
} }
......
...@@ -398,7 +398,7 @@ public BoundBlock Block() ...@@ -398,7 +398,7 @@ public BoundBlock Block()
public BoundBlock Block(ImmutableArray<BoundStatement> statements) public BoundBlock Block(ImmutableArray<BoundStatement> statements)
{ {
return Block(ImmutableArray<LocalSymbol>.Empty, statements); return Block(ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalFunctionSymbol>.Empty, statements);
} }
public BoundBlock Block(params BoundStatement[] statements) public BoundBlock Block(params BoundStatement[] statements)
...@@ -406,14 +406,14 @@ public BoundBlock Block(params BoundStatement[] statements) ...@@ -406,14 +406,14 @@ public BoundBlock Block(params BoundStatement[] statements)
return Block(ImmutableArray.Create(statements)); return Block(ImmutableArray.Create(statements));
} }
public BoundBlock Block(ImmutableArray<LocalSymbol> locals, params BoundStatement[] statements) public BoundBlock Block(ImmutableArray<LocalSymbol> locals, ImmutableArray<LocalFunctionSymbol> localFunctions, params BoundStatement[] statements)
{ {
return Block(locals, ImmutableArray.Create(statements)); return Block(locals, localFunctions, ImmutableArray.Create(statements));
} }
public BoundBlock Block(ImmutableArray<LocalSymbol> locals, ImmutableArray<BoundStatement> statements) public BoundBlock Block(ImmutableArray<LocalSymbol> locals, ImmutableArray<LocalFunctionSymbol> localFunctions, ImmutableArray<BoundStatement> statements)
{ {
return new BoundBlock(Syntax, locals, statements) { WasCompilerGenerated = true }; return new BoundBlock(Syntax, locals, localFunctions, statements) { WasCompilerGenerated = true };
} }
public BoundReturnStatement Return(BoundExpression expression = null) public BoundReturnStatement Return(BoundExpression expression = null)
......
...@@ -306,6 +306,7 @@ internal override BoundBlock CreateBody() ...@@ -306,6 +306,7 @@ internal override BoundBlock CreateBody()
return new BoundBlock(syntax, return new BoundBlock(syntax,
ImmutableArray.Create<LocalSymbol>(submissionLocal.LocalSymbol), ImmutableArray.Create<LocalSymbol>(submissionLocal.LocalSymbol),
ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create<BoundStatement>( ImmutableArray.Create<BoundStatement>(
// var script = new Script(); // var script = new Script();
new BoundExpressionStatement( new BoundExpressionStatement(
...@@ -440,6 +441,7 @@ internal override BoundBlock CreateBody() ...@@ -440,6 +441,7 @@ internal override BoundBlock CreateBody()
return new BoundBlock(syntax, return new BoundBlock(syntax,
ImmutableArray.Create<LocalSymbol>(submissionLocal.LocalSymbol), ImmutableArray.Create<LocalSymbol>(submissionLocal.LocalSymbol),
ImmutableArray<LocalFunctionSymbol>.Empty,
ImmutableArray.Create<BoundStatement>(submissionAssignment, returnStatement)) ImmutableArray.Create<BoundStatement>(submissionAssignment, returnStatement))
{ WasCompilerGenerated = true }; { WasCompilerGenerated = true };
} }
......
...@@ -2766,7 +2766,10 @@ static void Main(string[] args) ...@@ -2766,7 +2766,10 @@ static void Main(string[] args)
Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(6, 24), Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(6, 24),
// (6,26): error CS1023: Embedded statement cannot be a declaration or labeled statement // (6,26): error CS1023: Embedded statement cannot be a declaration or labeled statement
// void f() { if () const int i = 0; } // void f() { if () const int i = 0; }
Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "const int i = 0;").WithLocation(6, 26) Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "const int i = 0;").WithLocation(6, 26),
// (6,14): warning CS0168: The variable 'f' is declared but never used
// void f() { if () const int i = 0; }
Diagnostic(ErrorCode.WRN_UnreferencedVar, "f").WithArguments("f").WithLocation(6, 14)
); );
} }
......
...@@ -168,6 +168,7 @@ void Params(params int x) ...@@ -168,6 +168,7 @@ void Params(params int x)
{ {
Console.WriteLine(x); Console.WriteLine(x);
} }
Params(2);
} }
} }
"; ";
...@@ -190,6 +191,8 @@ void RefOut(ref int x = 2) ...@@ -190,6 +191,8 @@ void RefOut(ref int x = 2)
{ {
x++; x++;
} }
int y = 2;
RefOut(ref y);
} }
} }
"; ";
...@@ -214,6 +217,7 @@ void NamedOptional(string x = 2) ...@@ -214,6 +217,7 @@ void NamedOptional(string x = 2)
{ {
Console.WriteLine(x); Console.WriteLine(x);
} }
NamedOptional(""2"");
} }
} }
"; ";
...@@ -239,6 +243,7 @@ void CallerMemberName([CallerMemberName] int s = 2) ...@@ -239,6 +243,7 @@ void CallerMemberName([CallerMemberName] int s = 2)
{ {
Console.WriteLine(s); Console.WriteLine(s);
} }
CallerMemberName();
} }
} }
"; ";
...@@ -2184,11 +2189,13 @@ public void MainLocfuncIsntEntry() ...@@ -2184,11 +2189,13 @@ public void MainLocfuncIsntEntry()
var source = @" var source = @"
void Main() void Main()
{ {
Console.Write(""bad""); Console.Write(4);
} }
Console.Write(2); Console.Write(2);
Console.Write(' ');
Main();
"; ";
VerifyOutputInMain(source, "2", "System"); VerifyOutputInMain(source, "2 4", "System");
} }
[Fact] [Fact]
...@@ -2249,6 +2256,7 @@ void Local() ...@@ -2249,6 +2256,7 @@ void Local()
{ {
Console.WriteLine(2); Console.WriteLine(2);
} }
Local();
} }
Local(); Local();
...@@ -2261,12 +2269,13 @@ void Local2() ...@@ -2261,12 +2269,13 @@ void Local2()
} }
"; ";
VerifyDiagnostics(source, VerifyDiagnostics(source,
// (15,9): error CS0103: The name 'Local' does not exist in the current context // (16,9): error CS0103: The name 'Local' does not exist in the current context
// Local(); // Local();
Diagnostic(ErrorCode.ERR_NameNotInContext, "Local").WithArguments("Local").WithLocation(15, 9), Diagnostic(ErrorCode.ERR_NameNotInContext, "Local").WithArguments("Local").WithLocation(16, 9),
// (17,9): error CS0841: Cannot use local variable 'Local2' before it is declared // (18,9): error CS0841: Cannot use local variable 'Local2' before it is declared
// Local2(); // Local2();
Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "Local2").WithArguments("Local2").WithLocation(17, 9)); Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "Local2").WithArguments("Local2").WithLocation(18, 9)
);
} }
[Fact] [Fact]
...@@ -2279,13 +2288,17 @@ static void Main(string[] args) ...@@ -2279,13 +2288,17 @@ static void Main(string[] args)
{ {
void Duplicate() { } void Duplicate() { }
void Duplicate() { } void Duplicate() { }
Duplicate();
} }
} }
"; ";
VerifyDiagnostics(source, VerifyDiagnostics(source,
// (7,14): error CS0128: A local variable named 'Duplicate' is already defined in this scope // (7,14): error CS0128: A local variable named 'Duplicate' is already defined in this scope
// void Duplicate() { } // void Duplicate() { }
Diagnostic(ErrorCode.ERR_LocalDuplicate, "Duplicate").WithArguments("Duplicate").WithLocation(7, 14) Diagnostic(ErrorCode.ERR_LocalDuplicate, "Duplicate").WithArguments("Duplicate").WithLocation(7, 14),
// (7,14): warning CS0168: The variable 'Duplicate' is declared but never used
// void Duplicate() { }
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Duplicate").WithArguments("Duplicate").WithLocation(7, 14)
); );
} }
...@@ -2297,18 +2310,16 @@ class Program ...@@ -2297,18 +2310,16 @@ class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
int x; int x = 2;
void Param(int x) { } void Param(int x) { }
Param(x);
} }
} }
"; ";
VerifyDiagnostics(source, VerifyDiagnostics(source,
// (7,24): error CS0136: A local or parameter named 'x' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // (7,24): error CS0136: A local or parameter named 'x' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// void Param(int x) { } // void Param(int x) { }
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x").WithArguments("x").WithLocation(7, 24), Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "x").WithArguments("x").WithLocation(7, 24)
// (6,13): warning CS0168: The variable 'x' is declared but never used
// int x;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x").WithLocation(6, 13)
); );
} }
...@@ -2322,6 +2333,7 @@ static void Main(string[] args) ...@@ -2322,6 +2333,7 @@ static void Main(string[] args)
{ {
int T; int T;
void Generic<T>() { } void Generic<T>() { }
Generic<int>();
} }
} }
"; ";
...@@ -2354,7 +2366,10 @@ static void Main(string[] args) ...@@ -2354,7 +2366,10 @@ static void Main(string[] args)
Diagnostic(ErrorCode.ERR_LocalDuplicate, "Conflict").WithArguments("Conflict").WithLocation(7, 14), Diagnostic(ErrorCode.ERR_LocalDuplicate, "Conflict").WithArguments("Conflict").WithLocation(7, 14),
// (6,13): warning CS0168: The variable 'Conflict' is declared but never used // (6,13): warning CS0168: The variable 'Conflict' is declared but never used
// int Conflict; // int Conflict;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Conflict").WithArguments("Conflict").WithLocation(6, 13) Diagnostic(ErrorCode.WRN_UnreferencedVar, "Conflict").WithArguments("Conflict").WithLocation(6, 13),
// (7,14): warning CS0168: The variable 'Conflict' is declared but never used
// void Conflict() { }
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Conflict").WithArguments("Conflict").WithLocation(7, 14)
); );
} }
...@@ -2378,7 +2393,10 @@ static void Main(string[] args) ...@@ -2378,7 +2393,10 @@ static void Main(string[] args)
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "Conflict").WithArguments("Conflict").WithLocation(6, 14), Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "Conflict").WithArguments("Conflict").WithLocation(6, 14),
// (7,13): warning CS0168: The variable 'Conflict' is declared but never used // (7,13): warning CS0168: The variable 'Conflict' is declared but never used
// int Conflict; // int Conflict;
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Conflict").WithArguments("Conflict").WithLocation(7, 13) Diagnostic(ErrorCode.WRN_UnreferencedVar, "Conflict").WithArguments("Conflict").WithLocation(7, 13),
// (6,14): warning CS0168: The variable 'Conflict' is declared but never used
// void Conflict() { }
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Conflict").WithArguments("Conflict").WithLocation(6, 14)
); );
} }
...@@ -2676,7 +2694,7 @@ static void Main(string[] args) ...@@ -2676,7 +2694,7 @@ static void Main(string[] args)
); );
} }
[Fact(Skip = "No usage detection at the moment")] [Fact]
public void BadNotUsed() public void BadNotUsed()
{ {
var source = @" var source = @"
...@@ -2693,7 +2711,11 @@ static void Main(string[] args) ...@@ -2693,7 +2711,11 @@ static void Main(string[] args)
A(); A();
} }
}"; }";
VerifyDiagnostics(source /*, ... diagnostics ... */); VerifyDiagnostics(source,
// (6,14): warning CS0168: The variable 'Local' is declared but never used
// void Local()
Diagnostic(ErrorCode.WRN_UnreferencedVar, "Local").WithArguments("Local").WithLocation(6, 14)
);
} }
[Fact] [Fact]
...@@ -2710,6 +2732,7 @@ void Local() ...@@ -2710,6 +2732,7 @@ void Local()
{ {
Console.WriteLine(x); Console.WriteLine(x);
} }
Local();
} }
static void Main() static void Main()
{ {
...@@ -2736,6 +2759,7 @@ void Local() ...@@ -2736,6 +2759,7 @@ void Local()
{ {
Console.WriteLine(__arglist); Console.WriteLine(__arglist);
} }
Local();
} }
static void B(__arglist) static void B(__arglist)
{ {
...@@ -2743,6 +2767,7 @@ void Local() ...@@ -2743,6 +2767,7 @@ void Local()
{ {
Console.WriteLine(__arglist); Console.WriteLine(__arglist);
} }
Local();
} }
static void C() // C and D produce different errors static void C() // C and D produce different errors
{ {
...@@ -2750,6 +2775,7 @@ void Local(__arglist) ...@@ -2750,6 +2775,7 @@ void Local(__arglist)
{ {
Console.WriteLine(__arglist); Console.WriteLine(__arglist);
} }
Local(__arglist());
} }
static void D(__arglist) static void D(__arglist)
{ {
...@@ -2757,6 +2783,7 @@ void Local(__arglist) ...@@ -2757,6 +2783,7 @@ void Local(__arglist)
{ {
Console.WriteLine(__arglist); Console.WriteLine(__arglist);
} }
Local(__arglist());
} }
static void Main() static void Main()
{ {
...@@ -2767,15 +2794,15 @@ static void Main() ...@@ -2767,15 +2794,15 @@ static void Main()
// (10,31): error CS0190: The __arglist construct is valid only within a variable argument method // (10,31): error CS0190: The __arglist construct is valid only within a variable argument method
// Console.WriteLine(__arglist); // Console.WriteLine(__arglist);
Diagnostic(ErrorCode.ERR_ArgsInvalid, "__arglist").WithLocation(10, 31), Diagnostic(ErrorCode.ERR_ArgsInvalid, "__arglist").WithLocation(10, 31),
// (17,31): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method // (18,31): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method
// Console.WriteLine(__arglist); // Console.WriteLine(__arglist);
Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(17, 31), Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(18, 31),
// (24,31): error CS0190: The __arglist construct is valid only within a variable argument method // (26,31): error CS0190: The __arglist construct is valid only within a variable argument method
// Console.WriteLine(__arglist); // Console.WriteLine(__arglist);
Diagnostic(ErrorCode.ERR_ArgsInvalid, "__arglist").WithLocation(24, 31), Diagnostic(ErrorCode.ERR_ArgsInvalid, "__arglist").WithLocation(26, 31),
// (31,31): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method // (34,31): error CS4013: Instance of type 'RuntimeArgumentHandle' cannot be used inside an anonymous function, query expression, iterator block or async method
// Console.WriteLine(__arglist); // Console.WriteLine(__arglist);
Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(31, 31) Diagnostic(ErrorCode.ERR_SpecialByRefInLambda, "__arglist").WithArguments("System.RuntimeArgumentHandle").WithLocation(34, 31)
); );
} }
...@@ -2794,6 +2821,7 @@ void Local() ...@@ -2794,6 +2821,7 @@ void Local()
{ {
Console.WriteLine(_a); Console.WriteLine(_a);
} }
Local();
} }
static void Main() static void Main()
{ {
...@@ -2821,6 +2849,8 @@ IEnumerable<int> RefEnumerable(ref int x) ...@@ -2821,6 +2849,8 @@ IEnumerable<int> RefEnumerable(ref int x)
{ {
yield return x; yield return x;
} }
int y = 0;
RefEnumerable(ref y);
} }
} }
"; ";
...@@ -2835,6 +2865,7 @@ IEnumerable<int> RefEnumerable(ref int x) ...@@ -2835,6 +2865,7 @@ IEnumerable<int> RefEnumerable(ref int x)
public void BadRefAsync() public void BadRefAsync()
{ {
var source = @" var source = @"
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
class Program class Program
...@@ -2845,13 +2876,15 @@ async Task<int> RefAsync(ref int x) ...@@ -2845,13 +2876,15 @@ async Task<int> RefAsync(ref int x)
{ {
return await Task.FromResult(x); return await Task.FromResult(x);
} }
int y = 2;
Console.Write(RefAsync(ref y).Result);
} }
} }
"; ";
VerifyDiagnostics(source, VerifyDiagnostics(source,
// (8,42): error CS1988: Async methods cannot have ref or out parameters // (9,42): error CS1988: Async methods cannot have ref or out parameters
// async Task<int> RefAsync(ref int x) // async Task<int> RefAsync(ref int x)
Diagnostic(ErrorCode.ERR_BadAsyncArgType, "x").WithLocation(8, 42) Diagnostic(ErrorCode.ERR_BadAsyncArgType, "x").WithLocation(9, 42)
); );
} }
...@@ -2900,6 +2933,10 @@ static void LocalStatic() ...@@ -2900,6 +2933,10 @@ static void LocalStatic()
volatile void LocalVolatile() volatile void LocalVolatile()
{ {
} }
LocalConst();
LocalStatic();
LocalReadonly();
LocalVolatile();
} }
} }
"; ";
...@@ -3069,6 +3106,7 @@ var Local() ...@@ -3069,6 +3106,7 @@ var Local()
{ {
yield return 2; yield return 2;
} }
Local();
} }
} }
"; ";
...@@ -3091,6 +3129,7 @@ var Local() ...@@ -3091,6 +3129,7 @@ var Local()
{ {
yield break; yield break;
} }
Local();
} }
} }
"; ";
...@@ -3300,6 +3339,7 @@ static void Main(string[] args) ...@@ -3300,6 +3339,7 @@ static void Main(string[] args)
void Local() void Local()
{ {
} }
Local();
} }
} }
"; ";
......
...@@ -42,8 +42,9 @@ internal sealed class CapturedVariableRewriter : BoundTreeRewriter ...@@ -42,8 +42,9 @@ internal sealed class CapturedVariableRewriter : BoundTreeRewriter
public override BoundNode VisitBlock(BoundBlock node) public override BoundNode VisitBlock(BoundBlock node)
{ {
var rewrittenLocals = node.Locals.WhereAsArray(local => local.IsCompilerGenerated || local.Name == null || this.GetVariable(local.Name) == null); var rewrittenLocals = node.Locals.WhereAsArray(local => local.IsCompilerGenerated || local.Name == null || this.GetVariable(local.Name) == null);
var rewrittenLocalFunctions = node.LocalFunctions;
var rewrittenStatements = VisitList(node.Statements); var rewrittenStatements = VisitList(node.Statements);
return node.Update(rewrittenLocals, rewrittenStatements); return node.Update(rewrittenLocals, rewrittenLocalFunctions, rewrittenStatements);
} }
public override BoundNode VisitLocal(BoundLocal node) public override BoundNode VisitLocal(BoundLocal node)
......
...@@ -38,7 +38,7 @@ internal static BoundNode Rewrite(CSharpCompilation compilation, EENamedTypeSymb ...@@ -38,7 +38,7 @@ internal static BoundNode Rewrite(CSharpCompilation compilation, EENamedTypeSymb
if (hasChanged) if (hasChanged)
{ {
node = new BoundBlock(node.Syntax, ImmutableArray<LocalSymbol>.Empty, builder.ToImmutable()) { WasCompilerGenerated = true }; node = BoundBlock.SynthesizedNoLocals(node.Syntax, builder.ToImmutable());
} }
builder.Free(); builder.Free();
......
...@@ -18,6 +18,7 @@ internal EEConstructorSymbol(NamedTypeSymbol containingType) ...@@ -18,6 +18,7 @@ internal EEConstructorSymbol(NamedTypeSymbol containingType)
internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics) internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
{ {
var noLocals = ImmutableArray<LocalSymbol>.Empty; var noLocals = ImmutableArray<LocalSymbol>.Empty;
var noLocalFunctions = ImmutableArray<LocalFunctionSymbol>.Empty;
var initializerInvocation = MethodCompiler.BindConstructorInitializer(this, diagnostics, compilationState.Compilation); var initializerInvocation = MethodCompiler.BindConstructorInitializer(this, diagnostics, compilationState.Compilation);
var syntax = initializerInvocation.Syntax; var syntax = initializerInvocation.Syntax;
...@@ -25,6 +26,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, ...@@ -25,6 +26,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
new BoundBlock( new BoundBlock(
syntax, syntax,
noLocals, noLocals,
noLocalFunctions,
ImmutableArray.Create<BoundStatement>( ImmutableArray.Create<BoundStatement>(
new BoundExpressionStatement(syntax, initializerInvocation), new BoundExpressionStatement(syntax, initializerInvocation),
new BoundReturnStatement(syntax, null)))); new BoundReturnStatement(syntax, null))));
......
...@@ -482,7 +482,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, ...@@ -482,7 +482,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
} }
localsSet.Free(); localsSet.Free();
body = new BoundBlock(syntax, localsBuilder.ToImmutableAndFree(), statementsBuilder.ToImmutableAndFree()) { WasCompilerGenerated = true }; body = new BoundBlock(syntax, localsBuilder.ToImmutableAndFree(), ImmutableArray<LocalFunctionSymbol>.Empty, statementsBuilder.ToImmutableAndFree()) { WasCompilerGenerated = true };
Debug.Assert(!diagnostics.HasAnyErrors()); Debug.Assert(!diagnostics.HasAnyErrors());
Debug.Assert(!body.HasErrors); Debug.Assert(!body.HasErrors);
...@@ -600,7 +600,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, ...@@ -600,7 +600,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
localBuilder.Add(local); localBuilder.Add(local);
} }
body = block.Update(localBuilder.ToImmutableAndFree(), block.Statements); body = block.Update(localBuilder.ToImmutableAndFree(), block.LocalFunctions, block.Statements);
TypeParameterChecker.Check(body, _allTypeParameters); TypeParameterChecker.Check(body, _allTypeParameters);
compilationState.AddSynthesizedMethod(this, body); compilationState.AddSynthesizedMethod(this, body);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册