Browse Source

Add ThrowExpressionConversion.

pull/1600/head
Daniel Grunwald 7 years ago
parent
commit
58b0ddda9e
  1. 16
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 3
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs
  4. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 47
      ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs
  6. 19
      ICSharpCode.Decompiler/Semantics/Conversion.cs
  7. 29
      ICSharpCode.Decompiler/Semantics/ThrowResolveResult.cs

16
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -746,13 +746,6 @@ namespace ICSharpCode.Decompiler.CSharp @@ -746,13 +746,6 @@ namespace ICSharpCode.Decompiler.CSharp
return HandleThreeValuedLogic(inst, BinaryOperatorType.BitwiseOr, ExpressionType.Or);
}
protected internal override TranslatedExpression VisitThrow(Throw inst, TranslationContext context)
{
return new ThrowExpression(Translate(inst.Argument))
.WithILInstruction(inst)
.WithRR(new ResolveResult(SpecialType.NoType));
}
TranslatedExpression HandleThreeValuedLogic(BinaryInstruction inst, BinaryOperatorType op, ExpressionType eop)
{
var left = Translate(inst.Left);
@ -775,6 +768,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -775,6 +768,13 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(inst);
}
protected internal override TranslatedExpression VisitThrow(Throw inst, TranslationContext context)
{
return new ThrowExpression(Translate(inst.Argument))
.WithILInstruction(inst)
.WithRR(new ThrowResolveResult());
}
ExpressionWithResolveResult Assignment(TranslatedExpression left, TranslatedExpression right)
{
right = right.ConvertTo(left.Type, this, allowImplicitConversion: true);
@ -2189,7 +2189,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2189,7 +2189,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (rr.IsError) {
IType targetType;
if (fallback.Expression is ThrowExpression && fallback.Type.Equals(SpecialType.NoType)) {
targetType = value.Type;
targetType = NullableType.GetUnderlyingType(value.Type);
} else if (!value.Type.Equals(SpecialType.NullType) && !fallback.Type.Equals(SpecialType.NullType) && !value.Type.Equals(fallback.Type)) {
targetType = compilation.FindType(inst.UnderlyingResultType.ToKnownTypeCode());
} else {

3
ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

@ -115,6 +115,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -115,6 +115,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
if (c != Conversion.None)
return c;
}
if (resolveResult is ThrowResolveResult) {
return Conversion.ThrowExpressionConversion;
}
if (allowUserDefined && allowTuple) {
// if allowUserDefined and allowTuple are true, we might as well use the cache
c = ImplicitConversion(resolveResult.Type, toType);

2
ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs

@ -203,7 +203,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -203,7 +203,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (targetType.Kind == TypeKind.Unknown || targetType.Kind == TypeKind.Void || targetType.Kind == TypeKind.None) {
return this; // don't attempt to insert cast to '?' or 'void' as these are not valid.
}
if (Expression is ThrowExpression) {
if (Expression is ThrowExpression && allowImplicitConversion) {
return this; // Throw expressions have no type and are implicitly convertible to any type
}
if (Expression is TupleExpression tupleExpr && targetType is TupleType targetTupleType

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -326,6 +326,7 @@ @@ -326,6 +326,7 @@
<Compile Include="IL\Transforms\StatementTransform.cs" />
<Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" />
<Compile Include="Output\TextTokenWriter.cs" />
<Compile Include="Semantics\ThrowResolveResult.cs" />
<Compile Include="Semantics\TupleResolveResult.cs" />
<Compile Include="TypeSystem\NormalizeTypeVisitor.cs" />
<Compile Include="TypeSystem\TupleType.cs" />

47
ICSharpCode.Decompiler/IL/Transforms/NullCoalescingTransform.cs

@ -83,52 +83,5 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -83,52 +83,5 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
return false;
}
/// <summary>
/// Handles NullCoalescingInstruction case 1: reference types.
///
/// stloc s(valueInst)
/// if (comp(ldloc s == ldnull)) {
/// stloc s(fallbackInst)
/// }
/// =>
/// stloc s(if.notnull(valueInst, fallbackInst))
///
/// -------------------
///
/// stloc obj(valueInst)
/// if (comp(ldloc obj == ldnull)) {
/// throw(...)
/// }
/// =>
/// stloc obj(if.notnull(valueInst, throw(...)))
/// </summary>
bool TransformRefTypesA(Block block, int pos, StatementTransformContext context)
{
if (!(block.Instructions[pos] is StLoc stloc))
return false;
if (stloc.Variable.Kind != VariableKind.StackSlot)
return false;
if (!block.Instructions[pos + 1].MatchIfInstruction(out var condition, out var trueInst))
return false;
if (!(condition.MatchCompEquals(out var left, out var right) && left.MatchLdLoc(stloc.Variable) && right.MatchLdNull()))
return false;
trueInst = Block.Unwrap(trueInst);
if (trueInst.MatchStLoc(stloc.Variable, out var fallbackValue)) {
context.Step("NullCoalescingTransform (reference types)", stloc);
stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, fallbackValue);
block.Instructions.RemoveAt(pos + 1); // remove if instruction
ILInlining.InlineOneIfPossible(block, pos, false, context);
return true;
} else if (trueInst is Throw throwInst) {
context.Step("NullCoalescingTransform (throw expression)", stloc);
throwInst.resultType = StackType.O;
stloc.Value = new NullCoalescingInstruction(NullCoalescingKind.Ref, stloc.Value, throwInst);
block.Instructions.RemoveAt(pos + 1); // remove if instruction
ILInlining.InlineOneIfPossible(block, pos, false, context);
return true;
}
return false;
}
}
}

19
ICSharpCode.Decompiler/Semantics/Conversion.cs

@ -75,7 +75,12 @@ namespace ICSharpCode.Decompiler.Semantics @@ -75,7 +75,12 @@ namespace ICSharpCode.Decompiler.Semantics
/// C# 'as' cast.
/// </summary>
public static readonly Conversion TryCast = new BuiltinConversion(false, 9);
/// <summary>
/// C# 7 throw expression being converted to an arbitrary type.
/// </summary>
public static readonly Conversion ThrowExpressionConversion = new BuiltinConversion(true, 10);
public static Conversion UserDefinedConversion(IMethod operatorMethod, bool isImplicit, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted = false, bool isAmbiguous = false)
{
if (operatorMethod == null)
@ -227,6 +232,10 @@ namespace ICSharpCode.Decompiler.Semantics @@ -227,6 +232,10 @@ namespace ICSharpCode.Decompiler.Semantics
public override bool IsTryCast {
get { return type == 9; }
}
public override bool IsThrowExpressionConversion {
get { return type == 10; }
}
public override string ToString()
{
@ -257,6 +266,8 @@ namespace ICSharpCode.Decompiler.Semantics @@ -257,6 +266,8 @@ namespace ICSharpCode.Decompiler.Semantics
return "unboxing conversion";
case 9:
return "try cast";
case 10:
return "throw-expression conversion";
}
return (isImplicit ? "implicit " : "explicit ") + name + " conversion";
}
@ -443,7 +454,11 @@ namespace ICSharpCode.Decompiler.Semantics @@ -443,7 +454,11 @@ namespace ICSharpCode.Decompiler.Semantics
public virtual bool IsTryCast {
get { return false; }
}
public virtual bool IsThrowExpressionConversion {
get { return false; }
}
public virtual bool IsIdentityConversion {
get { return false; }
}

29
ICSharpCode.Decompiler/Semantics/ThrowResolveResult.cs

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
// Copyright (c) 2018 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.Semantics
{
class ThrowResolveResult : ResolveResult
{
public ThrowResolveResult() : base(SpecialType.NoType)
{
}
}
}
Loading…
Cancel
Save