提交 0f68d3ae 编写于 作者: G Gen Lu

Generate an AnalzyerDriver exception if operation collector crashes

Log non-fatal-watson if exception is not caused by stack overflow in OperationWalker.
上级 16480a0b
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -1262,6 +1263,47 @@ public void M0()
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new NoneOperationTestAnalyzer() }, null, null, false);
}
// This test can't reliablely trigger stack overflow on Linux
[ClrOnlyFact, WorkItem(9025, "https://github.com/dotnet/roslyn/issues/9025")]
public void LongArithmeticExpressionCSharp()
{
Func<int, string> buildSequenceOfBinaryExpressions =
(count) =>
{
var builder = new System.Text.StringBuilder();
int i;
for (i = 0; i < count; i++)
{
builder.Append(i + 1);
builder.Append(" * ");
builder.Append("f[");
builder.Append(i);
builder.Append("] + ");
}
builder.Append(i + 1);
return builder.ToString();
};
// This code will cause OperationWalker to throw `InsufficientExecutionStackException`
var source = @"
class Test
{
public static long Calculate1(long[] f)
{
long x;
" + $" x = { buildSequenceOfBinaryExpressions(8192) };" + @"
return x;
}
}";
CreateCompilationWithMscorlib45(source)
.VerifyDiagnostics()
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new AssignmentOperationSyntaxTestAnalyzer() }, null, null, true,
Diagnostic("AD0002").WithArguments("System.InsufficientExecutionStackException", "Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space.").WithLocation(1, 1),
Diagnostic(AssignmentOperationSyntaxTestAnalyzer.AssignmentSyntaxDescriptor.Id, $"x = { buildSequenceOfBinaryExpressions(8192) }").WithLocation(7, 9));
}
[WorkItem(9020, "https://github.com/dotnet/roslyn/issues/9020")]
[Fact]
public void AddressOfExpressionCSharp()
......
......@@ -1948,6 +1948,50 @@ public sealed override void Initialize(AnalysisContext context)
}
}
public class AssignmentOperationSyntaxTestAnalyzer : DiagnosticAnalyzer
{
private const string ReliabilityCategory = "Reliability";
public static readonly DiagnosticDescriptor AssignmentOperationDescriptor = new DiagnosticDescriptor(
"AssignmentOperation",
"An assignment operation is found",
"An assignment operation is found",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public static readonly DiagnosticDescriptor AssignmentSyntaxDescriptor = new DiagnosticDescriptor(
"AssignmentSyntax",
"An assignment syntax is found",
"An assignment syntax is found",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(AssignmentOperationDescriptor, AssignmentSyntaxDescriptor); }
}
public sealed override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction(
(operationContext) =>
{
operationContext.ReportDiagnostic(Diagnostic.Create(AssignmentOperationDescriptor, operationContext.Operation.Syntax.GetLocation()));
},
OperationKind.AssignmentExpression);
context.RegisterSyntaxNodeAction(
(syntaxContext) =>
{
syntaxContext.ReportDiagnostic(Diagnostic.Create(AssignmentSyntaxDescriptor, syntaxContext.Node.GetLocation()));
},
CSharp.SyntaxKind.SimpleAssignmentExpression);
}
}
public class LiteralTestAnalyzer : DiagnosticAnalyzer
{
private const string ReliabilityCategory = "Reliability";
......
......@@ -1548,7 +1548,20 @@ private static void ComputeDeclarationsInNode(SemanticModel semanticModel, ISymb
if (shouldExecuteOperationActions || shouldExecuteOperationBlockActions)
{
var operationBlocksToAnalyze = GetOperationBlocksToAnalyze(executableCodeBlocks, semanticModel, cancellationToken);
var operationsToAnalyze = GetOperationsToAnalyze(operationBlocksToAnalyze);
var operationsToAnalyze = ImmutableArray<IOperation>.Empty;
try
{
operationsToAnalyze = GetOperationsToAnalyze(operationBlocksToAnalyze);
}
catch (Exception ex) when (StackGuard.IsInsufficientExecutionStackException(ex) || FatalError.ReportWithoutCrashUnlessCanceled(ex))
{
// the exception filter will short-circuit if `ex` is `InsufficientExecutionStackException` (from OperationWalker)
// and no non-fatal-watson will be logged as a result.
var diagnostic = AnalyzerExecutor.CreateDriverExceptionDiagnostic(ex);
var analyzer = this.analyzers[0];
analyzerExecutor.OnAnalyzerException(ex, analyzer, diagnostic);
}
if (!operationsToAnalyze.IsEmpty)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册