Skip to content

Commit

Permalink
Properly handle expression variable declared within VariableDeclarato…
Browse files Browse the repository at this point in the history
…rSyntax.ArgumentList in ‘fixed’, ‘for’ and ‘using’ statements.

Related to dotnet#12597.
Fixes dotnet#13459, dotnet#13460.
  • Loading branch information
AlekseyTs committed Sep 1, 2016
1 parent cc05b66 commit f0304e0
Show file tree
Hide file tree
Showing 8 changed files with 1,735 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,7 @@ protected BoundLocalDeclaration BindVariableDeclaration(
return new BoundLocalDeclaration(associatedSyntaxNode, localSymbol, boundDeclType, initializerOpt, arguments, hasErrors);
}

private ImmutableArray<BoundExpression> BindDeclaratorArguments(VariableDeclaratorSyntax declarator, DiagnosticBag diagnostics)
internal ImmutableArray<BoundExpression> BindDeclaratorArguments(VariableDeclaratorSyntax declarator, DiagnosticBag diagnostics)
{
// It is possible that we have a bracketed argument list, like "int x[];" or "int x[123];"
// in a non-fixed-size-array declaration . This is a common error made by C++ programmers.
Expand Down
6 changes: 2 additions & 4 deletions src/Compilers/CSharp/Portable/Binder/FixedStatementBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ override protected ImmutableArray<LocalSymbol> BuildLocals()
{
locals.Add(MakeLocal(_syntax.Declaration, declarator, LocalDeclarationKind.FixedVariable));

if (declarator.Initializer != null)
{
ExpressionVariableFinder.FindExpressionVariables(this, locals, declarator.Initializer.Value);
}
// also gather expression-declared variables from the bracketed argument lists and the initializers
ExpressionVariableFinder.FindExpressionVariables(this, locals, declarator);
}

return locals.ToImmutable();
Expand Down
4 changes: 3 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/ForLoopBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ override protected ImmutableArray<LocalSymbol> BuildLocals()
{
var localSymbol = MakeLocal(_syntax.Declaration, vdecl, LocalDeclarationKind.ForInitializerVariable);
locals.Add(localSymbol);
ExpressionVariableFinder.FindExpressionVariables(this, locals, vdecl.Initializer?.Value);

// also gather expression-declared variables from the bracketed argument lists and the initializers
ExpressionVariableFinder.FindExpressionVariables(this, locals, vdecl);
}
}
else
Expand Down
27 changes: 10 additions & 17 deletions src/Compilers/CSharp/Portable/Binder/LocalBinderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,7 @@ public override void VisitUsingStatement(UsingStatementSyntax node)
{
foreach (VariableDeclaratorSyntax declarator in declarationSyntax.Variables)
{
if (declarator.Initializer != null)
{
Visit(declarator.Initializer.Value, usingBinder);
}
Visit(declarator, usingBinder);
}
}

Expand Down Expand Up @@ -401,10 +398,7 @@ public override void VisitForStatement(ForStatementSyntax node)
{
foreach (var variable in declaration.Variables)
{
if (variable.Initializer != null)
{
Visit(variable.Initializer.Value, binder);
}
Visit(variable, binder);
}
}
else
Expand Down Expand Up @@ -478,10 +472,7 @@ public override void VisitFixedStatement(FixedStatementSyntax node)
{
foreach (VariableDeclaratorSyntax declarator in node.Declaration.Variables)
{
if (declarator.Initializer != null)
{
Visit(declarator.Initializer.Value, binder);
}
Visit(declarator, binder);
}
}

Expand Down Expand Up @@ -651,14 +642,16 @@ public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyn
{
foreach (var decl in node.Declaration.Variables)
{
var value = decl.Initializer?.Value;
if (value != null)
{
Visit(value, _enclosing);
}
Visit(decl);
}
}

public override void VisitVariableDeclarator(VariableDeclaratorSyntax node)
{
Visit(node.ArgumentList);
Visit(node.Initializer?.Value);
}

public override void VisitDeconstructionDeclarationStatement(DeconstructionDeclarationStatementSyntax node)
{
Visit(node.Assignment.Value, _enclosing);
Expand Down
6 changes: 2 additions & 4 deletions src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ override protected ImmutableArray<LocalSymbol> BuildLocals()
{
locals.Add(MakeLocal(declarationSyntax, declarator, LocalDeclarationKind.UsingVariable));

if (declarator.Initializer != null)
{
ExpressionVariableFinder.FindExpressionVariables(this, locals, declarator.Initializer.Value);
}
// also gather expression-declared variables from the bracketed argument lists and the initializers
ExpressionVariableFinder.FindExpressionVariables(this, locals, declarator);
}

return locals.ToImmutableAndFree();
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1660,7 +1660,7 @@ public override BoundNode VisitUsingStatement(BoundUsingStatement node)
}
}

Debug.Assert(localsOpt.Where(l => l.DeclarationKind != LocalDeclarationKind.PatternVariable).All(_usedVariables.Contains));
Debug.Assert(localsOpt.Where(l => l.DeclarationKind == LocalDeclarationKind.UsingVariable).All(_usedVariables.Contains));

return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -752,23 +752,7 @@ protected override TypeSymbol InferTypeOfVarVariable(DiagnosticBag diagnostics)
// This occurs, for example, in
// int x, y[out var Z, 1 is int I];
// for (int x, y[out var Z, 1 is int I]; ;) {}
var declarator = (VariableDeclaratorSyntax)_nodeToBind;
if (declarator.ArgumentList != null)
{
foreach (var arg in declarator.ArgumentList.Arguments)
{
var expression = arg.Expression;
if (expression.Kind() == SyntaxKind.DeclarationExpression)
{
this.SetType(_nodeBinder.CreateErrorType("var"));
// no error is necessary, as they would be dropped on the floor by the caller
}
else
{
_nodeBinder.BindExpression(expression, diagnostics);
}
}
}
_nodeBinder.BindDeclaratorArguments((VariableDeclaratorSyntax)_nodeToBind, diagnostics);
break;
default:
_nodeBinder.BindExpression((ExpressionSyntax)_nodeToBind, diagnostics);
Expand Down
Loading

0 comments on commit f0304e0

Please sign in to comment.