Improve scoping of SWIG %template directives

Refs #768 & Refs #769
This commit is contained in:
Derek Bankieris 2019-05-10 13:31:03 -05:00
parent cbc37dd67e
commit e6509df362
4 changed files with 118 additions and 4 deletions

View File

@ -60,6 +60,7 @@ my %sim ;
my %out_of_date ;
my ($version, $thread, $year) ;
my %processed_templates ;
my $global_template_typedefs ;
my $typedef_def = qr/typedef\s+ # the word typedef
(?:[_A-Za-z][\s\w]*\s*) # resolved type
@ -336,6 +337,7 @@ sub process_file() {
}
print OUT "\n$new_contents" ;
print OUT "$contents\n" ;
print OUT $global_template_typedefs ;
# Add a trick_cast_as macro line for each class parsed in the file. These lines must appear at the bottom of the
# file to ensure they are not in a namespace directive and they are after the #define statements they depend on.
undef %class_typemap_printed ;
@ -638,13 +640,27 @@ 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
my $qualified = $template_type_no_sp =~ /^\w+(::)\w+</ ;
#print "*** template_type_no_sp = $template_type_no_sp ***\n" ;
if ( ! exists $processed_templates{$template_type_no_sp} ) {
$$new_contents_ref .= "\n#define TRICK_SWIG_TEMPLATE_$class_name${var_name}_template\n" ;
$template_typedefs .= "\n#ifdef TRICK_SWIG_TEMPLATE_$class_name${var_name}_template\n" ;
$template_typedefs .= "\%template ($class_name${var_name}_template) $template_full_type ;\n" ;
$template_typedefs .= "#undef TRICK_SWIG_TEMPLATE_$class_name${var_name}_template\n" ;
$template_typedefs .= "#endif\n" ;
my $typedef = "\n#ifdef TRICK_SWIG_TEMPLATE_$class_name${var_name}_template\n" ;
$typedef .= "\%template($class_name${var_name}_template) $template_full_type;\n" ;
$typedef .= "#undef TRICK_SWIG_TEMPLATE_$class_name${var_name}_template\n" ;
$typedef .= "#endif\n" ;
if ($qualified) {
$global_template_typedefs .= $typedef
} else {
$template_typedefs .= $typedef
}
$processed_templates{$template_type_no_sp} = 1 ;
}
}

View File

@ -0,0 +1,2 @@
#include "sim_objects/default_trick_sys.sm"
##include "Classes.hh"

View File

@ -0,0 +1,3 @@
TRICK_CONVERT_SWIG_FLAGS := -s
TRICK_CFLAGS += -Imodels
TRICK_CXXFLAGS += -Imodels

View File

@ -0,0 +1,93 @@
#include <vector>
namespace a {
template<class> class A {
private:
void operator=(const A&);
};
}
namespace b {
template<class> class A {};
template<class> class B {};
class C {
public:
std::vector<int> v;
a::A<int> a;
a::A<int> a2;
A<int> a3;
A<int> a4;
B<int> b;
B<int> b2;
b::B<int> b3;
b::B<int> b4;
B<a::A<int> > ba;
B<a::A<int> > ba2;
b::B<a::A<int> > ba3;
b::B<a::A<int> > ba4;
B<A<int> > ba5;
B<A<int> > ba6;
// These don't work. Because the type is qualified, convert_swig assumes
// it's fully qualified and puts the %template directive in the global
// namespace. However, there is no A in the global namespace, so the wrapper
// code fails to compile. Bonus points if you can fix this without breaking
// something else.
//b::B<A<int> > ba7;
//b::B<A<int> > ba8;
};
// This class is the same as the previous. Seems weird, but it reveals scoping
// errors under SWIG 2. The replication is not necessary in SWIG 4, which has
// better error detection.
class D {
public:
std::vector<int> v;
a::A<int> a;
a::A<int> a2;
A<int> a3;
A<int> a4;
B<int> b;
B<int> b2;
b::B<int> b3;
b::B<int> b4;
B<a::A<int> > ba;
B<a::A<int> > ba2;
b::B<a::A<int> > ba3;
b::B<a::A<int> > ba4;
B<A<int> > ba5;
B<A<int> > ba6;
//b::B<A<int> > ba7;
//b::B<A<int> > ba8;
};
}
class E {
public:
std::vector<int> v;
a::A<int> a;
a::A<int> a2;
b::B<int> b3;
b::B<int> b4;
b::B<a::A<int> > ba3;
b::B<a::A<int> > ba4;
};
namespace a {
class B {
public:
std::vector<int> v;
a::A<int> a;
a::A<int> a2;
A<int> a3;
A<int> a4;
b::B<int> b3;
b::B<int> b4;
b::B<a::A<int> > ba3;
b::B<a::A<int> > ba4;
//b::B<A<int> > ba7;
//b::B<A<int> > ba8;
};
}