diff --git a/sources/ClangSharp.Interop/Extensions/CXCursor.cs b/sources/ClangSharp.Interop/Extensions/CXCursor.cs index f889bdc3..6f066085 100644 --- a/sources/ClangSharp.Interop/Extensions/CXCursor.cs +++ b/sources/ClangSharp.Interop/Extensions/CXCursor.cs @@ -688,6 +688,8 @@ public readonly string CastKindSpelling public readonly bool CXXRecord_IsAbstract => clang.CXXRecord_isAbstract(this) != 0; + public readonly bool CXXRecord_IsPOD => clangsharp.Cursor_getCXXRecord_IsPOD(this) != 0; + public readonly CXType DeclaredReturnType => clangsharp.Cursor_getDeclaredReturnType(this); public readonly CX_DeclKind DeclKind => clangsharp.Cursor_getDeclKind(this); diff --git a/sources/ClangSharp.Interop/clangsharp/clangsharp.cs b/sources/ClangSharp.Interop/clangsharp/clangsharp.cs index cb0ea241..b3fb377b 100644 --- a/sources/ClangSharp.Interop/clangsharp/clangsharp.cs +++ b/sources/ClangSharp.Interop/clangsharp/clangsharp.cs @@ -167,6 +167,10 @@ public static partial class @clangsharp [DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getCtor", ExactSpelling = true)] public static extern CXCursor Cursor_getCtor(CXCursor C, [NativeTypeName("unsigned int")] uint i); + [DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getCXXRecord_IsPOD", ExactSpelling = true)] + [return: NativeTypeName("unsigned int")] + public static extern uint Cursor_getCXXRecord_IsPOD(CXCursor C); + [DllImport("libClangSharp", CallingConvention = CallingConvention.Cdecl, EntryPoint = "clangsharp_Cursor_getBoolLiteralValue", ExactSpelling = true)] [return: NativeTypeName("unsigned int")] public static extern uint Cursor_getBoolLiteralValue(CXCursor C); diff --git a/sources/ClangSharp/Cursors/Decls/CXXRecordDecl.cs b/sources/ClangSharp/Cursors/Decls/CXXRecordDecl.cs index b4c5bce3..904f6595 100644 --- a/sources/ClangSharp/Cursors/Decls/CXXRecordDecl.cs +++ b/sources/ClangSharp/Cursors/Decls/CXXRecordDecl.cs @@ -55,6 +55,8 @@ private protected CXXRecordDecl(CXCursor handle, CXCursorKind expectedCursorKind public bool IsAbstract => Handle.CXXRecord_IsAbstract; + public bool IsPOD => Handle.CXXRecord_IsPOD; + public IReadOnlyList Bases => _bases; public new CXXRecordDecl CanonicalDecl => (CXXRecordDecl)base.CanonicalDecl; diff --git a/sources/libClangSharp/ClangSharp.cpp b/sources/libClangSharp/ClangSharp.cpp index 1338c0e1..2f696db6 100644 --- a/sources/libClangSharp/ClangSharp.cpp +++ b/sources/libClangSharp/ClangSharp.cpp @@ -899,6 +899,18 @@ CXCursor clangsharp_Cursor_getCtor(CXCursor C, unsigned i) { return clang_getNullCursor(); } +unsigned clangsharp_Cursor_getCXXRecord_IsPOD(CXCursor C) { + if (isDeclOrTU(C.kind)) { + const Decl* D = getCursorDecl(C); + + if (const CXXRecordDecl* CRD = dyn_cast(D)) { + return CRD->isPOD(); + } + } + + return 0; +} + unsigned clangsharp_Cursor_getBoolLiteralValue(CXCursor C) { if (isStmtOrExpr(C.kind)) { const Stmt* S = getCursorStmt(C); diff --git a/sources/libClangSharp/ClangSharp.h b/sources/libClangSharp/ClangSharp.h index c8a609c7..e97c4747 100644 --- a/sources/libClangSharp/ClangSharp.h +++ b/sources/libClangSharp/ClangSharp.h @@ -333,6 +333,8 @@ CLANGSHARP_LINKAGE int clangsharp_Cursor_getContextParamPosition(CXCursor C); CLANGSHARP_LINKAGE CXCursor clangsharp_Cursor_getCtor(CXCursor C, unsigned i); +CLANGSHARP_LINKAGE unsigned clangsharp_Cursor_getCXXRecord_IsPOD(CXCursor C); + CLANGSHARP_LINKAGE unsigned clangsharp_Cursor_getBoolLiteralValue(CXCursor C); CLANGSHARP_LINKAGE CXType clangsharp_Cursor_getDeclaredReturnType(CXCursor C); diff --git a/tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs b/tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs index a8a49d9a..399abb94 100644 --- a/tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs +++ b/tests/ClangSharp.UnitTests/CursorTests/DeclTest.cs @@ -96,4 +96,33 @@ class tuple; Assert.That(packElements[0].AsType.AsString, Is.EqualTo("int")); Assert.That(packElements[1].AsType.AsString, Is.EqualTo("long")); } + + [Test] + public void IsPodTest() + { + AssertNeedNewClangSharp(); + + var inputContents = $$""" +struct A { + int a; +}; +struct B { + int b; +private: + int p; +}; +"""; + + using var translationUnit = CreateTranslationUnit(inputContents); + + var decls = translationUnit.TranslationUnitDecl.Decls.OfType().ToList(); + + var structA = decls.SingleOrDefault(d => d.Name == "A")!; + Assert.That(structA, Is.Not.Null, "struct A not found"); + Assert.That(structA.IsPOD, Is.True, "struct A should be POD"); + + var structB = decls.SingleOrDefault(d => d.Name == "B")!; + Assert.That(structB, Is.Not.Null, "struct B not found"); + Assert.That(structB.IsPOD, Is.False, "struct B should be not POD"); + } } diff --git a/tests/ClangSharp.UnitTests/ObjectiveCTest.cs b/tests/ClangSharp.UnitTests/ObjectiveCTest.cs index 7588ba0c..7c071b23 100644 --- a/tests/ClangSharp.UnitTests/ObjectiveCTest.cs +++ b/tests/ClangSharp.UnitTests/ObjectiveCTest.cs @@ -217,15 +217,4 @@ @interface MyClass Assert.That(methodStaticMethodAttrs.Count, Is.EqualTo(1), "methodStaticMethodAttrs.Count"); Assert.That(methodStaticMethodAttrs[0].PrettyPrint(), Is.EqualTo("__attribute__((availability(ios, introduced=13.0)))"), "methodStaticMethod.Attr.PrettyPrint"); } - - private static void AssertNeedNewClangSharp() - { - var forceRun = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("FORCE_RUN")); - - if (forceRun) - { - return; - } - Assert.Ignore("TODO: this needs a new version of libClangSharp published."); - } } diff --git a/tests/ClangSharp.UnitTests/TranslationUnitTest.cs b/tests/ClangSharp.UnitTests/TranslationUnitTest.cs index 19fbda6c..2c1f1eb3 100644 --- a/tests/ClangSharp.UnitTests/TranslationUnitTest.cs +++ b/tests/ClangSharp.UnitTests/TranslationUnitTest.cs @@ -1,5 +1,6 @@ // 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. +using System; using System.Collections.Generic; using System.Text; using ClangSharp.Interop; @@ -62,4 +63,15 @@ public abstract class TranslationUnitTest return TranslationUnit.GetOrCreate(translationUnit); } + + protected static void AssertNeedNewClangSharp() + { + var forceRun = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("FORCE_RUN")); + + if (forceRun) + { + return; + } + Assert.Ignore("TODO: this needs a new version of libClangSharp published."); + } }