Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
b7c20b22
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,体验更适合开发者的 AI 搜索 >>
提交
b7c20b22
编写于
7月 14, 2016
作者:
J
Jonathon Marolf
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'upstream/dev15-preview-4' into master
# Conflicts: # src/Tools/SignRoslyn/BinaryData.json
上级
2bfce76b
b6ed1896
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
223 addition
and
53 deletion
+223
-53
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs
...ing/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs
+105
-52
src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
...ers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
+10
-0
src/Compilers/CSharp/Test/Semantic/Semantics/PatternSubsumptionTests.cs
...CSharp/Test/Semantic/Semantics/PatternSubsumptionTests.cs
+106
-0
src/Tools/SignRoslyn/BinaryData.json
src/Tools/SignRoslyn/BinaryData.json
+2
-1
未找到文件。
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs
浏览文件 @
b7c20b22
...
...
@@ -236,44 +236,13 @@ private void LowerDecisionTree(DecisionTree.ByValue byValue)
return
;
}
switch
(
byValue
.
Type
.
SpecialType
)
if
(
byValue
.
Type
.
SpecialType
==
SpecialType
.
System_Boolean
)
{
case
SpecialType
.
System_Byte
:
case
SpecialType
.
System_Char
:
case
SpecialType
.
System_Int16
:
case
SpecialType
.
System_Int32
:
case
SpecialType
.
System_Int64
:
case
SpecialType
.
System_SByte
:
case
SpecialType
.
System_UInt16
:
case
SpecialType
.
System_UInt32
:
case
SpecialType
.
System_UInt64
:
case
SpecialType
.
System_String
:
// switch on a string
// switch on an integral or string type
LowerBasicSwitch
(
byValue
);
return
;
case
SpecialType
.
System_Boolean
:
// switch on a boolean
LowerBooleanSwitch
(
byValue
);
return
;
// switch on a type requiring sequential comparisons. Note that we use constant.Equals(value), depending if
// possible on the one from IEquatable<T>. If that does not exist, we use instance method object.Equals(object)
// with the (now boxed) constant on the left.
case
SpecialType
.
System_Decimal
:
case
SpecialType
.
System_Double
:
case
SpecialType
.
System_Single
:
LowerOtherSwitch
(
byValue
);
return
;
default
:
if
(
byValue
.
Type
.
TypeKind
==
TypeKind
.
Enum
)
{
LowerBasicSwitch
(
byValue
);
return
;
}
// There are no other types of constants that could be used as patterns.
throw
ExceptionUtilities
.
UnexpectedValue
(
byValue
.
Type
);
LowerBooleanSwitch
(
byValue
);
}
else
{
LowerBasicSwitch
(
byValue
);
}
}
...
...
@@ -392,26 +361,120 @@ private void LowerBasicSwitch(DecisionTree.ByValue byValue)
var
rewrittenSections
=
switchSections
.
ToImmutableAndFree
();
MethodSymbol
stringEquality
=
null
;
if
(
byValue
.
Type
.
SpecialType
==
SpecialType
.
System_String
)
if
(
underlyingSwitch
Type
.
SpecialType
==
SpecialType
.
System_String
)
{
LocalRewriter
.
EnsureStringHashFunction
(
rewrittenSections
,
_factory
.
Syntax
);
stringEquality
=
LocalRewriter
.
GetSpecialTypeMethod
(
_factory
.
Syntax
,
SpecialMember
.
System_String__op_Equality
);
}
// Emit requires a constant target when there are no sections, so we accomodate that here.
// CONSIDER: can we get better code generated by giving a constant target more often here,
// e.g. when the switch expression is a constant?
// The BoundSwitchStatement requires a constant target when there are no sections, so we accomodate that here.
var
constantTarget
=
rewrittenSections
.
IsEmpty
?
noValueMatches
:
null
;
var
switchStatement
=
new
BoundSwitchStatement
(
_factory
.
Syntax
,
null
,
_factory
.
Convert
(
underlyingSwitchType
,
byValue
.
Expression
),
constantTarget
,
ImmutableArray
<
LocalSymbol
>.
Empty
,
ImmutableArray
<
LocalFunctionSymbol
>.
Empty
,
rewrittenSections
,
noValueMatches
,
stringEquality
);
_loweredDecisionTree
.
Add
(
switchStatement
);
// The bound switch statement implicitly defines the label noValueMatches at the end, so we do not add it explicitly.
switch
(
underlyingSwitchType
.
SpecialType
)
{
case
SpecialType
.
System_Boolean
:
// boolean switch is handled in LowerBooleanSwitch, not here.
throw
ExceptionUtilities
.
Unreachable
;
case
SpecialType
.
System_String
:
case
SpecialType
.
System_Byte
:
case
SpecialType
.
System_Char
:
case
SpecialType
.
System_Int16
:
case
SpecialType
.
System_Int32
:
case
SpecialType
.
System_Int64
:
case
SpecialType
.
System_SByte
:
case
SpecialType
.
System_UInt16
:
case
SpecialType
.
System_UInt32
:
case
SpecialType
.
System_UInt64
:
{
// emit knows how to efficiently generate code for these kinds of switches.
_loweredDecisionTree
.
Add
(
switchStatement
);
break
;
}
default
:
{
// other types, such as float, double, and decimal, are not currently
// handled by emit and must be lowered here.
_loweredDecisionTree
.
Add
(
LowerNonprimitiveSwitch
(
switchStatement
));
break
;
}
}
LowerDecisionTree
(
byValue
.
Expression
,
byValue
.
Default
);
}
private
BoundStatement
LowerNonprimitiveSwitch
(
BoundSwitchStatement
switchStatement
)
{
// Here we handle "other" types, such as float, double, and decimal, by
// lowering the BoundSwitchStatement.
// We compare the constant values using value.Equals(input), using ordinary
// overload resolution. Note that we cannot and do not rely on switching
// on the hash code, as it may not be consistent with the behavior of Equals;
// see https://github.com/dotnet/coreclr/issues/6237. Also, the hash code is
// not guaranteed to be the same on the compilation platform as the runtime
// platform.
// CONSIDER: can we improve the quality of the code using comparisons, like
// we do for other numeric types, by generating a series of tests
// that use divide-and-conquer to efficiently find a matching value?
// If so, we should use the BoundSwitchStatement and do that in emit.
// Moreover, we should be able to use `==` rather than `.Equals`
// for cases (such as non-NaN) where we know the result to be the same.
var
rewrittenSections
=
switchStatement
.
SwitchSections
;
var
expression
=
switchStatement
.
Expression
;
var
noValueMatches
=
switchStatement
.
BreakLabel
;
Debug
.
Assert
(
switchStatement
.
LoweredPreambleOpt
==
null
);
Debug
.
Assert
(
switchStatement
.
InnerLocals
.
IsDefaultOrEmpty
);
Debug
.
Assert
(
switchStatement
.
InnerLocalFunctions
.
IsDefaultOrEmpty
);
Debug
.
Assert
(
switchStatement
.
StringEquality
==
null
);
LabelSymbol
nextLabel
=
null
;
var
builder
=
ArrayBuilder
<
BoundStatement
>.
GetInstance
();
foreach
(
var
section
in
rewrittenSections
)
{
foreach
(
var
boundSwitchLabel
in
section
.
SwitchLabels
)
{
if
(
nextLabel
!=
null
)
{
builder
.
Add
(
_factory
.
Label
(
nextLabel
));
}
nextLabel
=
_factory
.
GenerateLabel
(
"failcase+"
+
section
.
SwitchLabels
[
0
].
ConstantValueOpt
.
Value
);
Debug
.
Assert
(
boundSwitchLabel
.
ConstantValueOpt
!=
null
);
// generate (if (value.Equals(input)) goto label;
var
literal
=
LocalRewriter
.
MakeLiteral
(
_factory
.
Syntax
,
boundSwitchLabel
.
ConstantValueOpt
,
expression
.
Type
);
var
condition
=
_factory
.
InstanceCall
(
literal
,
"Equals"
,
expression
);
if
(!
condition
.
HasErrors
&&
condition
.
Type
.
SpecialType
!=
SpecialType
.
System_Boolean
)
{
var
call
=
(
BoundCall
)
condition
;
// '{1} {0}' has the wrong return type
_factory
.
Diagnostics
.
Add
(
ErrorCode
.
ERR_BadRetType
,
boundSwitchLabel
.
Syntax
.
GetLocation
(),
call
.
Method
,
call
.
Type
);
}
builder
.
Add
(
_factory
.
ConditionalGoto
(
condition
,
boundSwitchLabel
.
Label
,
true
));
builder
.
Add
(
_factory
.
Goto
(
nextLabel
));
}
foreach
(
var
boundSwitchLabel
in
section
.
SwitchLabels
)
{
builder
.
Add
(
_factory
.
Label
(
boundSwitchLabel
.
Label
));
}
builder
.
Add
(
_factory
.
Block
(
section
.
Statements
));
// this location should not be reachable.
}
Debug
.
Assert
(
nextLabel
!=
null
);
builder
.
Add
(
_factory
.
Label
(
nextLabel
));
builder
.
Add
(
_factory
.
Label
(
noValueMatches
));
return
_factory
.
Block
(
builder
.
ToImmutableAndFree
());
}
private
void
LowerBooleanSwitch
(
DecisionTree
.
ByValue
byValue
)
{
switch
(
byValue
.
ValueAndDecision
.
Count
)
...
...
@@ -462,16 +525,6 @@ private void LowerBooleanSwitch(DecisionTree.ByValue byValue)
throw
ExceptionUtilities
.
UnexpectedValue
(
byValue
.
ValueAndDecision
.
Count
);
}
}
/// <summary>
/// We handle "other" types, such as float, double, and decimal here. We compare the constant values using IEquatable.
/// For other value types, since there is no literal notation, there will be no constants to test.
/// </summary>
private
void
LowerOtherSwitch
(
DecisionTree
.
ByValue
byValue
)
{
this
.
LocalRewriter
.
_diagnostics
.
Add
(
ErrorCode
.
ERR_FeatureIsUnimplemented
,
_factory
.
Syntax
.
GetLocation
(),
"switch on float, double, or decimal"
);
throw
new
NotImplementedException
();
}
}
}
}
src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs
浏览文件 @
b7c20b22
...
...
@@ -566,6 +566,11 @@ public BoundObjectCreationExpression New(MethodSymbol ctor, params BoundExpressi
return
new
BoundObjectCreationExpression
(
Syntax
,
ctor
,
args
)
{
WasCompilerGenerated
=
true
};
}
public
BoundExpression
InstanceCall
(
BoundExpression
receiver
,
string
name
,
BoundExpression
arg
)
{
return
MakeInvocationExpression
(
BinderFlags
.
None
,
this
.
Syntax
,
receiver
,
name
,
ImmutableArray
.
Create
(
arg
),
this
.
Diagnostics
);
}
public
BoundExpression
StaticCall
(
TypeSymbol
receiver
,
string
name
,
params
BoundExpression
[]
args
)
{
return
MakeInvocationExpression
(
BinderFlags
.
None
,
this
.
Syntax
,
this
.
Type
(
receiver
),
name
,
args
.
ToImmutableArray
(),
this
.
Diagnostics
);
...
...
@@ -851,6 +856,11 @@ public BoundLiteral Literal(string value)
return
StringLiteral
(
stringConst
);
}
public
BoundLiteral
Literal
(
ConstantValue
value
,
TypeSymbol
type
)
{
return
new
CSharp
.
BoundLiteral
(
Syntax
,
value
,
type
)
{
WasCompilerGenerated
=
true
};
}
public
BoundLiteral
StringLiteral
(
ConstantValue
stringConst
)
{
Debug
.
Assert
(
stringConst
.
IsString
||
stringConst
.
IsNull
);
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/PatternSubsumptionTests.cs
浏览文件 @
b7c20b22
...
...
@@ -865,5 +865,111 @@ public static void M(object o)
sasquatch"
;
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
expectedOutput
);
}
[
Fact
]
public
void
WhenClause02
()
{
var
source
=
@"using System;
class Program
{
public static void Main()
{
M(0.0);
M(-0.0);
M(2.1);
M(1.0);
M(double.NaN);
M(-double.NaN);
M(0.0f);
M(-0.0f);
M(2.1f);
M(1.0f);
M(float.NaN);
M(-float.NaN);
M(0.0m);
M(0m);
M(2.1m);
M(1.0m);
M(null);
}
public static void M(object o)
{
switch (o)
{
case 0.0f:
Console.WriteLine(""0.0f !"");
break;
case 0.0d:
Console.WriteLine(""0.0d !"");
break;
case 0.0m:
Console.WriteLine(""0.0m !"");
break;
case 1.0f:
Console.WriteLine(""1.0f !"");
break;
case 1.0d:
Console.WriteLine(""1.0d !"");
break;
case 1.0m:
Console.WriteLine(""1.0m !"");
break;
case 2.0f:
Console.WriteLine(""2.0f !"");
break;
case 2.0d:
Console.WriteLine(""2.0d !"");
break;
case 2.0m:
Console.WriteLine(""2.0m !"");
break;
case float.NaN:
Console.WriteLine(""float.NaN !"");
break;
case double.NaN:
Console.WriteLine(""double.NaN !"");
break;
case float f when f is float g:
Console.WriteLine(""float "" + g);
break;
case double d when d is double e:
Console.WriteLine(""double "" + e);
break;
case decimal d when d is decimal e:
Console.WriteLine(""decimal "" + e);
break;
case null:
Console.WriteLine(""null"");
break;
case object k:
Console.WriteLine(k.GetType() + "" + "" + k);
break;
}
}
}"
;
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
TestOptions
.
DebugExe
,
parseOptions
:
s_patternParseOptions
);
compilation
.
VerifyDiagnostics
();
var
expectedOutput
=
@"0.0d !
0.0d !
double 2.1
1.0d !
double.NaN !
double.NaN !
0.0f !
0.0f !
float 2.1
1.0f !
float.NaN !
float.NaN !
0.0m !
0.0m !
decimal 2.1
1.0m !
null"
;
var
comp
=
CompileAndVerify
(
compilation
,
expectedOutput
:
expectedOutput
);
}
}
}
src/Tools/SignRoslyn/BinaryData.json
浏览文件 @
b7c20b22
...
...
@@ -49,6 +49,8 @@
"Roslyn.Hosting.Diagnostics.dll"
,
"Roslyn.VisualStudio.DiagnosticsWindow.dll"
,
"Roslyn.VisualStudio.InteractiveComponents.dll"
,
"Roslyn.VisualStudio.Setup.Interactive.dll"
,
"Roslyn.VisualStudio.Test.Utilities.dll"
,
"SDK
\\
Roslyn.SyntaxVisualizer.DgmlHelper.dll"
,
"SDK
\\
Roslyn.SyntaxVisualizer.Control.dll"
,
"SDK
\\
Roslyn.SyntaxVisualizer.Extension.dll"
,
...
...
@@ -93,7 +95,6 @@
"Roslyn.Deployment.Full.Next.vsix"
,
"Roslyn.VisualStudio.DiagnosticsWindow.vsix"
,
"Roslyn.VisualStudio.InteractiveComponents.vsix"
,
"Roslyn.VisualStudio.Setup.Interactive.dll"
,
"Roslyn.VisualStudio.Setup.Interactive.vsix"
,
"Roslyn.VisualStudio.Setup.Next.vsix"
,
"Roslyn.VisualStudio.Setup.vsix"
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录