diff --git a/ctypeslib/codegen/cursorhandler.py b/ctypeslib/codegen/cursorhandler.py index cc3e9ec..ce08ebe 100644 --- a/ctypeslib/codegen/cursorhandler.py +++ b/ctypeslib/codegen/cursorhandler.py @@ -985,8 +985,11 @@ def FIELD_DECL(self, cursor): # Note: cursor.is_anonymous seems to be unreliable/inconsistent across # libclang versions, and we will consider the field as anonymous if # cursor.spelling is empty + # but at least with clang-17.. anonymous fields have a name "type (anonymous at ..)" name = cursor.spelling offset = parent.type.get_offset(name) + if "(anonymous" in name: + name = "" if not name and cursor.is_anonymous() and not cursor.is_bitfield(): # anonymous type, that is not a bitfield field case: offset = cursor.get_field_offsetof() diff --git a/ctypeslib/codegen/handler.py b/ctypeslib/codegen/handler.py index 38ee1f5..20f3992 100644 --- a/ctypeslib/codegen/handler.py +++ b/ctypeslib/codegen/handler.py @@ -1,6 +1,6 @@ """Abstract Handler with helper methods.""" -from clang.cindex import CursorKind, TypeKind +from clang.cindex import CursorKind, TypeKind, Cursor from ctypeslib.codegen import typedesc from ctypeslib.codegen.util import log_entity @@ -126,6 +126,8 @@ def _make_unknown_name(self, cursor, field_name): def get_unique_name(self, cursor, field_name=None): """get the spelling or create a unique name for a cursor""" + # this gets called for both cursors and types! + # so cursor.kind can be a CursorKind or a TypeKind if cursor.kind in [CursorKind.UNEXPOSED_DECL]: return '' # covers most cases @@ -133,6 +135,12 @@ def get_unique_name(self, cursor, field_name=None): if cursor.kind == CursorKind.CXX_BASE_SPECIFIER: name = cursor.type.spelling # if it's a record decl or field decl and its type is anonymous + # clang > 16 changes anonymous names to have a parenthetical name + # so force it to have blank name like it did in earlier clang versions + # only cursors, not types have .is_anonymous() + if (isinstance(cursor.kind, CursorKind) and + cursor.is_anonymous() and '(' in name): + name = '' if name == '': # if cursor.is_anonymous(): # a unnamed object at the root TU diff --git a/ctypeslib/codegen/util.py b/ctypeslib/codegen/util.py index e3e250f..2f73248 100644 --- a/ctypeslib/codegen/util.py +++ b/ctypeslib/codegen/util.py @@ -114,7 +114,7 @@ def log_entity(func): def fn(*args, **kwargs): name = args[0].get_unique_name(args[1]) if name == '': - parent = args[1].semantic_parent + parent = getattr(args[1], 'semantic_parent', None) if parent: name = 'child of %s' % parent.displayname log.debug("%s: displayname:'%s'",func.__name__, name)