提交 38281970 编写于 作者: N Neal Gafter

Merge pull request #6731 from gafter/fix6726

Enforce the precedence of a query expression
...@@ -198,7 +198,7 @@ protected override bool NeedsProxy(Symbol localOrParameter) ...@@ -198,7 +198,7 @@ protected override bool NeedsProxy(Symbol localOrParameter)
// No closures or lambda methods are generated. // No closures or lambda methods are generated.
// E.g. // E.g.
// int y = 0; // int y = 0;
// var b = false && from z in new X(y) select f(z + y) // var b = false && (from z in new X(y) select f(z + y))
return loweredBody; return loweredBody;
} }
......
...@@ -6500,7 +6500,7 @@ private StatementSyntax ParseStatementNoDeclaration(bool allowAnyExpression) ...@@ -6500,7 +6500,7 @@ private StatementSyntax ParseStatementNoDeclaration(bool allowAnyExpression)
} }
else if (this.IsQueryExpression(mayBeVariableDeclaration: true, mayBeMemberDeclaration: allowAnyExpression)) else if (this.IsQueryExpression(mayBeVariableDeclaration: true, mayBeMemberDeclaration: allowAnyExpression))
{ {
return this.ParseExpressionStatement(this.ParseQueryExpression()); return this.ParseExpressionStatement(this.ParseQueryExpression(0));
} }
else else
{ {
...@@ -8330,7 +8330,7 @@ private ExpressionSyntax ParseSubExpressionCore(uint precedence) ...@@ -8330,7 +8330,7 @@ private ExpressionSyntax ParseSubExpressionCore(uint precedence)
} }
else if (this.IsQueryExpression(mayBeVariableDeclaration: false, mayBeMemberDeclaration: false)) else if (this.IsQueryExpression(mayBeVariableDeclaration: false, mayBeMemberDeclaration: false))
{ {
leftOperand = this.ParseQueryExpression(); leftOperand = this.ParseQueryExpression(precedence);
} }
else if (this.CurrentToken.ContextualKind == SyntaxKind.FromKeyword && IsInQuery) else if (this.CurrentToken.ContextualKind == SyntaxKind.FromKeyword && IsInQuery)
{ {
...@@ -8448,10 +8448,10 @@ private ExpressionSyntax ParseSubExpressionCore(uint precedence) ...@@ -8448,10 +8448,10 @@ private ExpressionSyntax ParseSubExpressionCore(uint precedence)
{ {
var questionToken = this.EatToken(); var questionToken = this.EatToken();
var colonLeft = this.ParseSubExpression(nullCoalescingPrecedence - 1); var colonLeft = this.ParseExpressionCore();
var colon = this.EatToken(SyntaxKind.ColonToken); var colon = this.EatToken(SyntaxKind.ColonToken);
var colonRight = this.ParseSubExpression(nullCoalescingPrecedence - 1); var colonRight = this.ParseExpressionCore();
leftOperand = _syntaxFactory.ConditionalExpression(leftOperand, questionToken, colonLeft, colon, colonRight); leftOperand = _syntaxFactory.ConditionalExpression(leftOperand, questionToken, colonLeft, colon, colonRight);
} }
...@@ -10193,11 +10193,16 @@ private bool IsQueryExpressionAfterFrom(bool mayBeVariableDeclaration, bool mayB ...@@ -10193,11 +10193,16 @@ private bool IsQueryExpressionAfterFrom(bool mayBeVariableDeclaration, bool mayB
return false; return false;
} }
private QueryExpressionSyntax ParseQueryExpression() private QueryExpressionSyntax ParseQueryExpression(uint precedence)
{ {
this.EnterQuery(); this.EnterQuery();
var fc = this.ParseFromClause(); var fc = this.ParseFromClause();
fc = CheckFeatureAvailability(fc, MessageID.IDS_FeatureQueryExpression); fc = CheckFeatureAvailability(fc, MessageID.IDS_FeatureQueryExpression);
if (precedence > 1 && IsStrict)
{
fc = this.AddError(fc, ErrorCode.ERR_InvalidExprTerm, SyntaxFacts.GetText(SyntaxKind.FromKeyword));
}
var body = this.ParseQueryBody(); var body = this.ParseQueryBody();
this.LeaveQuery(); this.LeaveQuery();
return _syntaxFactory.QueryExpression(fc, body); return _syntaxFactory.QueryExpression(fc, body);
...@@ -10440,6 +10445,8 @@ private QueryContinuationSyntax ParseQueryContinuation() ...@@ -10440,6 +10445,8 @@ private QueryContinuationSyntax ParseQueryContinuation()
return _syntaxFactory.QueryContinuation(@into, name, body); return _syntaxFactory.QueryContinuation(@into, name, body);
} }
private bool IsStrict => this.Options.Features.ContainsKey("strict");
[Obsolete("Use IsIncrementalAndFactoryContextMatches")] [Obsolete("Use IsIncrementalAndFactoryContextMatches")]
private new bool IsIncremental private new bool IsIncremental
{ {
......
...@@ -1797,6 +1797,18 @@ static int Main() ...@@ -1797,6 +1797,18 @@ static int Main()
return (errCount > 0) ? 1 : 0; return (errCount > 0) ? 1 : 0;
} }
}"; }";
// the grammar does not allow a query on the right-hand-side of &&, but we allow it except in strict mode.
CreateCompilationWithMscorlibAndSystemCore(source, parseOptions: TestOptions.Regular.WithFeature("strict", "true")).VerifyDiagnostics(
// (23,26): error CS1525: Invalid expression term 'from'
// var b = false && from x in src select x; // WRN CS0429
Diagnostic(ErrorCode.ERR_InvalidExprTerm, "from x in src").WithArguments("from").WithLocation(23, 26),
// (4,1): hidden CS8019: Unnecessary using directive.
// using System.Collections.Generic;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Collections.Generic;").WithLocation(4, 1),
// (3,1): hidden CS8019: Unnecessary using directive.
// using System.Linq;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Linq;").WithLocation(3, 1)
);
CompileAndVerify(source, additionalRefs: new[] { LinqAssemblyRef }, CompileAndVerify(source, additionalRefs: new[] { LinqAssemblyRef },
expectedOutput: "0"); expectedOutput: "0");
} }
......
...@@ -508,6 +508,16 @@ public void TestConditional() ...@@ -508,6 +508,16 @@ public void TestConditional()
Assert.Equal("c", ts.WhenFalse.ToString()); Assert.Equal("c", ts.WhenFalse.ToString());
} }
[Fact]
public void TestConditional02()
{
// ensure that ?: has lower precedence than assignment.
var text = "a ? b=c : d=e";
var expr = this.ParseExpression(text);
Assert.Equal(SyntaxKind.ConditionalExpression, expr.Kind());
Assert.False(expr.HasErrors);
}
[Fact] [Fact]
public void TestCast() public void TestCast()
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册