Browse Source

Merge pull request #136 from erik-kallen/sizeof

Improved handling of sizeof(x)
pull/32/merge
Daniel Grunwald 13 years ago
parent
commit
463e5916ee
  1. 10
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  2. 21
      ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs
  3. 4
      ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
  4. 122
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/SizeOfTests.cs
  5. 1
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  6. 15
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  7. 15
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  8. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  9. 66
      ICSharpCode.NRefactory/Semantics/SizeOfResolveResult.cs

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

@ -2233,8 +2233,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2233,8 +2233,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public ResolveResult ResolveSizeOf(IType type)
{
IType int32 = compilation.FindType(KnownTypeCode.Int32);
int size;
switch (ReflectionHelper.GetTypeCode(type)) {
int? size = null;
var typeForConstant = (type.Kind == TypeKind.Enum) ? type.GetDefinition().EnumUnderlyingType : type;
switch (ReflectionHelper.GetTypeCode(typeForConstant)) {
case TypeCode.Boolean:
case TypeCode.SByte:
case TypeCode.Byte:
@ -2255,10 +2257,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2255,10 +2257,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
case TypeCode.Double:
size = 8;
break;
default:
return new ResolveResult(int32);
}
return new ConstantResolveResult(int32, size);
return new SizeOfResolveResult(int32, type, size);
}
#endregion

21
ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs

@ -488,4 +488,25 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues @@ -488,4 +488,25 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues
}
}
}
/// <summary>
/// Used for sizeof() expressions in constants.
/// </summary>
[Serializable]
public sealed class SizeOfConstantValue : ConstantExpression
{
readonly ITypeReference type;
public SizeOfConstantValue(ITypeReference type)
{
if (type == null)
throw new ArgumentNullException("type");
this.type = type;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
return resolver.ResolveSizeOf(type.Resolve(resolver.CurrentTypeResolveContext));
}
}
}

4
ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs

@ -978,6 +978,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -978,6 +978,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return interningProvider.Intern(
new PrimitiveConstantExpression(KnownTypeReference.Object, null));
}
public override ConstantExpression VisitSizeOfExpression(SizeOfExpression sizeOfExpression) {
return new SizeOfConstantValue(sizeOfExpression.Type.ToTypeReference(NameLookupMode.Type, interningProvider));
}
public override ConstantExpression VisitPrimitiveExpression(PrimitiveExpression primitiveExpression)
{

122
ICSharpCode.NRefactory.Tests/CSharp/Resolver/SizeOfTests.cs

@ -0,0 +1,122 @@ @@ -0,0 +1,122 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// 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 System;
using ICSharpCode.NRefactory.Semantics;
using NUnit.Framework;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
[TestFixture]
public class SizeOfTests : ResolverTestBase
{
[Test]
public void SizeOfPrimitiveTypes()
{
foreach (var t in new[] { new { t = "sbyte", n = 1 },
new { t = "byte", n = 1 },
new { t = "short", n = 2 },
new { t = "ushort", n = 2 },
new { t = "int", n = 4 },
new { t = "uint", n = 4 },
new { t = "long", n = 8 },
new { t = "ulong", n = 8 },
new { t = "char", n = 2 },
new { t = "float", n = 4 },
new { t = "double", n = 8 },
new { t = "bool", n = 1 }
}) {
string program = @"using System;
class TestClass {
static void Main() {
public int s = $sizeof(" + t.t + @")$;
}
}";
var rr = Resolve<SizeOfResolveResult>(program);
Assert.IsTrue(rr.Type.IsKnownType(KnownTypeCode.Int32));
Assert.IsFalse(rr.IsError);
Assert.AreEqual(t.n, rr.ConstantValue);
Assert.IsTrue(Type.GetType(rr.ReferencedType.FullName).IsPrimitive);
}
}
[Test]
public void SizeOfEnum()
{
string program = @"
enum TestEnum {}
class TestClass {
static void Main() {
int s = $sizeof(TestEnum)$;
}
}";
var rr = Resolve<SizeOfResolveResult>(program);
Assert.IsTrue(rr.Type.IsKnownType(KnownTypeCode.Int32));
Assert.IsFalse(rr.IsError);
Assert.AreEqual(4, rr.ConstantValue);
Assert.AreEqual("TestEnum", rr.ReferencedType.Name);
program = @"
enum TestEnum2 : short {}
class TestClass {
static void Main() {
int s = $sizeof(TestEnum2)$;
}
}";
rr = Resolve<SizeOfResolveResult>(program);
Assert.IsTrue(rr.Type.IsKnownType(KnownTypeCode.Int32));
Assert.IsFalse(rr.IsError);
Assert.AreEqual(2, rr.ConstantValue);
Assert.AreEqual("TestEnum2", rr.ReferencedType.Name);
}
[Test]
public void SizeOfStructIsNotAConstant()
{
string program = @"
struct MyStruct {}
class TestClass {
static void Main() {
int s = $sizeof(MyStruct)$;
}
}";
var rr = Resolve<SizeOfResolveResult>(program);
Assert.IsTrue(rr.Type.IsKnownType(KnownTypeCode.Int32));
Assert.IsFalse(rr.IsError);
Assert.IsNull(rr.ConstantValue);
Assert.AreEqual("MyStruct", rr.ReferencedType.Name);
}
[Test]
public void SizeOfReferenceTypeIsAnError() {
string program = @"
class MyClass {}
class TestClass {
static void Main() {
int s = $sizeof(MyClass)$;
}
}";
var rr = Resolve<SizeOfResolveResult>(program);
Assert.IsTrue(rr.Type.IsKnownType(KnownTypeCode.Int32));
Assert.IsTrue(rr.IsError);
Assert.IsNull(rr.ConstantValue);
Assert.AreEqual("MyClass", rr.ReferencedType.Name);
}
}
}

