Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
5c602fc6
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,发现更多精彩内容 >>
提交
5c602fc6
编写于
10月 07, 2015
作者:
V
vsadov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Removed extra conversion emitted into expression trees for a lifted binary enum operator.
Fixes #5734
上级
c816547a
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
198 addition
and
7 deletion
+198
-7
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/ExpressionLambdaRewriter.cs
...table/Lowering/LambdaRewriter/ExpressionLambdaRewriter.cs
+30
-7
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
...pilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
+168
-0
未找到文件。
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/ExpressionLambdaRewriter.cs
浏览文件 @
5c602fc6
...
...
@@ -414,15 +414,13 @@ private BoundExpression VisitBinaryOperator(BinaryOperatorKind opKind, MethodSym
right
=
_bound
.
Default
(
left
.
Type
);
}
var
loweredLeft
=
Visit
(
left
);
var
loweredRight
=
Visit
(
right
);
// Enums are handled as per their promoted underlying type
switch
(
opKind
.
OperandTypes
())
{
case
BinaryOperatorKind
.
Enum
:
case
BinaryOperatorKind
.
EnumAndUnderlying
:
case
BinaryOperatorKind
.
UnderlyingAndEnum
:
case
BinaryOperatorKind
.
Enum
:
{
var
enumOperand
=
(
opKind
.
OperandTypes
()
==
BinaryOperatorKind
.
UnderlyingAndEnum
)
?
right
:
left
;
var
promotedType
=
PromotedType
(
enumOperand
.
Type
.
StrippedType
().
GetEnumUnderlyingType
());
...
...
@@ -431,18 +429,38 @@ private BoundExpression VisitBinaryOperator(BinaryOperatorKind opKind, MethodSym
promotedType
=
_nullableType
.
Construct
(
promotedType
);
}
loweredLeft
=
PromoteEnumOperand
(
left
,
loweredL
eft
,
promotedType
,
isChecked
);
loweredRight
=
PromoteEnumOperand
(
right
,
loweredR
ight
,
promotedType
,
isChecked
);
var
loweredLeft
=
VisitAndPromoteEnumOperand
(
l
eft
,
promotedType
,
isChecked
);
var
loweredRight
=
VisitAndPromoteEnumOperand
(
r
ight
,
promotedType
,
isChecked
);
var
result
=
MakeBinary
(
methodOpt
,
type
,
isLifted
,
requiresLifted
,
opName
,
loweredLeft
,
loweredRight
);
return
Demote
(
result
,
type
,
isChecked
);
}
default
:
{
var
loweredLeft
=
Visit
(
left
);
var
loweredRight
=
Visit
(
right
);
return
MakeBinary
(
methodOpt
,
type
,
isLifted
,
requiresLifted
,
opName
,
loweredLeft
,
loweredRight
);
}
}
}
private
static
BoundExpression
DemoteEnumOperand
(
BoundExpression
left
)
{
if
(
left
.
Kind
==
BoundKind
.
Conversion
)
{
var
conversion
=
(
BoundConversion
)
left
;
if
(!
conversion
.
ConversionKind
.
IsUserDefinedConversion
()
&&
conversion
.
ConversionKind
.
IsImplicitConversion
()
&&
conversion
.
Type
.
StrippedType
().
IsEnumType
())
{
left
=
conversion
.
Operand
;
}
}
return
left
;
}
private
BoundExpression
PromoteEnumOperand
(
BoundExpression
operand
,
BoundExpression
loweredO
perand
,
TypeSymbol
promotedType
,
bool
isChecked
)
private
BoundExpression
VisitAndPromoteEnumOperand
(
BoundExpression
o
perand
,
TypeSymbol
promotedType
,
bool
isChecked
)
{
var
literal
=
operand
as
BoundLiteral
;
if
(
literal
!=
null
)
...
...
@@ -452,6 +470,11 @@ private BoundExpression PromoteEnumOperand(BoundExpression operand, BoundExpress
}
else
{
// COMPAT: if we have an operand converted to enum, we should unconvert it first
// Otherwise we will have an extra conversion in the tree: op -> enum -> underlying
// where native compiler would just directly convert to underlying
var
demotedOperand
=
DemoteEnumOperand
(
operand
);
var
loweredOperand
=
Visit
(
demotedOperand
);
return
Convert
(
loweredOperand
,
operand
.
Type
,
promotedType
,
isChecked
,
false
);
}
}
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
浏览文件 @
5c602fc6
...
...
@@ -4536,6 +4536,174 @@ public static void Main()
expectedOutput
:
expectedOutput
);
}
[
Fact
,
WorkItem
(
4471
,
"https://github.com/dotnet/roslyn/issues/5734"
)]
public
void
EnumEquality001
()
{
string
source
=
@"
using System;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
enum YesNo
{
Yes,
No
}
class MyType
{
public string Name { get; set; }
public YesNo? YesNo { get; set; }
public int? Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
Expression<Func<MyType, bool>> expr = (MyType x) => x.YesNo == YesNo.Yes;
Console.WriteLine(expr.Dump());
}
}
}"
;
string
expectedOutput
=
"Equal(Convert(MemberAccess(Parameter(x Type:ConsoleApplication1.MyType).YesNo Type:System.Nullable`1[ConsoleApplication1.YesNo]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Constant(Yes Type:ConsoleApplication1.YesNo) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted Type:System.Boolean)"
;
CompileAndVerify
(
new
[]
{
source
,
ExpressionTestLibrary
},
new
[]
{
ExpressionAssemblyRef
},
expectedOutput
:
expectedOutput
);
}
[
Fact
,
WorkItem
(
4471
,
"https://github.com/dotnet/roslyn/issues/5734"
)]
public
void
EnumEquality002
()
{
string
source
=
@"
using System;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
enum YesNo
{
Yes,
No
}
class MyType
{
public string Name { get; set; }
public YesNo? YesNo { get; set; }
public int? Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
Expression<Func<MyType, bool>> expr = (MyType x) => x.YesNo == x.YesNo;
Console.WriteLine(expr.Dump());
}
}
}"
;
string
expectedOutput
=
"Equal(Convert(MemberAccess(Parameter(x Type:ConsoleApplication1.MyType).YesNo Type:System.Nullable`1[ConsoleApplication1.YesNo]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(MemberAccess(Parameter(x Type:ConsoleApplication1.MyType).YesNo Type:System.Nullable`1[ConsoleApplication1.YesNo]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted Type:System.Boolean)"
;
CompileAndVerify
(
new
[]
{
source
,
ExpressionTestLibrary
},
new
[]
{
ExpressionAssemblyRef
},
expectedOutput
:
expectedOutput
);
}
[
Fact
,
WorkItem
(
4471
,
"https://github.com/dotnet/roslyn/issues/5734"
)]
public
void
EnumEquality003
()
{
string
source
=
@"
using System;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
enum YesNo
{
Yes,
No
}
class MyType
{
public string Name { get; set; }
public YesNo YesNo { get; set; }
public int? Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
Expression<Func<MyType, bool>> expr = (MyType x) => x.YesNo == x.YesNo;
Console.WriteLine(expr.Dump());
}
}
}"
;
string
expectedOutput
=
"Equal(Convert(MemberAccess(Parameter(x Type:ConsoleApplication1.MyType).YesNo Type:ConsoleApplication1.YesNo) Type:System.Int32) Convert(MemberAccess(Parameter(x Type:ConsoleApplication1.MyType).YesNo Type:ConsoleApplication1.YesNo) Type:System.Int32) Type:System.Boolean)"
;
CompileAndVerify
(
new
[]
{
source
,
ExpressionTestLibrary
},
new
[]
{
ExpressionAssemblyRef
},
expectedOutput
:
expectedOutput
);
}
[
Fact
,
WorkItem
(
4471
,
"https://github.com/dotnet/roslyn/issues/5734"
)]
public
void
EnumEquality004
()
{
string
source
=
@"
using System;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
enum YesNo
{
Yes,
No
}
class MyType
{
public string Name { get; set; }
public YesNo? YesNo { get; set; }
public int? Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
Expression<Func<MyType, bool>> expr = (MyType x) => x.YesNo == (YesNo)1;
Console.WriteLine(expr.Dump());
}
}
}"
;
string
expectedOutput
=
"Equal(Convert(MemberAccess(Parameter(x Type:ConsoleApplication1.MyType).YesNo Type:System.Nullable`1[ConsoleApplication1.YesNo]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Constant(No Type:ConsoleApplication1.YesNo) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted Type:System.Boolean)"
;
CompileAndVerify
(
new
[]
{
source
,
ExpressionTestLibrary
},
new
[]
{
ExpressionAssemblyRef
},
expectedOutput
:
expectedOutput
);
}
[
WorkItem
(
546618
,
"DevDiv"
)]
[
Fact
]
public
void
TildeNullableEnum
()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录