diff --git a/CHANGES.current b/CHANGES.current index bc28d8fc1..e00984fe0 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,6 +1,14 @@ Version 1.3.41 (in progress) ============================ +2009-11-18: wsfulton + Fix #491476 - multiple declarations of nested structs, for example: + struct Outer { + struct { + int val; + } inner1, inner2, *inner3, inner4[1]; + } outer; + 2009-11-17: wsfulton Fix parsing of enum declaration and initialization, for example: diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index db28917ef..f9e06c0c4 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -80,7 +80,6 @@ CPP_TEST_BROKEN += \ exception_partial_info \ extend_variable \ li_std_vector_ptr \ - nested_structs \ overload_complicated \ template_default_pointer \ template_expr @@ -461,6 +460,7 @@ C_TEST_CASES += \ long_long \ name \ nested \ + nested_structs \ newobject2 \ overload_extend \ overload_extendc \ diff --git a/Examples/test-suite/java/nested_structs_runme.java b/Examples/test-suite/java/nested_structs_runme.java new file mode 100644 index 000000000..6e103cd12 --- /dev/null +++ b/Examples/test-suite/java/nested_structs_runme.java @@ -0,0 +1,37 @@ + +import nested_structs.*; + +public class nested_structs_runme { + + static { + try { + System.loadLibrary("nested_structs"); + } 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(); + nested_structs.setValues(outer, 10); + + Outer_inner1 inner1 = outer.getInner1(); + Outer_inner2 inner2 = outer.getInner2(); + Outer_inner3 inner3 = outer.getInner3(); + Outer_inner4 inner4 = outer.getInner4(); + if (inner1.getVal() != 10) throw new RuntimeException("failed inner1"); + if (inner2.getVal() != 20) throw new RuntimeException("failed inner2"); + if (inner3.getVal() != 20) throw new RuntimeException("failed inner3"); + if (inner4.getVal() != 40) throw new RuntimeException("failed inner4"); + + Outer_inside1 inside1 = outer.getInside1(); + Outer_inside2 inside2 = outer.getInside2(); + Outer_inside3 inside3 = outer.getInside3(); + Outer_inside4 inside4 = outer.getInside4(); + if (inside1.getVal() != 100) throw new RuntimeException("failed inside1"); + if (inside2.getVal() != 200) throw new RuntimeException("failed inside2"); + if (inside3.getVal() != 200) throw new RuntimeException("failed inside3"); + if (inside4.getVal() != 400) throw new RuntimeException("failed inside4"); + } +} diff --git a/Examples/test-suite/nested_class.i b/Examples/test-suite/nested_class.i index cccebb136..89c9a8058 100644 --- a/Examples/test-suite/nested_class.i +++ b/Examples/test-suite/nested_class.i @@ -104,6 +104,11 @@ struct Outer { InnerStruct4* getInnerStruct4() { return 0; } InnerClass4* getInnerClass4() { return 0; } InnerUnion4* getInnerUnion4() { return 0; } + + /////////////////////////////////////////// + struct InnerMultiple { + Integer x; + } MultipleInstance1, MultipleInstance2; }; %} diff --git a/Examples/test-suite/nested_structs.i b/Examples/test-suite/nested_structs.i index 41cdd63fb..60e34a638 100644 --- a/Examples/test-suite/nested_structs.i +++ b/Examples/test-suite/nested_structs.i @@ -2,11 +2,26 @@ // bug #491476 %inline %{ -struct { -struct { -int a; -} a, b; -} a; +struct Outer { + struct { + int val; + } inner1, inner2, *inner3, inner4[1]; + struct Named { + int val; + } inside1, inside2, *inside3, inside4[1]; +} outer; +void setValues(struct Outer *outer, int val) { + outer->inner1.val = val; + outer->inner2.val = val * 2; + outer->inner3 = &outer->inner2; + outer->inner4[0].val = val * 4; + + val = val * 10; + outer->inside1.val = val; + outer->inside2.val = val * 2; + outer->inside3 = &outer->inside2; + outer->inside4[0].val = val * 4; +} %} diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 8b4521ef1..c7ca713f0 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -985,18 +985,16 @@ static String *resolve_node_scope(String *cname) { - - /* Structures for handling code fragments built for nested classes */ typedef struct Nested { String *code; /* Associated code fragment */ int line; /* line number where it starts */ - char *name; /* Name associated with this nested class */ - char *kind; /* Kind of class */ + const char *name; /* Name associated with this nested class */ + const char *kind; /* Kind of class */ int unnamed; /* unnamed class */ SwigType *type; /* Datatype associated with the name */ - struct Nested *next; /* Next code fragment in list */ + struct Nested *next; /* Next code fragment in list */ } Nested; /* Some internal variables for saving nested class information */ @@ -1006,15 +1004,96 @@ static Nested *nested_list = 0; /* Add a function to the nested list */ static void add_nested(Nested *n) { - Nested *n1; - if (!nested_list) nested_list = n; - else { - n1 = nested_list; - while (n1->next) n1 = n1->next; + if (!nested_list) { + nested_list = n; + } else { + Nested *n1 = nested_list; + while (n1->next) + n1 = n1->next; n1->next = n; } } +/* ----------------------------------------------------------------------------- + * nested_new_struct() + * + * Nested struct handling creates a global struct from the nested struct. + * ----------------------------------------------------------------------------- */ + +static void nested_new_struct(Node *cpp_opt_declarators, const char *kind, String *struct_code) { + String *name; + String *decl; + + /* Create a new global struct declaration which is just a copy of the nested struct */ + Nested *nested = (Nested *) malloc(sizeof(Nested)); + Nested *n = nested; + + name = Getattr(cpp_opt_declarators, "name"); + decl = Getattr(cpp_opt_declarators, "decl"); + n->code = NewStringEmpty(); + Printv(n->code, "typedef ", kind, " ", struct_code, " $classname_", name, ";\n", NIL); + n->name = Swig_copy_string(Char(name)); + n->line = cparse_start_line; + n->type = NewStringEmpty(); + n->kind = kind; + n->unnamed = 0; + SwigType_push(n->type, decl); + n->next = 0; + + /* Repeat for any multiple instances of the nested struct */ + { + Node *p = cpp_opt_declarators; + p = nextSibling(p); + while (p) { + Nested *nn = (Nested *) malloc(sizeof(Nested)); + + name = Getattr(p, "name"); + decl = Getattr(p, "decl"); + nn->code = NewStringEmpty(); + Printv(nn->code, "typedef ", kind, " ", struct_code, " $classname_", name, ";\n", NIL); + nn->name = Swig_copy_string(Char(name)); + nn->line = cparse_start_line; + nn->type = NewStringEmpty(); + nn->kind = kind; + nn->unnamed = 0; + SwigType_push(nn->type, decl); + nn->next = 0; + n->next = nn; + n = nn; + p = nextSibling(p); + } + } + + add_nested(nested); +} + +/* ----------------------------------------------------------------------------- + * nested_forward_declaration() + * + * 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); + + 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); + } + return n; +} + /* Strips C-style and C++-style comments from string in-place. */ static void strip_comments(char *string) { int state = 0; /* @@ -1434,33 +1513,6 @@ static void default_arguments(Node *n) { } } -/* ----------------------------------------------------------------------------- - * nested_forward_declaration() - * - * 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); - - 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); - } - return n; -} - /* ----------------------------------------------------------------------------- * tag_nodes() * @@ -1609,7 +1661,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) { %type pragma_arg; %type includetype; %type pointer primitive_type; -%type declarator direct_declarator notso_direct_declarator parameter_declarator typemap_parameter_declarator nested_decl; +%type declarator direct_declarator notso_direct_declarator parameter_declarator typemap_parameter_declarator; %type abstract_declarator direct_abstract_declarator ctor_end; %type typemap_type; %type idcolon idcolontail idcolonnt idcolontailnt idtemplate stringbrace stringbracesemi; @@ -4427,56 +4479,40 @@ cpp_protection_decl : PUBLIC COLON { /* struct sname { } id; or struct sname { }; declaration */ -cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}'); - } nested_decl SEMI { +cpp_nested : storage_class cpptype ID LBRACE { + cparse_start_line = cparse_line; skip_balanced('{','}'); + $$ = 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.id) { - /* Generate some code for a new struct */ - Nested *n = (Nested *) malloc(sizeof(Nested)); - n->code = NewStringEmpty(); - Printv(n->code, "typedef ", $2, " ", Char(scanner_ccode), " $classname_", $6.id, ";\n", NIL); - n->name = Swig_copy_string($6.id); - n->line = cparse_start_line; - n->type = NewStringEmpty(); - n->kind = $2; - n->unnamed = 0; - SwigType_push(n->type, $6.type); - n->next = 0; - add_nested(n); + } else if ($6) { + nested_new_struct($6, $2, $5); } } + Delete($5); } /* struct { } id; or struct { }; declaration */ - | storage_class cpptype LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}'); - } nested_decl SEMI { + | storage_class cpptype LBRACE { + cparse_start_line = cparse_line; skip_balanced('{','}'); + $$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */ + } cpp_opt_declarators { $$ = 0; if (cplus_mode == CPLUS_PUBLIC) { - if ($5.id) { + if ($5) { if (cparse_cplusplus) { - $$ = nested_forward_declaration($2, $5.id); + $$ = nested_forward_declaration($2, Getattr($5, "name")); } else { - /* Generate some code for a new struct */ - Nested *n = (Nested *) malloc(sizeof(Nested)); - n->code = NewStringEmpty(); - Printv(n->code, "typedef ", $2, " " , Char(scanner_ccode), " $classname_", $5.id, ";\n",NIL); - n->name = Swig_copy_string($5.id); - n->line = cparse_start_line; - n->type = NewStringEmpty(); - n->kind = $2; - n->unnamed = 1; - SwigType_push(n->type,$5.type); - n->next = 0; - add_nested(n); + nested_new_struct($5, $2, $4); } } else { Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2); } } + Delete($4); } /* class name : base_list { }; declaration */ @@ -4502,11 +4538,6 @@ cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line */ ; -nested_decl : declarator { $$ = $1;} - | empty { $$.id = 0; } - ; - - /* These directives can be included inside a class definition */ cpp_swig_directive: pragma_directive { $$ = $1; }