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)
============================
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
The wrappers for C nested structs are now generated in the same order as declared
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
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) SpatialIndex::Variant::val;
#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
%inline %{
namespace SpatialIndex

View file

@ -7,12 +7,18 @@
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass2;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct2;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion2;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass3Name;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct3Name;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion3Name;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass4;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct4;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion4;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass4Typedef;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct4Typedef;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerUnion4Typedef;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerClass5;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::InnerStruct5;
%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 %{
struct Outer {
@ -51,64 +57,150 @@ struct Outer {
class InnerClass2 {
public:
Integer x;
} InnerClass2Name;
} InnerClass2Instance;
struct InnerStruct2 {
Integer x;
} InnerStruct2Name;
} InnerStruct2Instance;
union InnerUnion2 {
Integer x;
double y;
} InnerUnion2Name;
} InnerUnion2Instance;
///////////////////////////////////////////
class {
public:
Integer x;
} InnerClass3Name;
} InnerClass3Instance;
struct {
Integer x;
} InnerStruct3Name;
} InnerStruct3Instance;
union {
Integer x;
double y;
} InnerUnion3Name;
} InnerUnion3Instance;
///////////////////////////////////////////
typedef class {
public:
Integer x;
} InnerClass4;
} InnerClass4Typedef;
typedef struct {
Integer x;
} InnerStruct4;
} InnerStruct4Typedef;
typedef union {
Integer x;
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
InnerStruct1* getInnerStruct1() { return 0; }
InnerClass1* getInnerClass1() { return 0; }
InnerUnion1* getInnerUnion1() { return 0; }
InnerStruct1* makeInnerStruct1() { return 0; }
InnerClass1* makeInnerClass1() { return 0; }
InnerUnion1* makeInnerUnion1() { return 0; }
InnerStruct2* getInnerStruct2() { return 0; }
InnerClass2* getInnerClass2() { return 0; }
InnerUnion2* getInnerUnion2() { return 0; }
InnerStruct2* makeInnerStruct2() { return 0; }
InnerClass2* makeInnerClass2() { return 0; }
InnerUnion2* makeInnerUnion2() { return 0; }
InnerStruct4* getInnerStruct4() { return 0; }
InnerClass4* getInnerClass4() { return 0; }
InnerUnion4* getInnerUnion4() { return 0; }
InnerStruct4Typedef* makeInnerStruct4Typedef() { return 0; }
InnerClass4Typedef* makeInnerClass4Typedef() { 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 {
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
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) s1::n;
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) a::d;
#pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
// this example shows a problem with 'dump_nested' (parser.y).
// bug #949654
%inline %{
typedef struct s1 {
union {
int fsc; /* genie structure hiding - Conductor
*/
int fso; /* genie structure hiding - FSOptions
*/
struct {
double *vals;
int size;
} vector_val; /* matrix values are mainly used
in rlgc models */
char *name;
} n ;
} s2;
typedef struct s1 {
union {
int fsc; /* genie structure hiding - Conductor
*/
int fso; /* genie structure hiding - FSOptions
*/
struct {
double *vals;
int size;
} vector_val; /* matrix values are mainly used
in rlgc models */
char *name;
} n ;
} s2;
%}
// comment in nested struct

View file

@ -1017,10 +1017,21 @@ static void add_nested(Nested *n) {
/* -----------------------------------------------------------------------------
* 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 *decl;
@ -1072,28 +1083,76 @@ static void nested_new_struct(Node *cpp_opt_declarators, const char *kind, Strin
/* -----------------------------------------------------------------------------
* nested_forward_declaration()
*
* Nested struct handling for C++ code only.
*
* Treat the nested class/struct/union as a forward declaration until a proper
* nested class solution is implemented.
* ----------------------------------------------------------------------------- */
static Node *nested_forward_declaration(const char *kind, const char *name) {
Node *n = new_node("classforward");
Setfile(n,cparse_file);
Setline(n,cparse_line);
Setattr(n,"kind", kind);
Setattr(n,"name", name);
Setattr(n,"sym:weak", "1");
add_symbols(n);
static Node *nested_forward_declaration(const char *storage, const char *kind, String *sname, const char *name, Node *cpp_opt_declarators) {
Node *nn = 0;
int warned = 0;
if (GetFlag(n, "feature:nestedworkaround")) {
Swig_symbol_remove(n);
n = 0;
} 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, name);
SWIG_WARN_NODE_END(n);
if (sname) {
/* Add forward declaration of the nested type */
Node *n = new_node("classforward");
Setfile(n, cparse_file);
Setline(n, cparse_line);
Setattr(n, "kind", kind);
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. */
@ -4460,67 +4519,64 @@ cpp_protection_decl : PUBLIC COLON {
;
/* ----------------------------------------------------------------------
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!
/* ------------------------------------------------------------
Named nested structs:
struct sname { };
struct sname { } id;
struct sname : bases { };
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
code attached to the nested class to generate both C/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.
---------------------------------------------------------------------- */
Adding inheritance, ie replacing 'ID' with 'idcolon inherit'
added one shift/reduce
------------------------------------------------------------ */
/* struct sname { } id; or struct sname { }; declaration */
cpp_nested : storage_class cpptype ID LBRACE {
cpp_nested : storage_class cpptype idcolon inherit LBRACE {
cparse_start_line = cparse_line; skip_balanced('{','}');
$<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */
} cpp_opt_declarators {
$$ = 0;
if (cplus_mode == CPLUS_PUBLIC) {
if (cparse_cplusplus) {
$$ = nested_forward_declaration($2, $3);
} else if ($6) {
nested_new_struct($6, $2, $<str>5);
$$ = nested_forward_declaration($1, $2, $3, $3, $7);
} else if ($7) {
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('{','}');
$<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */
} cpp_opt_declarators {
$$ = 0;
if (cplus_mode == CPLUS_PUBLIC) {
if ($5) {
if (cparse_cplusplus) {
$$ = nested_forward_declaration($2, Getattr($5, "name"));
} else {
nested_new_struct($5, $2, $<str>4);
}
if (cparse_cplusplus) {
const char *name = $6 ? Getattr($6, "name") : 0;
$$ = nested_forward_declaration($1, $2, 0, name, $6);
} 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. */
/*