Skip to content

Commit bb0dcd6

Browse files
authored
Merge branch 'main' into objctypeparamdecl-variance-and-bounds
2 parents 4ff8f28 + 85eebc8 commit bb0dcd6

9 files changed

Lines changed: 181 additions & 0 deletions

File tree

sources/ClangSharp.Interop/Extensions/CXCursor.cs

Lines changed: 4 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;
@@ -1271,6 +1273,8 @@ public readonly CXCursor DefaultArg
12711273

12721274
public readonly CXString ObjCPropertySetterName => clang.Cursor_getObjCPropertySetterName(this);
12731275

1276+
public readonly CXString ObjCRuntimeNameAttrMetadataName => clangsharp.Cursor_getObjCRuntimeNameAttrMetadataName(this);
1277+
12741278
public readonly int ObjCSelectorIndex => clang.Cursor_getObjCSelectorIndex(this);
12751279

12761280
public readonly long OffsetOfField => clang.Cursor_getOffsetOfField(this);

sources/ClangSharp.Interop/clangsharp/clangsharp.cs

Lines changed: 7 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);
@@ -748,6 +752,9 @@ public static partial class @clangsharp
748752
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getNumVBases", ExactSpelling = true)]
749753
public static extern int Cursor_getNumVBases(CXCursor C);
750754

755+
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getObjCRuntimeNameAttrMetadataName", ExactSpelling = true)]
756+
public static extern CXString Cursor_getObjCRuntimeNameAttrMetadataName(CXCursor C);
757+
751758
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getOpaqueValue", ExactSpelling = true)]
752759
public static extern CXCursor Cursor_getOpaqueValue(CXCursor C);
753760

sources/ClangSharp/Cursors/Attrs/Attr.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,4 +473,6 @@ private protected Attr(CXCursor handle) : base(handle, handle.Kind)
473473
public string KindSpelling => Handle.AttrKindSpelling;
474474

475475
public string PrettyPrint() => Handle.PrettyPrintAttribute().ToString();
476+
477+
public string ObjCRuntimeNameMetadataName => Handle.ObjCRuntimeNameAttrMetadataName.ToString();
476478
}

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: 32 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);
@@ -2225,6 +2237,10 @@ unsigned clangsharp_Cursor_getIsExternC(CXCursor C) {
22252237
if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
22262238
return FD->isExternC();
22272239
}
2240+
2241+
if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
2242+
return VD->isExternC();
2243+
}
22282244
}
22292245

22302246
return 0;
@@ -3682,6 +3698,22 @@ int clangsharp_Cursor_getNumVBases(CXCursor C) {
36823698
return -1;
36833699
}
36843700

3701+
CLANGSHARP_LINKAGE CXString clangsharp_Cursor_getObjCRuntimeNameAttrMetadataName(CXCursor C)
3702+
{
3703+
if (clang_isAttribute(C.kind)) {
3704+
const Attr* A = getCursorAttr(C);
3705+
3706+
StringRef message;
3707+
if (const auto *OCRN = dyn_cast<ObjCRuntimeNameAttr>(A)) {
3708+
message = OCRN->getMetadataName();
3709+
}
3710+
3711+
return createDup(message);
3712+
}
3713+
3714+
return createEmpty();
3715+
}
3716+
36853717
CXCursor clangsharp_Cursor_getOpaqueValue(CXCursor C) {
36863718
if (isStmtOrExpr(C.kind)) {
36873719
const Stmt* S = getCursorStmt(C);

sources/libClangSharp/ClangSharp.h

Lines changed: 4 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);
@@ -657,6 +659,8 @@ CLANGSHARP_LINKAGE int clangsharp_Cursor_getNumTypeParams(CXCursor C);
657659

658660
CLANGSHARP_LINKAGE int clangsharp_Cursor_getNumVBases(CXCursor C);
659661

662+
CLANGSHARP_LINKAGE CXString clangsharp_Cursor_getObjCRuntimeNameAttrMetadataName(CXCursor C);
663+
660664
CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getOpaqueValue(CXCursor C);
661665

662666
CLANGSHARP_LINKAGE CXType clangsharp_Cursor_getOriginalType(CXCursor C);

tests/ClangSharp.UnitTests/CXCursor.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
22

3+
using System.Collections.Generic;
34
using System.Linq;
45
using NUnit.Framework;
56

@@ -25,4 +26,38 @@ public void AttrKindSpelling()
2526
Assert.That (functionDecl.Handle.AttrKindSpelling, Is.Not.Null.Or.Empty, "AttrKindSpelling");
2627
}
2728
}
29+
30+
[Test]
31+
public void IsExternC()
32+
{
33+
AssertNeedNewClangSharp();
34+
35+
var inputContents =
36+
$$"""
37+
extern "C" {
38+
int theUniverseAndEverything = 0;
39+
int hitchhike ();
40+
}
41+
""";
42+
43+
using var translationUnit = CreateTranslationUnit(inputContents);
44+
45+
var allDecls = new List<Decl>();
46+
allDecls.AddRange(translationUnit.TranslationUnitDecl.Decls);
47+
allDecls.AddRange(allDecls.OfType<LinkageSpecDecl>().SelectMany(v => v.Decls).ToList());
48+
49+
var functionDecls = allDecls.OfType<FunctionDecl>().ToList();
50+
Assert.That(functionDecls.Count, Is.GreaterThan(0), "Function");
51+
foreach (var decl in functionDecls)
52+
{
53+
Assert.That(decl.IsExternC, Is.True, "IsExternC function");
54+
}
55+
56+
var varDecls = allDecls.OfType<VarDecl>().ToList();
57+
Assert.That(varDecls.Count, Is.GreaterThan(0), "Var");
58+
foreach (var decl in varDecls)
59+
{
60+
Assert.That(decl.IsExternC, Is.True, "IsExternC var");
61+
}
62+
}
2863
}

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
}

