diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
index 1aa8d4b578..58c2b2ece1 100644
--- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
+++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
@@ -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
case TypeCode.Double:
size = 8;
break;
- default:
- return new ResolveResult(int32);
}
- return new ConstantResolveResult(int32, size);
+ return new SizeOfResolveResult(int32, type, size);
}
#endregion
diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs
index 79ed801716..4802837e36 100644
--- a/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs
+++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs
@@ -488,4 +488,25 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues
}
}
}
+
+ ///
+ /// Used for sizeof() expressions in constants.
+ ///
+ [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));
+ }
+ }
}
diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
index 94f5159151..be50d2e671 100644
--- a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
+++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs
@@ -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)
{
diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/SizeOfTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/SizeOfTests.cs
new file mode 100644
index 0000000000..627d026fb9
--- /dev/null
+++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/SizeOfTests.cs
@@ -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(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(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(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(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(program);
+ Assert.IsTrue(rr.Type.IsKnownType(KnownTypeCode.Int32));
+ Assert.IsTrue(rr.IsError);
+ Assert.IsNull(rr.ConstantValue);
+ Assert.AreEqual("MyClass", rr.ReferencedType.Name);
+ }
+ }
+}
diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
index a01aff64e4..8185e9258e 100644
--- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
+++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
@@ -233,6 +233,7 @@
+
diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
index d233d0dd48..2b19b4887e 100644
--- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
+++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
@@ -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);
}
}
diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
index e4fafe3ae0..daa441f3ed 100644
--- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
+++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
@@ -1263,6 +1263,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
AssertConstantField(type, "Cd", 42);
AssertConstantField(type, "Cf", 42);
AssertConstantField(type, "Cm", 42);
+ AssertConstantField(type, "S", "hello, world");
+
+ AssertConstantField(type, "SOsb", sizeof(sbyte));
+ AssertConstantField(type, "SOb", sizeof(byte));
+ AssertConstantField(type, "SOs", sizeof(short));
+ AssertConstantField(type, "SOus", sizeof(ushort));
+ AssertConstantField(type, "SOi", sizeof(int));
+ AssertConstantField(type, "SOui", sizeof(uint));
+ AssertConstantField(type, "SOl", sizeof(long));
+ AssertConstantField(type, "SOul", sizeof(ulong));
+ AssertConstantField(type, "SOc", sizeof(char));
+ AssertConstantField(type, "SOf", sizeof(float));
+ AssertConstantField(type, "SOd", sizeof(double));
+ AssertConstantField(type, "SObl", sizeof(bool));
+ AssertConstantField(type, "SOe", sizeof(MyEnum));
}
}
}
diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
index 4d509330fe..e415dbff55 100644
--- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
+++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
@@ -111,6 +111,7 @@
+
diff --git a/ICSharpCode.NRefactory/Semantics/SizeOfResolveResult.cs b/ICSharpCode.NRefactory/Semantics/SizeOfResolveResult.cs
new file mode 100644
index 0000000000..a4c949bdd6
--- /dev/null
+++ b/ICSharpCode.NRefactory/Semantics/SizeOfResolveResult.cs
@@ -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
+{
+ ///
+ /// Represents the 'typeof'.
+ ///
+ 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;
+ }
+
+ ///
+ /// The type referenced by the 'sizeof'.
+ ///
+ 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;
+ }
+ }
+ }
+}