Skip to content

Commit a6c0ab9

Browse files
Merge pull request #674 from rolfbjarne/integerliteral-unsignedvalue
Add IntegerLiteral.UnsignedValue.
2 parents e1e186e + 20b41e8 commit a6c0ab9

File tree

6 files changed

+81
-0
lines changed

6 files changed

+81
-0
lines changed

sources/ClangSharp.Interop/Extensions/CXCursor.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,8 @@ public readonly CXCursor DefaultArg
10031003

10041004
public readonly long IntegerLiteralValue => clangsharp.Cursor_getIntegerLiteralValue(this);
10051005

1006+
public readonly ulong UnsignedIntegerLiteralValue => clangsharp.Cursor_getUnsignedIntegerLiteralValue(this);
1007+
10061008
public readonly bool IsAllEnumCasesCovered => clangsharp.Cursor_getIsAllEnumCasesCovered(this) != 0;
10071009

10081010
public readonly bool IsAlwaysNull => clangsharp.Cursor_getIsAlwaysNull(this) != 0;

sources/ClangSharp.Interop/clangsharp/clangsharp.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,10 @@ public static partial class @clangsharp
380380
[return: NativeTypeName("int64_t")]
381381
public static extern long Cursor_getIntegerLiteralValue(CXCursor C);
382382

383+
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getUnsignedIntegerLiteralValue", ExactSpelling = true)]
384+
[return: NativeTypeName("uint64_t")]
385+
public static extern ulong Cursor_getUnsignedIntegerLiteralValue(CXCursor C);
386+
383387
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getIsAllEnumCasesCovered", ExactSpelling = true)]
384388
[return: NativeTypeName("unsigned int")]
385389
public static extern uint Cursor_getIsAllEnumCasesCovered(CXCursor C);

sources/ClangSharp/Cursors/Exprs/IntegerLiteral.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,7 @@ internal IntegerLiteral(CXCursor handle) : base(handle, CXCursor_IntegerLiteral,
4343

4444
public long Value => Handle.IntegerLiteralValue;
4545

46+
public ulong UnsignedValue => Handle.UnsignedIntegerLiteralValue;
47+
4648
public string ValueString => _valueString.Value;
4749
}

sources/libClangSharp/ClangSharp.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,18 @@ int64_t clangsharp_Cursor_getIntegerLiteralValue(CXCursor C) {
19391939
return 0;
19401940
}
19411941

1942+
uint64_t clangsharp_Cursor_getUnsignedIntegerLiteralValue(CXCursor C) {
1943+
if (isStmtOrExpr(C.kind)) {
1944+
const Stmt* S = getCursorStmt(C);
1945+
1946+
if (const IntegerLiteral* IL = dyn_cast<IntegerLiteral>(S)) {
1947+
return IL->getValue().getZExtValue();
1948+
}
1949+
}
1950+
1951+
return 0;
1952+
}
1953+
19421954
unsigned clangsharp_Cursor_getIsAllEnumCasesCovered(CXCursor C) {
19431955
if (isStmtOrExpr(C.kind)) {
19441956
const Stmt* S = getCursorStmt(C);

sources/libClangSharp/ClangSharp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,8 @@ CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getInstantiatedFromMember(CXCursor
455455

456456
CLANGSHARP_LINKAGE int64_t clangsharp_Cursor_getIntegerLiteralValue(CXCursor C);
457457

458+
CLANGSHARP_LINKAGE uint64_t clangsharp_Cursor_getUnsignedIntegerLiteralValue(CXCursor C);
459+
458460
CLANGSHARP_LINKAGE unsigned clangsharp_Cursor_getIsAllEnumCasesCovered(CXCursor C);
459461

460462
CLANGSHARP_LINKAGE unsigned clangsharp_Cursor_getIsAlwaysNull(CXCursor C);

tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,63 @@ struct B {
125125
Assert.That(structB, Is.Not.Null, "struct B not found");
126126
Assert.That(structB.IsPOD, Is.False, "struct B should be not POD");
127127
}
128+
129+
[Test]
130+
public void UnsignedValue()
131+
{
132+
ObjectiveCTest.AssertNeedNewClangSharp();
133+
134+
var inputContents = $$"""
135+
enum E {
136+
A = 1,
137+
B = 4294967295U,
138+
C = 4294967296U,
139+
D = 18446744073709551615ULL,
140+
E = -1,
141+
F = -4294967295,
142+
G = -4294967296,
143+
H = -18446744073709551615LL,
144+
};
145+
""";
146+
147+
using var translationUnit = CreateTranslationUnit(inputContents);
148+
149+
var decls = translationUnit.TranslationUnitDecl.Decls.OfType<EnumDecl>().ToList();
150+
151+
var enumE = decls.SingleOrDefault(d => d.Name == "E")!;
152+
Assert.That(enumE, Is.Not.Null, "enum E not found");
153+
154+
var checkField = (string fieldName, long expectedValue, ulong expectedUnsignedValue, bool negative) => {
155+
var field = enumE.Enumerators.SingleOrDefault(e => e.Name == fieldName)!;
156+
Assert.That(field, Is.Not.Null, $"enum E::{fieldName} not found");
157+
var initExpr = field.InitExpr;
158+
Assert.That(initExpr, Is.Not.Null, $"enum E::{fieldName} InitExpr is null");
159+
160+
var isNegativeExpression = false;
161+
var castExpr = (ImplicitCastExpr)initExpr!;
162+
var subExpr = castExpr.SubExpr;
163+
if (subExpr is UnaryOperator unaryOperator)
164+
{
165+
Assert.That(unaryOperator.Opcode, Is.EqualTo(CXUnaryOperatorKind.CXUnaryOperator_Minus), $"enum E::{fieldName} InitExpr is not a minus UnaryOperator");
166+
subExpr = unaryOperator.SubExpr;
167+
isNegativeExpression = true;
168+
}
169+
var literalExpr = subExpr as IntegerLiteral;
170+
Assert.That(literalExpr, Is.Not.Null, $"enum E::{fieldName} InitExpr is not IntegerLiteral {castExpr.SubExpr!.GetType().Name}");
171+
Assert.That(literalExpr!.Value, Is.EqualTo(expectedValue), $"enum E::{fieldName} value mismatch");
172+
Assert.That(literalExpr!.UnsignedValue, Is.EqualTo(expectedUnsignedValue), $"enum E::{fieldName} unsigned value mismatch");
173+
Assert.That(negative, Is.EqualTo(isNegativeExpression), $"enum E::{fieldName} negative mismatch");
174+
};
175+
176+
Assert.Multiple(() => {
177+
checkField("A", 1, 1, false);
178+
checkField("B", -1, 4294967295UL, false);
179+
checkField("C", 4294967296, 4294967296UL, false);
180+
checkField("D", -1, 18446744073709551615UL, false);
181+
checkField("E", 1, 1, true);
182+
checkField("F", 4294967295, 4294967295, true);
183+
checkField("G", 4294967296, 4294967296, true);
184+
checkField("H", -1, 18446744073709551615UL, true);
185+
});
186+
}
128187
}

0 commit comments

Comments
 (0)