Fix nested template classes within a namespace generating uncompileable code by incorrectly adding in symbols into the symbol tables and not setting the scope correctly after the nested template was parsed
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11727 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
deba0e9285
commit
ec6bf1ec96
5 changed files with 500 additions and 333 deletions
|
|
@ -1,6 +1,11 @@
|
||||||
Version 1.3.41 (in progress)
|
Version 1.3.41 (in progress)
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
2009-11-07: wsfulton
|
||||||
|
Bug #1514681 - Fix nested template classes within a namespace generated uncompileable
|
||||||
|
code and introduced strange side effects to other wrapper code especially code
|
||||||
|
after the nested template class. Note that nested template classes are still ignored.
|
||||||
|
|
||||||
2009-11-07: wsfulton
|
2009-11-07: wsfulton
|
||||||
Add new debug options:
|
Add new debug options:
|
||||||
-debug-symtabs - Display symbol tables information
|
-debug-symtabs - Display symbol tables information
|
||||||
|
|
@ -13,7 +18,7 @@ Version 1.3.41 (in progress)
|
||||||
namespace AA { /* ... */ }
|
namespace AA { /* ... */ }
|
||||||
using namespace ::AA;
|
using namespace ::AA;
|
||||||
|
|
||||||
and bug #1816802 - SwigValueWrapper should be used ::
|
and bug #1816802 - SwigValueWrapper should be used:
|
||||||
|
|
||||||
struct CC {
|
struct CC {
|
||||||
CC(int); // no default constructor
|
CC(int); // no default constructor
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,7 @@ CPP_TEST_CASES += \
|
||||||
template_inherit_abstract \
|
template_inherit_abstract \
|
||||||
template_int_const \
|
template_int_const \
|
||||||
template_methods \
|
template_methods \
|
||||||
|
template_nested \
|
||||||
template_nested_typemaps \
|
template_nested_typemaps \
|
||||||
template_ns \
|
template_ns \
|
||||||
template_ns2 \
|
template_ns2 \
|
||||||
|
|
|
||||||
30
Examples/test-suite/java/template_nested_runme.java
Normal file
30
Examples/test-suite/java/template_nested_runme.java
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
import template_nested.*;
|
||||||
|
|
||||||
|
public class template_nested_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("template_nested");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
new T_NormalTemplateNormalClass().tmethod(new NormalClass());
|
||||||
|
new OuterClass().T_OuterTMethodNormalClass(new NormalClass());
|
||||||
|
|
||||||
|
TemplateFuncs tf = new TemplateFuncs();
|
||||||
|
if (tf.T_TemplateFuncs1Int(-10) != -10)
|
||||||
|
throw new RuntimeException("it failed");
|
||||||
|
if (tf.T_TemplateFuncs2Double(-12.3) != -12.3)
|
||||||
|
throw new RuntimeException("it failed");
|
||||||
|
|
||||||
|
T_NestedOuterTemplateDouble tn = new T_NestedOuterTemplateDouble();
|
||||||
|
if (tn.hohum(-12.3) != -12.3)
|
||||||
|
throw new RuntimeException("it failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
91
Examples/test-suite/template_nested.i
Normal file
91
Examples/test-suite/template_nested.i
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
%module template_nested
|
||||||
|
|
||||||
|
// Test nested templates - that is template classes and template methods within a class.
|
||||||
|
|
||||||
|
#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
|
||||||
|
namespace ns {
|
||||||
|
|
||||||
|
class NormalClass {
|
||||||
|
public:
|
||||||
|
NormalClass() {}
|
||||||
|
~NormalClass() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> struct NormalTemplate {
|
||||||
|
void tmethod(T t) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OuterClass {
|
||||||
|
public:
|
||||||
|
template <class T> struct Inner1 {
|
||||||
|
template <class U> struct SuperInner1 {
|
||||||
|
void method1(U t) {}
|
||||||
|
};
|
||||||
|
template <class V> struct SuperInner2 {
|
||||||
|
void method1(V t) {}
|
||||||
|
};
|
||||||
|
template <class W> void tmethod(W w) {}
|
||||||
|
template <class X> void tmethodAgain(X x) {}
|
||||||
|
template <class Y> struct SuperBase : public SuperInner1<Y> {
|
||||||
|
void method1(Y y) {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Z> void InnerTMethod(Z z) {}
|
||||||
|
|
||||||
|
template <class T> class Inner2 : public NormalTemplate<T> {
|
||||||
|
public:
|
||||||
|
template <class U> class SuperInner1 {
|
||||||
|
public:
|
||||||
|
SuperInner1() {}
|
||||||
|
void method1(U t) {}
|
||||||
|
};
|
||||||
|
template <class V> struct SuperInner2 {
|
||||||
|
void method1(V t) {}
|
||||||
|
};
|
||||||
|
int embeddedVar;
|
||||||
|
template <class X> void tmethod(X x) {}
|
||||||
|
template <class Y> struct SuperBase : public SuperInner1<Y> {
|
||||||
|
void method1(Y y) {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
int iii;
|
||||||
|
};
|
||||||
|
struct ABC {
|
||||||
|
ABC() {}
|
||||||
|
~ABC() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TemplateFuncs {
|
||||||
|
template <class X> X templateMethod1(X x) { return x; }
|
||||||
|
template <class X> X templateMethod2(X x) { return x; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename UU> struct OuterTemplate {
|
||||||
|
template <typename VV> struct NestedInnerTemplate1 {
|
||||||
|
template <typename Z> void NestedInnerInnerTMethod(Z z) {}
|
||||||
|
void hohum() {}
|
||||||
|
};
|
||||||
|
template <typename W> void NestedInnerTMethod(UU u, W w) {}
|
||||||
|
template <typename VV> struct NestedInnerTemplate2 {
|
||||||
|
void hohum() {}
|
||||||
|
};
|
||||||
|
UU hohum(UU u) { return u; }
|
||||||
|
struct NestedStruct {
|
||||||
|
NestedStruct() {}
|
||||||
|
void hohum() {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%template(T_NormalTemplateNormalClass) ns::NormalTemplate<ns::NormalClass>;
|
||||||
|
%template(T_OuterTMethodNormalClass) ns::OuterClass::InnerTMethod<ns::NormalClass>;
|
||||||
|
%template(T_TemplateFuncs1Int) ns::TemplateFuncs::templateMethod1<int>;
|
||||||
|
%template(T_TemplateFuncs2Double) ns::TemplateFuncs::templateMethod2<double>;
|
||||||
|
%template(T_NestedOuterTemplateDouble) ns::OuterTemplate<double>;
|
||||||
|
|
||||||
|
|
@ -43,6 +43,7 @@ static Node *module_node = 0;
|
||||||
static String *Classprefix = 0;
|
static String *Classprefix = 0;
|
||||||
static String *Namespaceprefix = 0;
|
static String *Namespaceprefix = 0;
|
||||||
static int inclass = 0;
|
static int inclass = 0;
|
||||||
|
static int nested_template = 0; /* template class/function definition within a class */
|
||||||
static char *last_cpptype = 0;
|
static char *last_cpptype = 0;
|
||||||
static int inherit_list = 0;
|
static int inherit_list = 0;
|
||||||
static Parm *template_parameters = 0;
|
static Parm *template_parameters = 0;
|
||||||
|
|
@ -272,6 +273,14 @@ static int add_only_one = 0;
|
||||||
static void add_symbols(Node *n) {
|
static void add_symbols(Node *n) {
|
||||||
String *decl;
|
String *decl;
|
||||||
String *wrn = 0;
|
String *wrn = 0;
|
||||||
|
|
||||||
|
if (nested_template) {
|
||||||
|
if (!(n && Equal(nodeType(n), "template"))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* continue if template function, but not template class, declared within a class */
|
||||||
|
}
|
||||||
|
|
||||||
if (inclass && n) {
|
if (inclass && n) {
|
||||||
cparse_normalize_void(n);
|
cparse_normalize_void(n);
|
||||||
}
|
}
|
||||||
|
|
@ -3227,10 +3236,10 @@ cpp_declaration : cpp_class_decl { $$ = $1; }
|
||||||
| cpp_catch_decl { $$ = 0; }
|
| cpp_catch_decl { $$ = 0; }
|
||||||
;
|
;
|
||||||
|
|
||||||
cpp_class_decl :
|
|
||||||
|
|
||||||
/* A simple class/struct/union definition */
|
/* A simple class/struct/union definition */
|
||||||
storage_class cpptype idcolon inherit LBRACE {
|
cpp_class_decl : storage_class cpptype idcolon inherit LBRACE {
|
||||||
|
if (nested_template == 0) {
|
||||||
List *bases = 0;
|
List *bases = 0;
|
||||||
Node *scope = 0;
|
Node *scope = 0;
|
||||||
$<node>$ = new_node("class");
|
$<node>$ = new_node("class");
|
||||||
|
|
@ -3344,7 +3353,9 @@ cpp_class_decl :
|
||||||
}
|
}
|
||||||
class_decl[class_level++] = $<node>$;
|
class_decl[class_level++] = $<node>$;
|
||||||
inclass = 1;
|
inclass = 1;
|
||||||
|
}
|
||||||
} cpp_members RBRACE cpp_opt_declarators {
|
} cpp_members RBRACE cpp_opt_declarators {
|
||||||
|
if (nested_template == 0) {
|
||||||
Node *p;
|
Node *p;
|
||||||
SwigType *ty;
|
SwigType *ty;
|
||||||
Symtab *cscope = prev_symtab;
|
Symtab *cscope = prev_symtab;
|
||||||
|
|
@ -3458,6 +3469,12 @@ cpp_class_decl :
|
||||||
Swig_symbol_setscope(cscope);
|
Swig_symbol_setscope(cscope);
|
||||||
Delete(Namespaceprefix);
|
Delete(Namespaceprefix);
|
||||||
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
|
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
|
||||||
|
} else {
|
||||||
|
$$ = new_node("class");
|
||||||
|
Setattr($$,"kind",$2);
|
||||||
|
Setattr($$,"name",NewString($3));
|
||||||
|
SetFlag($$,"nestedtemplateclass");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* An unnamed struct, possibly with a typedef */
|
/* An unnamed struct, possibly with a typedef */
|
||||||
|
|
@ -3617,7 +3634,24 @@ cpp_forward_class_decl : storage_class cpptype idcolon SEMI {
|
||||||
template<...> decl
|
template<...> decl
|
||||||
------------------------------------------------------------ */
|
------------------------------------------------------------ */
|
||||||
|
|
||||||
cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_parameters = $3; } cpp_temp_possible {
|
cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
|
||||||
|
template_parameters = $3;
|
||||||
|
if (inclass)
|
||||||
|
nested_template++;
|
||||||
|
|
||||||
|
} cpp_temp_possible {
|
||||||
|
|
||||||
|
/* Don't ignore templated functions declared within a class, unless the templated function is within a nested class */
|
||||||
|
if (nested_template <= 1) {
|
||||||
|
int is_nested_template_class = $6 && GetFlag($6, "nestedtemplateclass");
|
||||||
|
if (is_nested_template_class) {
|
||||||
|
/* Nested template classes would probably better be ignored like ordinary nested classes using cpp_nested, but that introduces shift/reduce conflicts */
|
||||||
|
if (cplus_mode == CPLUS_PUBLIC) {
|
||||||
|
Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested template %s not currently supported (%s ignored)\n", Getattr($6, "kind"), Getattr($6, "name"));
|
||||||
|
}
|
||||||
|
Delete($6);
|
||||||
|
$$ = 0;
|
||||||
|
} else {
|
||||||
String *tname = 0;
|
String *tname = 0;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
|
|
@ -3639,7 +3673,6 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para
|
||||||
$6 = ni;
|
$6 = ni;
|
||||||
}
|
}
|
||||||
|
|
||||||
template_parameters = 0;
|
|
||||||
$$ = $6;
|
$$ = $6;
|
||||||
if ($$) tname = Getattr($$,"name");
|
if ($$) tname = Getattr($$,"name");
|
||||||
|
|
||||||
|
|
@ -3730,7 +3763,7 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para
|
||||||
Setattr($$,"templateparms",tp);
|
Setattr($$,"templateparms",tp);
|
||||||
Delete(tp);
|
Delete(tp);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
/* Patch the parameter list */
|
/* Patch the parameter list */
|
||||||
if (tempn) {
|
if (tempn) {
|
||||||
Parm *p,*p1;
|
Parm *p,*p1;
|
||||||
|
|
@ -3752,7 +3785,7 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para
|
||||||
} else {
|
} else {
|
||||||
Setattr($$,"templateparms",$3);
|
Setattr($$,"templateparms",$3);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Delattr($$,"specialization");
|
Delattr($$,"specialization");
|
||||||
Setattr($$,"partialspecialization","1");
|
Setattr($$,"partialspecialization","1");
|
||||||
/* Create a specialized name for matching */
|
/* Create a specialized name for matching */
|
||||||
|
|
@ -3865,6 +3898,13 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN { template_para
|
||||||
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
|
Namespaceprefix = Swig_symbol_qualifiedscopename(0);
|
||||||
if (error) $$ = 0;
|
if (error) $$ = 0;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$$ = 0;
|
||||||
|
}
|
||||||
|
template_parameters = 0;
|
||||||
|
if (inclass)
|
||||||
|
nested_template--;
|
||||||
|
}
|
||||||
| TEMPLATE cpptype idcolon {
|
| TEMPLATE cpptype idcolon {
|
||||||
Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
|
Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
|
||||||
$$ = 0;
|
$$ = 0;
|
||||||
|
|
@ -4377,7 +4417,6 @@ cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line
|
||||||
if (cplus_mode == CPLUS_PUBLIC) {
|
if (cplus_mode == CPLUS_PUBLIC) {
|
||||||
if (strcmp($2,"class") == 0) {
|
if (strcmp($2,"class") == 0) {
|
||||||
Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n");
|
Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n");
|
||||||
/* Generate some code for a new class */
|
|
||||||
} else if ($5.id) {
|
} else if ($5.id) {
|
||||||
/* Generate some code for a new class */
|
/* Generate some code for a new class */
|
||||||
Nested *n = (Nested *) malloc(sizeof(Nested));
|
Nested *n = (Nested *) malloc(sizeof(Nested));
|
||||||
|
|
@ -4409,6 +4448,7 @@ cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line
|
||||||
Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n");
|
Swig_warning(WARN_PARSE_NESTED_CLASS,cparse_file, cparse_line,"Nested class not currently supported (ignored)\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* This unfortunately introduces 4 shift/reduce conflicts, so instead the somewhat hacky nested_template is used for ignore nested template classes. */
|
||||||
/*
|
/*
|
||||||
| TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype idcolon LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
|
| TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype idcolon LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
|
||||||
} SEMI {
|
} SEMI {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue