diff --git a/Directory.Build.props b/Directory.Build.props
index 4797b4f0..39a8f51d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -47,7 +47,7 @@
17.0.0
ClangSharp
ClangSharp
- 18.1.0.3
+ 18.1.0.4
rc1
pr
diff --git a/scripts/build.ps1 b/scripts/build.ps1
index 5558ed50..882eba52 100644
--- a/scripts/build.ps1
+++ b/scripts/build.ps1
@@ -20,7 +20,7 @@ $ErrorActionPreference = "Stop"
function Build() {
$logFile = Join-Path -Path $LogDir -ChildPath "$configuration\build.binlog"
- & dotnet build -c "$configuration" --no-restore -v "$verbosity" /bl:"$logFile" /err "$properties" "$solution"
+ & dotnet build -c "$configuration" --no-restore -v "$verbosity" /bl:"$logFile" /err $properties "$solution"
if ($LastExitCode -ne 0) {
throw "'Build' failed for '$solution'"
@@ -57,7 +57,7 @@ function Help() {
function Pack() {
$logFile = Join-Path -Path $LogDir -ChildPath "$configuration\pack.binlog"
- & dotnet pack -c "$configuration" --no-build --no-restore -v "$verbosity" /bl:"$logFile" /err "$properties" "$solution"
+ & dotnet pack -c "$configuration" --no-build --no-restore -v "$verbosity" /bl:"$logFile" /err $properties "$solution"
if ($LastExitCode -ne 0) {
throw "'Pack' failed for '$solution'"
@@ -66,7 +66,7 @@ function Pack() {
function Restore() {
$logFile = Join-Path -Path $LogDir -ChildPath "$configuration\restore.binlog"
- & dotnet restore -v "$verbosity" /bl:"$logFile" /err "$properties" "$solution"
+ & dotnet restore -v "$verbosity" /bl:"$logFile" /err $properties "$solution"
if ($LastExitCode -ne 0) {
throw "'Restore' failed for '$solution'"
@@ -75,7 +75,7 @@ function Restore() {
function Test() {
$logFile = Join-Path -Path $LogDir -ChildPath "$configuration\test.binlog"
- & dotnet test -c "$configuration" --no-build --no-restore -v "$verbosity" /bl:"$logFile" /err "$properties" "$solution"
+ & dotnet test -c "$configuration" --no-build --no-restore -v "$verbosity" /bl:"$logFile" /err $properties "$solution"
if ($LastExitCode -ne 0) {
throw "'Test' failed for '$solution'"
diff --git a/sources/ClangSharp.Interop/clangsharp/clangsharp.cs b/sources/ClangSharp.Interop/clangsharp/clangsharp.cs
index 91979977..540329f0 100644
--- a/sources/ClangSharp.Interop/clangsharp/clangsharp.cs
+++ b/sources/ClangSharp.Interop/clangsharp/clangsharp.cs
@@ -1043,6 +1043,9 @@ public static partial class @clangsharp
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Type_getOriginalType", ExactSpelling = true)]
public static extern CXType Type_getOriginalType(CXType CT);
+ [DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Type_getSubstTemplateTypeParamAssociatedDecl", ExactSpelling = true)]
+ public static extern CXCursor Type_getSubstTemplateTypeParamAssociatedDecl(CXType CT);
+
[DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Type_getOwnedTagDecl", ExactSpelling = true)]
public static extern CXCursor Type_getOwnedTagDecl(CXType CT);
diff --git a/sources/ClangSharp.PInvokeGenerator/Abstractions/FunctionOrDelegateDesc.cs b/sources/ClangSharp.PInvokeGenerator/Abstractions/FunctionOrDelegateDesc.cs
index d05c90b3..0a33d680 100644
--- a/sources/ClangSharp.PInvokeGenerator/Abstractions/FunctionOrDelegateDesc.cs
+++ b/sources/ClangSharp.PInvokeGenerator/Abstractions/FunctionOrDelegateDesc.cs
@@ -21,6 +21,7 @@ internal struct FunctionOrDelegateDesc
public bool HasBody { get; set; }
public bool IsInherited { get; set; }
public bool NeedsUnscopedRef { get; set; }
+ public string[]? ParameterTypes { get; set; }
public bool IsVirtual
{
diff --git a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs
index 712f8c81..8380a582 100644
--- a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs
+++ b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs
@@ -372,6 +372,12 @@ public void BeginFunctionOrDelegate(in FunctionOrDelegateDesc desc, ref bool isM
Write(desc.ParentName);
Write('.');
Write(desc.EscapedName);
+ if (desc.ParameterTypes is not null)
+ {
+ Write('(');
+ Write(string.Join(", ", desc.ParameterTypes));
+ Write(')');
+ }
WriteLine("\" />");
}
else
diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
index c1e270f5..2e37bb02 100644
--- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
+++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
@@ -501,6 +501,7 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
var name = GetRemappedCursorName(functionDecl);
var cxxMethodDecl = functionDecl as CXXMethodDecl;
+ uint overloadCount = 0;
if (cxxMethodDecl is not null and CXXConstructorDecl)
{
@@ -509,6 +510,11 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
name = GetRemappedCursorName(parent);
}
+ if (cxxMethodDecl is not null)
+ {
+ overloadCount = GetOverloadCount(cxxMethodDecl);
+ }
+
var isManualImport = _config.WithManualImports.Contains(name);
var className = name;
@@ -622,6 +628,7 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
}
},
CustomAttrGeneratorData = (functionDecl, _outputBuilder, this),
+ ParameterTypes = overloadCount > 1 ? functionDecl.Parameters.Select(param => GetTargetTypeName(param, out var _)).ToArray() : null,
};
Debug.Assert(_outputBuilder is not null);
@@ -1404,7 +1411,15 @@ private void VisitRecordDecl(RecordDecl recordDecl)
var className = GetClass(uuidName);
_testOutputBuilder.AddUsingDirective("System");
- _testOutputBuilder.AddUsingDirective($"static {GetNamespace(className)}.{className}");
+
+ if (_config.DontUseUsingStaticsForGuidMember)
+ {
+ _testOutputBuilder.AddUsingDirective($"{GetNamespace(className)}");
+ }
+ else
+ {
+ _testOutputBuilder.AddUsingDirective($"static {GetNamespace(className)}.{className}");
+ }
_testOutputBuilder.WriteIndented("/// Validates that the of the ExcludedNames
public bool StripEnumMemberTypeName => _options.HasFlag(PInvokeGeneratorConfigurationOptions.StripEnumMemberTypeName);
+ public bool DontUseUsingStaticsForGuidMember => _options.HasFlag(PInvokeGeneratorConfigurationOptions.DontUseUsingStaticsForGuidMember);
+
public string HeaderText => _headerText;
[AllowNull]
diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfigurationOptions.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfigurationOptions.cs
index c2a34293..cd77e71c 100644
--- a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfigurationOptions.cs
+++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfigurationOptions.cs
@@ -88,4 +88,6 @@ public enum PInvokeGeneratorConfigurationOptions : long
GenerateGenericPointerWrapper = 1L << 38,
StripEnumMemberTypeName = 1L << 39,
+
+ DontUseUsingStaticsForGuidMember = 1L << 40,
}
diff --git a/sources/ClangSharp/Cursors/Decls/TemplateTypeParmDecl.cs b/sources/ClangSharp/Cursors/Decls/TemplateTypeParmDecl.cs
index f68532c1..ca0f4b1f 100644
--- a/sources/ClangSharp/Cursors/Decls/TemplateTypeParmDecl.cs
+++ b/sources/ClangSharp/Cursors/Decls/TemplateTypeParmDecl.cs
@@ -5,13 +5,14 @@
using ClangSharp.Interop;
using static ClangSharp.Interop.CXCursorKind;
using static ClangSharp.Interop.CX_DeclKind;
+using static ClangSharp.Interop.CXTypeKind;
namespace ClangSharp;
public sealed class TemplateTypeParmDecl : TypeDecl
{
private readonly Lazy> _associatedConstraints;
- private readonly Lazy _defaultArgument;
+ private readonly Lazy _defaultArgument;
internal TemplateTypeParmDecl(CXCursor handle) : base(handle, CXCursor_TemplateTypeParameter, CX_DeclKind_TemplateTypeParm)
{
@@ -27,12 +28,15 @@ internal TemplateTypeParmDecl(CXCursor handle) : base(handle, CXCursor_TemplateT
return associatedConstraints;
});
- _defaultArgument = new Lazy(() => TranslationUnit.GetOrCreate(Handle.DefaultArgType));
+ _defaultArgument = new Lazy(() => {
+ CXType defaultArgType = Handle.DefaultArgType;
+ return defaultArgType.kind == CXType_Invalid ? null : TranslationUnit.GetOrCreate(defaultArgType);
+ });
}
public IReadOnlyList AssociatedConstraints => _associatedConstraints.Value;
- public Type DefaultArgument => _defaultArgument.Value;
+ public Type? DefaultArgument => _defaultArgument.Value;
public bool DefaultArgumentWasInherited => Handle.HasInheritedDefaultArg;
diff --git a/sources/ClangSharp/Types/SubstTemplateTypeParmType.cs b/sources/ClangSharp/Types/SubstTemplateTypeParmType.cs
index 517d387b..d09e2a5c 100644
--- a/sources/ClangSharp/Types/SubstTemplateTypeParmType.cs
+++ b/sources/ClangSharp/Types/SubstTemplateTypeParmType.cs
@@ -9,14 +9,21 @@ namespace ClangSharp;
public sealed class SubstTemplateTypeParmType : Type
{
+ private readonly Lazy _associatedDecl;
private readonly Lazy _replacedParameter;
internal SubstTemplateTypeParmType(CXType handle) : base(handle, CXType_Unexposed, CX_TypeClass_SubstTemplateTypeParm)
{
+ _associatedDecl = new Lazy(() => {
+ CXCursor cursor = clangsharp.Type_getSubstTemplateTypeParamAssociatedDecl(Handle);
+ return cursor.IsNull ? null : TranslationUnit.GetOrCreate(cursor);
+ });
_replacedParameter = new Lazy(() => TranslationUnit.GetOrCreate(Handle.OriginalType));
}
public TemplateTypeParmType ReplacedParameter => _replacedParameter.Value;
public Type ReplacementType => Desugar;
+
+ public Decl? AssociatedDecl => _associatedDecl.Value;
}
diff --git a/sources/ClangSharpPInvokeGenerator/Program.cs b/sources/ClangSharpPInvokeGenerator/Program.cs
index 322ef1e4..8bad0657 100644
--- a/sources/ClangSharpPInvokeGenerator/Program.cs
+++ b/sources/ClangSharpPInvokeGenerator/Program.cs
@@ -444,6 +444,13 @@ public static void Run(InvocationContext context)
break;
}
+ case "exclude-using-statics-for-guid-members":
+ case "dont-use-using-statics-for-guid-members":
+ {
+ configOptions |= PInvokeGeneratorConfigurationOptions.DontUseUsingStaticsForGuidMember;
+ break;
+ }
+
// VTBL Options
case "explicit-vtbls":
diff --git a/sources/libClangSharp/ClangSharp.cpp b/sources/libClangSharp/ClangSharp.cpp
index 5880900c..d0f0c8a9 100644
--- a/sources/libClangSharp/ClangSharp.cpp
+++ b/sources/libClangSharp/ClangSharp.cpp
@@ -26,10 +26,38 @@ using namespace clang::cxstring;
using namespace clang::cxtu;
using namespace clang::cxtype;
+CXTemplateArgumentKind ConvertTemplateArgumentKind(TemplateArgument::ArgKind kind) {
+ switch (kind) {
+ case TemplateArgument::Null:
+ return CXTemplateArgumentKind_Null;
+ case TemplateArgument::Type:
+ return CXTemplateArgumentKind_Type;
+ case TemplateArgument::Declaration:
+ return CXTemplateArgumentKind_Declaration;
+ case TemplateArgument::NullPtr:
+ return CXTemplateArgumentKind_NullPtr;
+ case TemplateArgument::Integral:
+ return CXTemplateArgumentKind_Integral;
+ case TemplateArgument::StructuralValue:
+ // Does not exist in CXTemplateArgumentKind
+ return CXTemplateArgumentKind_Invalid;
+ case TemplateArgument::Template:
+ return CXTemplateArgumentKind_Template;
+ case TemplateArgument::TemplateExpansion:
+ return CXTemplateArgumentKind_TemplateExpansion;
+ case TemplateArgument::Expression:
+ return CXTemplateArgumentKind_Expression;
+ case TemplateArgument::Pack:
+ return CXTemplateArgumentKind_Pack;
+ default:
+ return CXTemplateArgumentKind_Invalid;
+ }
+}
+
CX_TemplateArgument MakeCXTemplateArgument(const TemplateArgument* TA, CXTranslationUnit TU, bool needsDispose = false) {
if (TA) {
assert(TU && "Invalid arguments!");
- return { static_cast(TA->getKind()), (needsDispose ? 1 : 0), TA, TU };
+ return { ConvertTemplateArgumentKind(TA->getKind()), (needsDispose ? 1 : 0), TA, TU };
}
return { };
@@ -1009,15 +1037,19 @@ CXCursor clangsharp_Cursor_getDefaultArg(CXCursor C) {
}
CXType clangsharp_Cursor_getDefaultArgType(CXCursor C) {
+ QualType QT;
+
if (isDeclOrTU(C.kind)) {
const Decl* D = getCursorDecl(C);
if (const TemplateTypeParmDecl* TTPD = dyn_cast(D)) {
- return MakeCXType(TTPD->getDefaultArgument(), getCursorTU(C));
+ if (TTPD->hasDefaultArgument()) {
+ QT = TTPD->getDefaultArgument();
+ }
}
}
- return MakeCXType(QualType(), getCursorTU(C));
+ return MakeCXType(QT, getCursorTU(C));
}
CXCursor clangsharp_Cursor_getDefinition(CXCursor C) {
@@ -5369,6 +5401,17 @@ CXType clangsharp_Type_getOriginalType(CXType CT) {
return MakeCXType(QualType(), GetTypeTU(CT));
}
+CXCursor clangsharp_Type_getSubstTemplateTypeParamAssociatedDecl(CXType CT) {
+ QualType T = GetQualType(CT);
+ const Type* TP = T.getTypePtrOrNull();
+
+ if (const SubstTemplateTypeParmType* STTPT = dyn_cast(TP)) {
+ return MakeCXCursor(STTPT->getAssociatedDecl(), GetTypeTU(CT));
+ }
+
+ clang_getNullCursor();
+}
+
CXCursor clangsharp_Type_getOwnedTagDecl(CXType CT) {
QualType T = GetQualType(CT);
const Type* TP = T.getTypePtrOrNull();
diff --git a/sources/libClangSharp/ClangSharp.h b/sources/libClangSharp/ClangSharp.h
index 01120c2b..b7ea675a 100644
--- a/sources/libClangSharp/ClangSharp.h
+++ b/sources/libClangSharp/ClangSharp.h
@@ -841,6 +841,8 @@ CLANGSHARP_LINKAGE int clangsharp_Type_getNumRows(CXType CT);
CLANGSHARP_LINKAGE CXType clangsharp_Type_getOriginalType(CXType CT);
+CLANGSHARP_LINKAGE CXCursor clangsharp_Type_getSubstTemplateTypeParamAssociatedDecl(CXType CT);
+
CLANGSHARP_LINKAGE CXCursor clangsharp_Type_getOwnedTagDecl(CXType CT);
CLANGSHARP_LINKAGE CXType clangsharp_Type_getPointeeType(CXType CT);
diff --git a/tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs b/tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs
index 067280f1..e216b73b 100644
--- a/tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs
+++ b/tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs
@@ -74,4 +74,27 @@ class MyClass
var templateParameter = classTemplatePartialSpecializationDecl.TemplateParameters.Single();
Assert.That(templateParameter.Name, Is.EqualTo("U"));
}
+
+ [Test]
+ [Ignore("TODO: LibClangSharp needs to be recompiled first")]
+ public void TemplateParameterPackTest()
+ {
+ var inputContents = $@"template
+class tuple;
+
+tuple SomeFunction();
+";
+
+ using var translationUnit = CreateTranslationUnit(inputContents);
+
+ var functionDecl = translationUnit.TranslationUnitDecl.Decls.OfType().Single();
+ var tupleDecl = functionDecl.ReturnType.AsCXXRecordDecl as ClassTemplateSpecializationDecl;
+ Assert.That(tupleDecl, Is.Not.Null);
+ Assert.That(tupleDecl!.TemplateArgs.Count, Is.EqualTo(1));
+
+ var packElements = tupleDecl.TemplateArgs[0].PackElements;
+ Assert.That(packElements.Count, Is.EqualTo(2));
+ Assert.That(packElements[0].AsType.AsString, Is.EqualTo("int"));
+ Assert.That(packElements[1].AsType.AsString, Is.EqualTo("long"));
+ }
}