Nested class improvements - Fixed inconsistency in handling C++ nested classes - sometimes they were treated as forward declarations, other times as if C nested struct was parsed. Added the nestedworkaround feature for C++ nested class handling. Document improved nested class handling. Numerous C and C++ nested struct/class/union test cases added.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11734 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
a0ff0a86d0
commit
ebed6508e4
12 changed files with 300 additions and 82 deletions
|
|
@ -1,12 +1,30 @@
|
|||
Version 1.3.41 (in progress)
|
||||
============================
|
||||
2009-11-11: wsfulton
|
||||
Added the nestedworkaround feature as a way to use the full functionality of a nested class
|
||||
(C++ mode only). It removes the nested class from SWIG's type information so it is as if SWIG
|
||||
had never parsed the nested class. The documented nested class workarounds using a global
|
||||
fake class stopped working when SWIG treated the nested class as an opaque pointer, and
|
||||
this feature reverts this behaviour. The documentation has been updated with details of how
|
||||
to use and implement it, see the "Nested classes" section in SWIGPlus.html.
|
||||
|
||||
2009-11-11: wsfulton
|
||||
There were a number of C++ cases where nested classes/structs/unions were being handled
|
||||
as if C code was being parsed which would oftentimes lead to uncompileable code as an
|
||||
attempt was made to wrap the nested structs like it is documented for C code. Now all
|
||||
nested structs/classes/unions are ignored in C++ mode, as was always documented. However,
|
||||
there is an improvement as usage of nested structs/classes/unions is now always treated
|
||||
as an opaque type by default, resulting in generated code that should always compile.
|
||||
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2009-11-09: drjoe
|
||||
Fix R for -fcompact and add std_map.i
|
||||
|
||||
2009-11-08: wsfulton
|
||||
Fix inconsistency for inner structs/unions/classes. Uncompileable code was being
|
||||
generated when inner struct and union declarations were used as types within
|
||||
the inner struct. The inner struct/union is now treated as a forward declaration making the
|
||||
Fix inconsistency for nested structs/unions/classes. Uncompileable code was being
|
||||
generated when inner struct and union declarations were used as types within the
|
||||
inner struct. The inner struct/union is now treated as a forward declaration making the
|
||||
behaviour the same as an inner class. (C++ code), eg:
|
||||
|
||||
struct Outer {
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ major features include:
|
|||
|
||||
<p>
|
||||
Currently, the only major C++ feature not supported is nested classes--a limitation
|
||||
that will be removed in a future release.
|
||||
that should be removed in a future release, but has some workarounds for the moment.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ currently supported:
|
|||
For example, SWIG does not support declarations such as the following
|
||||
(even though this is legal C):
|
||||
|
||||
<p>
|
||||
<div class="code">
|
||||
<pre>
|
||||
/* Non-conventional placement of storage specifier (extern) */
|
||||
|
|
@ -347,6 +348,7 @@ void bar(Spam (Grok)(Doh));
|
|||
|
||||
</pre>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In practice, few (if any) C programmers actually write code like
|
||||
|
|
@ -360,6 +362,7 @@ is not recommended. Even though SWIG can parse C++ class declarations,
|
|||
it ignores declarations that are decoupled from their
|
||||
original class definition (the declarations are parsed, but a lot of warning
|
||||
messages may be generated). For example:
|
||||
<p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
|
|
@ -369,11 +372,12 @@ int foo::bar(int) {
|
|||
}
|
||||
</pre>
|
||||
</div>
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li>Certain advanced features of C++ such as nested classes
|
||||
are not yet supported. Please see the section on using SWIG
|
||||
with C++ for more information.
|
||||
are not yet fully supported. Please see the <a href="SWIGPlus.html">C++ section</a>
|
||||
for more information.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
|
@ -2633,6 +2637,12 @@ If you have a lot nested structure declarations, it is
|
|||
advisable to double-check them after running SWIG. Although,
|
||||
there is a good chance that they will work, you may have to
|
||||
modify the interface file in certain cases.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, note that nesting is handled differently in C++ mode,
|
||||
see <a href="SWIGPlus.html#SWIGPlus_nested_classes">Nested classes</a>.
|
||||
</p>
|
||||
|
||||
<H3><a name="SWIG_nn39"></a>5.5.8 Other things to note about structure wrapping</H3>
|
||||
|
||||
|
|
|
|||
|
|
@ -4695,37 +4695,49 @@ public:
|
|||
|
||||
|
||||
<p>
|
||||
There is limited support for nested structs and unions when wrapping C code, see <a href="SWIG.html#SWIG_nested_structs">Nested structures</a> for further details.
|
||||
However, there is no nested class/struct/union support when wrapping C++ code (using the -c++ commandline option).
|
||||
This may be added at a future date, however, until then some of the following workarounds can be applied.
|
||||
There is some support for nested structs and unions when wrapping C code,
|
||||
see <a href="SWIG.html#SWIG_nested_structs">Nested structures</a> for further details.
|
||||
The added complexity of C++ compared to C means this approach does not work well for
|
||||
C++ code (when using the -c++ command line option).
|
||||
For C++, a nested class is treated much like an opaque pointer, so anything useful within the nested class, such as its
|
||||
methods and variables, are not accessible from the target language.
|
||||
True nested class support may be added to SWIG in the future, however,
|
||||
until then some of the following workarounds can be applied to improve the situation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It might be possible to use partial class information. Since
|
||||
SWIG does not need the entire class specification to work, conditional
|
||||
compilation can be used to comment out the problematic nested class definition, you might do this:
|
||||
It might be possible to use partial class information as often you can accept that the nested class is not needed,
|
||||
especially if it is not actually used in any methods you need from the target language.
|
||||
Imagine you are wrapping the following <tt>Outer</tt> class which contains a nested class <tt>Inner</tt>.
|
||||
The easiest thing to do is turn a blind eye to the warning that SWIG generates, or simply suppress it:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
class Foo {
|
||||
#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS
|
||||
class Outer {
|
||||
public:
|
||||
#ifndef SWIG
|
||||
class Bar {
|
||||
public:
|
||||
...
|
||||
};
|
||||
#endif
|
||||
Foo();
|
||||
~Foo();
|
||||
...
|
||||
class Inner {
|
||||
public:
|
||||
...
|
||||
};
|
||||
Inner getInner();
|
||||
void useInner(const Inner& inner);
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The next workaround assumes you cannot modify the source code as was done above and it provides a solution for methods that use nested class types.
|
||||
Imagine we are wrapping the <tt>Outer</tt> class which contains a nested class <tt>Inner</tt>:
|
||||
Note that if <tt>Inner</tt> can be used as an opaque type, the default wrapping approach suffices.
|
||||
For example, if the nested class does not need to be created from the target language, but can be obtained via a method
|
||||
call, such as the <tt>getInner()</tt> method above, the returned value can then be passed around, such as passed into the
|
||||
<tt>useInner()</tt> method.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
With some more effort the above situation can be improved somewhat and a nested class can be constructed and used
|
||||
from the target language much like any other non-nested class. Assuming we have the <tt>Outer</tt> class in a header file:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -4738,14 +4750,18 @@ public:
|
|||
int var;
|
||||
Inner(int v = 0) : var(v) {}
|
||||
};
|
||||
void method(Inner inner);
|
||||
Inner getInner();
|
||||
void useInner(const Inner& inner);
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The following interface file works around SWIG nested class limitations by redefining the nested class as a global class.
|
||||
A typedef for the compiler is also required in order for the generated wrappers to compile.
|
||||
The following interface file works around the nested class limitations by redefining the nested class as a global class.
|
||||
A typedef for the compiler and the <tt>nestedworkaround</tt>
|
||||
<a href="Customization.html#Customization_feature_flags">feature flag</a> is also required in
|
||||
order for the generated wrappers to compile. This flag simply removes all the type information from SWIG, so SWIG treats
|
||||
the nested class as if it had not been parsed at all.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -4753,9 +4769,6 @@ A typedef for the compiler is also required in order for the generated wrappers
|
|||
// File : example.i
|
||||
%module example
|
||||
|
||||
// Suppress SWIG warning
|
||||
#pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS
|
||||
|
||||
// Redefine nested class in global scope in order for SWIG to generate
|
||||
// a proxy class. Only SWIG parses this definition.
|
||||
class Inner {
|
||||
|
|
@ -4764,24 +4777,62 @@ class Inner {
|
|||
Inner(int v = 0) : var(v) {}
|
||||
};
|
||||
|
||||
%nestedworkaround Outer::Inner;
|
||||
|
||||
%{
|
||||
#include "outer.h"
|
||||
%}
|
||||
%include "outer.h"
|
||||
|
||||
// We've fooled SWIG into thinking that Inner is a global class, so now we need
|
||||
// to trick the C++ compiler into understanding this apparent global type.
|
||||
%{
|
||||
// SWIG thinks that Inner is a global class, so we need to trick the C++
|
||||
// compiler into understanding this so called global type.
|
||||
typedef Outer::Inner Inner;
|
||||
%}
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The downside to this approach is having to maintain two definitions of <tt>Inner</tt>, the real one and the one in the interface file that SWIG parses.
|
||||
The downside to this approach is a more complex interface file and having to maintain two definitions of <tt>Inner</tt>,
|
||||
the real one and the one in the interface file that SWIG parses.
|
||||
However, the upside is that all the methods/variables in the nested class are available from the target language
|
||||
as a proxy class is generated instead of treating the nested class as an opaque type.
|
||||
The proxy class can be constructed from the target language and passed into any methods accepting the nested class.
|
||||
Also note that the original header file is parsed unmodified.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, conditional compilation can be used as a workaround to comment out nested class definitions in the actual headers,
|
||||
assuming you are able to modify them.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
// File outer.h
|
||||
class Outer {
|
||||
public:
|
||||
#ifndef SWIG
|
||||
class Inner {
|
||||
public:
|
||||
...
|
||||
};
|
||||
#endif
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
This workaround used to be common when SWIG could not deal with nested classes particulary well.
|
||||
This should just be a last resort for unusual corner cases now as SWIG can parse nested classes and even handle nested template classes fairly well.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Compatibility Note:</b> SWIG-1.3.40 and earlier versions did not have the <tt>nestedworkaround</tt> feature
|
||||
and the generated code resulting from parsing nested classes did not always compile.
|
||||
</p>
|
||||
|
||||
|
||||
<H2><a name="SWIGPlus_nn37"></a>6.27 A brief rant about const-correctness</H2>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ CPP_TEST_CASES += \
|
|||
naturalvar \
|
||||
nested_class \
|
||||
nested_comment \
|
||||
nested_workaround \
|
||||
newobject1 \
|
||||
null_pointer \
|
||||
operator_overload \
|
||||
|
|
|
|||
|
|
@ -12,6 +12,27 @@ struct TestStruct {
|
|||
int a;
|
||||
};
|
||||
|
||||
struct OuterStructNamed {
|
||||
struct InnerStructNamed {
|
||||
double dd;
|
||||
} inner_struct_named;
|
||||
union InnerUnionNamed {
|
||||
double ee;
|
||||
int ff;
|
||||
} inner_union_named;
|
||||
};
|
||||
|
||||
struct OuterStructUnnamed {
|
||||
struct {
|
||||
double xx;
|
||||
} inner_struct_unnamed;
|
||||
union {
|
||||
double yy;
|
||||
int zz;
|
||||
} inner_union_unnamed;
|
||||
};
|
||||
|
||||
|
||||
typedef struct OuterStruct {
|
||||
union {
|
||||
|
||||
|
|
|
|||
|
|
@ -4,52 +4,94 @@
|
|||
|
||||
%inline %{
|
||||
struct Outer {
|
||||
typedef int Integer;
|
||||
///////////////////////////////////////////
|
||||
struct InnerStruct1 {
|
||||
int x;
|
||||
Integer x;
|
||||
};
|
||||
|
||||
class InnerClass1 {
|
||||
public:
|
||||
int x;
|
||||
Integer x;
|
||||
};
|
||||
|
||||
union InnerUnion1 {
|
||||
int x;
|
||||
Integer x;
|
||||
double y;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////
|
||||
class {
|
||||
public:
|
||||
int a;
|
||||
Integer a;
|
||||
};
|
||||
|
||||
struct {
|
||||
int b;
|
||||
Integer b;
|
||||
};
|
||||
|
||||
union {
|
||||
int c;
|
||||
Integer c;
|
||||
double d;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////
|
||||
class InnerClass2 {
|
||||
public:
|
||||
int x;
|
||||
Integer x;
|
||||
} InnerClass2Name;
|
||||
|
||||
struct InnerStruct2 {
|
||||
int x;
|
||||
Integer x;
|
||||
} InnerStruct2Name;
|
||||
|
||||
union InnerUnion2 {
|
||||
int x;
|
||||
Integer x;
|
||||
double y;
|
||||
} InnerUnion2Name;
|
||||
|
||||
///////////////////////////////////////////
|
||||
class {
|
||||
public:
|
||||
Integer x;
|
||||
} InnerClass3Name;
|
||||
|
||||
struct {
|
||||
Integer x;
|
||||
} InnerStruct3Name;
|
||||
|
||||
union {
|
||||
Integer x;
|
||||
double y;
|
||||
} InnerUnion3Name;
|
||||
|
||||
///////////////////////////////////////////
|
||||
typedef class {
|
||||
public:
|
||||
Integer x;
|
||||
} InnerClass4;
|
||||
|
||||
typedef struct {
|
||||
Integer x;
|
||||
} InnerStruct4;
|
||||
|
||||
typedef union {
|
||||
Integer x;
|
||||
double y;
|
||||
} InnerUnion4;
|
||||
|
||||
// bug #909387 - inner declared types are treated as forward declarations
|
||||
InnerStruct1* getInnerStruct1() { return 0; }
|
||||
InnerClass1* getInnerClass1() { return 0; }
|
||||
InnerUnion1* getInnerUnion1() { return 0; }
|
||||
|
||||
InnerStruct2* getInnerStruct2() { return 0; }
|
||||
InnerClass2* getInnerClass2() { return 0; }
|
||||
InnerUnion2* getInnerUnion2() { return 0; }
|
||||
|
||||
InnerStruct4* getInnerStruct4() { return 0; }
|
||||
InnerClass4* getInnerClass4() { return 0; }
|
||||
InnerUnion4* getInnerUnion4() { return 0; }
|
||||
};
|
||||
|
||||
%}
|
||||
|
|
|
|||
38
Examples/test-suite/nested_workaround.i
Normal file
38
Examples/test-suite/nested_workaround.i
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
%module nested_workaround
|
||||
// Similar to "Nested classes" documentation example.
|
||||
|
||||
class Inner {
|
||||
int val;
|
||||
public:
|
||||
Inner(int v = 0) : val(v) {}
|
||||
void setValue(int v) { val = v; }
|
||||
int getValue() const { return val; }
|
||||
};
|
||||
%nestedworkaround Outer::Inner;
|
||||
|
||||
%inline %{
|
||||
class Outer {
|
||||
public:
|
||||
class Inner {
|
||||
int val;
|
||||
public:
|
||||
Inner(int v = 0) : val(v) {}
|
||||
void setValue(int v) { val = v; }
|
||||
int getValue() const { return val; }
|
||||
};
|
||||
Inner createInner(int v) const { return Inner(v); }
|
||||
int getInnerValue(const Inner& i) const { return i.getValue(); }
|
||||
Inner doubleInnerValue(Inner inner) {
|
||||
inner.setValue(inner.getValue() * 2);
|
||||
return inner;
|
||||
}
|
||||
};
|
||||
%}
|
||||
|
||||
// We've fooled SWIG into thinking that Inner is a global class, so now we need
|
||||
// to trick the C++ compiler into understanding this apparent global type.
|
||||
%{
|
||||
typedef Outer::Inner Inner;
|
||||
%}
|
||||
|
||||
|
||||
13
Examples/test-suite/python/nested_workaround_runme.py
Normal file
13
Examples/test-suite/python/nested_workaround_runme.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
from nested_workaround import *
|
||||
|
||||
inner = Inner(5)
|
||||
outer = Outer()
|
||||
newInner = outer.doubleInnerValue(inner)
|
||||
if newInner.getValue() != 10:
|
||||
raise RuntimeError
|
||||
|
||||
outer = Outer()
|
||||
inner = outer.createInner(3)
|
||||
newInner = outer.doubleInnerValue(inner)
|
||||
if outer.getInnerValue(newInner) != 6:
|
||||
raise RuntimeError
|
||||
|
|
@ -136,6 +136,11 @@
|
|||
#define %nocallback %feature("callback","0")
|
||||
#define %clearcallback %feature("callback","")
|
||||
|
||||
/* the %nestedworkaround directive */
|
||||
#define %nestedworkaround %feature("nestedworkaround")
|
||||
#define %nonestedworkaround %feature("nestedworkaround","0")
|
||||
#define %clearnestedworkaround %feature("nestedworkaround","")
|
||||
|
||||
/* the %fastdispatch directive */
|
||||
#define %fastdispatch %feature("fastdispatch")
|
||||
#define %nofastdispatch %feature("fastdispatch","0")
|
||||
|
|
|
|||
|
|
@ -4374,18 +4374,33 @@ cpp_protection_decl : PUBLIC COLON {
|
|||
by SWIG or this whole thing is going to puke.
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
/* A struct sname { } id; declaration */
|
||||
/* struct sname { } id; or struct sname { }; declaration */
|
||||
|
||||
cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
|
||||
} nested_decl SEMI {
|
||||
$$ = 0;
|
||||
if (cplus_mode == CPLUS_PUBLIC) {
|
||||
if ($6.id && strcmp($2, "class") != 0) {
|
||||
if (cparse_cplusplus) {
|
||||
/* Treat the nested class/struct/union as a forward declaration until a proper nested class solution is implemented */
|
||||
$$ = new_node("classforward");
|
||||
Setfile($$,cparse_file);
|
||||
Setline($$,cparse_line);
|
||||
Setattr($$,"kind",$2);
|
||||
Setattr($$,"name",$3);
|
||||
Setattr($$,"sym:weak", "1");
|
||||
add_symbols($$);
|
||||
|
||||
if (GetFlag($$, "feature:nestedworkaround")) {
|
||||
Swig_symbol_remove($$);
|
||||
$$ = 0;
|
||||
} else {
|
||||
Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (%s ignored).\n", $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);
|
||||
|
||||
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();
|
||||
|
|
@ -4394,50 +4409,53 @@ cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line
|
|||
SwigType_push(n->type, $6.type);
|
||||
n->next = 0;
|
||||
add_nested(n);
|
||||
} else {
|
||||
Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (%s ignored).\n", $2, $3);
|
||||
|
||||
/* For now, just treat the nested class/struct/union as a forward
|
||||
* declaration (SF bug #909387). */
|
||||
$$ = new_node("classforward");
|
||||
Setfile($$,cparse_file);
|
||||
Setline($$,cparse_line);
|
||||
Setattr($$,"kind",$2);
|
||||
Setattr($$,"name",$3);
|
||||
Setattr($$,"sym:weak", "1");
|
||||
add_symbols($$);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* A struct { } id; declaration */
|
||||
|
||||
/* struct { } id; or struct { }; declaration */
|
||||
|
||||
| storage_class cpptype LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
|
||||
} nested_decl SEMI {
|
||||
$$ = 0;
|
||||
if (cplus_mode == CPLUS_PUBLIC) {
|
||||
if (strcmp($2,"class") == 0) {
|
||||
if ($5.id)
|
||||
Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line,"Nested class not currently supported (%s ignored)\n", $5.id);
|
||||
else
|
||||
Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line,"Nested class not currently supported (ignored)\n");
|
||||
} else if ($5.id) {
|
||||
/* Generate some code for a new class */
|
||||
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);
|
||||
if ($5.id) {
|
||||
if (cparse_cplusplus) {
|
||||
/* Treat the nested class/struct/union as a forward declaration until a proper nested class solution is implemented */
|
||||
$$ = new_node("classforward");
|
||||
Setfile($$,cparse_file);
|
||||
Setline($$,cparse_line);
|
||||
Setattr($$,"kind",$2);
|
||||
Setattr($$,"name",$5.id);
|
||||
Setattr($$,"sym:weak", "1");
|
||||
add_symbols($$);
|
||||
|
||||
if (GetFlag($$, "feature:nestedworkaround")) {
|
||||
Swig_symbol_remove($$);
|
||||
$$ = 0;
|
||||
} else {
|
||||
Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", $2, $5.id);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
} else {
|
||||
Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", $2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A 'class name : base_list { };' declaration, always ignored */
|
||||
/*****
|
||||
This fixes derived_nested.i, but it adds one shift/reduce. Anyway,
|
||||
|
|
@ -4445,12 +4463,12 @@ cpp_nested : storage_class cpptype ID LBRACE { cparse_start_line = cparse_line
|
|||
*****/
|
||||
| storage_class cpptype idcolon COLON base_list LBRACE { cparse_start_line = cparse_line; skip_balanced('{','}');
|
||||
} SEMI {
|
||||
Printf(stdout, "cpp_nested (c)\n");
|
||||
$$ = 0;
|
||||
if (cplus_mode == CPLUS_PUBLIC) {
|
||||
Swig_warning(WARN_PARSE_NESTED_CLASS, cparse_file, cparse_line,"Nested %s not currently supported (%s ignored)\n", $2, $3);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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('{','}');
|
||||
|
|
|
|||
|
|
@ -1331,7 +1331,8 @@ void Swig_symbol_remove(Node *n) {
|
|||
Setattr(symtab, symname, symnext);
|
||||
fixovername = symnext; /* fix as symbol to remove is at head of linked list */
|
||||
} else {
|
||||
Delattr(symtab, symname);
|
||||
if (symname)
|
||||
Delattr(symtab, symname);
|
||||
}
|
||||
}
|
||||
if (symnext) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue