Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
e459e69d
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e459e69d
编写于
12月 21, 2016
作者:
N
Neal Gafter
提交者:
GitHub
12月 21, 2016
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make ScanType() and ParseType() agree not to accept pointer types in deconstruction (#15975)
Fixes #15934
上级
c7bcaed1
变更
5
展开全部
隐藏空白更改
内联
并排
Showing
5 changed file
with
703 addition
and
24 deletion
+703
-24
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+28
-13
src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
...mpilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
+2
-11
src/Compilers/CSharp/Test/Semantic/Semantics/DeconstructionTests.cs
...ers/CSharp/Test/Semantic/Semantics/DeconstructionTests.cs
+120
-0
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
...rs/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
+98
-0
src/Compilers/CSharp/Test/Syntax/Parsing/DeconstructionTests.cs
...mpilers/CSharp/Test/Syntax/Parsing/DeconstructionTests.cs
+455
-0
未找到文件。
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
浏览文件 @
e459e69d
...
...
@@ -6179,7 +6179,12 @@ private ScanTypeFlags ScanType()
private
ScanTypeFlags
ScanType
(
out
SyntaxToken
lastTokenOfType
)
{
ScanTypeFlags
result
=
this
.
ScanNonArrayType
(
out
lastTokenOfType
);
return
ScanType
(
ParseTypeMode
.
Normal
,
out
lastTokenOfType
);
}
private
ScanTypeFlags
ScanType
(
ParseTypeMode
mode
,
out
SyntaxToken
lastTokenOfType
)
{
ScanTypeFlags
result
=
this
.
ScanNonArrayType
(
mode
,
out
lastTokenOfType
);
if
(
result
==
ScanTypeFlags
.
NotType
)
{
...
...
@@ -6236,10 +6241,10 @@ private ScanTypeFlags ScanNamedTypePart(out SyntaxToken lastTokenOfType)
private
ScanTypeFlags
ScanNonArrayType
()
{
SyntaxToken
lastTokenOfType
;
return
ScanNonArrayType
(
out
lastTokenOfType
);
return
ScanNonArrayType
(
ParseTypeMode
.
Normal
,
out
lastTokenOfType
);
}
private
ScanTypeFlags
ScanNonArrayType
(
out
SyntaxToken
lastTokenOfType
)
private
ScanTypeFlags
ScanNonArrayType
(
ParseTypeMode
mode
,
out
SyntaxToken
lastTokenOfType
)
{
ScanTypeFlags
result
;
...
...
@@ -6311,17 +6316,27 @@ private ScanTypeFlags ScanNonArrayType(out SyntaxToken lastTokenOfType)
}
// Now check for pointer type(s)
while
(
this
.
CurrentToken
.
Kind
==
SyntaxKind
.
AsteriskToken
)
switch
(
mode
)
{
lastTokenOfType
=
this
.
EatToken
();
if
(
result
==
ScanTypeFlags
.
GenericTypeOrExpression
||
result
==
ScanTypeFlags
.
NonGenericTypeOrExpression
)
{
result
=
ScanTypeFlags
.
PointerOrMultiplication
;
}
else
if
(
result
==
ScanTypeFlags
.
GenericTypeOrMethod
)
{
result
=
ScanTypeFlags
.
MustBeType
;
}
case
ParseTypeMode
.
FirstElementOfPossibleTupleLiteral
:
case
ParseTypeMode
.
AfterTupleComma
:
// We are parsing the type for a declaration expression in a tuple, which does
// not permit pointer types. In that context a `*` is parsed as a multiplication.
break
;
default
:
while
(
this
.
CurrentToken
.
Kind
==
SyntaxKind
.
AsteriskToken
)
{
lastTokenOfType
=
this
.
EatToken
();
if
(
result
==
ScanTypeFlags
.
GenericTypeOrExpression
||
result
==
ScanTypeFlags
.
NonGenericTypeOrExpression
)
{
result
=
ScanTypeFlags
.
PointerOrMultiplication
;
}
else
if
(
result
==
ScanTypeFlags
.
GenericTypeOrMethod
)
{
result
=
ScanTypeFlags
.
MustBeType
;
}
}
break
;
}
return
result
;
...
...
src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
浏览文件 @
e459e69d
...
...
@@ -152,18 +152,9 @@ private bool IsPossibleDeclarationExpression(ParseTypeMode mode, bool permitTupl
{
bool
typeIsVar
=
IsVarType
();
SyntaxToken
lastTokenOfType
;
switch
(
ScanType
(
out
lastTokenOfType
)
)
if
(
ScanType
(
mode
,
out
lastTokenOfType
)
==
ScanTypeFlags
.
NotType
)
{
case
ScanTypeFlags
.
PointerOrMultiplication
:
if
(
mode
==
ParseTypeMode
.
FirstElementOfPossibleTupleLiteral
||
mode
==
ParseTypeMode
.
AfterTupleComma
)
{
// Tuples cannot contain pointer types because pointers may not be generic type arguments.
return
false
;
}
break
;
case
ScanTypeFlags
.
NotType
:
return
false
;
return
false
;
}
// check for a designation
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/DeconstructionTests.cs
浏览文件 @
e459e69d
...
...
@@ -2601,5 +2601,125 @@ static void Main()
Diagnostic
(
ErrorCode
.
ERR_TypeVarNotFound
,
"var"
).
WithLocation
(
6
,
15
)
);
}
[
Fact
,
WorkItem
(
15934
,
"https://github.com/dotnet/roslyn/issues/15934"
)]
public
void
PointerTypeInDeconstruction
()
{
string
source
=
@"
unsafe class C
{
static void Main(C c)
{
(int* x1, int y1) = c;
(var* x2, int y2) = c;
(int*[] x3, int y3) = c;
(var*[] x4, int y4) = c;
}
public void Deconstruct(out dynamic x, out dynamic y)
{
x = y = null;
}
}
"
;
var
comp
=
CreateCompilationWithMscorlibAndSystemCore
(
source
,
references
:
new
[]
{
ValueTupleRef
,
SystemRuntimeFacadeRef
},
options
:
TestOptions
.
UnsafeDebugDll
);
// The precise diagnostics here are not important, and may be sensitive to parser
// adjustments. This is a test that we don't crash. The errors here are likely to
// change as we adjust the parser and semantic analysis of error cases.
comp
.
VerifyDiagnostics
(
// (6,10): error CS1525: Invalid expression term 'int'
// (int* x1, int y1) = c;
Diagnostic
(
ErrorCode
.
ERR_InvalidExprTerm
,
"int"
).
WithArguments
(
"int"
).
WithLocation
(
6
,
10
),
// (8,10): error CS1525: Invalid expression term 'int'
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_InvalidExprTerm
,
"int"
).
WithArguments
(
"int"
).
WithLocation
(
8
,
10
),
// (8,14): error CS1525: Invalid expression term '['
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_InvalidExprTerm
,
"["
).
WithArguments
(
"["
).
WithLocation
(
8
,
14
),
// (8,15): error CS0443: Syntax error; value expected
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_ValueExpected
,
"]"
).
WithLocation
(
8
,
15
),
// (8,17): error CS1026: ) expected
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_CloseParenExpected
,
"x3"
).
WithLocation
(
8
,
17
),
// (8,17): error CS1002: ; expected
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_SemicolonExpected
,
"x3"
).
WithLocation
(
8
,
17
),
// (8,19): error CS1002: ; expected
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_SemicolonExpected
,
","
).
WithLocation
(
8
,
19
),
// (8,19): error CS1513: } expected
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_RbraceExpected
,
","
).
WithLocation
(
8
,
19
),
// (8,27): error CS1002: ; expected
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_SemicolonExpected
,
")"
).
WithLocation
(
8
,
27
),
// (8,27): error CS1513: } expected
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_RbraceExpected
,
")"
).
WithLocation
(
8
,
27
),
// (8,29): error CS1525: Invalid expression term '='
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_InvalidExprTerm
,
"="
).
WithArguments
(
"="
).
WithLocation
(
8
,
29
),
// (9,14): error CS1525: Invalid expression term '['
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_InvalidExprTerm
,
"["
).
WithArguments
(
"["
).
WithLocation
(
9
,
14
),
// (9,15): error CS0443: Syntax error; value expected
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_ValueExpected
,
"]"
).
WithLocation
(
9
,
15
),
// (9,17): error CS1026: ) expected
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_CloseParenExpected
,
"x4"
).
WithLocation
(
9
,
17
),
// (9,17): error CS1002: ; expected
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_SemicolonExpected
,
"x4"
).
WithLocation
(
9
,
17
),
// (9,19): error CS1002: ; expected
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_SemicolonExpected
,
","
).
WithLocation
(
9
,
19
),
// (9,19): error CS1513: } expected
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_RbraceExpected
,
","
).
WithLocation
(
9
,
19
),
// (9,27): error CS1002: ; expected
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_SemicolonExpected
,
")"
).
WithLocation
(
9
,
27
),
// (9,27): error CS1513: } expected
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_RbraceExpected
,
")"
).
WithLocation
(
9
,
27
),
// (9,29): error CS1525: Invalid expression term '='
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_InvalidExprTerm
,
"="
).
WithArguments
(
"="
).
WithLocation
(
9
,
29
),
// (6,15): error CS0103: The name 'x1' does not exist in the current context
// (int* x1, int y1) = c;
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"x1"
).
WithArguments
(
"x1"
).
WithLocation
(
6
,
15
),
// (6,9): error CS8184: A deconstruction cannot mix declarations and expressions on the left-hand-side.
// (int* x1, int y1) = c;
Diagnostic
(
ErrorCode
.
ERR_MixedDeconstructionUnsupported
,
"(int* x1, int y1)"
).
WithLocation
(
6
,
9
),
// (7,10): error CS0103: The name 'var' does not exist in the current context
// (var* x2, int y2) = c;
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"var"
).
WithArguments
(
"var"
).
WithLocation
(
7
,
10
),
// (7,15): error CS0103: The name 'x2' does not exist in the current context
// (var* x2, int y2) = c;
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"x2"
).
WithArguments
(
"x2"
).
WithLocation
(
7
,
15
),
// (7,9): error CS8184: A deconstruction cannot mix declarations and expressions on the left-hand-side.
// (var* x2, int y2) = c;
Diagnostic
(
ErrorCode
.
ERR_MixedDeconstructionUnsupported
,
"(var* x2, int y2)"
).
WithLocation
(
7
,
9
),
// (8,17): error CS0103: The name 'x3' does not exist in the current context
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"x3"
).
WithArguments
(
"x3"
).
WithLocation
(
8
,
17
),
// (9,10): error CS0103: The name 'var' does not exist in the current context
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"var"
).
WithArguments
(
"var"
).
WithLocation
(
9
,
10
),
// (9,17): error CS0103: The name 'x4' does not exist in the current context
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"x4"
).
WithArguments
(
"x4"
).
WithLocation
(
9
,
17
),
// (8,25): warning CS0168: The variable 'y3' is declared but never used
// (int*[] x3, int y3) = c;
Diagnostic
(
ErrorCode
.
WRN_UnreferencedVar
,
"y3"
).
WithArguments
(
"y3"
).
WithLocation
(
8
,
25
),
// (9,25): warning CS0168: The variable 'y4' is declared but never used
// (var*[] x4, int y4) = c;
Diagnostic
(
ErrorCode
.
WRN_UnreferencedVar
,
"y4"
).
WithArguments
(
"y4"
).
WithLocation
(
9
,
25
)
);
}
}
}
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
浏览文件 @
e459e69d
...
...
@@ -4057,5 +4057,103 @@ public static void Main()
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"_"
).
WithArguments
(
"_"
).
WithLocation
(
19
,
23
)
);
}
[
Fact
]
public
void
PointerTypeInPattern
()
{
// pointer types are not supported in patterns. Therefore an attempt to use
// a pointer type will be interpreted by the parser as a multiplication
// (i.e. an expression that is a constant pattern rather than a declaration
// pattern)
var
source
=
@"
public class var {}
unsafe public class Typ
{
public static void Main(int* a, var* c, Typ* e)
{
{
if (a is int* b) {}
if (c is var* d) {}
if (e is Typ* f) {}
}
{
switch (a) { case int* b: break; }
switch (c) { case var* d: break; }
switch (e) { case Typ* f: break; }
}
}
}
"
;
var
compilation
=
CreateCompilationWithMscorlibAndSystemCore
(
source
,
options
:
TestOptions
.
UnsafeDebugDll
);
compilation
.
VerifyDiagnostics
(
// if (a is int* b) {}
Diagnostic
(
ErrorCode
.
ERR_InvalidExprTerm
,
"int"
).
WithArguments
(
"int"
).
WithLocation
(
8
,
22
),
// (13,31): error CS1525: Invalid expression term 'int'
// switch (a) { case int* b: break; }
Diagnostic
(
ErrorCode
.
ERR_InvalidExprTerm
,
"int"
).
WithArguments
(
"int"
).
WithLocation
(
13
,
31
),
// (5,37): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('var')
// public static void Main(int* a, var* c, Typ* e)
Diagnostic
(
ErrorCode
.
ERR_ManagedAddr
,
"var*"
).
WithArguments
(
"var"
).
WithLocation
(
5
,
37
),
// (5,45): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('Typ')
// public static void Main(int* a, var* c, Typ* e)
Diagnostic
(
ErrorCode
.
ERR_ManagedAddr
,
"Typ*"
).
WithArguments
(
"Typ"
).
WithLocation
(
5
,
45
),
// (8,27): error CS0103: The name 'b' does not exist in the current context
// if (a is int* b) {}
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"b"
).
WithArguments
(
"b"
).
WithLocation
(
8
,
27
),
// (9,22): error CS0119: 'var' is a type, which is not valid in the given context
// if (c is var* d) {}
Diagnostic
(
ErrorCode
.
ERR_BadSKunknown
,
"var"
).
WithArguments
(
"var"
,
"type"
).
WithLocation
(
9
,
22
),
// (9,27): error CS0103: The name 'd' does not exist in the current context
// if (c is var* d) {}
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"d"
).
WithArguments
(
"d"
).
WithLocation
(
9
,
27
),
// (10,22): error CS0119: 'Typ' is a type, which is not valid in the given context
// if (e is Typ* f) {}
Diagnostic
(
ErrorCode
.
ERR_BadSKunknown
,
"Typ"
).
WithArguments
(
"Typ"
,
"type"
).
WithLocation
(
10
,
22
),
// (10,27): error CS0103: The name 'f' does not exist in the current context
// if (e is Typ* f) {}
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"f"
).
WithArguments
(
"f"
).
WithLocation
(
10
,
27
),
// (13,36): error CS0103: The name 'b' does not exist in the current context
// switch (a) { case int* b: break; }
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"b"
).
WithArguments
(
"b"
).
WithLocation
(
13
,
36
),
// (14,31): error CS0119: 'var' is a type, which is not valid in the given context
// switch (c) { case var* d: break; }
Diagnostic
(
ErrorCode
.
ERR_BadSKunknown
,
"var"
).
WithArguments
(
"var"
,
"type"
).
WithLocation
(
14
,
31
),
// (14,36): error CS0103: The name 'd' does not exist in the current context
// switch (c) { case var* d: break; }
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"d"
).
WithArguments
(
"d"
).
WithLocation
(
14
,
36
),
// (15,31): error CS0119: 'Typ' is a type, which is not valid in the given context
// switch (e) { case Typ* f: break; }
Diagnostic
(
ErrorCode
.
ERR_BadSKunknown
,
"Typ"
).
WithArguments
(
"Typ"
,
"type"
).
WithLocation
(
15
,
31
),
// (15,36): error CS0103: The name 'f' does not exist in the current context
// switch (e) { case Typ* f: break; }
Diagnostic
(
ErrorCode
.
ERR_NameNotInContext
,
"f"
).
WithArguments
(
"f"
).
WithLocation
(
15
,
36
)
);
}
[
Fact
]
public
void
MultiplyInPattern
()
{
// pointer types are not supported in patterns. Therefore an attempt to use
// a pointer type will be interpreted by the parser as a multiplication
// (i.e. an expression that is a constant pattern rather than a declaration
// pattern)
var
source
=
@"
public class Program
{
public static void Main()
{
const int two = 2;
const int three = 3;
int six = two * three;
System.Console.WriteLine(six is two * three);
}
}
"
;
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
TestOptions
.
DebugExe
);
compilation
.
VerifyDiagnostics
();
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
"True"
);
}
}
}
src/Compilers/CSharp/Test/Syntax/Parsing/DeconstructionTests.cs
浏览文件 @
e459e69d
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录