Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion sources/ClangSharp/Cursors/Decls/Decl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ public class Decl : Cursor

private protected Decl(CXCursor handle, CXCursorKind expectedCursorKind, CX_DeclKind expectedDeclKind) : base(handle, expectedCursorKind)
{
if ((handle.DeclKind == CX_DeclKind_Invalid) || (handle.DeclKind != expectedDeclKind))
// When the native libClangSharp doesn't have a mapping for a declaration kind,
// it returns CX_DeclKind_Invalid. When the default case in Decl.Create() constructs
// a generic Decl with expectedDeclKind == CX_DeclKind_Invalid, we should allow it
// rather than throwing, so that unknown declaration kinds degrade gracefully to a
// base Decl wrapper instead of crashing the entire traversal.
if (handle.DeclKind != expectedDeclKind)
{
throw new ArgumentOutOfRangeException(nameof(handle));
}
Expand Down
24 changes: 17 additions & 7 deletions sources/ClangSharp/Types/Type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,29 @@ public unsafe class Type : IEquatable<Type>

protected Type(CXType handle, CXTypeKind expectedKind, CX_TypeClass expectedTypeClass, params ReadOnlySpan<CXTypeKind> additionalExpectedKinds)
{
#if NET10_0_OR_GREATER
if (handle.kind != expectedKind && !additionalExpectedKinds.Contains(handle.kind))
#else
if (handle.kind != expectedKind && !Contains(additionalExpectedKinds, handle.kind))
#endif
if ((handle.TypeClass == CX_TypeClass_Invalid) || (handle.TypeClass != expectedTypeClass))
{
throw new ArgumentOutOfRangeException(nameof(handle));
}

if ((handle.TypeClass == CX_TypeClass_Invalid) || (handle.TypeClass != expectedTypeClass))
// CXTypeKind is validated after TypeClass because libclang's CXTypeKind uses a
// coarser classification than libClangSharp's CX_TypeClass. For example, libclang
// may return CXType_ObjCId or CXType_Unexposed for a type that libClangSharp
// correctly classifies as CX_TypeClass_Attributed via the Clang AST. Since
// TypeClass is the authoritative classifier and already validated above, a
// CXTypeKind mismatch is not fatal.
var kindMatches = handle.kind == expectedKind
#if NET10_0_OR_GREATER
|| additionalExpectedKinds.Contains(handle.kind);
#else
|| Contains(additionalExpectedKinds, handle.kind);
#endif

if (!kindMatches)
{
throw new ArgumentOutOfRangeException(nameof(handle));
Debug.WriteLine($"Unexpected CXTypeKind for {handle.TypeClass}: {handle.kind}.");
}

Handle = handle;

_asString = new ValueLazy<string>(Handle.Spelling.ToString);
Expand Down
Loading
Loading