提交 155a75ca 编写于 作者: A AlekseyTs

Avoid stack overflow on long binary expressions. (changeset 1319674)

上级 9a748926
......@@ -363,7 +363,7 @@ private static bool IsLegalDynamicOperand(BoundExpression operand)
hasErrors: hasError);
}
private static bool IsSimpleBinaryOperator(SyntaxKind kind)
protected static bool IsSimpleBinaryOperator(SyntaxKind kind)
{
// We deliberately exclude &&, ||, ??, etc.
switch (kind)
......
......@@ -395,6 +395,41 @@ public override void VisitIfStatement(IfStatementSyntax node)
{
return;
}
public override void VisitBinaryExpression(BinaryExpressionSyntax node)
{
if (!IsSimpleBinaryOperator(node.Kind))
{
base.VisitBinaryExpression(node);
return;
}
// The simple binary operators are left-associative, and expressions of the form
// a + b + c + d .... are relatively common in machine-generated code. The parser can handle
// creating a deep-on-the-left syntax tree no problem, and then we promptly blow the stack during
// semantic analysis. Here we build an explicit stack to handle the left-hand recursion.
var operands = ArrayBuilder<ExpressionSyntax>.GetInstance();
ExpressionSyntax current = node;
do
{
var binOp = (BinaryExpressionSyntax)current;
operands.Push(binOp.Right);
current = binOp.Left;
}
while (IsSimpleBinaryOperator(current.Kind));
Visit(current);
while (operands.Count > 0)
{
Visit(operands.Pop());
}
operands.Free();
}
}
protected void BuildLabels(SyntaxList<StatementSyntax> statements, ref ArrayBuilder<LabelSymbol> labels)
......
......@@ -6,6 +6,7 @@
using System.Globalization;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
......@@ -177,7 +178,44 @@ public override BoundNode Visit(BoundNode node)
map.Add(current.Syntax, current);
}
// In machine-generated code we frequently end up with binary operator trees that are deep on the left,
// such as a + b + c + d ...
// To avoid blowing the call stack, we build an explicit stack to handle the left-hand recursion.
var binOp = current as BoundBinaryOperator;
if (binOp != null)
{
var stack = ArrayBuilder<BoundExpression>.GetInstance();
stack.Push(binOp.Right);
current = binOp.Left;
binOp = current as BoundBinaryOperator;
while (binOp != null)
{
if (ShouldAddNode(binOp))
{
map.Add(binOp.Syntax, binOp);
}
stack.Push(binOp.Right);
current = binOp.Left;
binOp = current as BoundBinaryOperator;
}
Visit(current);
while (stack.Count > 0)
{
Visit(stack.Pop());
}
stack.Free();
}
else
{
base.Visit(current);
}
return null;
}
......@@ -209,6 +247,11 @@ public override BoundNode VisitQueryClause(BoundQueryClause node)
VisitUnoptimizedForm(node);
return null;
}
public override BoundNode VisitBinaryOperator(BoundBinaryOperator node)
{
throw ExceptionUtilities.Unreachable;
}
}
}
}
......@@ -1009,13 +1009,10 @@ private SynthesizedExplicitImplementationForwardingMethod SynthesizeInterfaceMem
MethodSymbol implementingMethod = (MethodSymbol)implementingMember;
//explicit implementations are always respected by the CLR
foreach (MethodSymbol implemented in implementingMethod.ExplicitInterfaceImplementations)
{
if (implemented == interfaceMethod)
if (implementingMethod.ExplicitInterfaceImplementations.Contains(interfaceMethod))
{
return null;
}
}
MethodSymbol implementingMethodOriginalDefinition = implementingMethod.OriginalDefinition;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册