Improved C++ nested class support - nested typedef'd classes now parsed and treated as forward class declaration

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11756 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2009-11-23 23:02:01 +00:00
commit 2a59a2e6a9
6 changed files with 324 additions and 99 deletions

View file

@ -1,6 +1,12 @@
Version 1.3.41 (in progress) Version 1.3.41 (in progress)
============================ ============================
2009-11-23: wsfulton
C++ nested typedef classes can now be handled too, for example:
struct Outer {
typedef Foo { } FooTypedef1, FooTypedef2;
};
2009-11-18: wsfulton 2009-11-18: wsfulton
The wrappers for C nested structs are now generated in the same order as declared The wrappers for C nested structs are now generated in the same order as declared
in the parsed code. in the parsed code.

View file

@ -0,0 +1,72 @@
import nested_class.*;
public class nested_class_runme {
static {
try {
System.loadLibrary("nested_class");
} 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[]) {
Outer outer = new Outer();
SWIGTYPE_p_Outer__InnerStruct1 is1 = outer.makeInnerStruct1();
SWIGTYPE_p_Outer__InnerClass1 ic1 = outer.makeInnerClass1();
SWIGTYPE_p_Outer__InnerUnion1 iu1 = outer.makeInnerUnion1();
SWIGTYPE_p_Outer__InnerStruct2 is2 = outer.makeInnerStruct2();
SWIGTYPE_p_Outer__InnerClass2 ic2 = outer.makeInnerClass2();
SWIGTYPE_p_Outer__InnerUnion2 iu2 = outer.makeInnerUnion2();
SWIGTYPE_p_Outer__InnerClass4Typedef ic4 = outer.makeInnerClass4Typedef();
SWIGTYPE_p_Outer__InnerStruct4Typedef is4 = outer.makeInnerStruct4Typedef();
SWIGTYPE_p_Outer__InnerUnion4Typedef iu4 = outer.makeInnerUnion4Typedef();
SWIGTYPE_p_Outer__InnerClass5 ic5 = outer.makeInnerClass5();
SWIGTYPE_p_Outer__InnerStruct5 is5 = outer.makeInnerStruct5();
SWIGTYPE_p_Outer__InnerUnion5 iu5 = outer.makeInnerUnion5();
ic5 = outer.makeInnerClass5Typedef();
is5 = outer.makeInnerStruct5Typedef();
iu5 = outer.makeInnerUnion5Typedef();
{
SWIGTYPE_p_Outer__InnerMultiple im1 = outer.getMultipleInstance1();
SWIGTYPE_p_Outer__InnerMultiple im2 = outer.getMultipleInstance2();
SWIGTYPE_p_Outer__InnerMultiple im3 = outer.getMultipleInstance3();
SWIGTYPE_p_Outer__InnerMultiple im4 = outer.getMultipleInstance4();
}
{
SWIGTYPE_p_Outer__InnerMultipleDerived im1 = outer.getMultipleDerivedInstance1();
SWIGTYPE_p_Outer__InnerMultipleDerived im2 = outer.getMultipleDerivedInstance2();
SWIGTYPE_p_Outer__InnerMultipleDerived im3 = outer.getMultipleDerivedInstance3();
SWIGTYPE_p_Outer__InnerMultipleDerived im4 = outer.getMultipleDerivedInstance4();
}
{
SWIGTYPE_p_Outer__InnerMultipleDerived im1 = outer.getMultipleDerivedInstance1();
SWIGTYPE_p_Outer__InnerMultipleDerived im2 = outer.getMultipleDerivedInstance2();
SWIGTYPE_p_Outer__InnerMultipleDerived im3 = outer.getMultipleDerivedInstance3();
SWIGTYPE_p_Outer__InnerMultipleDerived im4 = outer.getMultipleDerivedInstance4();
}
{
SWIGTYPE_p_Outer__InnerMultipleAnonTypedef1 mat1 = outer.makeInnerMultipleAnonTypedef1();
SWIGTYPE_p_Outer__InnerMultipleAnonTypedef2 mat2 = outer.makeInnerMultipleAnonTypedef2();
SWIGTYPE_p_Outer__InnerMultipleAnonTypedef3 mat3 = outer.makeInnerMultipleAnonTypedef3();
SWIGTYPE_p_Outer__InnerMultipleNamedTypedef mnt = outer.makeInnerMultipleNamedTypedef();
SWIGTYPE_p_Outer__InnerMultipleNamedTypedef mnt1 = outer.makeInnerMultipleNamedTypedef1();
SWIGTYPE_p_Outer__InnerMultipleNamedTypedef mnt2 = outer.makeInnerMultipleNamedTypedef2();
SWIGTYPE_p_p_Outer__InnerMultipleNamedTypedef mnt3 = outer.makeInnerMultipleNamedTypedef3();
}
{
SWIGTYPE_p_Outer__InnerSameName isn = outer.makeInnerSameName();
}
}
}

