Skip to content

Commit b523d6c

Browse files
Merge pull request #677 from rolfbjarne/objctypeparamdecl-variance-and-bounds
Expose ObjCTypeParamDecl->hasExplicitBound|getVariance to ClangSharp.
2 parents 61c44ba + bb0dcd6 commit b523d6c

7 files changed

Lines changed: 99 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
@@ -1925,6 +1925,10 @@ public readonly int GetPlatformAvailability(out bool alwaysDeprecated, out CXStr
19251925

19261926
public readonly CXCursor GetTypeParam(uint index) => clangsharp.Cursor_getTypeParam(this, index);
19271927

1928+
public readonly bool TypeParamHasExplicitBound => clangsharp.Cursor_getTypeParamHasExplicitBound(this) != 0;
1929+
1930+
public readonly ObjCTypeParamVariance TypeParamVariance => (ObjCTypeParamVariance)clangsharp.Cursor_getTypeParamVariance(this);
1931+
19281932
public readonly CXCursor GetVBase(uint index) => clangsharp.Cursor_getVBase(this, index);
19291933

19301934
public override readonly string ToString() => Spelling.ToString();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// 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.
2+
3+
// Ported from https://github.com/llvm/llvm-project/tree/llvmorg-21.1.8/clang/include/clang-c
4+
// Original source is Copyright (c) the LLVM Project and Contributors. Licensed under the Apache License v2.0 with LLVM Exceptions. See NOTICE.txt in the project root for license information.
5+
6+
using System;
7+
8+
namespace ClangSharp.Interop;
9+
10+
public enum ObjCTypeParamVariance
11+
{
12+
Invariant,
13+
Covariant,
14+
Contravariant,
15+
}

sources/ClangSharp.Interop/clangsharp/clangsharp.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,14 @@ public static partial class @clangsharp
906906
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getUsedContext", ExactSpelling = true)]
907907
public static extern CXCursor Cursor_getUsedContext(CXCursor C);
908908

909+
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getTypeParamHasExplicitBound", ExactSpelling = true)]
910+
[return: NativeTypeName("unsigned int")]
911+
public static extern uint Cursor_getTypeParamHasExplicitBound(CXCursor C);
912+
913+
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getTypeParamVariance", ExactSpelling = true)]
914+
[return: NativeTypeName("unsigned int")]
915+
public static extern uint Cursor_getTypeParamVariance(CXCursor C);
916+
909917
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getVBase", ExactSpelling = true)]
910918
public static extern CXCursor Cursor_getVBase(CXCursor C, [NativeTypeName("unsigned int")] uint i);
911919

sources/ClangSharp/Cursors/Decls/ObjCTypeParamDecl.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,8 @@ internal ObjCTypeParamDecl(CXCursor handle) : base(handle, CXCursor_TemplateType
1313
}
1414

1515
public uint Index => unchecked((uint)Handle.TemplateTypeParmIndex);
16+
17+
public bool HasExplicitBound => Handle.TypeParamHasExplicitBound;
18+
19+
public ObjCTypeParamVariance Variance => Handle.TypeParamVariance;
1620
}

sources/libClangSharp/ClangSharp.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4944,6 +4944,32 @@ CXCursor clangsharp_Cursor_getUsedContext(CXCursor C) {
49444944
return clang_getNullCursor();
49454945
}
49464946

