From 72b3fcaa096ccc55bec7b5c46e571204faa0d75c Mon Sep 17 00:00:00 2001 From: Pherring04 Date: Wed, 26 Jun 2024 14:08:03 -0500 Subject: [PATCH] Updated documentation and testing --- docs/developer_docs/DesConvertSwig.md | 11 ++-- libexec/trick/convert_swig | 10 +-- test/SIM_test_ip/RUN_test/unit_test.py | 18 ++++++ .../test_ip/include/ClassOfEverything.hh | 7 +++ .../models/test_ip/include/Namespace_tests.hh | 21 ------- .../models/test_ip/include/TemplateTest.hh | 62 +++++++++++++++++-- 6 files changed, 94 insertions(+), 35 deletions(-) diff --git a/docs/developer_docs/DesConvertSwig.md b/docs/developer_docs/DesConvertSwig.md index 4264384c..c66f9310 100644 --- a/docs/developer_docs/DesConvertSwig.md +++ b/docs/developer_docs/DesConvertSwig.md @@ -275,10 +275,13 @@ Add the class_string to the SWIG interface text. 1. While there's class content text remaining to be processed, repeatedly search for data members that match : template_name '<' template-params '>' name ; For each match, create a SWIG %template directive to create an instantiation -of the specific templated type used by the data member. Add the -SWIG %template directive to the templated typedefs string that -Otherwise append whatever wasn't matched in process contents to -the SWIG interface text. +of the specific templated type used by the data member. Due to changes in SWIG 4, +template directives must be specified before their respective data members. As such, +the template directives are inserted immediately prior to the class definition. +SWIG does not resolve namespaces in these directives the same as C++ does +(it will only check local scope, not global). To account for this, +if the directive specifies a template outside the local namespace, convert_swig will +escape the current namespace in the format : } template_directive namespace name { ## process_typedef_struct diff --git a/libexec/trick/convert_swig b/libexec/trick/convert_swig index f816c34a..5cbf0e88 100755 --- a/libexec/trick/convert_swig +++ b/libexec/trick/convert_swig @@ -646,9 +646,6 @@ sub process_class($$$$$) { my ($template_type_no_sp) = $template_full_type ; $template_type_no_sp =~ s/\s//g ; - # If the type is qualified, assume it's fully qualified and put the - # %template directive in the global namespace. - # See https://github.com/nasa/trick/issues/768 #print "*** template_type_no_sp = $template_type_no_sp ***\n" ; if ( ! exists $processed_templates{$template_type_no_sp} ) { @@ -656,11 +653,16 @@ sub process_class($$$$$) { my $identifier = "${sanitized_namespace}${class_name}_${var_name}" ; my $trick_swig_template = "TRICK_SWIG_TEMPLATE_$identifier" ; + # Insert template directive immediately before intsance + # This is required as of SWIG 4 my $typedef = "\n#ifndef $trick_swig_template\n" ; $typedef .= "#define $trick_swig_template\n" ; $typedef .= "\%template($identifier) $template_full_type;\n" ; $typedef .= "#endif\n" ; + # SWIG namespace resolution for template directives starts at the local space + # Therefore, if the type is qualified, assume it's fully qualified and put the + # %template directive in the global namespace by escaping the current namespace if ($curr_namespace ne "") { my $in_same_namespace = 1 ; if ($template_full_type =~ /^\w*(::)\w+ msi ; std::list < std::string > ls ; + ClassNoNS class_no_ns ; + NS2::ClassNS class_ns ; + + a::Foo foo1; + b::Foo2 foo2; + private: ClassOfEverything (const ClassOfEverything &); ClassOfEverything & operator= (const ClassOfEverything &); diff --git a/test/SIM_test_ip/models/test_ip/include/Namespace_tests.hh b/test/SIM_test_ip/models/test_ip/include/Namespace_tests.hh index 1d1ae34d..a765b809 100644 --- a/test/SIM_test_ip/models/test_ip/include/Namespace_tests.hh +++ b/test/SIM_test_ip/models/test_ip/include/Namespace_tests.hh @@ -15,27 +15,6 @@ PURPOSE: #include #include -template -class TemplateNoNS {}; - -class ClassNoNS { - public: - TemplateNoNS tnns; -}; - -namespace a { - - template - class Bar {}; - - class Foo { - public: - Bar bar; - }; - -} - - namespace my_ns { class BB { diff --git a/test/SIM_test_ip/models/test_ip/include/TemplateTest.hh b/test/SIM_test_ip/models/test_ip/include/TemplateTest.hh index 845da5ea..a5bf042b 100644 --- a/test/SIM_test_ip/models/test_ip/include/TemplateTest.hh +++ b/test/SIM_test_ip/models/test_ip/include/TemplateTest.hh @@ -11,10 +11,10 @@ PURPOSE: #define TEMPLATETEST_HH template -class TTT { +class TTT_test { public: - TTT() { + TTT_test() { aa = 0 ; bb = 0 ; cc = NULL ; @@ -22,11 +22,11 @@ class TTT { } ; A aa ; B bb ; - TTT * ttt ; + TTT_test * ttt ; - typedef TTT C ; + typedef TTT_test C ; C * cc ; - typedef TTT D ; + typedef TTT_test D ; D * dd ; } ; @@ -36,7 +36,7 @@ class TemplateTest { friend void init_attrTemplateTest() ; public: - TTT< int , double > TTT_var ; + TTT_test< int , double > TTT_var ; }; @@ -44,5 +44,55 @@ class TemplateTest { %struct_str(TemplateTest) #endif +//Verify we can build templates/intsantiations defined in different combinations of namespaces +template +struct TemplateNoNS {T x;}; + +namespace NS1 { + template + struct TemplateNS {T y;}; +} + +class ClassNoNS { + public: + TemplateNoNS tnns; + NS1::TemplateNS tns; +}; + +namespace NS2 { + class ClassNS { + public: + TemplateNoNS tnns; + NS1::TemplateNS tns; + }; +} + +//Verify we can build templates/intsantiations defined in the same namespace +namespace a { + + template + struct Bar {T z;}; + + class Foo { + public: + Bar bar; + }; + +} + +//Verify we can build templates/intsantiations defined in different namespaces +namespace b { + + class Foo2 { + public: + a::Bar bar; + }; + +} + +//Verify we can build with templated functions (isn't actually SWIG-ified, but should be ignored) +template void templated_function() {} + + #endif /* _BALL_HH_ */