View file

@ -1,6 +1,6 @@
%module namespace_union %module namespace_union
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) SpatialIndex::Variant::val; #pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
%inline %{ %inline %{
namespace SpatialIndex namespace SpatialIndex

View file

@ -7,12 +7,18 @@
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass2; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass2;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct2; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct2;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion2; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion2;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass3Name; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass4Typedef;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct3Name; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct4Typedef;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion3Name; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion4Typedef;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass4; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass5;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct4; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct5;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion4; %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion5;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultiple;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleDerived;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleAnonTypedef1;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerMultipleNamedTypedef;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerSameName;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer2::IgnoreMe;
%inline %{ %inline %{
struct Outer { struct Outer {
@ -51,64 +57,150 @@ struct Outer {
class InnerClass2 { class InnerClass2 {
public: public:
Integer x; Integer x;
} InnerClass2Name; } InnerClass2Instance;
struct InnerStruct2 { struct InnerStruct2 {
Integer x; Integer x;
} InnerStruct2Name; } InnerStruct2Instance;
union InnerUnion2 { union InnerUnion2 {
Integer x; Integer x;
double y; double y;
} InnerUnion2Name; } InnerUnion2Instance;
/////////////////////////////////////////// ///////////////////////////////////////////
class { class {
public: public:
Integer x; Integer x;
} InnerClass3Name; } InnerClass3Instance;
struct { struct {
Integer x; Integer x;
} InnerStruct3Name; } InnerStruct3Instance;
union { union {
Integer x; Integer x;
double y; double y;
} InnerUnion3Name; } InnerUnion3Instance;
/////////////////////////////////////////// ///////////////////////////////////////////
typedef class { typedef class {
public: public:
Integer x; Integer x;
} InnerClass4; } InnerClass4Typedef;
typedef struct { typedef struct {
Integer x; Integer x;
} InnerStruct4; } InnerStruct4Typedef;
typedef union { typedef union {
Integer x; Integer x;
double y; double y;
} InnerUnion4; } InnerUnion4Typedef;
///////////////////////////////////////////
typedef class InnerClass5 {
public:
Integer x;
} InnerClass5Typedef;
typedef struct InnerStruct5 {
Integer x;
} InnerStruct5Typedef;
typedef union InnerUnion5 {
Integer x;
double y;
} InnerUnion5Typedef;
// bug #909387 - inner declared types are treated as forward declarations // bug #909387 - inner declared types are treated as forward declarations
InnerStruct1* getInnerStruct1() { return 0; } InnerStruct1* makeInnerStruct1() { return 0; }
InnerClass1* getInnerClass1() { return 0; } InnerClass1* makeInnerClass1() { return 0; }
InnerUnion1* getInnerUnion1() { return 0; } InnerUnion1* makeInnerUnion1() { return 0; }
InnerStruct2* getInnerStruct2() { return 0; } InnerStruct2* makeInnerStruct2() { return 0; }
InnerClass2* getInnerClass2() { return 0; } InnerClass2* makeInnerClass2() { return 0; }
InnerUnion2* getInnerUnion2() { return 0; } InnerUnion2* makeInnerUnion2() { return 0; }
InnerStruct4* getInnerStruct4() { return 0; } InnerStruct4Typedef* makeInnerStruct4Typedef() { return 0; }
InnerClass4* getInnerClass4() { return 0; } InnerClass4Typedef* makeInnerClass4Typedef() { return 0; }
InnerUnion4* getInnerUnion4() { return 0; } InnerUnion4Typedef* makeInnerUnion4Typedef() { return 0; }
InnerStruct5* makeInnerStruct5() { return 0; }
InnerClass5* makeInnerClass5() { return 0; }
InnerUnion5* makeInnerUnion5() { return 0; }
InnerStruct5Typedef* makeInnerStruct5Typedef() { return 0; }
InnerClass5Typedef* makeInnerClass5Typedef() { return 0; }
InnerUnion5Typedef* makeInnerUnion5Typedef() { return 0; }
/////////////////////////////////////////// ///////////////////////////////////////////
struct InnerMultiple { struct InnerMultiple {
Integer x; Integer x;
} MultipleInstance1, MultipleInstance2; } MultipleInstance1, MultipleInstance2, *MultipleInstance3, MultipleInstance4[2];
struct InnerMultipleDerived : public InnerMultiple {
Integer xx;
} MultipleDerivedInstance1, MultipleDerivedInstance2, *MultipleDerivedInstance3, MultipleDerivedInstance4[2];
struct {
Integer x;
} MultipleInstanceAnon1, MultipleInstanceAnon2, *MultipleInstanceAnon3, MultipleInstanceAnon4[2];
struct : public InnerMultiple {
Integer xx;
} MultipleInstanceAnonDerived1, MultipleInstanceAnonDerived2, *MultipleInstanceAnonDerived3, MultipleInstanceAnonDerived4[2];
struct : public InnerMultiple {
Integer xx;
};
class : public InnerMultiple {
public:
Integer yy;
};
///////////////////////////////////////////
typedef struct {
Integer x;
} InnerMultipleAnonTypedef1, InnerMultipleAnonTypedef2, *InnerMultipleAnonTypedef3;
InnerMultipleAnonTypedef1* makeInnerMultipleAnonTypedef1() { return 0; }
InnerMultipleAnonTypedef2* makeInnerMultipleAnonTypedef2() { return 0; }
InnerMultipleAnonTypedef3* makeInnerMultipleAnonTypedef3() { return 0; }
typedef struct InnerMultipleNamedTypedef {
Integer x;
} InnerMultipleNamedTypedef1, InnerMultipleNamedTypedef2, *InnerMultipleNamedTypedef3;
InnerMultipleNamedTypedef* makeInnerMultipleNamedTypedef() { return 0; }
InnerMultipleNamedTypedef1* makeInnerMultipleNamedTypedef1() { return 0; }
InnerMultipleNamedTypedef2* makeInnerMultipleNamedTypedef2() { return 0; }
InnerMultipleNamedTypedef3* makeInnerMultipleNamedTypedef3() { return 0; }
///////////////////////////////////////////
typedef struct InnerSameName {
Integer x;
} InnerSameName;
InnerSameName* makeInnerSameName() { return 0; }
};
%}
// Ignore nested struct instance
%ignore Outer2::IgnoreMeInstance;
%{
struct Outer2 {
struct IgnoreMe {
int xx;
};
};
%}
struct Outer2 {
struct IgnoreMe {
int xx;
} IgnoreMeInstance;
}; };
%}

View file

@ -1,26 +1,25 @@
%module nested_comment %module nested_comment
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) s1::n; #pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) a::d;
// this example shows a problem with 'dump_nested' (parser.y). // this example shows a problem with 'dump_nested' (parser.y).
// bug #949654 // bug #949654
%inline %{ %inline %{
typedef struct s1 { typedef struct s1 {
union { union {
int fsc; /* genie structure hiding - Conductor int fsc; /* genie structure hiding - Conductor
*/ */
int fso; /* genie structure hiding - FSOptions int fso; /* genie structure hiding - FSOptions
*/ */
struct { struct {
double *vals; double *vals;
int size; int size;
} vector_val; /* matrix values are mainly used } vector_val; /* matrix values are mainly used
in rlgc models */ in rlgc models */
char *name; char *name;
} n ; } n ;
} s2; } s2;
%} %}
// comment in nested struct // comment in nested struct

View file

@ -1017,10 +1017,21 @@ static void add_nested(Nested *n) {
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* nested_new_struct() * nested_new_struct()
* *
* Nested struct handling creates a global struct from the nested struct. * Nested struct handling for C code only creates a global struct from the nested struct.
*
* Nested structure. This is a sick "hack". If we encounter
* a nested structure, we're going to grab the text of its definition and
* feed it back into the scanner. In the meantime, we need to grab
* variable declaration information and generate the associated wrapper
* code later. Yikes!
*
* This really only works in a limited sense. Since we use the
* code attached to the nested class to generate both C code
* it can't have any SWIG directives in it. It also needs to be parsable
* by SWIG or this whole thing is going to puke.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
static void nested_new_struct(Node *cpp_opt_declarators, const char *kind, String *struct_code) { static void nested_new_struct(const char *kind, String *struct_code, Node *cpp_opt_declarators) {
String *name; String *name;
String *decl; String *decl;
@ -1072,28 +1083,76 @@ static void nested_new_struct(Node *cpp_opt_declarators, const char *kind, Strin
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* nested_forward_declaration() * nested_forward_declaration()
* *
* Nested struct handling for C++ code only.
*
* Treat the nested class/struct/union as a forward declaration until a proper * Treat the nested class/struct/union as a forward declaration until a proper
* nested class solution is implemented. * nested class solution is implemented.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
static Node *nested_forward_declaration(const char *kind, const char *name) { static Node *nested_forward_declaration(const char *storage, const char *kind, String *sname, const char *name, Node *cpp_opt_declarators) {
Node *n = new_node("classforward"); Node *nn = 0;
Setfile(n,cparse_file); int warned = 0;
Setline(n,cparse_line);
Setattr(n,"kind", kind);
Setattr(n,"name", name);
Setattr(n,"sym:weak", "1");
add_symbols(n);
if (GetFlag(n, "feature:nestedworkaround")) { if (sname) {
Swig_symbol_remove(n); /* Add forward declaration of the nested type */
n = 0; Node *n = new_node("classforward");
} else { Setfile(n, cparse_file);
SWIG_WARN_NODE_BEGIN(n); Setline(n, cparse_line);
Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", kind, name); Setattr(n, "kind", kind);
SWIG_WARN_NODE_END(n); Setattr(n, "name", sname);
Setattr(n, "storage", storage);
Setattr(n, "sym:weak", "1");
add_symbols(n);
nn = n;
} }
return n;
/* Add any variable instances. Also add in any further typedefs of the nested type.
Note that anonymous typedefs (eg typedef struct {...} a, b;) are treated as class forward declarations */
if (cpp_opt_declarators) {
int storage_typedef = (storage && (strcmp(storage, "typedef") == 0));
int variable_of_anonymous_type = !sname && !storage_typedef;
if (!variable_of_anonymous_type) {
int anonymous_typedef = !sname && (storage && (strcmp(storage, "typedef") == 0));
Node *n = cpp_opt_declarators;
SwigType *type = NewString(name);
while (n) {
Setattr(n, "type", type);
Setattr(n, "storage", storage);
if (anonymous_typedef) {
Setattr(n, "nodeType", "classforward");
Setattr(n, "sym:weak", "1");
}
n = nextSibling(n);
}
Delete(type);
add_symbols(cpp_opt_declarators);
if (nn) {
set_nextSibling(nn, cpp_opt_declarators);
} else {
nn = cpp_opt_declarators;
}
}
}
if (nn && Equal(nodeType(nn), "classforward")) {
Node *n = nn;
if (GetFlag(n, "feature:nestedworkaround")) {
Swig_symbol_remove(n);
nn = 0;
warned = 1;
} else {
SWIG_WARN_NODE_BEGIN(n);
Swig_warning(WARN_PARSE_NAMED_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", kind, sname ? sname : name);
SWIG_WARN_NODE_END(n);
warned = 1;
}
}
if (!warned)
Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", kind);
return nn;
} }
/* Strips C-style and C++-style comments from string in-place. */ /* Strips C-style and C++-style comments from string in-place. */
@ -4460,67 +4519,64 @@ cpp_protection_decl : PUBLIC COLON {
; ;
/* ---------------------------------------------------------------------- /* ------------------------------------------------------------
Nested structure. This is a sick "hack". If we encounter Named nested structs:
a nested structure, we're going to grab the text of its definition and struct sname { };
feed it back into the scanner. In the meantime, we need to grab struct sname { } id;
variable declaration information and generate the associated wrapper struct sname : bases { };
code later. Yikes! struct sname : bases { } id;
typedef sname struct { } td;
typedef sname struct : bases { } td;
This really only works in a limited sense. Since we use the Adding inheritance, ie replacing 'ID' with 'idcolon inherit'
code attached to the nested class to generate both C/C++ code, added one shift/reduce
it can't have any SWIG directives in it. It also needs to be parsable ------------------------------------------------------------ */
by SWIG or this whole thing is going to puke.
---------------------------------------------------------------------- */
/* struct sname { } id; or struct sname { }; declaration */ cpp_nested : storage_class cpptype idcolon inherit LBRACE {
cpp_nested : storage_class cpptype ID LBRACE {
cparse_start_line = cparse_line; skip_balanced('{','}'); cparse_start_line = cparse_line; skip_balanced('{','}');
$<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */ $<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */
} cpp_opt_declarators { } cpp_opt_declarators {
$$ = 0; $$ = 0;
if (cplus_mode == CPLUS_PUBLIC) { if (cplus_mode == CPLUS_PUBLIC) {
if (cparse_cplusplus) { if (cparse_cplusplus) {
$$ = nested_forward_declaration($2, $3); $$ = nested_forward_declaration($1, $2, $3, $3, $7);
} else if ($6) { } else if ($7) {
nested_new_struct($6, $2, $<str>5); nested_new_struct($2, $<str>6, $7);
} }
} }
Delete($<str>5); Delete($<str>6);
} }
/* struct { } id; or struct { }; declaration */ /* ------------------------------------------------------------
Unnamed/anonymous nested structs:
struct { };
struct { } id;
struct : bases { };
struct : bases { } id;
typedef struct { } td;
typedef struct : bases { } td;
------------------------------------------------------------ */
| storage_class cpptype LBRACE { | storage_class cpptype inherit LBRACE {
cparse_start_line = cparse_line; skip_balanced('{','}'); cparse_start_line = cparse_line; skip_balanced('{','}');
$<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */ $<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */
} cpp_opt_declarators { } cpp_opt_declarators {
$$ = 0; $$ = 0;
if (cplus_mode == CPLUS_PUBLIC) { if (cplus_mode == CPLUS_PUBLIC) {
if ($5) { if (cparse_cplusplus) {
if (cparse_cplusplus) { const char *name = $6 ? Getattr($6, "name") : 0;
$$ = nested_forward_declaration($2, Getattr($5, "name")); $$ = nested_forward_declaration($1, $2, 0, name, $6);
} else {
nested_new_struct($5, $2, $<str>4);
}
} else { } else {
Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2); if ($6) {
nested_new_struct($2, $<str>5, $6);
} else {
Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2);
}
} }
} }
Delete($<str>4); Delete($<str>5);
} }
/* class name : base_list { }; declaration */
/* This adds one shift/reduce. */
| storage_class cpptype idcolon COLON base_list LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
} cpp_opt_declarators {
$$ = 0;
if (cplus_mode == CPLUS_PUBLIC) {
$$ = nested_forward_declaration($2, $3);
}
}
/* This unfortunately introduces 4 shift/reduce conflicts, so instead the somewhat hacky nested_template is used for ignore nested template classes. */ /* This unfortunately introduces 4 shift/reduce conflicts, so instead the somewhat hacky nested_template is used for ignore nested template classes. */
/* /*