4947+
CLANGSHARP_LINKAGE unsigned clangsharp_Cursor_getTypeParamHasExplicitBound(CXCursor C)
4948+
{
4949+
if (isDeclOrTU(C.kind)) {
4950+
const Decl* D = getCursorDecl(C);
4951+
4952+
if (const ObjCTypeParamDecl* OCTPD = dyn_cast<ObjCTypeParamDecl>(D)) {
4953+
return OCTPD->hasExplicitBound();
4954+
}
4955+
}
4956+
4957+
return 0;
4958+
}
4959+
4960+
CLANGSHARP_LINKAGE unsigned clangsharp_Cursor_getTypeParamVariance(CXCursor C)
4961+
{
4962+
if (isDeclOrTU(C.kind)) {
4963+
const Decl* D = getCursorDecl(C);
4964+
4965+
if (const ObjCTypeParamDecl* OCTPD = dyn_cast<ObjCTypeParamDecl>(D)) {
4966+
return (unsigned int) OCTPD->getVariance();
4967+
}
4968+
}
4969+
4970+
return 0 /* ObjCTypeParamVariance::Invariant */;
4971+
}
4972+
49474973
CXCursor clangsharp_Cursor_getVBase(CXCursor C, unsigned i) {
49484974
if (isDeclOrTU(C.kind)) {
49494975
const Decl* D = getCursorDecl(C);

sources/libClangSharp/ClangSharp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,10 @@ CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getUninstantiatedDefaultArg(CXCurs
759759

760760
CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getUsedContext(CXCursor C);
761761

762+
CLANGSHARP_LINKAGE unsigned clangsharp_Cursor_getTypeParamHasExplicitBound(CXCursor C);
763+
764+
CLANGSHARP_LINKAGE unsigned clangsharp_Cursor_getTypeParamVariance(CXCursor C);
765+
762766
CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getVBase(CXCursor C, unsigned i);
763767

764768
CLANGSHARP_LINKAGE int64_t clangsharp_Cursor_getDtorVtblIdx(CXCursor C, CX_DestructorType dtor);

tests/ClangSharp.UnitTests/ObjectiveCTest.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,12 @@ @interface NSObject
357357
@interface MyClass<T, Y> (MyCategory)
358358
@end
359359
360+
@interface MyVariantClass<__contravariant T, __covariant U, V> : NSObject
361+
@end
362+
363+
@interface MyBoundedClass<T : NSObject*> : NSObject
364+
@end
365+
360366
""";
361367
using var translationUnit = CreateTranslationUnit(inputContents, "objective-c++");
362368

@@ -368,7 +374,11 @@ @interface MyClass<T, Y> (MyCategory)
368374
var myClassTypeParams = myClass.TypeParamList.ToList();
369375
Assert.That(myClassTypeParams.Count, Is.EqualTo(2), "myClassTypeParams.Count");
370376
Assert.That(myClassTypeParams[0].Name, Is.EqualTo("A"), "myClassTypeParams[0].Name");
377+
Assert.That(myClassTypeParams[0].HasExplicitBound, Is.EqualTo(false), "myClassTypeParams[0].HasExplicitBound");
378+
Assert.That(myClassTypeParams[0].Variance, Is.EqualTo(ObjCTypeParamVariance.Invariant), "myClassTypeParams[0].Variance");
371379
Assert.That(myClassTypeParams[1].Name, Is.EqualTo("B"), "myClassTypeParams[1].Name");
380+
Assert.That(myClassTypeParams[1].HasExplicitBound, Is.EqualTo(false), "myClassTypeParams[1].HasExplicitBound");
381+
Assert.That(myClassTypeParams[1].Variance, Is.EqualTo(ObjCTypeParamVariance.Invariant), "myClassTypeParams[1].Variance");
372382

373383
var categories = translationUnit.TranslationUnitDecl.Decls.OfType<ObjCCategoryDecl>().ToList();
374384
var myCategory = categories.SingleOrDefault(v => v.Name == "MyCategory")!;
@@ -377,7 +387,35 @@ @interface MyClass<T, Y> (MyCategory)
377387
var myCategoryTypeParams = myCategory.TypeParamList.ToList();
378388
Assert.That(myCategoryTypeParams.Count, Is.EqualTo(2), "myCategoryTypeParams.Count");
379389
Assert.That(myCategoryTypeParams[0].Name, Is.EqualTo("T"), "myCategoryTypeParams[0].Name");
390+
Assert.That(myCategoryTypeParams[0].HasExplicitBound, Is.EqualTo(false), "myCategoryTypeParams[0].HasExplicitBound");
391+
Assert.That(myCategoryTypeParams[0].Variance, Is.EqualTo(ObjCTypeParamVariance.Invariant), "myCategoryTypeParams[0].Variance");
380392
Assert.That(myCategoryTypeParams[1].Name, Is.EqualTo("Y"), "myCategoryTypeParams[1].Name");
393+
Assert.That(myCategoryTypeParams[1].HasExplicitBound, Is.EqualTo(false), "myCategoryTypeParams[1].HasExplicitBound");
394+
Assert.That(myCategoryTypeParams[1].Variance, Is.EqualTo(ObjCTypeParamVariance.Invariant), "myCategoryTypeParams[1].Variance");
395+
396+
var myVariantClass = classes.SingleOrDefault(v => v.Name == "MyVariantClass")!;
397+
Assert.That(myVariantClass, Is.Not.Null, "MyVariantClass");
398+
Assert.That(myVariantClass.TypeParamList, Is.Not.Null, "myVariantClass TypeParamList");
399+
var myVariantClassTypeParams = myVariantClass.TypeParamList.ToList();
400+
Assert.That(myVariantClassTypeParams.Count, Is.EqualTo(3), "myVariantClassTypeParams.Count");
401+
Assert.That(myVariantClassTypeParams[0].Name, Is.EqualTo("T"), "myVariantClassTypeParams[0].Name");
402+
Assert.That(myVariantClassTypeParams[1].Name, Is.EqualTo("U"), "myVariantClassTypeParams[1].Name");
403+
Assert.That(myVariantClassTypeParams[2].Name, Is.EqualTo("V"), "myVariantClassTypeParams[2].Name");
404+
Assert.That(myVariantClassTypeParams[0].HasExplicitBound, Is.EqualTo(false), "myVariantClassTypeParams[0].HasExplicitBound");
405+
Assert.That(myVariantClassTypeParams[1].HasExplicitBound, Is.EqualTo(false), "myVariantClassTypeParams[1].HasExplicitBound");
406+
Assert.That(myVariantClassTypeParams[2].HasExplicitBound, Is.EqualTo(false), "myBoundedClassTypeParams[2].HasExplicitBound");
407+
Assert.That(myVariantClassTypeParams[0].Variance, Is.EqualTo(ObjCTypeParamVariance.Contravariant), "myVariantClassTypeParams[0].Variance");
408+
Assert.That(myVariantClassTypeParams[1].Variance, Is.EqualTo(ObjCTypeParamVariance.Covariant), "myVariantClassTypeParams[1].Variance");
409+
Assert.That(myVariantClassTypeParams[2].Variance, Is.EqualTo(ObjCTypeParamVariance.Invariant), "myVariantClassTypeParams[2].Variance");
410+
411+
var myBoundedClass = classes.SingleOrDefault(v => v.Name == "MyBoundedClass")!;
412+
Assert.That(myBoundedClass, Is.Not.Null, "MyBoundedClass");
413+
Assert.That(myBoundedClass.TypeParamList, Is.Not.Null, "myBoundedClass TypeParamList");
414+
var myBoundedClassTypeParams = myBoundedClass.TypeParamList.ToList();
415+
Assert.That(myBoundedClassTypeParams.Count, Is.EqualTo(1), "myBoundedClassTypeParams.Count");
416+
Assert.That(myBoundedClassTypeParams[0].Name, Is.EqualTo("T"), "myBoundedClassTypeParams[0].Name");
417+
Assert.That(myBoundedClassTypeParams[0].HasExplicitBound, Is.EqualTo(true), "myBoundedClassTypeParams[0].HasExplicitBound");
418+
Assert.That(myBoundedClassTypeParams[0].Variance, Is.EqualTo(ObjCTypeParamVariance.Invariant), "myBoundedClassTypeParams[0].Variance");
381419
}
382420

383421
[Test]

0 commit comments

Comments
 (0)