1
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -233,6 +233,7 @@ @@ -233,6 +233,7 @@
<Compile Include="CSharp\Resolver\CastTests.cs" />
<Compile Include="CSharp\Resolver\ComTests.cs" />
<Compile Include="CSharp\Resolver\ConditionalOperatorTests.cs" />
<Compile Include="CSharp\Resolver\SizeOfTests.cs" />
<Compile Include="CSharp\Resolver\DynamicTests.cs" />
<Compile Include="CSharp\Resolver\ExplicitConversionsTest.cs" />
<Compile Include="CSharp\Resolver\ExtensionMethodTests.cs" />

15
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs

@ -358,5 +358,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -358,5 +358,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
public const double Cd = 42;
public const float Cf = 42;
public const decimal Cm = 42;
public const string S = "hello, world";
public const int SOsb = sizeof(sbyte);
public const int SOb = sizeof(byte);
public const int SOs = sizeof(short);
public const int SOus = sizeof(ushort);
public const int SOi = sizeof(int);
public const int SOui = sizeof(uint);
public const int SOl = sizeof(long);
public const int SOul = sizeof(ulong);
public const int SOc = sizeof(char);
public const int SOf = sizeof(float);
public const int SOd = sizeof(double);
public const int SObl = sizeof(bool);
public const int SOe = sizeof(MyEnum);
}
}

15
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -1263,6 +1263,21 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1263,6 +1263,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
AssertConstantField<double>(type, "Cd", 42);
AssertConstantField<float>(type, "Cf", 42);
AssertConstantField<decimal>(type, "Cm", 42);
AssertConstantField<string>(type, "S", "hello, world");
AssertConstantField<int>(type, "SOsb", sizeof(sbyte));
AssertConstantField<int>(type, "SOb", sizeof(byte));
AssertConstantField<int>(type, "SOs", sizeof(short));
AssertConstantField<int>(type, "SOus", sizeof(ushort));
AssertConstantField<int>(type, "SOi", sizeof(int));
AssertConstantField<int>(type, "SOui", sizeof(uint));
AssertConstantField<int>(type, "SOl", sizeof(long));
AssertConstantField<int>(type, "SOul", sizeof(ulong));
AssertConstantField<int>(type, "SOc", sizeof(char));
AssertConstantField<int>(type, "SOf", sizeof(float));
AssertConstantField<int>(type, "SOd", sizeof(double));
AssertConstantField<int>(type, "SObl", sizeof(bool));
AssertConstantField<int>(type, "SOe", sizeof(MyEnum));
}
}
}

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -111,6 +111,7 @@ @@ -111,6 +111,7 @@
<Compile Include="Semantics\ByReferenceResolveResult.cs" />
<Compile Include="Semantics\ConstantResolveResult.cs" />
<Compile Include="Semantics\ConversionResolveResult.cs" />
<Compile Include="Semantics\SizeOfResolveResult.cs" />
<Compile Include="Semantics\ErrorResolveResult.cs" />
<Compile Include="Semantics\Conversion.cs" />
<Compile Include="Semantics\ForEachResolveResult.cs" />

66
ICSharpCode.NRefactory/Semantics/SizeOfResolveResult.cs

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// 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 System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the 'typeof'.
/// </summary>
public class SizeOfResolveResult : ResolveResult
{
readonly IType referencedType;
readonly int? constantValue;
public SizeOfResolveResult(IType int32, IType referencedType, int? constantValue)
: base(int32)
{
if (referencedType == null)
throw new ArgumentNullException("referencedType");
this.referencedType = referencedType;
this.constantValue = constantValue;
}
/// <summary>
/// The type referenced by the 'sizeof'.
/// </summary>
public IType ReferencedType {
get { return referencedType; }
}
public override bool IsCompileTimeConstant {
get {
return constantValue != null;
}
}
public override object ConstantValue {
get {
return constantValue;
}
}
public override bool IsError {
get {
return referencedType.IsReferenceType != false;
}
}
}
}
Loading…
Cancel
Save