tests/ClangSharp.UnitTests/ObjectiveCTest.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,42 @@ namespace ClangSharp.UnitTests;
1010
[Platform("macosx")]
1111
public sealed class ObjectiveCTest : TranslationUnitTest
1212
{
13+
[Test]
14+
public void Attribute_ObjCRuntimeName()
15+
{
16+
AssertNeedNewClangSharp();
17+
18+
var inputContents = $$"""
19+
__attribute__((objc_runtime_name("MyRenamedClass")))
20+
@interface MyClass
21+
@end
22+
23+
__attribute__((objc_runtime_name("MyRenamedProtocol")))
24+
@protocol MyProtocol
25+
@end
26+
""";
27+
using var translationUnit = CreateTranslationUnit(inputContents, "objective-c++");
28+
29+
var classes = translationUnit.TranslationUnitDecl.Decls.OfType<ObjCInterfaceDecl>().ToList();
30+
31+
var myClass = classes.SingleOrDefault(v => v.Name == "MyClass")!;
32+
Assert.That(myClass, Is.Not.Null, "MyClass");
33+
var myClassAttrs = myClass.Attrs;
34+
Assert.That(myClassAttrs.Count, Is.EqualTo(1), "myClassAttrs.Count");
35+
var runtimeNameAttr = myClassAttrs[0];
36+
Assert.That(runtimeNameAttr.Kind, Is.EqualTo(CX_AttrKind.CX_AttrKind_ObjCRuntimeName), "myClass Attr Kind");
37+
Assert.That(runtimeNameAttr.ObjCRuntimeNameMetadataName, Is.EqualTo("MyRenamedClass"), "myClass Attr ObjCRuntimeNameMetadataName");
38+
39+
var protocols = translationUnit.TranslationUnitDecl.Decls.OfType<ObjCProtocolDecl>().ToList();
40+
var myProtocol = protocols.SingleOrDefault(v => v.Name == "MyProtocol")!;
41+
Assert.That(myProtocol, Is.Not.Null, "MyProtocol");
42+
var myProtocolAttrs = myProtocol.Attrs;
43+
Assert.That(myProtocolAttrs.Count, Is.EqualTo(1), "myProtocolAttrs.Count");
44+
runtimeNameAttr = myProtocolAttrs[0];
45+
Assert.That(runtimeNameAttr.Kind, Is.EqualTo(CX_AttrKind.CX_AttrKind_ObjCRuntimeName), "myProtocol Attr Kind");
46+
Assert.That(runtimeNameAttr.ObjCRuntimeNameMetadataName, Is.EqualTo("MyRenamedProtocol"), "myProtocol Attr ObjCRuntimeNameMetadataName");
47+
}
48+
1349
[Test]
1450
public void Type_IsObjCInstanceType()
1551
{

0 commit comments

Comments
 (0)