Fix multiple declarations of nested structs (C code)
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11753 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
7cb4e902d5
commit
a9ccc5a866
6 changed files with 176 additions and 80 deletions
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
37
Examples/test-suite/java/nested_structs_runme.java
Normal file
37
Examples/test-suite/java/nested_structs_runme.java
Normal file
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -104,6 +104,11 @@ struct Outer {
|
|||
InnerStruct4* getInnerStruct4() { return 0; }
|
||||
InnerClass4* getInnerClass4() { return 0; }
|
||||
InnerUnion4* getInnerUnion4() { return 0; }
|
||||
|
||||
///////////////////////////////////////////
|
||||
struct InnerMultiple {
|
||||
Integer x;
|
||||
} MultipleInstance1, MultipleInstance2;
|
||||
};
|
||||
|
||||
%}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
%}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <str> pragma_arg;
|
||||
%type <loc> includetype;
|
||||
%type <type> pointer primitive_type;
|
||||
%type <decl> declarator direct_declarator notso_direct_declarator parameter_declarator typemap_parameter_declarator nested_decl;
|
||||
%type <decl> declarator direct_declarator notso_direct_declarator parameter_declarator typemap_parameter_declarator;
|
||||
%type <decl> abstract_declarator direct_abstract_declarator ctor_end;
|
||||
%type <tmap> typemap_type;
|
||||
%type <str> 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('{','}');
|
||||
$<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.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, $<str>5);
|
||||
}
|
||||
}
|
||||
Delete($<str>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('{','}');
|
||||
$<str>$ = 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, $<str>4);
|
||||
}
|
||||
} else {
|
||||
Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2);
|
||||
}
|
||||
}
|
||||
Delete($<str>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; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue