Browse Source

Fixed resolving compile-time operations on enum types with an underlying type smaller than int. (always use unchecked context for the cast back to enum)

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
e62a04692b
  1. 12
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  2. 2
      ICSharpCode.NRefactory.ConsistencyCheck/Program.cs
  3. 17
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs

12
ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs

@ -119,6 +119,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -119,6 +119,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public CSharpResolver WithCheckForOverflow(bool checkForOverflow)
{
if (checkForOverflow == this.checkForOverflow)
return this;
return new CSharpResolver(compilation, conversions, context, checkForOverflow, isWithinLambdaExpression, currentTypeDefinitionCache, localVariableStack, objectInitializerStack);
}
@ -431,7 +433,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -431,7 +433,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// evaluate as (E)(~(U)x);
var U = compilation.FindType(expression.ConstantValue.GetType());
var unpackedEnum = new ConstantResolveResult(U, expression.ConstantValue);
return CheckErrorAndResolveCast(expression.Type, ResolveUnaryOperator(op, unpackedEnum));
return CheckErrorAndResolveUncheckedCast(expression.Type, ResolveUnaryOperator(op, unpackedEnum));
} else {
return UnaryOperatorResolveResult(expression.Type, op, expression, isNullable);
}
@ -911,7 +913,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -911,7 +913,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
rhs = ResolveCast(elementType, rhs);
if (rhs.IsError)
return rhs;
return CheckErrorAndResolveCast(elementType, ResolveBinaryOperator(BinaryOperatorType.Subtract, lhs, rhs));
return CheckErrorAndResolveUncheckedCast(elementType, ResolveBinaryOperator(BinaryOperatorType.Subtract, lhs, rhs));
}
IType resultType = MakeNullable(elementType, isNullable);
return BinaryOperatorResolveResult(resultType, lhs, BinaryOperatorType.Subtract, rhs, isNullable);
@ -937,7 +939,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -937,7 +939,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
rhs = ResolveCast(elementType, rhs);
if (rhs.IsError)
return rhs;
return CheckErrorAndResolveCast(enumType, ResolveBinaryOperator(op, lhs, rhs));
return CheckErrorAndResolveUncheckedCast(enumType, ResolveBinaryOperator(op, lhs, rhs));
}
IType resultType = MakeNullable(enumType, isNullable);
return BinaryOperatorResolveResult(resultType, lhs, op, rhs, isNullable);
@ -1302,12 +1304,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1302,12 +1304,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return Utils.CSharpPrimitiveCast.Cast(targetType, input, this.CheckForOverflow);
}
ResolveResult CheckErrorAndResolveCast(IType targetType, ResolveResult expression)
ResolveResult CheckErrorAndResolveUncheckedCast(IType targetType, ResolveResult expression)
{
if (expression.IsError)
return expression;
else
return ResolveCast(targetType, expression);
return WithCheckForOverflow(false).ResolveCast(targetType, expression);
}
#endregion

2
ICSharpCode.NRefactory.ConsistencyCheck/Program.cs

@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck
solution.AllFiles.Count(),
solution.Projects.Count);
//using (new Timer("ID String test... ")) TypeSystemTests.IDStringConsistencyCheck(solution);
using (new Timer("ID String test... ")) TypeSystemTests.IDStringConsistencyCheck(solution);
using (new Timer("Resolve unresolved members... ")) TypeSystemTests.ResolvedUnresolvedMembers(solution);
//RunTestOnAllFiles("Roundtripping test", RoundtripTest.RunTest);
RunTestOnAllFiles("Resolver test", ResolverTest.RunTest);

17
ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs

@ -257,5 +257,22 @@ class Test { @@ -257,5 +257,22 @@ class Test {
Assert.IsFalse(irr.IsError);
Assert.IsTrue(irr.IsLiftedOperator);
}
[Test]
public void UShortEnumNegation()
{
string program = @"
class Test {
enum UShortEnum : ushort { Three = 3 }
static void Inc() {
checked { // even in checked context, the implicit cast back to enum is unchecked
var a = $~UShortEnum.Three$;
}
}
}";
var rr = Resolve<ConstantResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.AreEqual(unchecked( (ushort)~3 ), rr.ConstantValue);
}
}
}

Loading…
Cancel
Save