From 3620fdc812e2cf35b473de20d33f5d75c94c092d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1s=CC=A7=20Y=C4=B1ld=C4=B1r=C4=B1m?= Date: Tue, 12 May 2026 14:53:39 +0300 Subject: [PATCH 1/2] Add unit test for issue #12437 to validate static and instance method dispatch on CPP targets --- tests/unit/src/unit/issues/Issue12437.hx | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/unit/src/unit/issues/Issue12437.hx diff --git a/tests/unit/src/unit/issues/Issue12437.hx b/tests/unit/src/unit/issues/Issue12437.hx new file mode 100644 index 00000000000..3cac15e6c2f --- /dev/null +++ b/tests/unit/src/unit/issues/Issue12437.hx @@ -0,0 +1,38 @@ +package unit.issues; + +#if (cpp && !cppia) +@:unreflective +private class Unreflective { + public static var lastInstance:String; + public static var lastStatic:String; + + public function new() {} + + public function onInstance(value:String):Void { + lastInstance = value; + } + + public static function onStatic(value:String):Void { + lastStatic = value; + } +} + +private class Dispatcher { + public static function call(listener:String->Void, value:String):Void { + listener(value); + } +} +#end + +class Issue12437 extends Test { + #if (cpp && !cppia) + function test() { + Dispatcher.call(Unreflective.onStatic, "static"); + eq("static", Unreflective.lastStatic); + + var u = new Unreflective(); + Dispatcher.call(u.onInstance, "instance"); + eq("instance", Unreflective.lastInstance); + } + #end +} From 31c1b192f2e2dd730a88c2e4314c347b4c258595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1s=CC=A7=20Y=C4=B1ld=C4=B1r=C4=B1m?= Date: Tue, 12 May 2026 15:10:07 +0300 Subject: [PATCH 2/2] Fix #12437 --- src/generators/cpp/gen/cppGenClassHeader.ml | 2 +- .../cpp/gen/cppGenClassImplementation.ml | 26 ++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/generators/cpp/gen/cppGenClassHeader.ml b/src/generators/cpp/gen/cppGenClassHeader.ml index 2954887cfa0..b74f786409d 100644 --- a/src/generators/cpp/gen/cppGenClassHeader.ml +++ b/src/generators/cpp/gen/cppGenClassHeader.ml @@ -65,7 +65,7 @@ let gen_member_function ctx class_def is_static func = Printf.sprintf "\t\t%s %s %s(%s);\n" attributes return_type_str func.tcf_name (print_arg_list func.tcf_args "") |> output; - if (not func.tcf_is_virtual || not func.tcf_is_overriding) && func.tcf_is_reflective then + if (not func.tcf_is_virtual || not func.tcf_is_overriding) && not (is_native_gen_class class_def) then let prefix = if is_static then "static " else "" in let signature = func_to_callable_string "::hx::Callable" func in Printf.sprintf "\t\t%s%s %s_dyn();\n" prefix signature func.tcf_name |> output; diff --git a/src/generators/cpp/gen/cppGenClassImplementation.ml b/src/generators/cpp/gen/cppGenClassImplementation.ml index e7094dedfac..34fb6f8c5e4 100644 --- a/src/generators/cpp/gen/cppGenClassImplementation.ml +++ b/src/generators/cpp/gen/cppGenClassImplementation.ml @@ -86,16 +86,24 @@ let gen_function ctx tcpp_class is_static func = output "\n\n"; (* generate dynamic version too ... *) - if (not func.tcf_is_virtual || not func.tcf_is_overriding) && func.tcf_is_reflective then + if (not func.tcf_is_virtual || not func.tcf_is_overriding) && not (is_native_gen_class tcpp_class.tcl_class) then let callable_name = Printf.sprintf "__%s%s" tcpp_class.tcl_name func.tcf_name in let signature = func_to_callable_string "::hx::Callable" func in if is_static then - Printf.sprintf - "%s %s::%s_dyn() { return _hx_alloc%s; }\n\n" - signature - tcpp_class.tcl_name - func.tcf_name - callable_name |> output + if func.tcf_is_reflective then + Printf.sprintf + "%s %s::%s_dyn() { return _hx_alloc%s; }\n\n" + signature + tcpp_class.tcl_name + func.tcf_name + callable_name |> output + else + Printf.sprintf + "%s %s::%s_dyn() { return new %s(); }\n\n" + signature + tcpp_class.tcl_name + func.tcf_name + callable_name |> output else Printf.sprintf "%s %s::%s_dyn() { return new %s(this); }\n\n" @@ -105,7 +113,7 @@ let gen_function ctx tcpp_class is_static func = callable_name |> output let gen_function_closures ctx tcpp_class is_static func = - if (not func.tcf_is_virtual || not func.tcf_is_overriding) && func.tcf_is_reflective then + if (not func.tcf_is_virtual || not func.tcf_is_overriding) && not (is_native_gen_class tcpp_class.tcl_class) then let output = ctx.ctx_output in let return_type_str = type_to_string ctx.ctx_common.basic func.tcf_func.tf_type in let return_type = cpp_type_of ctx.ctx_common.basic func.tcf_func.tf_type in @@ -125,7 +133,7 @@ let gen_function_closures ctx tcpp_class is_static func = write_callable_trailer captures output; - if is_static then + if is_static && func.tcf_is_reflective then let signature = func_to_callable_string "::hx::Callable" func in Printf.sprintf "%s _hx_alloc%s;\n\n" signature callable_name |> output