From a69b860057e9ffe7187b2a575d452f843092b264 Mon Sep 17 00:00:00 2001 From: "Scott L. Burson" Date: Thu, 18 Jun 2026 00:55:53 -0700 Subject: [PATCH] Handle inherited constructors When it finds a 'using' declaration referring to parent class constructors, adds them to the child's record decl. Squashed commit of the following: commit fbf87bd6a75e7bd13f640eaf71e61594444c5352 Author: Scott L. Burson Date: Wed Jun 17 14:17:08 2026 -0700 Clean up commit c39de93e4cc6955a93439e02aa1f51bb5eadf5d2 Merge: a9580d3 50d5460 Author: Scott L. Burson Date: Mon Jun 15 18:16:34 2026 -0700 Merge branch 'master' into inherited-constructors commit a9580d331b5d351f3e00a4bd70856b519fd6eedf Author: Scott L. Burson Date: Mon Jun 15 18:02:37 2026 -0700 Disable debug prints commit 501462a59d39074a594a2456b027fe33f56a4c9f Author: Scott L. Burson Date: Mon Jun 15 18:02:18 2026 -0700 Capture 'defaulted' on methods commit 8cda2520d0b75d441cc0df785f5c9ab2fd4e6849 Author: Scott L. Burson Date: Mon Jun 8 21:06:42 2026 -0700 WIP --- src/context.c | 12 ++++++++++++ src/decl.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/context.c b/src/context.c index 7b8c41e..dcee371 100644 --- a/src/context.c +++ b/src/context.c @@ -402,6 +402,18 @@ void resect_visit_cursor_for_declaration(resect_visit_context context, CXCursor return; } + // Enables walking `using' declarations to look for inherited constructors + if (cursor_kind == CXCursor_UsingDeclaration) { + CXCursor definition = clang_getCursorDefinition(cursor); + int overload_count = clang_getNumOverloadedDecls(definition); + for (int i = 0; i < overload_count; ++i) { + CXCursor overload = clang_getOverloadedDecl(definition, i); + if (clang_getCursorKind(overload) == CXCursor_Constructor) { + resect_visit_cursor_for_declaration(context, overload, data); + } + } + } + if (resect_is_forward_declaration(cursor)) { CXCursor definition = clang_getCursorDefinition(cursor); if ((clang_getCursorKind(definition) < CXCursor_FirstInvalid diff --git a/src/decl.c b/src/decl.c index 6e0976e..34dcd57 100644 --- a/src/decl.c +++ b/src/decl.c @@ -766,6 +766,7 @@ typedef struct P_resect_record_data { resect_collection methods; resect_collection parents; resect_bool abstract; + resect_bool has_inherited_constructor; } *resect_record_data; resect_bool resect_is_struct(resect_decl decl) { @@ -791,6 +792,12 @@ resect_bool resect_record_is_abstract(resect_decl decl) { return data->abstract; } +resect_bool resect_record_has_inherited_constructor(resect_decl decl) { + assert(resect_is_struct(decl)); + resect_record_data data = decl->data; + return data->has_inherited_constructor; +} + resect_collection resect_record_parents(resect_decl decl) { assert(resect_is_struct(decl)); resect_record_data data = decl->data; @@ -835,6 +842,8 @@ void resect_field_init(resect_visit_context visit_context, resect_translation_co decl->data = data; } +void resect_create_record_child(resect_decl_child_visit_data visit_data, CXCursor cursor); + enum CXChildVisitResult resect_visit_record_child(CXCursor cursor, CXCursor parent, CXClientData data) { resect_decl_child_visit_data visit_data = data; @@ -851,6 +860,28 @@ enum CXChildVisitResult resect_visit_record_child(CXCursor cursor, CXCursor pare return CXChildVisit_Continue; } + if (clang_getCursorKind(cursor) == CXCursor_UsingDeclaration) { + CXCursor definition = clang_getCursorDefinition(cursor); + // There's always more than one constructor; the copy and move constructors + // exist even if they're marked `= delete'. + int overload_count = clang_getNumOverloadedDecls(definition); + for (int i = 0; i < overload_count; ++i) { + CXCursor overload = clang_getOverloadedDecl(definition, i); + if (clang_getCursorKind(overload) == CXCursor_Constructor) { + record_data->has_inherited_constructor = resect_true; + resect_create_record_child(visit_data, overload); + } + } + } else { + resect_create_record_child(visit_data, cursor); + } + + return CXChildVisit_Continue; +} + +void resect_create_record_child(resect_decl_child_visit_data visit_data, CXCursor cursor) { + resect_record_data record_data = visit_data->parent->data; + resect_decl_result decl_result = resect_decl_create(visit_data->visit_context, visit_data->translation_context, cursor); @@ -869,8 +900,6 @@ enum CXChildVisitResult resect_visit_record_child(CXCursor cursor, CXCursor pare default:; } } - - return CXChildVisit_Continue; } void resect_record_data_free(void *data, resect_set deallocated) { @@ -893,6 +922,7 @@ void resect_record_init(resect_visit_context visit_context, resect_translation_c data->fields = resect_collection_create(); data->parents = resect_collection_create(); data->abstract = convert_bool_from_uint(clang_CXXRecord_isAbstract(cursor)); + data->has_inherited_constructor = resect_false; decl->data_deallocator = resect_record_data_free; decl->data = data;