mirror of
https://github.com/github/codeql.git
synced 2026-05-03 04:39:29 +02:00
C#: Implement recursive patterns
This commit is contained in:
@@ -1,15 +1,23 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
using Semmle.Extraction.Entities;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
class Discard : Expression<NameSyntax>
|
||||
class Discard : Expression
|
||||
{
|
||||
public Discard(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.DISCARD))
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Populate()
|
||||
public Discard(Context cx, DiscardDesignationSyntax discard, IExpressionParentEntity parent, int child) :
|
||||
base(new ExpressionInfo(cx, Type.Create(cx, cx.Model(discard).GetTypeInfo(discard).Type), cx.Create(discard.GetLocation()), ExprKind.DISCARD, parent, child, false, null))
|
||||
{
|
||||
}
|
||||
|
||||
public Discard(Context cx, DiscardPatternSyntax pattern, IExpressionParentEntity parent, int child) :
|
||||
base(new ExpressionInfo(cx, Type.Create(cx, cx.Model(pattern).GetTypeInfo(pattern).Type), cx.Create(pattern.GetLocation()), ExprKind.DISCARD, parent, child, false, null))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +238,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
case SyntaxKind.IndexExpression:
|
||||
return Unary.Create(info.SetKind(ExprKind.INDEX));
|
||||
|
||||
case SyntaxKind.SwitchExpression:
|
||||
return Switch.Create(info);
|
||||
|
||||
default:
|
||||
info.Context.ModelError(info.Node, $"Unhandled expression '{info.Node}' of kind '{info.Node.Kind()}'");
|
||||
return new Unknown(info);
|
||||
|
||||
@@ -6,6 +6,126 @@ using Semmle.Extraction.Entities;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
static class PatternExtensions
|
||||
{
|
||||
public static Expression CreatePattern(this Context cx, PatternSyntax syntax, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
switch (syntax)
|
||||
{
|
||||
case ConstantPatternSyntax constantPattern:
|
||||
return Expression.Create(cx, constantPattern.Expression, parent, child);
|
||||
|
||||
case DeclarationPatternSyntax declPattern:
|
||||
// Creates a single local variable declaration.
|
||||
{
|
||||
if (declPattern.Designation is VariableDesignationSyntax designation && cx.Model(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
|
||||
{
|
||||
var type = Type.Create(cx, symbol.Type);
|
||||
|
||||
return VariableDeclaration.Create(cx, symbol, type, cx.Create(syntax.GetLocation()), cx.Create(designation.GetLocation()), false, parent, child);
|
||||
}
|
||||
throw new InternalError(syntax, "Is pattern not handled");
|
||||
}
|
||||
|
||||
case RecursivePatternSyntax recPattern:
|
||||
return new RecursivePattern(cx, recPattern, parent, child, false);
|
||||
|
||||
case VarPatternSyntax varPattern:
|
||||
switch(varPattern.Designation)
|
||||
{
|
||||
case ParenthesizedVariableDesignationSyntax parDesignation:
|
||||
return VariableDeclaration.CreateParenthesized(cx, varPattern, parDesignation, parent, child);
|
||||
case SingleVariableDesignationSyntax varDesignation:
|
||||
if (cx.Model(syntax).GetDeclaredSymbol(varDesignation) is ILocalSymbol symbol2)
|
||||
{
|
||||
var type = Type.Create(cx, symbol2.Type);
|
||||
|
||||
return VariableDeclaration.Create(cx, symbol2, type, cx.Create(syntax.GetLocation()), cx.Create(varDesignation.GetLocation()), false, parent, child);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InternalError(varPattern, "Unable to get the declared symbol of the var pattern designation.");
|
||||
}
|
||||
default:
|
||||
throw new InternalError("var pattern designation is unhandled");
|
||||
}
|
||||
|
||||
case DiscardPatternSyntax dp:
|
||||
return new Discard(cx, dp, parent, child);
|
||||
|
||||
default:
|
||||
throw new InternalError(syntax, "Is pattern not handled");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class PropertyPattern : Expression
|
||||
{
|
||||
internal PropertyPattern(Context cx, PropertyPatternClauseSyntax pp, IExpressionParentEntity parent, int child) :
|
||||
base(new ExpressionInfo(cx, Type.Create(cx, null), cx.Create(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null))
|
||||
{
|
||||
child = 0;
|
||||
foreach (var sub in pp.Subpatterns)
|
||||
{
|
||||
cx.CreatePattern(sub.Pattern, this, child++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PositionalPattern : Expression
|
||||
{
|
||||
internal PositionalPattern(Context cx, PositionalPatternClauseSyntax posPc, IExpressionParentEntity parent, int child) :
|
||||
base(new ExpressionInfo(cx, Type.Create(cx, null), cx.Create(posPc.GetLocation()), ExprKind.POSITIONAL_PATTERN, parent, child, false, null))
|
||||
{
|
||||
child = 0;
|
||||
foreach (var sub in posPc.Subpatterns)
|
||||
{
|
||||
cx.CreatePattern(sub.Pattern, this, child++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RecursivePattern : Expression
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates and populates a recursive pattern.
|
||||
/// </summary>
|
||||
/// <param name="cx">The extraction context.</param>
|
||||
/// <param name="syntax">The syntax node of the recursive pattern.</param>
|
||||
/// <param name="parent">The parent pattern/expression.</param>
|
||||
/// <param name="child">The child index of this pattern.</param>
|
||||
/// <param name="isTopLevel">If this pattern is in the top level of a case/is. In that case, the variable and type access are populated elsewhere.</param>
|
||||
public RecursivePattern(Context cx, RecursivePatternSyntax syntax, IExpressionParentEntity parent, int child, bool isTopLevel) :
|
||||
base(new ExpressionInfo(cx, Type.Create(cx, null), cx.Create(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null))
|
||||
{
|
||||
if(!isTopLevel)
|
||||
{
|
||||
// Extract the type access
|
||||
if(syntax.Type is TypeSyntax t)
|
||||
Expressions.TypeAccess.Create(cx, t, this, 1);
|
||||
|
||||
// Extract the local variable declaration
|
||||
if (syntax.Designation is VariableDesignationSyntax designation && cx.Model(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
|
||||
{
|
||||
var type = Type.Create(cx, symbol.Type);
|
||||
|
||||
VariableDeclaration.Create(cx, symbol, type, cx.Create(syntax.GetLocation()), cx.Create(designation.GetLocation()), false, this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (syntax.PositionalPatternClause is PositionalPatternClauseSyntax posPc)
|
||||
{
|
||||
new PositionalPattern(cx, posPc, this, 2);
|
||||
}
|
||||
|
||||
if (syntax.PropertyPatternClause is PropertyPatternClauseSyntax pc)
|
||||
{
|
||||
new PropertyPattern(cx, pc, this, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IsPattern : Expression<IsPatternExpressionSyntax>
|
||||
{
|
||||
private IsPattern(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.IS))
|
||||
@@ -18,7 +138,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
if (!isVar)
|
||||
Expressions.TypeAccess.Create(cx, optionalType, this, 1);
|
||||
|
||||
if (cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
|
||||
if (!(designation is null) && cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
|
||||
{
|
||||
var type = Type.Create(cx, symbol.Type);
|
||||
|
||||
@@ -43,6 +163,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
case DeclarationPatternSyntax declPattern:
|
||||
PopulatePattern(declPattern, declPattern.Type, default(SyntaxToken), declPattern.Designation);
|
||||
return;
|
||||
case RecursivePatternSyntax recPattern:
|
||||
PopulatePattern(recPattern, recPattern.Type, default(SyntaxToken), recPattern.Designation);
|
||||
new RecursivePattern(cx, recPattern, this, 4, true);
|
||||
return;
|
||||
default:
|
||||
throw new InternalError(Syntax, "Is pattern not handled");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
class RangeExpression : Expression<RangeExpressionSyntax>
|
||||
{
|
||||
private RangeExpression(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.RANGE))
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Populate()
|
||||
{
|
||||
if (!(Syntax.LeftOperand is null))
|
||||
Expression.Create(cx, Syntax.LeftOperand, this, 0);
|
||||
if (!(Syntax.RightOperand is null))
|
||||
Expression.Create(cx, Syntax.RightOperand, this, 1);
|
||||
}
|
||||
|
||||
public static Expression Create(ExpressionNodeInfo info) => new RangeExpression(info).TryPopulate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Entities;
|
||||
using Semmle.Extraction.Kinds;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
class Switch : Expression<SwitchExpressionSyntax>
|
||||
{
|
||||
private Switch(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.SWITCH))
|
||||
{
|
||||
}
|
||||
|
||||
public static Expression Create(ExpressionNodeInfo info) => new Switch(info).TryPopulate();
|
||||
|
||||
public Expression SwitchedExpr { get; private set; }
|
||||
|
||||
protected override void Populate()
|
||||
{
|
||||
SwitchedExpr = Expression.Create(cx, Syntax.GoverningExpression, this, -1);
|
||||
int child = 0;
|
||||
foreach(var arm in Syntax.Arms)
|
||||
{
|
||||
new SwitchCase(cx, arm, this, child++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SwitchCase : Expression
|
||||
{
|
||||
internal SwitchCase(Context cx, SwitchExpressionArmSyntax arm, Switch parent, int child) :
|
||||
base(new ExpressionInfo(cx, parent.SwitchedExpr.Type, cx.Create(arm.GetLocation()), ExprKind.SWITCH_CASE, parent, child, false, null))
|
||||
{
|
||||
cx.CreatePattern(arm.Pattern, this, 0);
|
||||
if (arm.WhenClause is WhenClauseSyntax when)
|
||||
Expression.Create(cx, when.Condition, this, 1);
|
||||
Expression.Create(cx, arm.Expression, this, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,13 +26,13 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
if (variableSymbol == null)
|
||||
{
|
||||
cx.ModelError(node, "Failed to determine local variable");
|
||||
return new VariableDeclaration(cx, node, null, isVar, parent, child);
|
||||
return Create(cx, node, null, isVar, parent, child);
|
||||
}
|
||||
|
||||
var type = Type.Create(cx, variableSymbol.Type);
|
||||
var location = cx.Create(designation.GetLocation());
|
||||
|
||||
var ret = new VariableDeclaration(cx, designation, type, isVar, parent, child);
|
||||
var ret = Create(cx, designation, type, isVar, parent, child);
|
||||
cx.Try(null, null, () => LocalVariable.Create(cx, variableSymbol, ret, isVar, location));
|
||||
return ret;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
/// Create a tuple expression representing a parenthesized variable declaration.
|
||||
/// That is, we consider `var (x, y) = ...` to be equivalent to `(var x, var y) = ...`.
|
||||
/// </summary>
|
||||
static Expression CreateParenthesized(Context cx, DeclarationExpressionSyntax node, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
|
||||
public static Expression CreateParenthesized(Context cx, DeclarationExpressionSyntax node, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var type = Type.Create(cx, null); // Should ideally be a corresponding tuple type
|
||||
var tuple = new Expression(new ExpressionInfo(cx, type, cx.Create(node.GetLocation()), ExprKind.TUPLE, parent, child, false, null));
|
||||
@@ -56,41 +56,73 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
return tuple;
|
||||
}
|
||||
|
||||
public static Expression CreateParenthesized(Context cx, VarPatternSyntax varPattern, ParenthesizedVariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var type = Type.Create(cx, null); // Should ideally be a corresponding tuple type
|
||||
var tuple = new Expression(new ExpressionInfo(cx, type, cx.Create(varPattern.GetLocation()), ExprKind.TUPLE, parent, child, false, null));
|
||||
|
||||
cx.Try(null, null, () =>
|
||||
{
|
||||
var child0 = 0;
|
||||
foreach (var variable in designation.Variables)
|
||||
switch(variable)
|
||||
{
|
||||
case ParenthesizedVariableDesignationSyntax paren:
|
||||
CreateParenthesized(cx, varPattern, paren, tuple, child0++);
|
||||
break;
|
||||
case SingleVariableDesignationSyntax single:
|
||||
if (cx.Model(variable).GetDeclaredSymbol(single) is ILocalSymbol local)
|
||||
{
|
||||
var decl = Create(cx, variable, Type.Create(cx, local.Type), true, tuple, child0++);
|
||||
var id = single.Identifier;
|
||||
var declSymbol = cx.Model(single).GetDeclaredSymbol(single);
|
||||
var location = cx.Create(id.GetLocation());
|
||||
LocalVariable.Create(cx, local, decl, true, location);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InternalError(single, "Failed to access local variable");
|
||||
}
|
||||
break;
|
||||
case DiscardDesignationSyntax discard:
|
||||
new Discard(cx, discard, tuple, child0++);
|
||||
break;
|
||||
default:
|
||||
throw new InternalError(variable, "Unhandled designation type");
|
||||
}
|
||||
});
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
|
||||
static Expression Create(Context cx, DeclarationExpressionSyntax node, VariableDesignationSyntax designation, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var single = designation as SingleVariableDesignationSyntax;
|
||||
if (single != null)
|
||||
return CreateSingle(cx, node, single, parent, child);
|
||||
|
||||
var paren = designation as ParenthesizedVariableDesignationSyntax;
|
||||
if (paren != null)
|
||||
return CreateParenthesized(cx, node, paren, parent, child);
|
||||
|
||||
var discard = designation as DiscardDesignationSyntax;
|
||||
if (discard != null)
|
||||
switch(designation)
|
||||
{
|
||||
var type = cx.Model(node).GetTypeInfo(node).Type;
|
||||
return new VariableDeclaration(cx, node, Type.Create(cx, type), node.Type.IsVar, parent, child);
|
||||
case SingleVariableDesignationSyntax single:
|
||||
return CreateSingle(cx, node, single, parent, child);
|
||||
case ParenthesizedVariableDesignationSyntax paren:
|
||||
return CreateParenthesized(cx, node, paren, parent, child);
|
||||
case DiscardDesignationSyntax discard:
|
||||
var type = cx.Model(discard).GetTypeInfo(discard).Type;
|
||||
return Create(cx, node, Type.Create(cx, type), node.Type.IsVar, parent, child);
|
||||
default:
|
||||
cx.ModelError(node, "Failed to determine designation type");
|
||||
return Create(cx, node, null, node.Type.IsVar, parent, child);
|
||||
}
|
||||
|
||||
cx.ModelError(node, "Failed to determine designation type");
|
||||
return new VariableDeclaration(cx, node, null, node.Type.IsVar, parent, child);
|
||||
}
|
||||
|
||||
public static Expression Create(Context cx, DeclarationExpressionSyntax node, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
return Create(cx, node, node.Designation, parent, child);
|
||||
}
|
||||
public static Expression Create(Context cx, DeclarationExpressionSyntax node, IExpressionParentEntity parent, int child) =>
|
||||
Create(cx, node, node.Designation, parent, child);
|
||||
|
||||
VariableDeclaration(Context cx, CSharpSyntaxNode d, Type type, bool isVar, IExpressionParentEntity parent, int child)
|
||||
: base(new ExpressionInfo(cx, type, cx.Create(d.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null))
|
||||
{
|
||||
}
|
||||
public static VariableDeclaration Create(Context cx, CSharpSyntaxNode c, Type type, bool isVar, IExpressionParentEntity parent, int child) =>
|
||||
new VariableDeclaration(new ExpressionInfo(cx, type, cx.Create(c.FixedLocation()), ExprKind.LOCAL_VAR_DECL, parent, child, false, null));
|
||||
|
||||
public static VariableDeclaration Create(Context cx, CatchDeclarationSyntax d, bool isVar, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var type = Type.Create(cx, cx.Model(d).GetDeclaredSymbol(d).Type);
|
||||
var ret = new VariableDeclaration(cx, d, type, isVar, parent, child);
|
||||
var ret = Create(cx, d, type, isVar, parent, child);
|
||||
cx.Try(d, null, () =>
|
||||
{
|
||||
var id = d.Identifier;
|
||||
@@ -102,9 +134,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static VariableDeclaration Create(Context cx, VariableDeclaratorSyntax d, Type type, bool isVar, IExpressionParentEntity parent, int child)
|
||||
public static VariableDeclaration CreateDeclarator(Context cx, VariableDeclaratorSyntax d, Type type, bool isVar, IExpressionParentEntity parent, int child)
|
||||
{
|
||||
var ret = new VariableDeclaration(cx, d, type, isVar, parent, child);
|
||||
var ret = Create(cx, d, type, isVar, parent, child);
|
||||
cx.Try(d, null, () =>
|
||||
{
|
||||
var id = d.Identifier;
|
||||
@@ -137,7 +169,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
|
||||
foreach (var v in decl.Variables)
|
||||
{
|
||||
VariableDeclaration.Create(cx, v, type, decl.Type.IsVar, parent, child);
|
||||
VariableDeclaration.CreateDeclarator(cx, v, type, decl.Type.IsVar, parent, child);
|
||||
child += childIncrement;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,14 +73,29 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
||||
if(!isVar)
|
||||
Expressions.TypeAccess.Create(cx, optionalType, this, 1);
|
||||
|
||||
if (cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
|
||||
switch (designation)
|
||||
{
|
||||
var type = Type.Create(cx, symbol.Type);
|
||||
case SingleVariableDesignationSyntax single:
|
||||
if (cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
|
||||
{
|
||||
var type = Type.Create(cx, symbol.Type);
|
||||
|
||||
if (isVar)
|
||||
new Expression(new ExpressionInfo(cx, type, cx.Create(varKeyword.GetLocation()), ExprKind.TYPE_ACCESS, this, 1, false, null));
|
||||
if (isVar)
|
||||
new Expression(new ExpressionInfo(cx, type, cx.Create(varKeyword.GetLocation()), ExprKind.TYPE_ACCESS, this, 1, false, null));
|
||||
|
||||
Expressions.VariableDeclaration.Create(cx, symbol, type, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 0);
|
||||
Expressions.VariableDeclaration.Create(cx, symbol, type, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 0);
|
||||
}
|
||||
break;
|
||||
case DiscardDesignationSyntax discard:
|
||||
new Expressions.Discard(cx, discard, this, 0);
|
||||
break;
|
||||
case null:
|
||||
break;
|
||||
case ParenthesizedVariableDesignationSyntax paren:
|
||||
Expressions.VariableDeclaration.CreateParenthesized(cx, pattern as VarPatternSyntax, paren, this, 0);
|
||||
break;
|
||||
default:
|
||||
throw new InternalError(pattern, "Unhandled designation in case statement");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +112,10 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
||||
case ConstantPatternSyntax pattern:
|
||||
Expression.Create(cx, pattern.Expression, this, 0);
|
||||
break;
|
||||
case RecursivePatternSyntax recPattern:
|
||||
PopulatePattern(recPattern, recPattern.Type, default(SyntaxToken), recPattern.Designation);
|
||||
new Expressions.RecursivePattern(cx, recPattern, this, 4, true);
|
||||
break;
|
||||
default:
|
||||
throw new InternalError(Stmt, "Case pattern not handled");
|
||||
}
|
||||
|
||||
@@ -107,6 +107,11 @@ namespace Semmle.Extraction.Kinds
|
||||
REF = 110,
|
||||
DISCARD = 111,
|
||||
RANGE = 112,
|
||||
INDEX = 113
|
||||
INDEX = 113,
|
||||
SWITCH = 114,
|
||||
RECURSIVE_PATTERN = 115,
|
||||
PROPERTY_PATTERN = 116,
|
||||
POSITIONAL_PATTERN = 117,
|
||||
SWITCH_CASE = 118
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ namespace Semmle.Extraction.Entities
|
||||
: base(cx, init) { }
|
||||
|
||||
public static Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) =>
|
||||
loc == null || loc.Kind == Microsoft.CodeAnalysis.LocationKind.None ?
|
||||
GeneratedLocation.Create(cx) : loc.IsInSource ? SourceLocation.Create(cx, loc)
|
||||
(loc == null || loc.Kind == Microsoft.CodeAnalysis.LocationKind.None) ? GeneratedLocation.Create(cx)
|
||||
: loc.IsInSource ? SourceLocation.Create(cx, loc)
|
||||
: Assembly.Create(cx, loc);
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => symbol;
|
||||
|
||||
@@ -283,7 +283,8 @@ class ConstCase extends LabeledStmt, CaseStmt {
|
||||
|
||||
ConstCase() {
|
||||
expr = this.getChild(0) and
|
||||
not expr instanceof LocalVariableDeclExpr
|
||||
not expr instanceof LocalVariableDeclExpr and
|
||||
not exists(this.getChild(1))
|
||||
}
|
||||
|
||||
/** Gets the case expression. */
|
||||
@@ -309,7 +310,10 @@ class ConstCase extends LabeledStmt, CaseStmt {
|
||||
* ```
|
||||
*/
|
||||
class TypeCase extends LabeledStmt, CaseStmt {
|
||||
TypeCase() { this.getChild(1) instanceof TypeAccess }
|
||||
TypeCase() {
|
||||
this.getChild(1) instanceof TypeAccess and
|
||||
not this.getChild(4) instanceof RecursivePatternExpr
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local variable declaration of this type case, if any. For example,
|
||||
@@ -369,6 +373,38 @@ class TypeCase extends LabeledStmt, CaseStmt {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A recursive pattern case, for example `case string { Length: 0 } empty:`.
|
||||
*/
|
||||
class RecursivePatternCase extends LabeledStmt, CaseStmt {
|
||||
RecursivePatternExpr pattern;
|
||||
|
||||
RecursivePatternCase() { pattern = this.getChild(4) }
|
||||
|
||||
override string toString() { result = "case { ... }:" }
|
||||
|
||||
/**
|
||||
* Gets the type access of this recursive pattern case, if any.
|
||||
* For example, `string` in `case string { Length: 0 } empty:`.
|
||||
*/
|
||||
TypeAccess getTypeAccess() { result = getChild(1) }
|
||||
|
||||
/**
|
||||
* Gets the checked type of this recursive pattern, if any.
|
||||
* For example, `string` in `case string { Length: 0 } empty:`.
|
||||
*/
|
||||
Type getCheckedType() { result = getTypeAccess().getType() }
|
||||
|
||||
/**
|
||||
* Gets the recursive pattern of this case.
|
||||
* For example, `{ Length: 0 }` in `case string { Length: 0 } empty:`.
|
||||
*/
|
||||
|
||||
RecursivePatternExpr getRecursivePattern() { result = pattern }
|
||||
|
||||
LocalVariableDeclExpr getVariableDeclExpr() { result = getChild(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A default case of a `switch` statement, for example `default:` on
|
||||
* line 3 in
|
||||
|
||||
@@ -460,6 +460,7 @@ module ControlFlow {
|
||||
not this instanceof SwitchStmt and
|
||||
not this instanceof ConstCase and
|
||||
not this instanceof TypeCase and
|
||||
not this instanceof RecursivePatternCase and
|
||||
not this instanceof LoopStmt and
|
||||
not this instanceof TryStmt and
|
||||
not this instanceof SpecificCatchClause and
|
||||
@@ -645,7 +646,9 @@ module ControlFlow {
|
||||
not this instanceof ArrayCreation and
|
||||
not this instanceof QualifiedWriteAccess and
|
||||
not this instanceof AccessorWrite and
|
||||
not this instanceof NoNodeExpr
|
||||
not this instanceof NoNodeExpr and
|
||||
not this instanceof SwitchExpr and
|
||||
not this instanceof SwitchCaseExpr
|
||||
}
|
||||
|
||||
override ControlFlowElement getChildElement(int i) { result = getExprChildElement(this, i) }
|
||||
@@ -709,6 +712,8 @@ module ControlFlow {
|
||||
or
|
||||
this instanceof TypeCase
|
||||
or
|
||||
this instanceof RecursivePatternCase
|
||||
or
|
||||
this instanceof TryStmt
|
||||
or
|
||||
this instanceof SpecificCatchClause
|
||||
@@ -724,6 +729,10 @@ module ControlFlow {
|
||||
this instanceof NullCoalescingExpr
|
||||
or
|
||||
this instanceof ConditionalExpr
|
||||
or
|
||||
this instanceof SwitchExpr
|
||||
or
|
||||
this instanceof SwitchCaseExpr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -923,7 +932,8 @@ module ControlFlow {
|
||||
// Last case exits with a non-match
|
||||
exists(int last | last = max(int i | exists(ss.getCase(i))) |
|
||||
result = lastConstCaseNoMatch(ss.getCase(last), c) or
|
||||
result = lastTypeCaseNoMatch(ss.getCase(last), c)
|
||||
result = lastTypeCaseNoMatch(ss.getCase(last), c) or
|
||||
result = lastRecursivePatternCaseNoMatch(ss.getCase(last), c)
|
||||
)
|
||||
or
|
||||
// Last statement exits with any non-break completion
|
||||
@@ -947,6 +957,8 @@ module ControlFlow {
|
||||
result = lastTypeCaseNoMatch(tc, c)
|
||||
)
|
||||
or
|
||||
cfe = any(RecursivePatternCase rpc | result = lastRecursivePatternCaseNoMatch(rpc, c))
|
||||
or
|
||||
cfe = any(CaseStmt cs |
|
||||
// Condition exists with a `false` completion
|
||||
result = lastCaseCondition(cs, c) and
|
||||
@@ -1132,6 +1144,9 @@ module ControlFlow {
|
||||
c.isValidFor(result) and
|
||||
not c instanceof NormalCompletion
|
||||
)
|
||||
or
|
||||
// Result of a switch expression
|
||||
result = lastSwitchExpr(cfe, c)
|
||||
}
|
||||
|
||||
private ControlFlowElement lastConstCaseNoMatch(ConstCase cc, MatchingCompletion c) {
|
||||
@@ -1139,10 +1154,28 @@ module ControlFlow {
|
||||
not c.isMatch()
|
||||
}
|
||||
|
||||
private ControlFlowElement lastTypeCaseNoMatch(TypeCase tc, MatchingCompletion c) {
|
||||
result = tc.getTypeAccess() and
|
||||
not c.isMatch() and
|
||||
c.isValidFor(result)
|
||||
private ControlFlowElement lastTypeCaseNoMatch(TypeCase tc, Completion c) {
|
||||
c.isValidFor(result) and
|
||||
(
|
||||
result = tc.getTypeAccess() and
|
||||
c = any(MatchingCompletion mc | not mc.isMatch())
|
||||
or
|
||||
result = last(tc.getCondition(), _) and
|
||||
c instanceof FalseCompletion
|
||||
)
|
||||
}
|
||||
|
||||
private ControlFlowElement lastRecursivePatternCaseNoMatch(
|
||||
RecursivePatternCase rpc, Completion c
|
||||
) {
|
||||
c.isValidFor(result) and
|
||||
(
|
||||
result = rpc.getTypeAccess() and
|
||||
c = any(MatchingCompletion mc | not mc.isMatch())
|
||||
or
|
||||
result = last(rpc.getCondition(), _) and
|
||||
c instanceof FalseCompletion
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1290,6 +1323,8 @@ module ControlFlow {
|
||||
result = last(cs.(TypeCase).getStmt(), c)
|
||||
or
|
||||
result = last(cs.(ConstCase).getStmt(), c)
|
||||
or
|
||||
result = last(cs.(RecursivePatternCase).getStmt(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -1302,6 +1337,13 @@ module ControlFlow {
|
||||
result = last(tc.getVariableDeclExpr(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ControlFlowElement lastRecursivePatternCaseVariableDeclExpr(
|
||||
RecursivePatternCase tc, Completion c
|
||||
) {
|
||||
result = last(tc.getVariableDeclExpr(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ControlFlowElement lastLoopStmtCondition(LoopStmt ls, Completion c) {
|
||||
result = last(ls.getCondition(), c)
|
||||
@@ -1712,6 +1754,75 @@ module ControlFlow {
|
||||
result = first(tc.getStmt())
|
||||
)
|
||||
or
|
||||
exists(RecursivePatternCase tc |
|
||||
cfe = tc and
|
||||
result = tc.getTypeAccess() and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
// Preorder: From the case stmt:
|
||||
not exists(tc.getTypeAccess()) and
|
||||
cfe = tc and
|
||||
result = first(tc.getRecursivePattern()) and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
// Flow from type test (if exists) to recursive pattern
|
||||
cfe = tc.getTypeAccess() and
|
||||
result = first(tc.getRecursivePattern()) and
|
||||
c.isValidFor(cfe) and
|
||||
c = any(MatchingCompletion mc | mc.isMatch())
|
||||
or
|
||||
// Flow to the next case
|
||||
cfe = lastCaseNodeFailure(tc, c) and
|
||||
exists(SwitchStmt ss2, int i | tc = ss2.getCase(i) | result = first(ss2.getCase(i + 1)))
|
||||
or
|
||||
cfe = last(tc.getRecursivePattern(), _) and
|
||||
c.isValidFor(cfe) and
|
||||
c = any(MatchingCompletion mc |
|
||||
if mc.isMatch()
|
||||
then
|
||||
if exists(tc.getVariableDeclExpr())
|
||||
then
|
||||
// Flow from type test to first element of variable declaration
|
||||
result = first(tc.getVariableDeclExpr())
|
||||
else
|
||||
if exists(tc.getCondition())
|
||||
then
|
||||
// Flow from type test to first element of condition
|
||||
result = first(tc.getCondition())
|
||||
else
|
||||
// Flow from type test to first element of statement
|
||||
result = first(tc.getStmt())
|
||||
else
|
||||
// Flow from type test to first element of next case
|
||||
exists(SwitchStmt ss, int i | tc = ss.getCase(i) |
|
||||
result = first(ss.getCase(i + 1))
|
||||
)
|
||||
)
|
||||
or
|
||||
cfe = lastRecursivePatternCaseVariableDeclExpr(tc, c) and
|
||||
if exists(tc.getCondition())
|
||||
then
|
||||
// Flow from variable declaration to first element of condition
|
||||
result = first(tc.getCondition())
|
||||
else
|
||||
// Flow from variable declaration to first element of statement
|
||||
result = first(tc.getStmt())
|
||||
or
|
||||
cfe = lastTypeCaseVariableDeclExpr(tc, c) and
|
||||
if exists(tc.getCondition())
|
||||
then
|
||||
// Flow from variable declaration to first element of condition
|
||||
result = first(tc.getCondition())
|
||||
else
|
||||
// Flow from variable declaration to first element of statement
|
||||
result = first(tc.getStmt())
|
||||
or
|
||||
// Flow from condition to first element of statement
|
||||
cfe = lastCaseCondition(tc, c) and
|
||||
c instanceof TrueCompletion and
|
||||
result = first(tc.getStmt())
|
||||
)
|
||||
or
|
||||
exists(LoopStmt ls |
|
||||
// Flow from last element of condition to first element of loop body
|
||||
cfe = lastLoopStmtCondition(ls, c) and
|
||||
@@ -1954,6 +2065,28 @@ module ControlFlow {
|
||||
c instanceof NormalCompletion
|
||||
)
|
||||
)
|
||||
or
|
||||
switchExprSucc(_, cfe, result, c)
|
||||
}
|
||||
|
||||
/** Ways to leave a CaseStmt in the failure case. */
|
||||
ControlFlowElement lastCaseNodeFailure(CaseStmt cfe, Completion c) {
|
||||
c.isValidFor(result) and
|
||||
(
|
||||
c = any(MatchingCompletion m | not m.isMatch()) and
|
||||
(
|
||||
result = last(cfe.(ConstCase).getExpr(), _)
|
||||
or
|
||||
result = cfe.(RecursivePatternCase).getTypeAccess()
|
||||
or
|
||||
result = last(cfe.(RecursivePatternCase).getRecursivePattern(), c)
|
||||
or
|
||||
result = cfe.(TypeCase).getTypeAccess()
|
||||
)
|
||||
or
|
||||
c instanceof FalseCompletion and
|
||||
result = last(cfe.getCondition(), c)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1998,6 +2131,60 @@ module ControlFlow {
|
||||
cfe = last(result.getBody(), c) and
|
||||
not c instanceof GotoCompletion
|
||||
}
|
||||
|
||||
predicate switchExprSucc(
|
||||
SwitchExpr expr, ControlFlowElement a, ControlFlowElement b, Completion c
|
||||
) {
|
||||
a = expr and b = first(expr.getExpr()) and c instanceof SimpleCompletion
|
||||
or
|
||||
// Go to the first case
|
||||
a = last(expr.getExpr(), _) and b = first(expr.getCase(0)) and c instanceof SimpleCompletion
|
||||
or
|
||||
exists(SwitchCaseExpr case, int n | case = expr.getCase(n) |
|
||||
// Go to the pattern
|
||||
a = case and b = first(case.getPattern()) and c instanceof SimpleCompletion
|
||||
or
|
||||
// Pattern goes to result or condition
|
||||
a = last(case.getPattern(), _) and
|
||||
c = any(MatchingCompletion m | m.isMatch()) and
|
||||
(
|
||||
if exists(case.getCondition())
|
||||
then b = first(case.getCondition())
|
||||
else b = first(case.getResult())
|
||||
)
|
||||
or
|
||||
a = last(case.getCondition(), _) and
|
||||
b = first(case.getResult()) and
|
||||
c.(TrueCompletion).isValidFor(case.getCondition())
|
||||
or
|
||||
a = last(case.getCondition(), _) and
|
||||
b = expr.getCase(n + 1) and
|
||||
c.(FalseCompletion).isValidFor(case.getCondition())
|
||||
or
|
||||
a = last(case.getPattern(), _) and
|
||||
b = expr.getCase(n + 1) and
|
||||
c = any(MatchingCompletion m | not m.isMatch())
|
||||
)
|
||||
}
|
||||
|
||||
ControlFlowElement lastSwitchExpr(SwitchExpr e, Completion c) {
|
||||
result = last(e.getCase(_).getResult(), c)
|
||||
or
|
||||
exists(SwitchCaseExpr case, int i |
|
||||
case = e.getCase(i) and
|
||||
not e.getCase(i).matchesAll() and
|
||||
not exists(e.getCase(i + 1))
|
||||
|
|
||||
(
|
||||
result = case.getPattern() or
|
||||
result = last(case.getCondition(), _)
|
||||
) and
|
||||
c
|
||||
.(ThrowCompletion)
|
||||
.getExceptionClass()
|
||||
.hasQualifiedName("System.InvalidOperationException")
|
||||
)
|
||||
}
|
||||
}
|
||||
import Successor
|
||||
|
||||
|
||||
@@ -328,6 +328,8 @@ private predicate inBooleanContext(Expr e, boolean isBooleanCompletionForParent)
|
||||
or
|
||||
exists(CaseStmt cs | cs.getCondition() = e | isBooleanCompletionForParent = false)
|
||||
or
|
||||
exists(SwitchCaseExpr sce | sce.getCondition() = e | isBooleanCompletionForParent = false)
|
||||
or
|
||||
exists(SpecificCatchClause scc | scc.getFilterClause() = e | isBooleanCompletionForParent = false)
|
||||
or
|
||||
exists(LogicalNotExpr lne | lne.getAnOperand() = e |
|
||||
@@ -414,6 +416,10 @@ predicate switchMatching(SwitchStmt ss, CaseStmt cs, ControlFlowElement cfe) {
|
||||
cfe = cs.(ConstCase).getExpr()
|
||||
or
|
||||
cfe = cs.(TypeCase).getTypeAccess() // use type access to represent the type test
|
||||
or
|
||||
cfe = cs.(RecursivePatternCase).getTypeAccess() // use type access to represent the type test
|
||||
or
|
||||
cfe = cs.(RecursivePatternCase).getRecursivePattern() // a recursive pattern match
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -251,7 +251,8 @@ class UncheckedExpr extends Expr, @unchecked_expr {
|
||||
|
||||
/**
|
||||
* An `is` expression.
|
||||
* Either an `is` type expression (`IsTypeExpr`) or an `is` constant expression (`IsConstantExpr`).
|
||||
* Either an `is` type expression (`IsTypeExpr`), an `is` constant expression (`IsConstantExpr`),
|
||||
* or an `is` recursive pattern expression (`IsPatternExpr`).
|
||||
*/
|
||||
class IsExpr extends Expr, @is_expr {
|
||||
/**
|
||||
@@ -262,9 +263,7 @@ class IsExpr extends Expr, @is_expr {
|
||||
override string toString() { result = "... is ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `is` type expression, for example, `x is string` or `x is string s`.
|
||||
*/
|
||||
/** An `is` type expression, for example, `x is string` or `x is string s`. */
|
||||
class IsTypeExpr extends IsExpr {
|
||||
TypeAccess typeAccess;
|
||||
|
||||
@@ -283,19 +282,148 @@ class IsTypeExpr extends IsExpr {
|
||||
TypeAccess getTypeAccess() { result = typeAccess }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `is` pattern expression, for example `x is string s`.
|
||||
*/
|
||||
class IsPatternExpr extends IsTypeExpr {
|
||||
/** An `is` pattern expression, for example `x is string s`. */
|
||||
class IsPatternExpr extends IsExpr {
|
||||
LocalVariableDeclExpr typeDecl;
|
||||
|
||||
IsPatternExpr() { typeDecl = this.getChild(2) }
|
||||
IsPatternExpr() { typeDecl = this.getChild(2) and not this instanceof IsRecursivePatternExpr }
|
||||
|
||||
/**
|
||||
* Gets the local variable declaration in this `is` pattern expression.
|
||||
* For example `string s` in `x is string s`.
|
||||
*/
|
||||
LocalVariableDeclExpr getVariableDeclExpr() { result = typeDecl }
|
||||
|
||||
/**
|
||||
* Gets the type being accessed in this `is` expression, for example `string`
|
||||
* in `x is string`.
|
||||
*/
|
||||
Type getCheckedType() { result = getTypeAccess().getTarget() }
|
||||
|
||||
/**
|
||||
* Gets the type access in this `is` expression, for example `string` in
|
||||
* `x is string`.
|
||||
*/
|
||||
TypeAccess getTypeAccess() { result = this.getChild(1) }
|
||||
}
|
||||
|
||||
/** An `is` recursive pattern expression, for example `x is string { Length: 5 } s`. */
|
||||
class IsRecursivePatternExpr extends IsExpr {
|
||||
RecursivePatternExpr recursivePattern;
|
||||
|
||||
IsRecursivePatternExpr() { recursivePattern = this.getChild(4) }
|
||||
|
||||
override string toString() { result = "... is { ... }" }
|
||||
|
||||
/**
|
||||
* Gets the local variable declaration in this `is` pattern expression, if any.
|
||||
* For example `s` in `x is string { Length: 0 } s`.
|
||||
*/
|
||||
LocalVariableDeclExpr getVariableDeclExpr() { result = this.getChild(2) }
|
||||
|
||||
/**
|
||||
* Gets the recursive pattern of this `is` pattern expression. For example,
|
||||
* `{ Length: 5 }` in `x is string { Length: 5 } s`.
|
||||
*/
|
||||
RecursivePatternExpr getRecursivePattern() { result = recursivePattern }
|
||||
}
|
||||
|
||||
/**
|
||||
* A recursive pattern expression, for example `string { Length: 5 } s`
|
||||
*/
|
||||
class RecursivePatternExpr extends Expr, @recursive_pattern_expr {
|
||||
override string toString() { result = "{ ... }" }
|
||||
|
||||
/**
|
||||
* Gets the position patterns of this recursive pattern, if any.
|
||||
* For example, `(1,_)`.
|
||||
*/
|
||||
PositionalPatternExpr getPositionalPatterns() { result = this.getChild(2) }
|
||||
|
||||
/**
|
||||
* Gets the property patterns of this recursive pattern, if any.
|
||||
* For example,
|
||||
* `{ Length: 5 }` in `o is string { Length: 5 } s`
|
||||
*/
|
||||
PropertyPatternExpr getPropertyPatterns() { result = this.getChild(3) }
|
||||
|
||||
/**
|
||||
* Gets the type access of this recursive pattern, if any.
|
||||
* For example, `string` in `string { Length: 5 }`
|
||||
*/
|
||||
TypeAccess getTypeAccess() { result = this.getChild(1) }
|
||||
|
||||
/**
|
||||
* Gets the local variable declaration of this recursive pattern, if any.
|
||||
* For example, `s` in `string { Length: 5 } s`.
|
||||
*/
|
||||
LocalVariableDeclExpr getVariableDeclExpr() { result = this.getChild(0) }
|
||||
}
|
||||
|
||||
/** A property pattern. For example, `{Length: 5}`. */
|
||||
class PropertyPatternExpr extends Expr, @property_pattern_expr {
|
||||
override string toString() { result = "{ ... }" }
|
||||
|
||||
/** Gets the `n`th pattern. */
|
||||
Expr getPattern(int n) { result = this.getChild(n) }
|
||||
}
|
||||
|
||||
/** A property pattern. For example, `(int x, int y)`. */
|
||||
class PositionalPatternExpr extends Expr, @positional_pattern_expr {
|
||||
override string toString() { result = "( ... )" }
|
||||
|
||||
/** Gets the `n`th pattern. */
|
||||
Expr getPattern(int n) { result = this.getChild(n) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `switch` expression, for example
|
||||
* ```
|
||||
* (a,b) switch {
|
||||
* (false, false) => true,
|
||||
* _ => false
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
class SwitchExpr extends Expr, @switch_expr {
|
||||
override string toString() { result = "... switch { ... }" }
|
||||
|
||||
/** Gets the expression being switched. For example `x` in `x switch { ... }`. */
|
||||
Expr getExpr() { result = this.getChild(-1) }
|
||||
|
||||
/** Gets the `n`th case of this switch expression. */
|
||||
SwitchCaseExpr getCase(int n) { result = this.getChild(n) }
|
||||
}
|
||||
|
||||
/** An arm of a switch expression, for example `(false, false) => true`. */
|
||||
class SwitchCaseExpr extends Expr, @switch_case_expr {
|
||||
override string toString() { result = "... => ..." }
|
||||
|
||||
/**
|
||||
* Gets the pattern or matched expression in a switch arm, for example `(false, false)` in
|
||||
* `(false, false) => true`.
|
||||
*/
|
||||
Expr getPattern() { result = this.getChild(0) }
|
||||
|
||||
/**
|
||||
* Gets the `when` expression in a switch arm, if any.
|
||||
* For example `s.Length<10` in `string s when s.Length<10 => s`.
|
||||
*/
|
||||
Expr getCondition() { result = this.getChild(1) }
|
||||
|
||||
/**
|
||||
* Gets the result of a switch arm, for example `true` in
|
||||
* `(false, false) => true`.
|
||||
*/
|
||||
Expr getResult() { result = this.getChild(2) }
|
||||
|
||||
/** Holds if this case expression matches all expressions. */
|
||||
predicate matchesAll() {
|
||||
// Note: There may be other cases as well.
|
||||
// For example `(1,2) switch { (int x, int y) => x+y }`
|
||||
// would match all cases due to the type of the expression.
|
||||
getPattern() instanceof DiscardExpr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -975,8 +975,14 @@ case @expr.kind of
|
||||
| 109 = @local_function_invocation_expr
|
||||
| 110 = @ref_expr
|
||||
| 111 = @discard_expr
|
||||
/* C# 8.0 */
|
||||
| 112 = @range_expr
|
||||
| 113 = @index_expr
|
||||
| 114 = @switch_expr
|
||||
| 115 = @recursive_pattern_expr
|
||||
| 116 = @property_pattern_expr
|
||||
| 117 = @positional_pattern_expr
|
||||
| 118 = @switch_case_expr
|
||||
;
|
||||
|
||||
@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
|
||||
|
||||
@@ -1240,8 +1240,10 @@
|
||||
| Switch.cs:46:9:52:9 | switch (...) {...} | Switch.cs:46:9:52:9 | switch (...) {...} |
|
||||
| Switch.cs:46:17:46:17 | access to parameter o | Switch.cs:46:17:46:17 | access to parameter o |
|
||||
| Switch.cs:48:13:48:23 | case Int32: | Switch.cs:48:13:48:23 | case Int32: |
|
||||
| Switch.cs:48:22:48:22 | _ | Switch.cs:48:22:48:22 | _ |
|
||||
| Switch.cs:49:17:49:22 | break; | Switch.cs:49:17:49:22 | break; |
|
||||
| Switch.cs:50:13:50:39 | case Boolean: | Switch.cs:50:13:50:39 | case Boolean: |
|
||||
| Switch.cs:50:23:50:23 | _ | Switch.cs:50:23:50:23 | _ |
|
||||
| Switch.cs:50:30:50:30 | access to parameter o | Switch.cs:50:30:50:30 | access to parameter o |
|
||||
| Switch.cs:50:30:50:38 | ... != ... | Switch.cs:50:30:50:30 | access to parameter o |
|
||||
| Switch.cs:50:35:50:38 | null | Switch.cs:50:35:50:38 | null |
|
||||
@@ -1262,6 +1264,7 @@
|
||||
| Switch.cs:68:17:68:25 | (...) ... | Switch.cs:68:25:68:25 | access to parameter s |
|
||||
| Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:25:68:25 | access to parameter s |
|
||||
| Switch.cs:70:13:70:24 | case Int32: | Switch.cs:70:13:70:24 | case Int32: |
|
||||
| Switch.cs:70:22:70:22 | _ | Switch.cs:70:22:70:22 | _ |
|
||||
| Switch.cs:71:15:71:20 | break; | Switch.cs:71:15:71:20 | break; |
|
||||
| Switch.cs:72:13:72:21 | case ...: | Switch.cs:72:13:72:21 | case ...: |
|
||||
| Switch.cs:72:18:72:19 | "" | Switch.cs:72:18:72:19 | "" |
|
||||
@@ -1288,6 +1291,7 @@
|
||||
| Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:93:9:97:9 | switch (...) {...} |
|
||||
| Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:93:17:93:17 | access to parameter o |
|
||||
| Switch.cs:95:13:95:24 | case Int32: | Switch.cs:95:13:95:24 | case Int32: |
|
||||
| Switch.cs:95:22:95:22 | _ | Switch.cs:95:22:95:22 | _ |
|
||||
| Switch.cs:96:15:96:26 | return ...; | Switch.cs:96:22:96:25 | true |
|
||||
| Switch.cs:96:22:96:25 | true | Switch.cs:96:22:96:25 | true |
|
||||
| Switch.cs:98:9:98:21 | return ...; | Switch.cs:98:16:98:20 | false |
|
||||
|
||||
@@ -1553,6 +1553,7 @@
|
||||
| Switch.cs:25:35:25:35 | access to local variable s | Switch.cs:25:35:25:35 | access to local variable s | normal |
|
||||
| Switch.cs:26:17:26:23 | return ...; | Switch.cs:26:17:26:23 | return ...; | return |
|
||||
| Switch.cs:27:13:27:39 | case Double d: | Switch.cs:27:18:27:23 | access to type Double | no-match |
|
||||
| Switch.cs:27:13:27:39 | case Double d: | Switch.cs:27:32:27:38 | call to method Throw | false/false |
|
||||
| Switch.cs:27:13:27:39 | case Double d: | Switch.cs:27:32:27:38 | call to method Throw | throw(Exception) |
|
||||
| Switch.cs:27:13:27:39 | case Double d: | Switch.cs:28:17:28:21 | Label: | normal |
|
||||
| Switch.cs:27:18:27:25 | Double d | Switch.cs:27:18:27:25 | Double d | normal |
|
||||
@@ -1579,10 +1580,12 @@
|
||||
| Switch.cs:46:17:46:17 | access to parameter o | Switch.cs:46:17:46:17 | access to parameter o | normal |
|
||||
| Switch.cs:48:13:48:23 | case Int32: | Switch.cs:48:18:48:20 | access to type Int32 | no-match |
|
||||
| Switch.cs:48:13:48:23 | case Int32: | Switch.cs:49:17:49:22 | break; | break |
|
||||
| Switch.cs:48:22:48:22 | _ | Switch.cs:48:22:48:22 | _ | normal |
|
||||
| Switch.cs:49:17:49:22 | break; | Switch.cs:49:17:49:22 | break; | break |
|
||||
| Switch.cs:50:13:50:39 | case Boolean: | Switch.cs:50:18:50:21 | access to type Boolean | no-match |
|
||||
| Switch.cs:50:13:50:39 | case Boolean: | Switch.cs:50:30:50:38 | ... != ... | false/false |
|
||||
| Switch.cs:50:13:50:39 | case Boolean: | Switch.cs:51:17:51:22 | break; | break |
|
||||
| Switch.cs:50:23:50:23 | _ | Switch.cs:50:23:50:23 | _ | normal |
|
||||
| Switch.cs:50:30:50:30 | access to parameter o | Switch.cs:50:30:50:30 | access to parameter o | normal |
|
||||
| Switch.cs:50:30:50:38 | ... != ... | Switch.cs:50:30:50:38 | ... != ... | false/false |
|
||||
| Switch.cs:50:30:50:38 | ... != ... | Switch.cs:50:30:50:38 | ... != ... | true/true |
|
||||
@@ -1612,6 +1615,7 @@
|
||||
| Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:25:68:25 | access to parameter s | normal |
|
||||
| Switch.cs:70:13:70:24 | case Int32: | Switch.cs:70:18:70:20 | access to type Int32 | no-match |
|
||||
| Switch.cs:70:13:70:24 | case Int32: | Switch.cs:71:15:71:20 | break; | break |
|
||||
| Switch.cs:70:22:70:22 | _ | Switch.cs:70:22:70:22 | _ | normal |
|
||||
| Switch.cs:71:15:71:20 | break; | Switch.cs:71:15:71:20 | break; | break |
|
||||
| Switch.cs:72:13:72:21 | case ...: | Switch.cs:72:18:72:19 | "" | no-match |
|
||||
| Switch.cs:72:13:72:21 | case ...: | Switch.cs:73:15:73:20 | break; | break |
|
||||
@@ -1655,6 +1659,7 @@
|
||||
| Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:93:17:93:17 | access to parameter o | normal |
|
||||
| Switch.cs:95:13:95:24 | case Int32: | Switch.cs:95:18:95:20 | access to type Int32 | no-match |
|
||||
| Switch.cs:95:13:95:24 | case Int32: | Switch.cs:96:15:96:26 | return ...; | return |
|
||||
| Switch.cs:95:22:95:22 | _ | Switch.cs:95:22:95:22 | _ | normal |
|
||||
| Switch.cs:96:15:96:26 | return ...; | Switch.cs:96:15:96:26 | return ...; | return |
|
||||
| Switch.cs:96:22:96:25 | true | Switch.cs:96:22:96:25 | true | normal |
|
||||
| Switch.cs:98:9:98:21 | return ...; | Switch.cs:98:9:98:21 | return ...; | return |
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
| CSharp7.cs:224:17:224:17 | _ | Double |
|
||||
| CSharp7.cs:224:28:224:28 | _ | Boolean |
|
||||
| CSharp7.cs:225:10:225:10 | _ | Int32 |
|
||||
| CSharp7.cs:267:25:267:25 | _ | null |
|
||||
|
||||
66
csharp/ql/test/library-tests/csharp8/ispatternflow.expected
Normal file
66
csharp/ql/test/library-tests/csharp8/ispatternflow.expected
Normal file
@@ -0,0 +1,66 @@
|
||||
| patterns.cs:5:10:5:19 | enter IsPatterns | patterns.cs:6:5:30:5 | {...} | semmle.label | successor |
|
||||
| patterns.cs:6:5:30:5 | {...} | patterns.cs:7:9:7:42 | ... ...; | semmle.label | successor |
|
||||
| patterns.cs:7:9:7:42 | ... ...; | patterns.cs:7:20:7:41 | object creation of type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:7:16:7:41 | Object o = ... | patterns.cs:9:9:11:9 | if (...) ... | semmle.label | successor |
|
||||
| patterns.cs:7:20:7:41 | (...) ... | patterns.cs:7:16:7:41 | Object o = ... | semmle.label | successor |
|
||||
| patterns.cs:7:20:7:41 | object creation of type MyStruct | patterns.cs:7:39:7:39 | 2 | semmle.label | successor |
|
||||
| patterns.cs:7:33:7:41 | { ..., ... } | patterns.cs:7:20:7:41 | (...) ... | semmle.label | successor |
|
||||
| patterns.cs:7:35:7:39 | ... = ... | patterns.cs:7:33:7:41 | { ..., ... } | semmle.label | successor |
|
||||
| patterns.cs:7:39:7:39 | 2 | patterns.cs:7:35:7:39 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:9:9:11:9 | if (...) ... | patterns.cs:9:13:9:13 | access to local variable o | semmle.label | successor |
|
||||
| patterns.cs:9:13:9:13 | access to local variable o | patterns.cs:9:18:9:29 | MyStruct ms1 | semmle.label | successor |
|
||||
| patterns.cs:9:13:9:29 | ... is ... | patterns.cs:10:9:11:9 | {...} | semmle.label | true |
|
||||
| patterns.cs:9:13:9:29 | ... is ... | patterns.cs:13:9:15:9 | if (...) ... | semmle.label | false |
|
||||
| patterns.cs:9:18:9:29 | MyStruct ms1 | patterns.cs:9:13:9:29 | ... is ... | semmle.label | successor |
|
||||
| patterns.cs:10:9:11:9 | {...} | patterns.cs:13:9:15:9 | if (...) ... | semmle.label | successor |
|
||||
| patterns.cs:13:9:15:9 | if (...) ... | patterns.cs:13:13:13:56 | ... && ... | semmle.label | successor |
|
||||
| patterns.cs:13:13:13:13 | access to local variable o | patterns.cs:13:18:13:40 | MyStruct s | semmle.label | successor |
|
||||
| patterns.cs:13:13:13:40 | ... is { ... } | patterns.cs:13:45:13:45 | access to local variable x | semmle.label | true |
|
||||
| patterns.cs:13:13:13:40 | ... is { ... } | patterns.cs:17:9:19:9 | if (...) ... | semmle.label | false |
|
||||
| patterns.cs:13:13:13:47 | ... && ... | patterns.cs:13:13:13:13 | access to local variable o | semmle.label | successor |
|
||||
| patterns.cs:13:13:13:56 | ... && ... | patterns.cs:13:13:13:47 | ... && ... | semmle.label | successor |
|
||||
| patterns.cs:13:18:13:40 | MyStruct s | patterns.cs:13:32:13:36 | Int32 x | semmle.label | successor |
|
||||
| patterns.cs:13:18:13:40 | { ... } | patterns.cs:13:13:13:40 | ... is { ... } | semmle.label | successor |
|
||||
| patterns.cs:13:27:13:38 | { ... } | patterns.cs:13:18:13:40 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:13:32:13:36 | Int32 x | patterns.cs:13:27:13:38 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:13:45:13:45 | access to local variable x | patterns.cs:13:47:13:47 | 4 | semmle.label | successor |
|
||||
| patterns.cs:13:45:13:47 | ... < ... | patterns.cs:13:52:13:52 | access to local variable s | semmle.label | true |
|
||||
| patterns.cs:13:45:13:47 | ... < ... | patterns.cs:17:9:19:9 | if (...) ... | semmle.label | false |
|
||||
| patterns.cs:13:47:13:47 | 4 | patterns.cs:13:45:13:47 | ... < ... | semmle.label | successor |
|
||||
| patterns.cs:13:52:13:52 | access to local variable s | patterns.cs:13:52:13:54 | access to property Y | semmle.label | successor |
|
||||
| patterns.cs:13:52:13:54 | access to property Y | patterns.cs:13:56:13:56 | 2 | semmle.label | successor |
|
||||
| patterns.cs:13:52:13:56 | ... < ... | patterns.cs:14:9:15:9 | {...} | semmle.label | true |
|
||||
| patterns.cs:13:52:13:56 | ... < ... | patterns.cs:17:9:19:9 | if (...) ... | semmle.label | false |
|
||||
| patterns.cs:13:56:13:56 | 2 | patterns.cs:13:52:13:56 | ... < ... | semmle.label | successor |
|
||||
| patterns.cs:14:9:15:9 | {...} | patterns.cs:17:9:19:9 | if (...) ... | semmle.label | successor |
|
||||
| patterns.cs:17:9:19:9 | if (...) ... | patterns.cs:17:13:17:13 | access to local variable o | semmle.label | successor |
|
||||
| patterns.cs:17:13:17:13 | access to local variable o | patterns.cs:17:18:17:21 | Object p | semmle.label | successor |
|
||||
| patterns.cs:17:13:17:21 | ... is { ... } | patterns.cs:18:9:19:9 | {...} | semmle.label | true |
|
||||
| patterns.cs:17:13:17:21 | ... is { ... } | patterns.cs:22:9:24:9 | if (...) ... | semmle.label | false |
|
||||
| patterns.cs:17:18:17:19 | { ... } | patterns.cs:17:18:17:21 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:17:18:17:21 | Object p | patterns.cs:17:18:17:19 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:17:18:17:21 | { ... } | patterns.cs:17:13:17:21 | ... is { ... } | semmle.label | successor |
|
||||
| patterns.cs:18:9:19:9 | {...} | patterns.cs:22:9:24:9 | if (...) ... | semmle.label | successor |
|
||||
| patterns.cs:22:9:24:9 | if (...) ... | patterns.cs:22:13:22:13 | access to local variable o | semmle.label | successor |
|
||||
| patterns.cs:22:13:22:13 | access to local variable o | patterns.cs:22:31:22:32 | 12 | semmle.label | successor |
|
||||
| patterns.cs:22:13:22:53 | ... is { ... } | patterns.cs:23:9:24:9 | {...} | semmle.label | true |
|
||||
| patterns.cs:22:13:22:53 | ... is { ... } | patterns.cs:27:9:29:9 | if (...) ... | semmle.label | false |
|
||||
| patterns.cs:22:18:22:53 | { ... } | patterns.cs:22:13:22:53 | ... is { ... } | semmle.label | successor |
|
||||
| patterns.cs:22:27:22:53 | { ... } | patterns.cs:22:18:22:53 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:22:31:22:32 | 12 | patterns.cs:22:42:22:49 | Int32 subX | semmle.label | successor |
|
||||
| patterns.cs:22:38:22:51 | { ... } | patterns.cs:22:27:22:53 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:22:38:22:51 | { ... } | patterns.cs:22:38:22:51 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:22:42:22:49 | Int32 subX | patterns.cs:22:38:22:51 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:23:9:24:9 | {...} | patterns.cs:27:9:29:9 | if (...) ... | semmle.label | successor |
|
||||
| patterns.cs:27:9:29:9 | if (...) ... | patterns.cs:27:13:27:13 | access to local variable o | semmle.label | successor |
|
||||
| patterns.cs:27:13:27:13 | access to local variable o | patterns.cs:27:31:27:32 | 12 | semmle.label | successor |
|
||||
| patterns.cs:27:13:27:58 | ... is { ... } | patterns.cs:5:10:5:19 | exit IsPatterns | semmle.label | false |
|
||||
| patterns.cs:27:13:27:58 | ... is { ... } | patterns.cs:28:9:29:9 | {...} | semmle.label | true |
|
||||
| patterns.cs:27:18:27:58 | { ... } | patterns.cs:27:13:27:58 | ... is { ... } | semmle.label | successor |
|
||||
| patterns.cs:27:27:27:58 | { ... } | patterns.cs:27:18:27:58 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:27:31:27:32 | 12 | patterns.cs:27:38:27:56 | MyStruct ms | semmle.label | successor |
|
||||
| patterns.cs:27:38:27:56 | MyStruct ms | patterns.cs:27:51:27:51 | _ | semmle.label | successor |
|
||||
| patterns.cs:27:38:27:56 | { ... } | patterns.cs:27:27:27:58 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:27:47:27:53 | { ... } | patterns.cs:27:38:27:56 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:27:51:27:51 | _ | patterns.cs:27:47:27:53 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:28:9:29:9 | {...} | patterns.cs:5:10:5:19 | exit IsPatterns | semmle.label | successor |
|
||||
10
csharp/ql/test/library-tests/csharp8/ispatternflow.ql
Normal file
10
csharp/ql/test/library-tests/csharp8/ispatternflow.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
import csharp
|
||||
|
||||
query predicate edges(ControlFlow::Node a, ControlFlow::Node b, string label, string value) {
|
||||
exists(ControlFlow::SuccessorType t |
|
||||
a.getEnclosingCallable().getName() = "IsPatterns" and
|
||||
b = a.getASuccessorByType(t) and
|
||||
label = "semmle.label" and
|
||||
value = t.toString()
|
||||
)
|
||||
}
|
||||
166
csharp/ql/test/library-tests/csharp8/patterns.cs
Normal file
166
csharp/ql/test/library-tests/csharp8/patterns.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
|
||||
class Patterns
|
||||
{
|
||||
void IsPatterns()
|
||||
{
|
||||
object o = new MyStruct { X = 2 };
|
||||
|
||||
if (o is MyStruct ms1)
|
||||
{
|
||||
}
|
||||
|
||||
if (o is MyStruct { X: int x } s && x<4 && s.Y<2)
|
||||
{
|
||||
}
|
||||
|
||||
if (o is {} p)
|
||||
{
|
||||
}
|
||||
|
||||
// A sub-pattern match
|
||||
if (o is MyStruct {X: 12, S: {X: var subX } })
|
||||
{
|
||||
}
|
||||
|
||||
// A sub-pattern match
|
||||
if (o is MyStruct {X: 12, S: MyStruct {X: _ } ms })
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchStatements()
|
||||
{
|
||||
var s = new MyStruct { X = 0 };
|
||||
|
||||
switch (s)
|
||||
{
|
||||
case MyStruct ms1 when ms1.X == 10:
|
||||
Console.WriteLine("Hit the breakpoint");
|
||||
break;
|
||||
case MyStruct ms2 when ms2.X < 10:
|
||||
Console.WriteLine("Missed the breakpoint");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (s)
|
||||
{
|
||||
case MyStruct { X: int x } when x > 2:
|
||||
Console.WriteLine(x);
|
||||
break;
|
||||
case MyStruct { X: 10 } ms:
|
||||
Console.WriteLine("Hit the breakpoint");
|
||||
break;
|
||||
case { X: int x2 } when x2 > 2:
|
||||
Console.WriteLine(x2);
|
||||
break;
|
||||
case (1, 2):
|
||||
break;
|
||||
case var (x, y):
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (s)
|
||||
{
|
||||
case MyStruct { X: int x } when x > 2:
|
||||
Console.WriteLine(x);
|
||||
break;
|
||||
case MyStruct { X: 10 } ms when s.X==0:
|
||||
Console.WriteLine("Hit the breakpoint");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch (new object())
|
||||
{
|
||||
case (int x, float y) when x<y:
|
||||
break;
|
||||
case ():
|
||||
break;
|
||||
case {}:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(1,2)
|
||||
{
|
||||
case (1, 2): break;
|
||||
}
|
||||
|
||||
switch((1,2))
|
||||
{
|
||||
case (1, var x): break;
|
||||
case (2, _): break;
|
||||
}
|
||||
}
|
||||
|
||||
void Expressions(int x)
|
||||
{
|
||||
var size = x switch {
|
||||
int y when y > 10 => "large",
|
||||
_ => "small"
|
||||
};
|
||||
|
||||
int x0 = 0, y0 = 0;
|
||||
|
||||
// Potential fall through
|
||||
var (x1, y1) = (x0, y0) switch
|
||||
{
|
||||
(0,1) => (1,0),
|
||||
(1,0) => (0,1)
|
||||
};
|
||||
|
||||
// No fall through
|
||||
(x1, y1) = (x0, y0) switch
|
||||
{
|
||||
(0,var y2) => (y2, 0),
|
||||
(var x2, 0) => (0, x2),
|
||||
(var x2, var y2) => (0, 0)
|
||||
};
|
||||
}
|
||||
|
||||
void Expressions2()
|
||||
{
|
||||
var s = new MyStruct { X = 0 };
|
||||
var r = s switch
|
||||
{
|
||||
MyStruct { X: int x } when x > 2 => 0,
|
||||
MyStruct { X: 10 } ms => 1,
|
||||
(1, 2) => 2,
|
||||
var (x, _) => 3
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
r = 0 switch
|
||||
{
|
||||
1 => throw new ArgumentException(),
|
||||
2 => 3,
|
||||
object y when y is {} => 4
|
||||
};
|
||||
}
|
||||
catch(InvalidOperationException ex)
|
||||
{
|
||||
Console.WriteLine("Invalid operation");
|
||||
}
|
||||
}
|
||||
|
||||
struct MyStruct
|
||||
{
|
||||
public int X;
|
||||
public int Y => 10;
|
||||
|
||||
public MyStruct S => this;
|
||||
|
||||
public void Deconstruct(out int x, out int y)
|
||||
{
|
||||
x = X;
|
||||
y = Y;
|
||||
}
|
||||
|
||||
public void Deconstruct()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
164
csharp/ql/test/library-tests/csharp8/patterns.expected
Normal file
164
csharp/ql/test/library-tests/csharp8/patterns.expected
Normal file
@@ -0,0 +1,164 @@
|
||||
switchExprs
|
||||
| patterns.cs:100:20:103:9 | ... switch { ... } | patterns.cs:100:20:100:20 | access to parameter x |
|
||||
| patterns.cs:108:24:112:9 | ... switch { ... } | patterns.cs:108:24:108:31 | (..., ...) |
|
||||
| patterns.cs:115:20:120:9 | ... switch { ... } | patterns.cs:115:20:115:27 | (..., ...) |
|
||||
| patterns.cs:126:17:132:9 | ... switch { ... } | patterns.cs:126:17:126:17 | access to local variable s |
|
||||
| patterns.cs:136:17:141:13 | ... switch { ... } | patterns.cs:136:17:136:17 | 0 |
|
||||
switchExprCases
|
||||
| patterns.cs:101:13:101:40 | ... => ... | patterns.cs:101:13:101:17 | Int32 y | patterns.cs:101:34:101:40 | "large" |
|
||||
| patterns.cs:102:13:102:24 | ... => ... | patterns.cs:102:13:102:13 | _ | patterns.cs:102:18:102:24 | "small" |
|
||||
| patterns.cs:110:13:110:26 | ... => ... | patterns.cs:110:13:110:17 | { ... } | patterns.cs:110:22:110:26 | (..., ...) |
|
||||
| patterns.cs:111:13:111:26 | ... => ... | patterns.cs:111:13:111:17 | { ... } | patterns.cs:111:22:111:26 | (..., ...) |
|
||||
| patterns.cs:117:13:117:33 | ... => ... | patterns.cs:117:13:117:22 | { ... } | patterns.cs:117:27:117:33 | (..., ...) |
|
||||
| patterns.cs:118:13:118:34 | ... => ... | patterns.cs:118:13:118:23 | { ... } | patterns.cs:118:28:118:34 | (..., ...) |
|
||||
| patterns.cs:119:13:119:38 | ... => ... | patterns.cs:119:13:119:28 | { ... } | patterns.cs:119:33:119:38 | (..., ...) |
|
||||
| patterns.cs:128:13:128:49 | ... => ... | patterns.cs:128:13:128:33 | { ... } | patterns.cs:128:49:128:49 | 0 |
|
||||
| patterns.cs:129:13:129:38 | ... => ... | patterns.cs:129:13:129:33 | { ... } | patterns.cs:129:38:129:38 | 1 |
|
||||
| patterns.cs:130:13:130:23 | ... => ... | patterns.cs:130:13:130:18 | { ... } | patterns.cs:130:23:130:23 | 2 |
|
||||
| patterns.cs:131:13:131:27 | ... => ... | patterns.cs:131:13:131:22 | (..., ...) | patterns.cs:131:27:131:27 | 3 |
|
||||
| patterns.cs:138:17:138:50 | ... => ... | patterns.cs:138:17:138:17 | 1 | patterns.cs:138:22:138:50 | throw ... |
|
||||
| patterns.cs:139:17:139:22 | ... => ... | patterns.cs:139:17:139:17 | 2 | patterns.cs:139:22:139:22 | 3 |
|
||||
| patterns.cs:140:17:140:42 | ... => ... | patterns.cs:140:17:140:24 | Object y | patterns.cs:140:42:140:42 | 4 |
|
||||
switchFilters
|
||||
| patterns.cs:101:13:101:40 | ... => ... | patterns.cs:101:24:101:29 | ... > ... |
|
||||
| patterns.cs:128:13:128:49 | ... => ... | patterns.cs:128:40:128:44 | ... > ... |
|
||||
| patterns.cs:140:17:140:42 | ... => ... | patterns.cs:140:31:140:37 | ... is { ... } |
|
||||
propertyPatterns
|
||||
| patterns.cs:13:27:13:38 | { ... } |
|
||||
| patterns.cs:17:18:17:19 | { ... } |
|
||||
| patterns.cs:22:27:22:53 | { ... } |
|
||||
| patterns.cs:22:38:22:51 | { ... } |
|
||||
| patterns.cs:27:27:27:58 | { ... } |
|
||||
| patterns.cs:27:47:27:53 | { ... } |
|
||||
| patterns.cs:48:27:48:38 | { ... } |
|
||||
| patterns.cs:51:27:51:35 | { ... } |
|
||||
| patterns.cs:54:18:54:30 | { ... } |
|
||||
| patterns.cs:67:27:67:38 | { ... } |
|
||||
| patterns.cs:70:27:70:35 | { ... } |
|
||||
| patterns.cs:82:18:82:19 | { ... } |
|
||||
| patterns.cs:128:22:128:33 | { ... } |
|
||||
| patterns.cs:129:22:129:30 | { ... } |
|
||||
| patterns.cs:140:36:140:37 | { ... } |
|
||||
propertyPatternChild
|
||||
| patterns.cs:13:27:13:38 | { ... } | 0 | patterns.cs:13:32:13:36 | Int32 x |
|
||||
| patterns.cs:22:27:22:53 | { ... } | 0 | patterns.cs:22:31:22:32 | 12 |
|
||||
| patterns.cs:22:27:22:53 | { ... } | 1 | patterns.cs:22:38:22:51 | { ... } |
|
||||
| patterns.cs:22:38:22:51 | { ... } | 0 | patterns.cs:22:42:22:49 | Int32 subX |
|
||||
| patterns.cs:27:27:27:58 | { ... } | 0 | patterns.cs:27:31:27:32 | 12 |
|
||||
| patterns.cs:27:27:27:58 | { ... } | 1 | patterns.cs:27:38:27:56 | { ... } |
|
||||
| patterns.cs:27:47:27:53 | { ... } | 0 | patterns.cs:27:51:27:51 | _ |
|
||||
| patterns.cs:48:27:48:38 | { ... } | 0 | patterns.cs:48:32:48:36 | Int32 x |
|
||||
| patterns.cs:51:27:51:35 | { ... } | 0 | patterns.cs:51:32:51:33 | 10 |
|
||||
| patterns.cs:54:18:54:30 | { ... } | 0 | patterns.cs:54:23:54:28 | Int32 x2 |
|
||||
| patterns.cs:67:27:67:38 | { ... } | 0 | patterns.cs:67:32:67:36 | Int32 x |
|
||||
| patterns.cs:70:27:70:35 | { ... } | 0 | patterns.cs:70:32:70:33 | 10 |
|
||||
| patterns.cs:128:22:128:33 | { ... } | 0 | patterns.cs:128:27:128:31 | Int32 x |
|
||||
| patterns.cs:129:22:129:30 | { ... } | 0 | patterns.cs:129:27:129:28 | 10 |
|
||||
positionalPatterns
|
||||
| patterns.cs:57:18:57:23 | ( ... ) | patterns.cs:57:18:57:23 | { ... } | 0 | patterns.cs:57:19:57:19 | 1 |
|
||||
| patterns.cs:57:18:57:23 | ( ... ) | patterns.cs:57:18:57:23 | { ... } | 1 | patterns.cs:57:22:57:22 | 2 |
|
||||
| patterns.cs:78:18:78:33 | ( ... ) | patterns.cs:78:18:78:33 | { ... } | 0 | patterns.cs:78:19:78:23 | Int32 x |
|
||||
| patterns.cs:78:18:78:33 | ( ... ) | patterns.cs:78:18:78:33 | { ... } | 1 | patterns.cs:78:26:78:32 | Single y |
|
||||
| patterns.cs:88:18:88:23 | ( ... ) | patterns.cs:88:18:88:23 | { ... } | 0 | patterns.cs:88:19:88:19 | 1 |
|
||||
| patterns.cs:88:18:88:23 | ( ... ) | patterns.cs:88:18:88:23 | { ... } | 1 | patterns.cs:88:22:88:22 | 2 |
|
||||
| patterns.cs:93:18:93:27 | ( ... ) | patterns.cs:93:18:93:27 | { ... } | 0 | patterns.cs:93:19:93:19 | 1 |
|
||||
| patterns.cs:93:18:93:27 | ( ... ) | patterns.cs:93:18:93:27 | { ... } | 1 | patterns.cs:93:22:93:26 | Int32 x |
|
||||
| patterns.cs:94:18:94:23 | ( ... ) | patterns.cs:94:18:94:23 | { ... } | 0 | patterns.cs:94:19:94:19 | 2 |
|
||||
| patterns.cs:94:18:94:23 | ( ... ) | patterns.cs:94:18:94:23 | { ... } | 1 | patterns.cs:94:22:94:22 | _ |
|
||||
| patterns.cs:110:13:110:17 | ( ... ) | patterns.cs:110:13:110:17 | { ... } | 0 | patterns.cs:110:14:110:14 | 0 |
|
||||
| patterns.cs:110:13:110:17 | ( ... ) | patterns.cs:110:13:110:17 | { ... } | 1 | patterns.cs:110:16:110:16 | 1 |
|
||||
| patterns.cs:111:13:111:17 | ( ... ) | patterns.cs:111:13:111:17 | { ... } | 0 | patterns.cs:111:14:111:14 | 1 |
|
||||
| patterns.cs:111:13:111:17 | ( ... ) | patterns.cs:111:13:111:17 | { ... } | 1 | patterns.cs:111:16:111:16 | 0 |
|
||||
| patterns.cs:117:13:117:22 | ( ... ) | patterns.cs:117:13:117:22 | { ... } | 0 | patterns.cs:117:14:117:14 | 0 |
|
||||
| patterns.cs:117:13:117:22 | ( ... ) | patterns.cs:117:13:117:22 | { ... } | 1 | patterns.cs:117:16:117:21 | Int32 y2 |
|
||||
| patterns.cs:118:13:118:23 | ( ... ) | patterns.cs:118:13:118:23 | { ... } | 0 | patterns.cs:118:14:118:19 | Int32 x2 |
|
||||
| patterns.cs:118:13:118:23 | ( ... ) | patterns.cs:118:13:118:23 | { ... } | 1 | patterns.cs:118:22:118:22 | 0 |
|
||||
| patterns.cs:119:13:119:28 | ( ... ) | patterns.cs:119:13:119:28 | { ... } | 0 | patterns.cs:119:14:119:19 | Int32 x2 |
|
||||
| patterns.cs:119:13:119:28 | ( ... ) | patterns.cs:119:13:119:28 | { ... } | 1 | patterns.cs:119:22:119:27 | Int32 y2 |
|
||||
| patterns.cs:130:13:130:18 | ( ... ) | patterns.cs:130:13:130:18 | { ... } | 0 | patterns.cs:130:14:130:14 | 1 |
|
||||
| patterns.cs:130:13:130:18 | ( ... ) | patterns.cs:130:13:130:18 | { ... } | 1 | patterns.cs:130:17:130:17 | 2 |
|
||||
caseStatements
|
||||
| patterns.cs:38:13:38:47 | case MyStruct ms1: |
|
||||
| patterns.cs:41:13:41:46 | case MyStruct ms2: |
|
||||
| patterns.cs:48:13:48:50 | case { ... }: |
|
||||
| patterns.cs:51:13:51:39 | case { ... }: |
|
||||
| patterns.cs:54:13:54:43 | case { ... }: |
|
||||
| patterns.cs:57:13:57:24 | case { ... }: |
|
||||
| patterns.cs:59:13:59:28 | case ...: |
|
||||
| patterns.cs:61:13:61:20 | default: |
|
||||
| patterns.cs:67:13:67:50 | case { ... }: |
|
||||
| patterns.cs:70:13:70:51 | case { ... }: |
|
||||
| patterns.cs:78:13:78:43 | case { ... }: |
|
||||
| patterns.cs:80:13:80:20 | case { ... }: |
|
||||
| patterns.cs:82:13:82:20 | case { ... }: |
|
||||
| patterns.cs:88:13:88:24 | case { ... }: |
|
||||
| patterns.cs:93:13:93:28 | case { ... }: |
|
||||
| patterns.cs:94:13:94:24 | case { ... }: |
|
||||
recursivePatternCases
|
||||
| patterns.cs:48:13:48:50 | case { ... }: | patterns.cs:48:18:48:38 | { ... } |
|
||||
| patterns.cs:51:13:51:39 | case { ... }: | patterns.cs:51:18:51:38 | { ... } |
|
||||
| patterns.cs:54:13:54:43 | case { ... }: | patterns.cs:54:18:54:30 | { ... } |
|
||||
| patterns.cs:57:13:57:24 | case { ... }: | patterns.cs:57:18:57:23 | { ... } |
|
||||
| patterns.cs:67:13:67:50 | case { ... }: | patterns.cs:67:18:67:38 | { ... } |
|
||||
| patterns.cs:70:13:70:51 | case { ... }: | patterns.cs:70:18:70:38 | { ... } |
|
||||
| patterns.cs:78:13:78:43 | case { ... }: | patterns.cs:78:18:78:33 | { ... } |
|
||||
| patterns.cs:80:13:80:20 | case { ... }: | patterns.cs:80:18:80:19 | { ... } |
|
||||
| patterns.cs:82:13:82:20 | case { ... }: | patterns.cs:82:18:82:19 | { ... } |
|
||||
| patterns.cs:88:13:88:24 | case { ... }: | patterns.cs:88:18:88:23 | { ... } |
|
||||
| patterns.cs:93:13:93:28 | case { ... }: | patterns.cs:93:18:93:27 | { ... } |
|
||||
| patterns.cs:94:13:94:24 | case { ... }: | patterns.cs:94:18:94:23 | { ... } |
|
||||
recursiveCasePatternDecl
|
||||
| patterns.cs:51:13:51:39 | case { ... }: | patterns.cs:51:18:51:25 | access to type MyStruct | patterns.cs:51:18:51:38 | MyStruct ms |
|
||||
| patterns.cs:70:13:70:51 | case { ... }: | patterns.cs:70:18:70:25 | access to type MyStruct | patterns.cs:70:18:70:38 | MyStruct ms |
|
||||
recursivePatternDecl
|
||||
| patterns.cs:27:38:27:56 | { ... } | patterns.cs:27:38:27:56 | MyStruct ms |
|
||||
| patterns.cs:129:13:129:33 | { ... } | patterns.cs:129:13:129:33 | MyStruct ms |
|
||||
recursivePatterns
|
||||
| patterns.cs:13:18:13:40 | { ... } |
|
||||
| patterns.cs:17:18:17:21 | { ... } |
|
||||
| patterns.cs:22:18:22:53 | { ... } |
|
||||
| patterns.cs:22:38:22:51 | { ... } |
|
||||
| patterns.cs:27:18:27:58 | { ... } |
|
||||
| patterns.cs:27:38:27:56 | { ... } |
|
||||
| patterns.cs:48:18:48:38 | { ... } |
|
||||
| patterns.cs:51:18:51:38 | { ... } |
|
||||
| patterns.cs:54:18:54:30 | { ... } |
|
||||
| patterns.cs:57:18:57:23 | { ... } |
|
||||
| patterns.cs:67:18:67:38 | { ... } |
|
||||
| patterns.cs:70:18:70:38 | { ... } |
|
||||
| patterns.cs:78:18:78:33 | { ... } |
|
||||
| patterns.cs:80:18:80:19 | { ... } |
|
||||
| patterns.cs:82:18:82:19 | { ... } |
|
||||
| patterns.cs:88:18:88:23 | { ... } |
|
||||
| patterns.cs:93:18:93:27 | { ... } |
|
||||
| patterns.cs:94:18:94:23 | { ... } |
|
||||
| patterns.cs:110:13:110:17 | { ... } |
|
||||
| patterns.cs:111:13:111:17 | { ... } |
|
||||
| patterns.cs:117:13:117:22 | { ... } |
|
||||
| patterns.cs:118:13:118:23 | { ... } |
|
||||
| patterns.cs:119:13:119:28 | { ... } |
|
||||
| patterns.cs:128:13:128:33 | { ... } |
|
||||
| patterns.cs:129:13:129:33 | { ... } |
|
||||
| patterns.cs:130:13:130:18 | { ... } |
|
||||
| patterns.cs:140:36:140:37 | { ... } |
|
||||
discards
|
||||
| patterns.cs:27:51:27:51 | _ |
|
||||
| patterns.cs:94:22:94:22 | _ |
|
||||
| patterns.cs:102:13:102:13 | _ |
|
||||
| patterns.cs:131:21:131:21 | _ |
|
||||
isExprs
|
||||
| patterns.cs:9:13:9:29 | ... is ... |
|
||||
| patterns.cs:13:13:13:40 | ... is { ... } |
|
||||
| patterns.cs:17:13:17:21 | ... is { ... } |
|
||||
| patterns.cs:22:13:22:53 | ... is { ... } |
|
||||
| patterns.cs:27:13:27:58 | ... is { ... } |
|
||||
| patterns.cs:140:31:140:37 | ... is { ... } |
|
||||
isRecursivePatternExpr
|
||||
| patterns.cs:13:13:13:40 | ... is { ... } |
|
||||
| patterns.cs:17:13:17:21 | ... is { ... } |
|
||||
| patterns.cs:22:13:22:53 | ... is { ... } |
|
||||
| patterns.cs:27:13:27:58 | ... is { ... } |
|
||||
| patterns.cs:140:31:140:37 | ... is { ... } |
|
||||
isRecursivePatternExprWithDecl
|
||||
| patterns.cs:13:13:13:40 | ... is { ... } | patterns.cs:13:18:13:40 | MyStruct s |
|
||||
| patterns.cs:17:13:17:21 | ... is { ... } | patterns.cs:17:18:17:21 | Object p |
|
||||
50
csharp/ql/test/library-tests/csharp8/patterns.ql
Normal file
50
csharp/ql/test/library-tests/csharp8/patterns.ql
Normal file
@@ -0,0 +1,50 @@
|
||||
import csharp
|
||||
|
||||
query predicate switchExprs(SwitchExpr switch, Expr e) { e = switch.getExpr() }
|
||||
|
||||
query predicate switchExprCases(SwitchCaseExpr case, Expr pattern, Expr res) {
|
||||
pattern = case.getPattern() and res = case.getResult()
|
||||
}
|
||||
|
||||
query predicate switchFilters(SwitchCaseExpr case, Expr when) { when = case.getCondition() }
|
||||
|
||||
query predicate propertyPatterns(PropertyPatternExpr pp) { any() }
|
||||
|
||||
query predicate propertyPatternChild(PropertyPatternExpr pp, int n, Expr child) {
|
||||
child = pp.getPattern(n)
|
||||
}
|
||||
|
||||
query predicate positionalPatterns(PositionalPatternExpr pp, Expr parent, int n, Expr child) {
|
||||
parent = pp.getParent() and
|
||||
child = pp.getPattern(n)
|
||||
}
|
||||
|
||||
query predicate caseStatements(CaseStmt case) { any() }
|
||||
|
||||
query predicate recursivePatternCases(RecursivePatternCase case, RecursivePatternExpr p) {
|
||||
p = case.getRecursivePattern()
|
||||
}
|
||||
|
||||
query predicate recursiveCasePatternDecl(
|
||||
RecursivePatternCase case, TypeAccess ta, LocalVariableDeclExpr decl
|
||||
) {
|
||||
ta = case.getTypeAccess() and decl = case.getVariableDeclExpr()
|
||||
}
|
||||
|
||||
query predicate recursivePatternDecl(RecursivePatternExpr pattern, LocalVariableDeclExpr decl) {
|
||||
decl = pattern.getVariableDeclExpr()
|
||||
}
|
||||
|
||||
query predicate recursivePatterns(RecursivePatternExpr expr) { any() }
|
||||
|
||||
query predicate discards(DiscardExpr discard) { any() }
|
||||
|
||||
query predicate isExprs(IsExpr is) { any() }
|
||||
|
||||
query predicate isRecursivePatternExpr(IsRecursivePatternExpr expr) { any() }
|
||||
|
||||
query predicate isRecursivePatternExprWithDecl(
|
||||
IsRecursivePatternExpr expr, LocalVariableDeclExpr decl
|
||||
) {
|
||||
decl = expr.getVariableDeclExpr()
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
| patterns.cs:98:10:98:20 | enter Expressions | patterns.cs:99:5:121:5 | {...} | semmle.label | successor |
|
||||
| patterns.cs:99:5:121:5 | {...} | patterns.cs:100:9:103:10 | ... ...; | semmle.label | successor |
|
||||
| patterns.cs:100:9:103:10 | ... ...; | patterns.cs:100:20:103:9 | ... switch { ... } | semmle.label | successor |
|
||||
| patterns.cs:100:13:103:9 | String size = ... | patterns.cs:105:9:105:27 | ... ...; | semmle.label | successor |
|
||||
| patterns.cs:100:20:100:20 | access to parameter x | patterns.cs:101:13:101:40 | ... => ... | semmle.label | successor |
|
||||
| patterns.cs:100:20:103:9 | ... switch { ... } | patterns.cs:100:20:100:20 | access to parameter x | semmle.label | successor |
|
||||
| patterns.cs:101:13:101:17 | Int32 y | patterns.cs:101:24:101:24 | access to local variable y | semmle.label | match |
|
||||
| patterns.cs:101:13:101:17 | Int32 y | patterns.cs:102:13:102:24 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:101:13:101:40 | ... => ... | patterns.cs:101:13:101:17 | Int32 y | semmle.label | successor |
|
||||
| patterns.cs:101:24:101:24 | access to local variable y | patterns.cs:101:28:101:29 | 10 | semmle.label | successor |
|
||||
| patterns.cs:101:24:101:29 | ... > ... | patterns.cs:101:34:101:40 | "large" | semmle.label | true |
|
||||
| patterns.cs:101:24:101:29 | ... > ... | patterns.cs:102:13:102:24 | ... => ... | semmle.label | false |
|
||||
| patterns.cs:101:28:101:29 | 10 | patterns.cs:101:24:101:29 | ... > ... | semmle.label | successor |
|
||||
| patterns.cs:101:34:101:40 | "large" | patterns.cs:100:13:103:9 | String size = ... | semmle.label | successor |
|
||||
| patterns.cs:102:13:102:13 | _ | patterns.cs:102:18:102:24 | "small" | semmle.label | match |
|
||||
| patterns.cs:102:13:102:24 | ... => ... | patterns.cs:102:13:102:13 | _ | semmle.label | successor |
|
||||
| patterns.cs:102:18:102:24 | "small" | patterns.cs:100:13:103:9 | String size = ... | semmle.label | successor |
|
||||
| patterns.cs:105:9:105:27 | ... ...; | patterns.cs:105:18:105:18 | 0 | semmle.label | successor |
|
||||
| patterns.cs:105:13:105:18 | Int32 x0 = ... | patterns.cs:105:26:105:26 | 0 | semmle.label | successor |
|
||||
| patterns.cs:105:18:105:18 | 0 | patterns.cs:105:13:105:18 | Int32 x0 = ... | semmle.label | successor |
|
||||
| patterns.cs:105:21:105:26 | Int32 y0 = ... | patterns.cs:108:9:112:10 | ...; | semmle.label | successor |
|
||||
| patterns.cs:105:26:105:26 | 0 | patterns.cs:105:21:105:26 | Int32 y0 = ... | semmle.label | successor |
|
||||
| patterns.cs:108:9:108:20 | (..., ...) | patterns.cs:108:24:112:9 | ... switch { ... } | semmle.label | successor |
|
||||
| patterns.cs:108:9:112:9 | ... = ... | patterns.cs:115:9:120:10 | ...; | semmle.label | successor |
|
||||
| patterns.cs:108:9:112:10 | ...; | patterns.cs:108:14:108:15 | Int32 x1 | semmle.label | successor |
|
||||
| patterns.cs:108:14:108:15 | Int32 x1 | patterns.cs:108:18:108:19 | Int32 y1 | semmle.label | successor |
|
||||
| patterns.cs:108:18:108:19 | Int32 y1 | patterns.cs:108:9:108:20 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:108:24:108:31 | (..., ...) | patterns.cs:110:13:110:26 | ... => ... | semmle.label | successor |
|
||||
| patterns.cs:108:24:112:9 | ... switch { ... } | patterns.cs:108:25:108:26 | access to local variable x0 | semmle.label | successor |
|
||||
| patterns.cs:108:25:108:26 | access to local variable x0 | patterns.cs:108:29:108:30 | access to local variable y0 | semmle.label | successor |
|
||||
| patterns.cs:108:29:108:30 | access to local variable y0 | patterns.cs:108:24:108:31 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:110:13:110:17 | ( ... ) | patterns.cs:110:13:110:17 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:110:13:110:17 | { ... } | patterns.cs:110:23:110:23 | 1 | semmle.label | match |
|
||||
| patterns.cs:110:13:110:17 | { ... } | patterns.cs:111:13:111:26 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:110:13:110:26 | ... => ... | patterns.cs:110:14:110:14 | 0 | semmle.label | successor |
|
||||
| patterns.cs:110:14:110:14 | 0 | patterns.cs:110:16:110:16 | 1 | semmle.label | successor |
|
||||
| patterns.cs:110:16:110:16 | 1 | patterns.cs:110:13:110:17 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:110:22:110:26 | (..., ...) | patterns.cs:108:9:112:9 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:110:23:110:23 | 1 | patterns.cs:110:25:110:25 | 0 | semmle.label | successor |
|
||||
| patterns.cs:110:25:110:25 | 0 | patterns.cs:110:22:110:26 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:111:13:111:17 | ( ... ) | patterns.cs:111:13:111:17 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:111:13:111:17 | { ... } | patterns.cs:98:10:98:20 | exit Expressions | semmle.label | exception(InvalidOperationException) |
|
||||
| patterns.cs:111:13:111:17 | { ... } | patterns.cs:111:23:111:23 | 0 | semmle.label | match |
|
||||
| patterns.cs:111:13:111:26 | ... => ... | patterns.cs:111:14:111:14 | 1 | semmle.label | successor |
|
||||
| patterns.cs:111:14:111:14 | 1 | patterns.cs:111:16:111:16 | 0 | semmle.label | successor |
|
||||
| patterns.cs:111:16:111:16 | 0 | patterns.cs:111:13:111:17 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:111:22:111:26 | (..., ...) | patterns.cs:108:9:112:9 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:111:23:111:23 | 0 | patterns.cs:111:25:111:25 | 1 | semmle.label | successor |
|
||||
| patterns.cs:111:25:111:25 | 1 | patterns.cs:111:22:111:26 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:115:9:115:16 | (..., ...) | patterns.cs:115:20:120:9 | ... switch { ... } | semmle.label | successor |
|
||||
| patterns.cs:115:9:120:9 | ... = ... | patterns.cs:98:10:98:20 | exit Expressions | semmle.label | successor |
|
||||
| patterns.cs:115:9:120:10 | ...; | patterns.cs:115:9:115:16 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:115:20:115:27 | (..., ...) | patterns.cs:117:13:117:33 | ... => ... | semmle.label | successor |
|
||||
| patterns.cs:115:20:120:9 | ... switch { ... } | patterns.cs:115:21:115:22 | access to local variable x0 | semmle.label | successor |
|
||||
| patterns.cs:115:21:115:22 | access to local variable x0 | patterns.cs:115:25:115:26 | access to local variable y0 | semmle.label | successor |
|
||||
| patterns.cs:115:25:115:26 | access to local variable y0 | patterns.cs:115:20:115:27 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:117:13:117:22 | ( ... ) | patterns.cs:117:13:117:22 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:117:13:117:22 | { ... } | patterns.cs:117:28:117:29 | access to local variable y2 | semmle.label | match |
|
||||
| patterns.cs:117:13:117:22 | { ... } | patterns.cs:118:13:118:34 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:117:13:117:33 | ... => ... | patterns.cs:117:14:117:14 | 0 | semmle.label | successor |
|
||||
| patterns.cs:117:14:117:14 | 0 | patterns.cs:117:16:117:21 | Int32 y2 | semmle.label | successor |
|
||||
| patterns.cs:117:16:117:21 | Int32 y2 | patterns.cs:117:13:117:22 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:117:27:117:33 | (..., ...) | patterns.cs:115:9:120:9 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:117:28:117:29 | access to local variable y2 | patterns.cs:117:32:117:32 | 0 | semmle.label | successor |
|
||||
| patterns.cs:117:32:117:32 | 0 | patterns.cs:117:27:117:33 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:118:13:118:23 | ( ... ) | patterns.cs:118:13:118:23 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:118:13:118:23 | { ... } | patterns.cs:118:29:118:29 | 0 | semmle.label | match |
|
||||
| patterns.cs:118:13:118:23 | { ... } | patterns.cs:119:13:119:38 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:118:13:118:34 | ... => ... | patterns.cs:118:14:118:19 | Int32 x2 | semmle.label | successor |
|
||||
| patterns.cs:118:14:118:19 | Int32 x2 | patterns.cs:118:22:118:22 | 0 | semmle.label | successor |
|
||||
| patterns.cs:118:22:118:22 | 0 | patterns.cs:118:13:118:23 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:118:28:118:34 | (..., ...) | patterns.cs:115:9:120:9 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:118:29:118:29 | 0 | patterns.cs:118:32:118:33 | access to local variable x2 | semmle.label | successor |
|
||||
| patterns.cs:118:32:118:33 | access to local variable x2 | patterns.cs:118:28:118:34 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:119:13:119:28 | ( ... ) | patterns.cs:119:13:119:28 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:119:13:119:28 | { ... } | patterns.cs:98:10:98:20 | exit Expressions | semmle.label | exception(InvalidOperationException) |
|
||||
| patterns.cs:119:13:119:28 | { ... } | patterns.cs:119:34:119:34 | 0 | semmle.label | match |
|
||||
| patterns.cs:119:13:119:38 | ... => ... | patterns.cs:119:14:119:19 | Int32 x2 | semmle.label | successor |
|
||||
| patterns.cs:119:14:119:19 | Int32 x2 | patterns.cs:119:22:119:27 | Int32 y2 | semmle.label | successor |
|
||||
| patterns.cs:119:22:119:27 | Int32 y2 | patterns.cs:119:13:119:28 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:119:33:119:38 | (..., ...) | patterns.cs:115:9:120:9 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:119:34:119:34 | 0 | patterns.cs:119:37:119:37 | 0 | semmle.label | successor |
|
||||
| patterns.cs:119:37:119:37 | 0 | patterns.cs:119:33:119:38 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:123:10:123:21 | enter Expressions2 | patterns.cs:124:5:147:5 | {...} | semmle.label | successor |
|
||||
| patterns.cs:124:5:147:5 | {...} | patterns.cs:125:9:125:39 | ... ...; | semmle.label | successor |
|
||||
| patterns.cs:125:9:125:39 | ... ...; | patterns.cs:125:17:125:38 | object creation of type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:125:13:125:38 | MyStruct s = ... | patterns.cs:126:9:132:10 | ... ...; | semmle.label | successor |
|
||||
| patterns.cs:125:17:125:38 | object creation of type MyStruct | patterns.cs:125:36:125:36 | 0 | semmle.label | successor |
|
||||
| patterns.cs:125:30:125:38 | { ..., ... } | patterns.cs:125:13:125:38 | MyStruct s = ... | semmle.label | successor |
|
||||
| patterns.cs:125:32:125:36 | ... = ... | patterns.cs:125:30:125:38 | { ..., ... } | semmle.label | successor |
|
||||
| patterns.cs:125:36:125:36 | 0 | patterns.cs:125:32:125:36 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:126:9:132:10 | ... ...; | patterns.cs:126:17:132:9 | ... switch { ... } | semmle.label | successor |
|
||||
| patterns.cs:126:13:132:9 | Int32 r = ... | patterns.cs:134:9:146:9 | try {...} ... | semmle.label | successor |
|
||||
| patterns.cs:126:17:126:17 | access to local variable s | patterns.cs:128:13:128:49 | ... => ... | semmle.label | successor |
|
||||
| patterns.cs:126:17:132:9 | ... switch { ... } | patterns.cs:126:17:126:17 | access to local variable s | semmle.label | successor |
|
||||
| patterns.cs:128:13:128:33 | { ... } | patterns.cs:128:40:128:40 | access to local variable x | semmle.label | match |
|
||||
| patterns.cs:128:13:128:33 | { ... } | patterns.cs:129:13:129:38 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:128:13:128:49 | ... => ... | patterns.cs:128:27:128:31 | Int32 x | semmle.label | successor |
|
||||
| patterns.cs:128:22:128:33 | { ... } | patterns.cs:128:13:128:33 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:128:27:128:31 | Int32 x | patterns.cs:128:22:128:33 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:128:40:128:40 | access to local variable x | patterns.cs:128:44:128:44 | 2 | semmle.label | successor |
|
||||
| patterns.cs:128:40:128:44 | ... > ... | patterns.cs:128:49:128:49 | 0 | semmle.label | true |
|
||||
| patterns.cs:128:40:128:44 | ... > ... | patterns.cs:129:13:129:38 | ... => ... | semmle.label | false |
|
||||
| patterns.cs:128:44:128:44 | 2 | patterns.cs:128:40:128:44 | ... > ... | semmle.label | successor |
|
||||
| patterns.cs:128:49:128:49 | 0 | patterns.cs:126:13:132:9 | Int32 r = ... | semmle.label | successor |
|
||||
| patterns.cs:129:13:129:33 | MyStruct ms | patterns.cs:129:27:129:28 | 10 | semmle.label | successor |
|
||||
| patterns.cs:129:13:129:33 | { ... } | patterns.cs:129:38:129:38 | 1 | semmle.label | match |
|
||||
| patterns.cs:129:13:129:33 | { ... } | patterns.cs:130:13:130:23 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:129:13:129:38 | ... => ... | patterns.cs:129:13:129:33 | MyStruct ms | semmle.label | successor |
|
||||
| patterns.cs:129:22:129:30 | { ... } | patterns.cs:129:13:129:33 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:129:27:129:28 | 10 | patterns.cs:129:22:129:30 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:129:38:129:38 | 1 | patterns.cs:126:13:132:9 | Int32 r = ... | semmle.label | successor |
|
||||
| patterns.cs:130:13:130:18 | ( ... ) | patterns.cs:130:13:130:18 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:130:13:130:18 | { ... } | patterns.cs:130:23:130:23 | 2 | semmle.label | match |
|
||||
| patterns.cs:130:13:130:18 | { ... } | patterns.cs:131:13:131:27 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:130:13:130:23 | ... => ... | patterns.cs:130:14:130:14 | 1 | semmle.label | successor |
|
||||
| patterns.cs:130:14:130:14 | 1 | patterns.cs:130:17:130:17 | 2 | semmle.label | successor |
|
||||
| patterns.cs:130:17:130:17 | 2 | patterns.cs:130:13:130:18 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:130:23:130:23 | 2 | patterns.cs:126:13:132:9 | Int32 r = ... | semmle.label | successor |
|
||||
| patterns.cs:131:13:131:22 | (..., ...) | patterns.cs:123:10:123:21 | exit Expressions2 | semmle.label | exception(InvalidOperationException) |
|
||||
| patterns.cs:131:13:131:22 | (..., ...) | patterns.cs:131:27:131:27 | 3 | semmle.label | match |
|
||||
| patterns.cs:131:13:131:27 | ... => ... | patterns.cs:131:18:131:18 | Int32 x | semmle.label | successor |
|
||||
| patterns.cs:131:18:131:18 | Int32 x | patterns.cs:131:21:131:21 | _ | semmle.label | successor |
|
||||
| patterns.cs:131:21:131:21 | _ | patterns.cs:131:13:131:22 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:131:27:131:27 | 3 | patterns.cs:126:13:132:9 | Int32 r = ... | semmle.label | successor |
|
||||
| patterns.cs:134:9:146:9 | try {...} ... | patterns.cs:135:9:142:9 | {...} | semmle.label | successor |
|
||||
| patterns.cs:135:9:142:9 | {...} | patterns.cs:136:13:141:14 | ...; | semmle.label | successor |
|
||||
| patterns.cs:136:13:141:13 | ... = ... | patterns.cs:123:10:123:21 | exit Expressions2 | semmle.label | successor |
|
||||
| patterns.cs:136:13:141:14 | ...; | patterns.cs:136:17:141:13 | ... switch { ... } | semmle.label | successor |
|
||||
| patterns.cs:136:17:136:17 | 0 | patterns.cs:138:17:138:50 | ... => ... | semmle.label | successor |
|
||||
| patterns.cs:136:17:141:13 | ... switch { ... } | patterns.cs:136:17:136:17 | 0 | semmle.label | successor |
|
||||
| patterns.cs:138:17:138:17 | 1 | patterns.cs:138:28:138:50 | object creation of type ArgumentException | semmle.label | match |
|
||||
| patterns.cs:138:17:138:17 | 1 | patterns.cs:139:17:139:22 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:138:17:138:50 | ... => ... | patterns.cs:138:17:138:17 | 1 | semmle.label | successor |
|
||||
| patterns.cs:138:22:138:50 | throw ... | patterns.cs:143:9:146:9 | [exception: ArgumentException] catch (...) {...} | semmle.label | exception(ArgumentException) |
|
||||
| patterns.cs:138:28:138:50 | object creation of type ArgumentException | patterns.cs:138:22:138:50 | throw ... | semmle.label | successor |
|
||||
| patterns.cs:138:28:138:50 | object creation of type ArgumentException | patterns.cs:143:9:146:9 | [exception: Exception] catch (...) {...} | semmle.label | exception(Exception) |
|
||||
| patterns.cs:139:17:139:17 | 2 | patterns.cs:139:22:139:22 | 3 | semmle.label | match |
|
||||
| patterns.cs:139:17:139:17 | 2 | patterns.cs:140:17:140:42 | ... => ... | semmle.label | no-match |
|
||||
| patterns.cs:139:17:139:22 | ... => ... | patterns.cs:139:17:139:17 | 2 | semmle.label | successor |
|
||||
| patterns.cs:139:22:139:22 | 3 | patterns.cs:136:13:141:13 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:140:17:140:24 | Object y | patterns.cs:140:31:140:31 | access to local variable y | semmle.label | match |
|
||||
| patterns.cs:140:17:140:24 | Object y | patterns.cs:143:9:146:9 | [exception: InvalidOperationException] catch (...) {...} | semmle.label | exception(InvalidOperationException) |
|
||||
| patterns.cs:140:17:140:42 | ... => ... | patterns.cs:140:17:140:24 | Object y | semmle.label | successor |
|
||||
| patterns.cs:140:31:140:31 | access to local variable y | patterns.cs:140:36:140:37 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:140:31:140:37 | ... is { ... } | patterns.cs:140:42:140:42 | 4 | semmle.label | true |
|
||||
| patterns.cs:140:31:140:37 | ... is { ... } | patterns.cs:143:9:146:9 | [exception: InvalidOperationException] catch (...) {...} | semmle.label | exception(InvalidOperationException) |
|
||||
| patterns.cs:140:36:140:37 | { ... } | patterns.cs:140:31:140:37 | ... is { ... } | semmle.label | successor |
|
||||
| patterns.cs:140:36:140:37 | { ... } | patterns.cs:140:36:140:37 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:140:42:140:42 | 4 | patterns.cs:136:13:141:13 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:143:9:146:9 | [exception: ArgumentException] catch (...) {...} | patterns.cs:123:10:123:21 | exit Expressions2 | semmle.label | exception(ArgumentException) |
|
||||
| patterns.cs:143:9:146:9 | [exception: Exception] catch (...) {...} | patterns.cs:123:10:123:21 | exit Expressions2 | semmle.label | exception(Exception) |
|
||||
| patterns.cs:143:9:146:9 | [exception: Exception] catch (...) {...} | patterns.cs:143:41:143:42 | [exception: Exception] InvalidOperationException ex | semmle.label | match |
|
||||
| patterns.cs:143:9:146:9 | [exception: InvalidOperationException] catch (...) {...} | patterns.cs:143:41:143:42 | [exception: InvalidOperationException] InvalidOperationException ex | semmle.label | match |
|
||||
| patterns.cs:143:41:143:42 | [exception: Exception] InvalidOperationException ex | patterns.cs:144:9:146:9 | {...} | semmle.label | successor |
|
||||
| patterns.cs:143:41:143:42 | [exception: InvalidOperationException] InvalidOperationException ex | patterns.cs:144:9:146:9 | {...} | semmle.label | successor |
|
||||
| patterns.cs:144:9:146:9 | {...} | patterns.cs:145:13:145:51 | ...; | semmle.label | successor |
|
||||
| patterns.cs:145:13:145:50 | call to method WriteLine | patterns.cs:123:10:123:21 | exit Expressions2 | semmle.label | successor |
|
||||
| patterns.cs:145:13:145:51 | ...; | patterns.cs:145:31:145:49 | "Invalid operation" | semmle.label | successor |
|
||||
| patterns.cs:145:31:145:49 | "Invalid operation" | patterns.cs:145:13:145:50 | call to method WriteLine | semmle.label | successor |
|
||||
@@ -0,0 +1,10 @@
|
||||
import csharp
|
||||
|
||||
query predicate edges(ControlFlow::Node a, ControlFlow::Node b, string label, string value) {
|
||||
exists(ControlFlow::SuccessorType t |
|
||||
a.getEnclosingCallable().getName().matches("Expressions%") and
|
||||
b = a.getASuccessorByType(t) and
|
||||
label = "semmle.label" and
|
||||
value = t.toString()
|
||||
)
|
||||
}
|
||||
176
csharp/ql/test/library-tests/csharp8/switchstmtctrlflow.expected
Normal file
176
csharp/ql/test/library-tests/csharp8/switchstmtctrlflow.expected
Normal file
@@ -0,0 +1,176 @@
|
||||
| patterns.cs:32:10:32:25 | enter SwitchStatements | patterns.cs:33:5:96:5 | {...} | semmle.label | successor |
|
||||
| patterns.cs:33:5:96:5 | {...} | patterns.cs:34:9:34:39 | ... ...; | semmle.label | successor |
|
||||
| patterns.cs:34:9:34:39 | ... ...; | patterns.cs:34:17:34:38 | object creation of type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:34:13:34:38 | MyStruct s = ... | patterns.cs:36:9:44:9 | switch (...) {...} | semmle.label | successor |
|
||||
| patterns.cs:34:17:34:38 | object creation of type MyStruct | patterns.cs:34:36:34:36 | 0 | semmle.label | successor |
|
||||
| patterns.cs:34:30:34:38 | { ..., ... } | patterns.cs:34:13:34:38 | MyStruct s = ... | semmle.label | successor |
|
||||
| patterns.cs:34:32:34:36 | ... = ... | patterns.cs:34:30:34:38 | { ..., ... } | semmle.label | successor |
|
||||
| patterns.cs:34:36:34:36 | 0 | patterns.cs:34:32:34:36 | ... = ... | semmle.label | successor |
|
||||
| patterns.cs:36:9:44:9 | switch (...) {...} | patterns.cs:36:17:36:17 | access to local variable s | semmle.label | successor |
|
||||
| patterns.cs:36:17:36:17 | access to local variable s | patterns.cs:38:13:38:47 | case MyStruct ms1: | semmle.label | successor |
|
||||
| patterns.cs:38:13:38:47 | case MyStruct ms1: | patterns.cs:38:18:38:25 | access to type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:38:18:38:25 | access to type MyStruct | patterns.cs:38:18:38:29 | MyStruct ms1 | semmle.label | match |
|
||||
| patterns.cs:38:18:38:25 | access to type MyStruct | patterns.cs:41:13:41:46 | case MyStruct ms2: | semmle.label | no-match |
|
||||
| patterns.cs:38:18:38:29 | MyStruct ms1 | patterns.cs:38:36:38:38 | access to local variable ms1 | semmle.label | successor |
|
||||
| patterns.cs:38:36:38:38 | access to local variable ms1 | patterns.cs:38:36:38:40 | access to field X | semmle.label | successor |
|
||||
| patterns.cs:38:36:38:40 | access to field X | patterns.cs:38:45:38:46 | 10 | semmle.label | successor |
|
||||
| patterns.cs:38:36:38:46 | ... == ... | patterns.cs:39:17:39:56 | ...; | semmle.label | true |
|
||||
| patterns.cs:38:36:38:46 | ... == ... | patterns.cs:41:13:41:46 | case MyStruct ms2: | semmle.label | false |
|
||||
| patterns.cs:38:45:38:46 | 10 | patterns.cs:38:36:38:46 | ... == ... | semmle.label | successor |
|
||||
| patterns.cs:39:17:39:55 | call to method WriteLine | patterns.cs:40:17:40:22 | break; | semmle.label | successor |
|
||||
| patterns.cs:39:17:39:56 | ...; | patterns.cs:39:35:39:54 | "Hit the breakpoint" | semmle.label | successor |
|
||||
| patterns.cs:39:35:39:54 | "Hit the breakpoint" | patterns.cs:39:17:39:55 | call to method WriteLine | semmle.label | successor |
|
||||
| patterns.cs:40:17:40:22 | break; | patterns.cs:46:9:63:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:41:13:41:46 | case MyStruct ms2: | patterns.cs:41:18:41:25 | access to type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:41:18:41:25 | access to type MyStruct | patterns.cs:41:18:41:29 | MyStruct ms2 | semmle.label | match |
|
||||
| patterns.cs:41:18:41:25 | access to type MyStruct | patterns.cs:46:9:63:9 | switch (...) {...} | semmle.label | no-match |
|
||||
| patterns.cs:41:18:41:29 | MyStruct ms2 | patterns.cs:41:36:41:38 | access to local variable ms2 | semmle.label | successor |
|
||||
| patterns.cs:41:36:41:38 | access to local variable ms2 | patterns.cs:41:36:41:40 | access to field X | semmle.label | successor |
|
||||
| patterns.cs:41:36:41:40 | access to field X | patterns.cs:41:44:41:45 | 10 | semmle.label | successor |
|
||||
| patterns.cs:41:36:41:45 | ... < ... | patterns.cs:42:17:42:59 | ...; | semmle.label | true |
|
||||
| patterns.cs:41:36:41:45 | ... < ... | patterns.cs:46:9:63:9 | switch (...) {...} | semmle.label | false |
|
||||
| patterns.cs:41:44:41:45 | 10 | patterns.cs:41:36:41:45 | ... < ... | semmle.label | successor |
|
||||
| patterns.cs:42:17:42:58 | call to method WriteLine | patterns.cs:43:17:43:22 | break; | semmle.label | successor |
|
||||
| patterns.cs:42:17:42:59 | ...; | patterns.cs:42:35:42:57 | "Missed the breakpoint" | semmle.label | successor |
|
||||
| patterns.cs:42:35:42:57 | "Missed the breakpoint" | patterns.cs:42:17:42:58 | call to method WriteLine | semmle.label | successor |
|
||||
| patterns.cs:43:17:43:22 | break; | patterns.cs:46:9:63:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:46:9:63:9 | switch (...) {...} | patterns.cs:46:17:46:17 | access to local variable s | semmle.label | successor |
|
||||
| patterns.cs:46:17:46:17 | access to local variable s | patterns.cs:48:13:48:50 | case { ... }: | semmle.label | successor |
|
||||
| patterns.cs:48:13:48:50 | case { ... }: | patterns.cs:48:18:48:25 | access to type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:48:18:48:25 | access to type MyStruct | patterns.cs:48:32:48:36 | Int32 x | semmle.label | match |
|
||||
| patterns.cs:48:18:48:25 | access to type MyStruct | patterns.cs:51:13:51:39 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:48:18:48:38 | { ... } | patterns.cs:48:45:48:45 | access to local variable x | semmle.label | match |
|
||||
| patterns.cs:48:18:48:38 | { ... } | patterns.cs:51:13:51:39 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:48:27:48:38 | { ... } | patterns.cs:48:18:48:38 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:48:32:48:36 | Int32 x | patterns.cs:48:27:48:38 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:48:45:48:45 | access to local variable x | patterns.cs:48:49:48:49 | 2 | semmle.label | successor |
|
||||
| patterns.cs:48:45:48:49 | ... > ... | patterns.cs:49:17:49:37 | ...; | semmle.label | true |
|
||||
| patterns.cs:48:45:48:49 | ... > ... | patterns.cs:51:13:51:39 | case { ... }: | semmle.label | false |
|
||||
| patterns.cs:48:49:48:49 | 2 | patterns.cs:48:45:48:49 | ... > ... | semmle.label | successor |
|
||||
| patterns.cs:49:17:49:36 | call to method WriteLine | patterns.cs:50:17:50:22 | break; | semmle.label | successor |
|
||||
| patterns.cs:49:17:49:37 | ...; | patterns.cs:49:35:49:35 | access to local variable x | semmle.label | successor |
|
||||
| patterns.cs:49:35:49:35 | access to local variable x | patterns.cs:49:17:49:36 | call to method WriteLine | semmle.label | successor |
|
||||
| patterns.cs:50:17:50:22 | break; | patterns.cs:65:9:73:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:51:13:51:39 | case { ... }: | patterns.cs:51:18:51:25 | access to type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:51:18:51:25 | access to type MyStruct | patterns.cs:51:32:51:33 | 10 | semmle.label | match |
|
||||
| patterns.cs:51:18:51:25 | access to type MyStruct | patterns.cs:54:13:54:43 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:51:18:51:38 | MyStruct ms | patterns.cs:52:17:52:56 | ...; | semmle.label | successor |
|
||||
| patterns.cs:51:18:51:38 | { ... } | patterns.cs:51:18:51:38 | MyStruct ms | semmle.label | match |
|
||||
| patterns.cs:51:18:51:38 | { ... } | patterns.cs:54:13:54:43 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:51:27:51:35 | { ... } | patterns.cs:51:18:51:38 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:51:32:51:33 | 10 | patterns.cs:51:27:51:35 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:52:17:52:55 | call to method WriteLine | patterns.cs:53:17:53:22 | break; | semmle.label | successor |
|
||||
| patterns.cs:52:17:52:56 | ...; | patterns.cs:52:35:52:54 | "Hit the breakpoint" | semmle.label | successor |
|
||||
| patterns.cs:52:35:52:54 | "Hit the breakpoint" | patterns.cs:52:17:52:55 | call to method WriteLine | semmle.label | successor |
|
||||
| patterns.cs:53:17:53:22 | break; | patterns.cs:65:9:73:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:54:13:54:43 | case { ... }: | patterns.cs:54:23:54:28 | Int32 x2 | semmle.label | successor |
|
||||
| patterns.cs:54:18:54:30 | { ... } | patterns.cs:54:18:54:30 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:54:18:54:30 | { ... } | patterns.cs:54:37:54:38 | access to local variable x2 | semmle.label | match |
|
||||
| patterns.cs:54:18:54:30 | { ... } | patterns.cs:57:13:57:24 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:54:23:54:28 | Int32 x2 | patterns.cs:54:18:54:30 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:54:37:54:38 | access to local variable x2 | patterns.cs:54:42:54:42 | 2 | semmle.label | successor |
|
||||
| patterns.cs:54:37:54:42 | ... > ... | patterns.cs:55:17:55:38 | ...; | semmle.label | true |
|
||||
| patterns.cs:54:37:54:42 | ... > ... | patterns.cs:57:13:57:24 | case { ... }: | semmle.label | false |
|
||||
| patterns.cs:54:42:54:42 | 2 | patterns.cs:54:37:54:42 | ... > ... | semmle.label | successor |
|
||||
| patterns.cs:55:17:55:37 | call to method WriteLine | patterns.cs:56:17:56:22 | break; | semmle.label | successor |
|
||||
| patterns.cs:55:17:55:38 | ...; | patterns.cs:55:35:55:36 | access to local variable x2 | semmle.label | successor |
|
||||
| patterns.cs:55:35:55:36 | access to local variable x2 | patterns.cs:55:17:55:37 | call to method WriteLine | semmle.label | successor |
|
||||
| patterns.cs:56:17:56:22 | break; | patterns.cs:65:9:73:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:57:13:57:24 | case { ... }: | patterns.cs:57:19:57:19 | 1 | semmle.label | successor |
|
||||
| patterns.cs:57:18:57:23 | ( ... ) | patterns.cs:57:18:57:23 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:57:18:57:23 | { ... } | patterns.cs:58:17:58:22 | break; | semmle.label | match |
|
||||
| patterns.cs:57:18:57:23 | { ... } | patterns.cs:59:13:59:28 | case ...: | semmle.label | no-match |
|
||||
| patterns.cs:57:19:57:19 | 1 | patterns.cs:57:22:57:22 | 2 | semmle.label | successor |
|
||||
| patterns.cs:57:22:57:22 | 2 | patterns.cs:57:18:57:23 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:58:17:58:22 | break; | patterns.cs:65:9:73:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:59:13:59:28 | case ...: | patterns.cs:59:23:59:23 | Int32 x | semmle.label | successor |
|
||||
| patterns.cs:59:18:59:27 | (..., ...) | patterns.cs:60:17:60:22 | break; | semmle.label | match |
|
||||
| patterns.cs:59:18:59:27 | (..., ...) | patterns.cs:61:13:61:20 | default: | semmle.label | no-match |
|
||||
| patterns.cs:59:23:59:23 | Int32 x | patterns.cs:59:26:59:26 | Int32 y | semmle.label | successor |
|
||||
| patterns.cs:59:26:59:26 | Int32 y | patterns.cs:59:18:59:27 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:60:17:60:22 | break; | patterns.cs:65:9:73:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:61:13:61:20 | default: | patterns.cs:62:17:62:22 | break; | semmle.label | successor |
|
||||
| patterns.cs:62:17:62:22 | break; | patterns.cs:65:9:73:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:65:9:73:9 | switch (...) {...} | patterns.cs:65:17:65:17 | access to local variable s | semmle.label | successor |
|
||||
| patterns.cs:65:17:65:17 | access to local variable s | patterns.cs:67:13:67:50 | case { ... }: | semmle.label | successor |
|
||||
| patterns.cs:67:13:67:50 | case { ... }: | patterns.cs:67:18:67:25 | access to type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:67:18:67:25 | access to type MyStruct | patterns.cs:67:32:67:36 | Int32 x | semmle.label | match |
|
||||
| patterns.cs:67:18:67:25 | access to type MyStruct | patterns.cs:70:13:70:51 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:67:18:67:38 | { ... } | patterns.cs:67:45:67:45 | access to local variable x | semmle.label | match |
|
||||
| patterns.cs:67:18:67:38 | { ... } | patterns.cs:70:13:70:51 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:67:27:67:38 | { ... } | patterns.cs:67:18:67:38 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:67:32:67:36 | Int32 x | patterns.cs:67:27:67:38 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:67:45:67:45 | access to local variable x | patterns.cs:67:49:67:49 | 2 | semmle.label | successor |
|
||||
| patterns.cs:67:45:67:49 | ... > ... | patterns.cs:68:17:68:37 | ...; | semmle.label | true |
|
||||
| patterns.cs:67:45:67:49 | ... > ... | patterns.cs:70:13:70:51 | case { ... }: | semmle.label | false |
|
||||
| patterns.cs:67:49:67:49 | 2 | patterns.cs:67:45:67:49 | ... > ... | semmle.label | successor |
|
||||
| patterns.cs:68:17:68:36 | call to method WriteLine | patterns.cs:69:17:69:22 | break; | semmle.label | successor |
|
||||
| patterns.cs:68:17:68:37 | ...; | patterns.cs:68:35:68:35 | access to local variable x | semmle.label | successor |
|
||||
| patterns.cs:68:35:68:35 | access to local variable x | patterns.cs:68:17:68:36 | call to method WriteLine | semmle.label | successor |
|
||||
| patterns.cs:69:17:69:22 | break; | patterns.cs:76:9:84:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:70:13:70:51 | case { ... }: | patterns.cs:70:18:70:25 | access to type MyStruct | semmle.label | successor |
|
||||
| patterns.cs:70:18:70:25 | access to type MyStruct | patterns.cs:70:32:70:33 | 10 | semmle.label | match |
|
||||
| patterns.cs:70:18:70:25 | access to type MyStruct | patterns.cs:76:9:84:9 | switch (...) {...} | semmle.label | no-match |
|
||||
| patterns.cs:70:18:70:38 | MyStruct ms | patterns.cs:70:45:70:45 | access to local variable s | semmle.label | successor |
|
||||
| patterns.cs:70:18:70:38 | { ... } | patterns.cs:70:18:70:38 | MyStruct ms | semmle.label | match |
|
||||
| patterns.cs:70:27:70:35 | { ... } | patterns.cs:70:18:70:38 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:70:32:70:33 | 10 | patterns.cs:70:27:70:35 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:70:45:70:45 | access to local variable s | patterns.cs:70:45:70:47 | access to field X | semmle.label | successor |
|
||||
| patterns.cs:70:45:70:47 | access to field X | patterns.cs:70:50:70:50 | 0 | semmle.label | successor |
|
||||
| patterns.cs:70:45:70:50 | ... == ... | patterns.cs:71:17:71:56 | ...; | semmle.label | true |
|
||||
| patterns.cs:70:45:70:50 | ... == ... | patterns.cs:76:9:84:9 | switch (...) {...} | semmle.label | false |
|
||||
| patterns.cs:70:50:70:50 | 0 | patterns.cs:70:45:70:50 | ... == ... | semmle.label | successor |
|
||||
| patterns.cs:71:17:71:55 | call to method WriteLine | patterns.cs:72:17:72:22 | break; | semmle.label | successor |
|
||||
| patterns.cs:71:17:71:56 | ...; | patterns.cs:71:35:71:54 | "Hit the breakpoint" | semmle.label | successor |
|
||||
| patterns.cs:71:35:71:54 | "Hit the breakpoint" | patterns.cs:71:17:71:55 | call to method WriteLine | semmle.label | successor |
|
||||
| patterns.cs:72:17:72:22 | break; | patterns.cs:76:9:84:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:76:9:84:9 | switch (...) {...} | patterns.cs:76:17:76:28 | object creation of type Object | semmle.label | successor |
|
||||
| patterns.cs:76:17:76:28 | object creation of type Object | patterns.cs:78:13:78:43 | case { ... }: | semmle.label | successor |
|
||||
| patterns.cs:78:13:78:43 | case { ... }: | patterns.cs:78:19:78:23 | Int32 x | semmle.label | successor |
|
||||
| patterns.cs:78:18:78:33 | ( ... ) | patterns.cs:78:18:78:33 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:78:18:78:33 | { ... } | patterns.cs:78:40:78:40 | access to local variable x | semmle.label | match |
|
||||
| patterns.cs:78:18:78:33 | { ... } | patterns.cs:80:13:80:20 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:78:19:78:23 | Int32 x | patterns.cs:78:26:78:32 | Single y | semmle.label | successor |
|
||||
| patterns.cs:78:26:78:32 | Single y | patterns.cs:78:18:78:33 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:78:40:78:40 | (...) ... | patterns.cs:78:42:78:42 | access to local variable y | semmle.label | successor |
|
||||
| patterns.cs:78:40:78:40 | access to local variable x | patterns.cs:78:40:78:40 | (...) ... | semmle.label | successor |
|
||||
| patterns.cs:78:40:78:42 | ... < ... | patterns.cs:79:17:79:22 | break; | semmle.label | true |
|
||||
| patterns.cs:78:40:78:42 | ... < ... | patterns.cs:80:13:80:20 | case { ... }: | semmle.label | false |
|
||||
| patterns.cs:78:42:78:42 | access to local variable y | patterns.cs:78:40:78:42 | ... < ... | semmle.label | successor |
|
||||
| patterns.cs:79:17:79:22 | break; | patterns.cs:86:9:89:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:80:13:80:20 | case { ... }: | patterns.cs:80:18:80:19 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:80:18:80:19 | ( ... ) | patterns.cs:80:18:80:19 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:80:18:80:19 | { ... } | patterns.cs:81:17:81:22 | break; | semmle.label | match |
|
||||
| patterns.cs:80:18:80:19 | { ... } | patterns.cs:82:13:82:20 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:81:17:81:22 | break; | patterns.cs:86:9:89:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:82:13:82:20 | case { ... }: | patterns.cs:82:18:82:19 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:82:18:82:19 | { ... } | patterns.cs:82:18:82:19 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:82:18:82:19 | { ... } | patterns.cs:83:17:83:22 | break; | semmle.label | match |
|
||||
| patterns.cs:83:17:83:22 | break; | patterns.cs:86:9:89:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:86:9:89:9 | switch (...) {...} | patterns.cs:86:16:86:16 | 1 | semmle.label | successor |
|
||||
| patterns.cs:86:15:86:19 | (..., ...) | patterns.cs:88:13:88:24 | case { ... }: | semmle.label | successor |
|
||||
| patterns.cs:86:16:86:16 | 1 | patterns.cs:86:18:86:18 | 2 | semmle.label | successor |
|
||||
| patterns.cs:86:18:86:18 | 2 | patterns.cs:86:15:86:19 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:88:13:88:24 | case { ... }: | patterns.cs:88:19:88:19 | 1 | semmle.label | successor |
|
||||
| patterns.cs:88:18:88:23 | ( ... ) | patterns.cs:88:18:88:23 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:88:18:88:23 | { ... } | patterns.cs:88:26:88:31 | break; | semmle.label | match |
|
||||
| patterns.cs:88:19:88:19 | 1 | patterns.cs:88:22:88:22 | 2 | semmle.label | successor |
|
||||
| patterns.cs:88:22:88:22 | 2 | patterns.cs:88:18:88:23 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:88:26:88:31 | break; | patterns.cs:91:9:95:9 | switch (...) {...} | semmle.label | break |
|
||||
| patterns.cs:91:9:95:9 | switch (...) {...} | patterns.cs:91:17:91:17 | 1 | semmle.label | successor |
|
||||
| patterns.cs:91:16:91:20 | (..., ...) | patterns.cs:93:13:93:28 | case { ... }: | semmle.label | successor |
|
||||
| patterns.cs:91:17:91:17 | 1 | patterns.cs:91:19:91:19 | 2 | semmle.label | successor |
|
||||
| patterns.cs:91:19:91:19 | 2 | patterns.cs:91:16:91:20 | (..., ...) | semmle.label | successor |
|
||||
| patterns.cs:93:13:93:28 | case { ... }: | patterns.cs:93:19:93:19 | 1 | semmle.label | successor |
|
||||
| patterns.cs:93:18:93:27 | ( ... ) | patterns.cs:93:18:93:27 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:93:18:93:27 | { ... } | patterns.cs:93:30:93:35 | break; | semmle.label | match |
|
||||
| patterns.cs:93:18:93:27 | { ... } | patterns.cs:94:13:94:24 | case { ... }: | semmle.label | no-match |
|
||||
| patterns.cs:93:19:93:19 | 1 | patterns.cs:93:22:93:26 | Int32 x | semmle.label | successor |
|
||||
| patterns.cs:93:22:93:26 | Int32 x | patterns.cs:93:18:93:27 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:93:30:93:35 | break; | patterns.cs:32:10:32:25 | exit SwitchStatements | semmle.label | break |
|
||||
| patterns.cs:94:13:94:24 | case { ... }: | patterns.cs:94:19:94:19 | 2 | semmle.label | successor |
|
||||
| patterns.cs:94:18:94:23 | ( ... ) | patterns.cs:94:18:94:23 | { ... } | semmle.label | successor |
|
||||
| patterns.cs:94:18:94:23 | { ... } | patterns.cs:94:26:94:31 | break; | semmle.label | match |
|
||||
| patterns.cs:94:19:94:19 | 2 | patterns.cs:94:22:94:22 | _ | semmle.label | successor |
|
||||
| patterns.cs:94:22:94:22 | _ | patterns.cs:94:18:94:23 | ( ... ) | semmle.label | successor |
|
||||
| patterns.cs:94:26:94:31 | break; | patterns.cs:32:10:32:25 | exit SwitchStatements | semmle.label | break |
|
||||
10
csharp/ql/test/library-tests/csharp8/switchstmtctrlflow.ql
Normal file
10
csharp/ql/test/library-tests/csharp8/switchstmtctrlflow.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
import csharp
|
||||
|
||||
query predicate edges(ControlFlow::Node a, ControlFlow::Node b, string label, string value) {
|
||||
exists(ControlFlow::SuccessorType t |
|
||||
a.getEnclosingCallable().hasName("SwitchStatements") and
|
||||
b = a.getASuccessorByType(t) and
|
||||
label = "semmle.label" and
|
||||
value = t.toString()
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user