diff --git a/CHANGES b/CHANGES index ae4c97957..fc3018a1d 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,93 @@ SWIG (Simplified Wrapper and Interface Generator) See CHANGES.current for current version. +Version 1.3.35 (7 April 2008) +============================= + +04/07/2008: wsfulton + [Lua] Add missing pointer reference typemaps + +04/06/2008: wsfulton + Fix stack overflow when using typemap warning suppression, eg + %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK_MSG) + +04/05/2008: wsfulton + [Python] Fix shared_ptr typemaps so that %pythonnondynamic can be used. Also corrects + display of the proxy class type. Reported by Robert Lupton. + +04/04/2008: olly + [Python] Add %newobject reference to python memory management subsection of manual + (patch from mdbeachy in SF#1894610). + +03/27/2008: wsfulton + [Python] Fix shared_ptr typemaps where the pointer type is a templated type with + with more than one parameter. Reported by Robert Lupton. + +03/27/2008: mgossage + [Lua] Added a typemap DISOWN for SWIGTYPE* and SWIGTYPE[], and support for %delobject feature. + Added Examples/lua/owner which demonstrates the use of the memory management. + +03/26/2008: wsfulton + [Java] Apply patch #1844301 from Monty Taylor to suppress enum constructor + unused warnings. + +03/26/2008: wsfulton + [Python] Apply patch #1924524 from Casey Raymondson which ensures the + "No constructor defined" message is displayed when attempting to call a + constructor on a class that doesn't have a constructor wrapper, eg if + the C++ class is abstract. + +03/26/2008: wsfulton + [Python] Apply patch #1925702 from Casey Raymondson which removes warning 512 + for std::vector wrappers. + +03/26/2008: olly + [Python] Apply GCC 4.3 warnings patch from Philipp Thomas + (SF#1925122). + +03/21/2008: wsfulton + [Python] Thread safety patch for STL iterators from Abhinandan Jain. + +03/17/2008: mgossage + [Lua] Added %luacode feature to add source code into wrappers. + Updated documentation to document this. + Added Examples/lua/arrays to show its use (and typemaps) + +03/17/2008: olly + Fix nonportable sed usage which failed on Mac OS X (and probably + other platforms). Fixes SF#1903612. + +03/17/2008: olly + Fix memory leak in SWIG's parser (based on patch from Russell + Bryant in SF#1914023).` + +03/12/2008: wsfulton + Fix bug #1878285 - unnecessary cast for C struct creation wrappers. + +03/12/2008: wsfulton + [Python] Remove debugging info when using shared_ptr support + +03/06/2008: mgossage + [Lua] Updated documentation for Lua exceptions. + Added Examples/lua/exception and Examples/lua/embed2. + Small updates to the typemaps. + +03/04/2008: wsfulton + [Java, C#] Add char *& typemaps. + +03/04/2008: wsfulton + Fix occasional seg fault when attempting to report overloaded methods as being ignored. + +02/29/2008: wsfulton + [Perl] Fix #1904537 Swig causes a Perl warning "x used only once" in Perl 5.10 + reported by Ari Jolma + +02/29/2008: wsfulton + [Python] Add shared_ptr varin/varout typemaps for wrapping global variables. + +02/25/2008: wsfulton + Fix $wrapname to work in %exception (fixes some wrap:name assertions) + Version 1.3.34 (27 February 2008) ================================= diff --git a/CHANGES.current b/CHANGES.current index 719e32f52..f6dc3dd5b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,87 +1,12 @@ -Version 1.3.35 (7 April 2008) +Version 1.3.36 (in progress) ============================= -04/07/2008: wsfulton - [Lua] Add missing pointer reference typemaps +04/20/2008: wsfulton + Add the ability to wrap all protected members when using directors. + Previously only the virtual methods were available to the target language. + Now all protected members, (static and non-static variables, non-virtual methods + and static methods) are wrapped when using the allprotected mode. The allprotected + mode is turned on in the module declaration: -04/06/2008: wsfulton - Fix stack overflow when using typemap warning suppression, eg - %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK_MSG) - -04/05/2008: wsfulton - [Python] Fix shared_ptr typemaps so that %pythonnondynamic can be used. Also corrects - display of the proxy class type. Reported by Robert Lupton. - -04/04/2008: olly - [Python] Add %newobject reference to python memory management subsection of manual - (patch from mdbeachy in SF#1894610). - -03/27/2008: wsfulton - [Python] Fix shared_ptr typemaps where the pointer type is a templated type with - with more than one parameter. Reported by Robert Lupton. - -03/27/2008: mgossage - [Lua] Added a typemap DISOWN for SWIGTYPE* and SWIGTYPE[], and support for %delobject feature. - Added Examples/lua/owner which demonstrates the use of the memory management. - -03/26/2008: wsfulton - [Java] Apply patch #1844301 from Monty Taylor to suppress enum constructor - unused warnings. - -03/26/2008: wsfulton - [Python] Apply patch #1924524 from Casey Raymondson which ensures the - "No constructor defined" message is displayed when attempting to call a - constructor on a class that doesn't have a constructor wrapper, eg if - the C++ class is abstract. - -03/26/2008: wsfulton - [Python] Apply patch #1925702 from Casey Raymondson which removes warning 512 - for std::vector wrappers. - -03/26/2008: olly - [Python] Apply GCC 4.3 warnings patch from Philipp Thomas - (SF#1925122). - -03/21/2008: wsfulton - [Python] Thread safety patch for STL iterators from Abhinandan Jain. - -03/17/2008: mgossage - [Lua] Added %luacode feature to add source code into wrappers. - Updated documentation to document this. - Added Examples/lua/arrays to show its use (and typemaps) - -03/17/2008: olly - Fix nonportable sed usage which failed on Mac OS X (and probably - other platforms). Fixes SF#1903612. - -03/17/2008: olly - Fix memory leak in SWIG's parser (based on patch from Russell - Bryant in SF#1914023).` - -03/12/2008: wsfulton - Fix bug #1878285 - unnecessary cast for C struct creation wrappers. - -03/12/2008: wsfulton - [Python] Remove debugging info when using shared_ptr support - -03/06/2008: mgossage - [Lua] Updated documentation for Lua exceptions. - Added Examples/lua/exception and Examples/lua/embed2. - Small updates to the typemaps. - -03/04/2008: wsfulton - [Java, C#] Add char *& typemaps. - -03/04/2008: wsfulton - Fix occasional seg fault when attempting to report overloaded methods as being ignored. - -02/29/2008: wsfulton - [Perl] Fix #1904537 Swig causes a Perl warning "x used only once" in Perl 5.10 - reported by Ari Jolma - -02/29/2008: wsfulton - [Python] Add shared_ptr varin/varout typemaps for wrapping global variables. - -02/25/2008: wsfulton - Fix $wrapname to work in %exception (fixes some wrap:name assertions) + %module(directors="1", allprotected="1") modulename diff --git a/Examples/test-suite/allprotected.i b/Examples/test-suite/allprotected.i new file mode 100644 index 000000000..afd2fe919 --- /dev/null +++ b/Examples/test-suite/allprotected.i @@ -0,0 +1,68 @@ +// Tests for the allprotected option + +%module(directors="1", allprotected="1") allprotected + +%{ +#include +%} + +%include "std_string.i" + +%feature("director") PublicBase; +%feature("director") ProtectedBase; + +// protected types not supported (ProtectedEnum, IntegerType). Make sure they can be ignored. +%ignore ProtectedBase::protectedenum; +%ignore ProtectedBase::typedefs; + +%inline %{ +class Klass { + std::string name; +public: + Klass(const std::string& n) : name(n) {} + std::string getName() { return name; } +}; + +class PublicBase { + std::string str; +public: + enum AnEnum { EnumVal1, EnumVal2 }; +public: + PublicBase(const char* s): str(s) {} + virtual ~PublicBase() { } + virtual std::string virtualMethod() const { return "PublicBase"; } + Klass instanceMethod(Klass k) const { return k; } + static Klass staticMethod(Klass k) { return k; } + int instanceMemberVariable; + static int staticMemberVariable; + static const int staticConstMemberVariable = 20; + AnEnum anEnum; +}; +int PublicBase::staticMemberVariable = 10; + +class ProtectedBase { + std::string str; +public: + enum AnEnum { EnumVal1, EnumVal2 }; + std::string getName() { return str; } +protected: + ProtectedBase(const char* s): str(s) {} + virtual ~ProtectedBase() { } + virtual std::string virtualMethod() const { return "ProtectedBase"; } + Klass instanceMethod(Klass k) const { return k; } + static Klass staticMethod(Klass k) { return k; } + int instanceMemberVariable; + static int staticMemberVariable; + static const int staticConstMemberVariable = 20; + AnEnum anEnum; + +// unsupported: types defined with protected access and thus methods/variables which use them + enum ProtectedEnum { ProtEnumVal1, ProtEnumVal2 }; + typedef int IntegerType; + ProtectedEnum protectedenum; + IntegerType typedefs(IntegerType it) { return it; } +}; +int ProtectedBase::staticMemberVariable = 10; + +%} + diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 023dc2b3c..7aa4891ac 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -74,6 +74,7 @@ CPP_TEST_CASES += \ add_link \ aggregate \ allowexcept \ + allprotected \ anonymous_bitfield \ apply_signed_char \ apply_strings \ diff --git a/Examples/test-suite/csharp/allprotected_runme.cs b/Examples/test-suite/csharp/allprotected_runme.cs new file mode 100644 index 000000000..2ce659a31 --- /dev/null +++ b/Examples/test-suite/csharp/allprotected_runme.cs @@ -0,0 +1,55 @@ +using System; +using allprotectedNamespace; + +public class runme +{ + static void Main() + { + runme r = new runme(); + r.run(); + } + + void run() + { + MyProtectedBase mpb = new MyProtectedBase("MyProtectedBase"); + mpb.accessProtected(); + } +} + +class MyProtectedBase : ProtectedBase +{ + public MyProtectedBase(string name) : base(name) { + } + public void accessProtected() { + string s = virtualMethod(); + if (s != "ProtectedBase") + throw new Exception("Failed"); + + Klass k = instanceMethod(new Klass("xyz")); + if (k.getName() != "xyz") + throw new Exception("Failed"); + + k = staticMethod(new Klass("abc")); + if (k.getName() != "abc") + throw new Exception("Failed"); + + instanceMemberVariable = 30; + int i = instanceMemberVariable; + if (i != 30) + throw new Exception("Failed"); + + staticMemberVariable = 40; + i = staticMemberVariable; + if (i != 40) + throw new Exception("Failed"); + + i = staticConstMemberVariable; + if (i != 20) + throw new Exception("Failed"); + + anEnum = ProtectedBase.AnEnum.EnumVal1; + ProtectedBase.AnEnum ae = anEnum; + if (ae != ProtectedBase.AnEnum.EnumVal1) + throw new Exception("Failed"); + } +} diff --git a/Examples/test-suite/java/allprotected_runme.java b/Examples/test-suite/java/allprotected_runme.java new file mode 100755 index 000000000..04c74262c --- /dev/null +++ b/Examples/test-suite/java/allprotected_runme.java @@ -0,0 +1,58 @@ +import allprotected.*; + +public class allprotected_runme { + static { + try { + System.loadLibrary("allprotected"); + } 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[]) + { + MyProtectedBase mpb = new MyProtectedBase("MyProtectedBase"); + mpb.accessProtected(); + } +} + +class MyProtectedBase extends ProtectedBase +{ + MyProtectedBase(String name) { + super(name); + } + void accessProtected() { + String s = virtualMethod(); + if (!s.equals("ProtectedBase")) + throw new RuntimeException("Failed"); + + Klass k = instanceMethod(new Klass("xyz")); + if (!k.getName().equals("xyz")) + throw new RuntimeException("Failed"); + + k = staticMethod(new Klass("abc")); + if (!k.getName().equals("abc")) + throw new RuntimeException("Failed"); + + setInstanceMemberVariable(30); + int i = getInstanceMemberVariable(); + if (i != 30) + throw new RuntimeException("Failed"); + + setStaticMemberVariable(40); + i = getStaticMemberVariable(); + if (i != 40) + throw new RuntimeException("Failed"); + + i = staticConstMemberVariable; + if (i != 20) + throw new RuntimeException("Failed"); + + setAnEnum(ProtectedBase.AnEnum.EnumVal1); + ProtectedBase.AnEnum ae = getAnEnum(); + if (ae != ProtectedBase.AnEnum.EnumVal1) + throw new RuntimeException("Failed"); + } +} + diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 06e512db1..4fe8b47ed 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -282,6 +282,7 @@ static void add_symbols(Node *n) { Symtab *old_scope = 0; int isfriend = inclass && is_friend(n); int iscdecl = Cmp(nodeType(n),"cdecl") == 0; + int only_csymbol = 0; if (extendmode) { Setattr(n,"isextension","1"); } @@ -336,25 +337,17 @@ static void add_symbols(Node *n) { } if (!isfriend && inclass) { if ((cplus_mode != CPLUS_PUBLIC)) { - int only_csymbol = 1; + only_csymbol = 1; if (cplus_mode == CPLUS_PROTECTED) { Setattr(n,"access", "protected"); only_csymbol = !Swig_need_protected(n); } else { - /* private are needed only when they are pure virtuals */ Setattr(n,"access", "private"); - if ((Cmp(Getattr(n,"storage"),"virtual") == 0) - && (Cmp(Getattr(n,"value"),"0") == 0)) { - only_csymbol = !Swig_need_protected(n); + /* private are needed only when they are pure virtuals - why? */ + if ((Cmp(Getattr(n,"storage"),"virtual") == 0) && (Cmp(Getattr(n,"value"),"0") == 0)) { + only_csymbol = 0; } } - if (only_csymbol) { - /* Only add to C symbol table and continue */ - Swig_symbol_add(0, n); - if (add_only_one) break; - n = nextSibling(n); - continue; - } } else { Setattr(n,"access", "public"); } @@ -434,7 +427,8 @@ static void add_symbols(Node *n) { n = nextSibling(n); continue; } - if (GetFlag(n,"feature:ignore")) { + if (only_csymbol || GetFlag(n,"feature:ignore")) { + /* Only add to C symbol table and continue */ Swig_symbol_add(0, n); } else if (strncmp(Char(symname),"$ignore",7) == 0) { char *c = Char(symname)+7; @@ -2047,6 +2041,12 @@ module_directive: MODULE options idstring { if (Getattr($2,"directors")) { Wrapper_director_mode_set(1); } + if (Getattr($2,"dirprot")) { + Wrapper_director_protected_mode_set(1); + } + if (Getattr($2,"allprotected")) { + Wrapper_all_protected_mode_set(1); + } if (Getattr($2,"templatereduce")) { template_reduce = 1; } diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 927760609..fdb9c6979 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -274,6 +274,7 @@ public: if (Getattr(optionsnode, "dirprot")) { allow_dirprot(); } + allow_allprotected(GetFlag(optionsnode, "allprotected")); } /* Initialize all of the output files */ @@ -1238,14 +1239,17 @@ public: // The %csconst feature determines how the constant value is obtained int const_feature_flag = GetFlag(n, "feature:cs:const"); + const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); + methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); + if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) { // Wrap (non-anonymouse) enum using the typesafe enum pattern if (Getattr(n, "enumvalue")) { String *value = enumValue(n); - Printf(enum_code, " public static readonly %s %s = new %s(\"%s\", %s);\n", return_type, symname, return_type, symname, value); + Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value); Delete(value); } else { - Printf(enum_code, " public static readonly %s %s = new %s(\"%s\");\n", return_type, symname, return_type, symname); + Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname); } } else { // Simple integer constants @@ -1253,7 +1257,7 @@ public: // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later const char *const_readonly = const_feature_flag ? "const" : "static readonly"; String *value = enumValue(n); - Printf(enum_code, " public %s %s %s = %s;\n", const_readonly, return_type, symname, value); + Printf(enum_code, " %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value); Delete(value); } } @@ -1336,7 +1340,11 @@ public: if (outattributes) Printf(constants_code, " %s\n", outattributes); const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; - Printf(constants_code, " public %s %s %s = ", (const_feature_flag ? "const" : "static readonly"), return_type, itemname); + + const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); + methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); + + Printf(constants_code, " %s %s %s %s = ", methodmods, (const_feature_flag ? "const" : "static readonly"), return_type, itemname); // Check for the %csconstvalue feature String *value = Getattr(n, "feature:cs:constvalue"); @@ -3552,7 +3560,7 @@ public: Printf(w->code, "}"); - // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method + // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method String *inline_extra_method = NewString(""); if (dirprot_mode() && !is_public(n) && !pure_virtual) { Printv(inline_extra_method, declaration, NIL); diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index 014baddfc..5cf8a241b 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -415,9 +415,15 @@ void emit_action(Node *n, Wrapper *f) { action = Getattr(n, "wrap:action"); assert(action != 0); - if (!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) { - /* In order to call protected virtual director methods from the target language, we need - * to add an extra dynamic_cast to call the public C++ wrapper in the director class. */ + + /* In order to call protected virtual director methods from the target language, we need + * to add an extra dynamic_cast to call the public C++ wrapper in the director class. + * Also for non-static protected members when the allprotected option is on. */ +// TODO: why is the storage element removed in staticmemberfunctionHandler ?? + if (!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall")) || + (is_non_virtual_protected_access(n) && !(checkAttribute(n, "staticmemberfunctionHandler:storage", "static") || + checkAttribute(n, "storage", "static")) + && !Equal(nodeType(n), "constructor"))) { Node *parent = Getattr(n, "parentNode"); String *symname = Getattr(parent, "sym:name"); String *dirname = NewStringf("SwigDirector_%s", symname); diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 601b026ba..e2f00dc48 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -281,6 +281,7 @@ public: if (Getattr(optionsnode, "dirprot")) { allow_dirprot(); } + allow_allprotected(GetFlag(optionsnode, "allprotected")); } /* Initialize all of the output files */ @@ -893,12 +894,6 @@ public: // Premature garbage collection prevention parameter if (!is_destructor) { String *pgc_parameter = prematureGarbageCollectionPreventionParameter(pt, p); - /* - if (!pgc_parameter) { - Printf(stdout, "prematuregcp %s %s [%s]\n", symname, Getattr(n, "sym:overname"), pt); - Swig_print_node(p); - } - */ if (pgc_parameter) { Printf(imclass_class_code, ", %s %s_", pgc_parameter, arg); Printf(f->def, ", jobject %s_", arg); @@ -1294,21 +1289,24 @@ public: Delete(typemap_lookup_type); typemap_lookup_type = NULL; + const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); + methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); + if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) { // Wrap (non-anonymouse) enum using the typesafe enum pattern if (Getattr(n, "enumvalue")) { String *value = enumValue(n); - Printf(enum_code, " public final static %s %s = new %s(\"%s\", %s);\n", return_type, symname, return_type, symname, value); + Printf(enum_code, " %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value); Delete(value); } else { - Printf(enum_code, " public final static %s %s = new %s(\"%s\");\n", return_type, symname, return_type, symname); + Printf(enum_code, " %s final static %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname); } } else { // Simple integer constants // Note these are always generated for anonymous enums, no matter what enum_feature is specified // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later String *value = enumValue(n); - Printf(enum_code, " public final static %s %s = %s;\n", return_type, symname, value); + Printf(enum_code, " %s final static %s %s = %s;\n", methodmods, return_type, symname, value); Delete(value); } } @@ -1385,7 +1383,10 @@ public: } const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; - Printf(constants_code, " public final static %s %s = ", return_type, itemname); + const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); + methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); + + Printf(constants_code, " %s final static %s %s = ", methodmods, return_type, itemname); // Check for the %javaconstvalue feature String *value = Getattr(n, "feature:java:constvalue"); @@ -3743,7 +3744,7 @@ public: Printf(w->code, "}"); - // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method + // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method String *inline_extra_method = NewString(""); if (dirprot_mode() && !is_public(n) && !pure_virtual) { Printv(inline_extra_method, declaration, NIL); diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index ead4a1d95..b3dc28604 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -13,8 +13,10 @@ char cvsroot_lang_cxx[] = "$Id$"; #include "cparse.h" #include -static int director_mode = 0; /* set to 0 on default */ -static int director_protected_mode = 1; /* set to 1 on default */ +/* default mode settings */ +static int director_mode = 0; +static int director_protected_mode = 1; +static int all_protected_mode = 0; static int naturalvar_mode = 0; /* Set director_protected_mode */ @@ -26,6 +28,10 @@ void Wrapper_director_protected_mode_set(int flag) { director_protected_mode = flag; } +void Wrapper_all_protected_mode_set(int flag) { + all_protected_mode = flag; +} + void Wrapper_naturalvar_mode_set(int flag) { naturalvar_mode = flag; } @@ -34,6 +40,12 @@ extern "C" { int Swig_director_mode() { return director_mode; } + int Swig_director_protected_mode() { + return director_protected_mode; + } + int Swig_all_protected_mode() { + return all_protected_mode; + } } /* Some status variables used during parsing */ @@ -813,11 +825,13 @@ int Language::cDeclaration(Node *n) { /* except for friends, they are not affected by access control */ int isfriend = storage && (Cmp(storage, "friend") == 0); if (!isfriend) { - /* we check what the director needs. If the method is pure virtual, - it is always needed. */ - if (!(directorsEnabled() && is_member_director(CurrentClass, n) && need_nonpublic_member(n))) { - return SWIG_NOWRAP; + /* Check what the director needs. If the method is pure virtual, it is always needed. + * Also wrap non-virtual protected members if asked for (allprotected mode). */ + if (!(directorsEnabled() && ((is_member_director(CurrentClass, n) && need_nonpublic_member(n)) || is_non_virtual_protected_access(n)))) { + return SWIG_NOWRAP; } +#if 0 +// I don't see why this is needed - WSF /* prevent wrapping the method twice due to overload */ String *wrapname = NewStringf("nonpublic_%s%s", symname, Getattr(n, "sym:overname")); if (Getattr(CurrentClass, wrapname)) { @@ -826,6 +840,7 @@ int Language::cDeclaration(Node *n) { } SetFlag(CurrentClass, wrapname); Delete(wrapname); +#endif } } @@ -1217,9 +1232,9 @@ int Language::memberfunctionHandler(Node *n) { } } // Set up the type for the cast to this class for use when wrapping const director (virtual) methods. - // Note: protected director methods only. + // Note: protected director methods or when allprotected mode turned on. String *director_type = 0; - if (!is_public(n) && (is_member_director(CurrentClass, n) || GetFlag(n, "explicitcall"))) { + if (!is_public(n) && (is_member_director(CurrentClass, n) || GetFlag(n, "explicitcall") || is_non_virtual_protected_access(n))) { director_type = Copy(DirectorClassName); String *qualifier = Getattr(n, "qualifier"); if (qualifier) @@ -1238,6 +1253,7 @@ int Language::memberfunctionHandler(Node *n) { Swig_MethodToFunction(n, ClassType, Getattr(n, "template") ? SmartPointer : Extend | SmartPointer | DirectorExtraCall, director_type, is_member_director(CurrentClass, n)); Setattr(n, "sym:name", fname); + functionWrapper(n); Delete(director_type); @@ -1263,12 +1279,11 @@ int Language::staticmemberfunctionHandler(Node *n) { if (!Extend) { Node *sb = Getattr(n, "cplus:staticbase"); - String *sname = sb ? Getattr(sb, "name") : 0; - if (sname) { + String *sname = Getattr(sb, "name"); + if (is_non_virtual_protected_access(n)) + cname = NewStringf("%s::%s", DirectorClassName, name); + else cname = NewStringf("%s::%s", sname, name); - } else { - cname = NewStringf("%s::%s", ClassName, name); - } } else { String *mname = Swig_name_mangle(ClassName); cname = Swig_name_member(mname, name); @@ -1346,8 +1361,7 @@ int Language::variableHandler(Node *n) { SetFlag(n, "feature:immutable"); } } - if ((Cmp(storage, "static") == 0) - && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"))) { + if ((Cmp(storage, "static") == 0) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"))) { staticmembervariableHandler(n); } else { membervariableHandler(n); @@ -1421,6 +1435,8 @@ int Language::membervariableHandler(Node *n) { tm = Swig_typemap_lookup_new("memberin", n, target, 0); } int flags = Extend | SmartPointer | use_naturalvar_mode(n); + if (is_non_virtual_protected_access(n)) + flags = flags | CWRAP_ALL_PROTECTED_ACCESS; Swig_MembersetToFunction(n, ClassType, flags); Setattr(n, "memberset", "1"); @@ -1467,6 +1483,8 @@ int Language::membervariableHandler(Node *n) { /* Emit get function */ { int flags = Extend | SmartPointer | use_naturalvar_mode(n); + if (is_non_virtual_protected_access(n)) + flags = flags | CWRAP_ALL_PROTECTED_ACCESS; Swig_MembergetToFunction(n, ClassType, flags); Setattr(n, "sym:name", mrename_get); Setattr(n, "memberget", "1"); @@ -1525,7 +1543,8 @@ int Language::membervariableHandler(Node *n) { int Language::staticmembervariableHandler(Node *n) { Swig_require("staticmembervariableHandler", n, "*name", "*sym:name", "*type", "?value", NIL); String *value = Getattr(n, "value"); - String *classname = !SmartPointer ? ClassName : Getattr(CurrentClass, "allocate:smartpointerbase"); + String *classname = !SmartPointer ? (is_non_virtual_protected_access(n) ? DirectorClassName : ClassName) : Getattr(CurrentClass, "allocate:smartpointerbase"); + if (!value || !Getattr(n, "hasconsttype")) { String *name = Getattr(n, "name"); String *symname = Getattr(n, "sym:name"); @@ -1681,7 +1700,7 @@ int Language::memberconstantHandler(Node *n) { if (Extend) new_name = Copy(value); else - new_name = NewStringf("%s::%s", ClassName, name); + new_name = NewStringf("%s::%s", is_non_virtual_protected_access(n) ? DirectorClassName : ClassName, name); Setattr(n, "name", new_name); constantWrapper(n); @@ -2083,6 +2102,20 @@ int Language::classDirector(Node *n) { List *vtable = NewList(); int virtual_destructor = 0; unrollVirtualMethods(n, n, vtable, 0, virtual_destructor); + + // Emit all the using base::member statements for non virtual members (allprotected mode) + Node *ni; + String *using_protected_members_code = NewString(""); + for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) { + Node *nodeType = Getattr(ni, "nodeType"); + bool cdecl = (Cmp(nodeType, "cdecl") == 0); + if (cdecl && !GetFlag(ni, "feature:ignore")) { + if (is_non_virtual_protected_access(ni)) { + Printf(using_protected_members_code, " using %s::%s;\n", SwigType_namestr(ClassName), Getattr(ni, "name")); + } + } + } + if (virtual_destructor || Len(vtable) > 0) { if (!virtual_destructor) { String *classtype = Getattr(n, "classtype"); @@ -2096,9 +2129,14 @@ int Language::classDirector(Node *n) { classDirectorInit(n); classDirectorConstructors(n); classDirectorMethods(n); + + File *f_directors_h = Swig_filebyname("director_h"); + Printv(f_directors_h, using_protected_members_code, NIL); + classDirectorEnd(n); } Delete(vtable); + Delete(using_protected_members_code); return SWIG_OK; } @@ -3106,12 +3144,20 @@ void Language::allow_dirprot(int val) { director_protected_mode = val; } +/* ----------------------------------------------------------------------------- + * Language::allow_allprotected() + * ----------------------------------------------------------------------------- */ + +void Language::allow_allprotected(int val) { + all_protected_mode = val; +} + /* ----------------------------------------------------------------------------- * Language::dirprot_mode() * ----------------------------------------------------------------------------- */ int Language::dirprot_mode() const { - return directorsEnabled()? director_protected_mode : 0; + return directorsEnabled() ? director_protected_mode : 0; } /* ----------------------------------------------------------------------------- @@ -3183,8 +3229,7 @@ int Language::need_nonpublic_member(Node *n) { if (directorsEnabled()) { if (is_protected(n)) { if (dirprot_mode()) { - /* when using dirprot mode, the protected members are always - needed. */ + /* when using dirprot mode, the protected members are always needed. */ return 1; } else { /* if the method is pure virtual, we need it. */ diff --git a/Source/Modules/perl5.cxx b/Source/Modules/perl5.cxx index 47cf381e1..be86d9600 100644 --- a/Source/Modules/perl5.cxx +++ b/Source/Modules/perl5.cxx @@ -75,7 +75,7 @@ static File *f_pm = 0; static String *pm; /* Package initialization code */ static String *magic; /* Magic variable wrappers */ -static int is_static = 0; +static int staticoption = 0; /* The following variables are used to manage Perl5 classes */ @@ -150,7 +150,7 @@ public: export_all = 1; Swig_mark_arg(i); } else if (strcmp(argv[i], "-static") == 0) { - is_static = 1; + staticoption = 1; Swig_mark_arg(i); } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) { blessed = 1; @@ -298,7 +298,7 @@ public: Printf(f_pm, "package %s;\n", fullmodule); Printf(f_pm, "require Exporter;\n"); - if (!is_static) { + if (!staticoption) { Printf(f_pm, "require DynaLoader;\n"); Printf(f_pm, "@ISA = qw(Exporter DynaLoader);\n"); } else { @@ -378,7 +378,7 @@ public: Printf(f_pm, "package %s;\n", cmodule); - if (!is_static) { + if (!staticoption) { Printf(f_pm, "bootstrap %s;\n", fullmodule); } else { String *tmp = NewString(fullmodule); diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index 508730be8..53a40be9b 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -232,6 +232,9 @@ public: /* Allow director protected members related code generation */ void allow_dirprot(int val = 1); + /* Allow all protected members code generation (for directors) */ + void allow_allprotected(int val = 0); + /* Returns the dirprot mode */ int dirprot_mode() const; @@ -349,11 +352,10 @@ int is_private(Node *n); int is_protected(Node *n); int is_member_director(Node *parentnode, Node *member); int is_member_director(Node *member); +int is_non_virtual_protected_access(Node *n); /* Check if the non-virtual protected members are required (for directors) */ int use_naturalvar_mode(Node *n); void Wrapper_virtual_elimination_mode_set(int); -void Wrapper_director_mode_set(int); -void Wrapper_director_protected_mode_set(int); void Wrapper_fast_dispatch_mode_set(int); void Wrapper_cast_dispatch_mode_set(int); void Wrapper_naturalvar_mode_set(int); diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx index 8a89be5f2..ea7a3dde0 100644 --- a/Source/Modules/utils.cxx +++ b/Source/Modules/utils.cxx @@ -26,17 +26,19 @@ int is_protected(Node *n) { return access && !Cmp(access, "protected"); } -int is_member_director(Node *parentnode, Node *member) { - int director_mode = Swig_director_mode(); +static int is_member_director_helper(Node *parentnode, Node *member) { + int parent_nodirector = GetFlag(parentnode, "feature:nodirector"); + if (parent_nodirector) + return 0; + int parent_director = Swig_director_mode() && GetFlag(parentnode, "feature:director"); + int cdecl_director = parent_director || GetFlag(member, "feature:director"); + int cdecl_nodirector = GetFlag(member, "feature:nodirector"); + return cdecl_director && !cdecl_nodirector && !GetFlag(member, "feature:extend"); +} +int is_member_director(Node *parentnode, Node *member) { if (parentnode && checkAttribute(member, "storage", "virtual")) { - int parent_nodirector = GetFlag(parentnode, "feature:nodirector"); - if (parent_nodirector) - return 0; - int parent_director = director_mode && GetFlag(parentnode, "feature:director"); - int cdecl_director = parent_director || GetFlag(member, "feature:director"); - int cdecl_nodirector = GetFlag(member, "feature:nodirector"); - return cdecl_director && !cdecl_nodirector && !GetFlag(member, "feature:extend"); + return is_member_director_helper(parentnode, member); } else { return 0; } @@ -46,6 +48,17 @@ int is_member_director(Node *member) { return is_member_director(Getattr(member, "parentNode"), member); } +// Identifies the additional protected members that are generated when the allprotected option is used. +// This does not include protected virtual methods as they are turned on with the dirprot option. +int is_non_virtual_protected_access(Node *n) { + int result = 0; + if (Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode() && is_protected(n) && !checkAttribute(n, "storage", "virtual")) { + if (is_member_director_helper(Getattr(n, "parentNode"), n)) + result = 1; + } + return result; +} + /* Clean overloaded list. Removes templates, ignored, and errors */ void clean_overloaded(Node *n) { diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 2ca3192f6..5906b3768 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -975,7 +975,7 @@ int Swig_MethodToFunction(Node *n, String *classname, int flags, SwigType *direc Node *Swig_methodclass(Node *n) { Node *nodetype = nodeType(n); - if (!Cmp(nodetype, "class")) + if (Cmp(nodetype, "class") == 0) return n; return GetFlag(n, "feature:extend") ? parentNode(parentNode(n)) : parentNode(n); } @@ -1227,6 +1227,9 @@ int Swig_MembersetToFunction(Node *n, String *classname, int flags) { if (flags & CWRAP_SMART_POINTER) { self = NewString("(*this)->"); } + if (flags & CWRAP_ALL_PROTECTED_ACCESS) { + self = NewStringf("darg->"); + } name = Getattr(n, "name"); type = Getattr(n, "type"); @@ -1313,6 +1316,9 @@ int Swig_MembergetToFunction(Node *n, String *classname, int flags) { self = NewString("(*this)->"); } } + if (flags & CWRAP_ALL_PROTECTED_ACCESS) { + self = NewStringf("darg->"); + } name = Getattr(n, "name"); type = Getattr(n, "type"); diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index fdbd4a313..519e5b59e 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -966,22 +966,28 @@ int Swig_need_redefined_warn(Node *a, Node *b, int InClass) { * int Swig_need_protected(Node* n) * * Detects when we need to fully register the protected member. + * This is basically any protected members when the allprotected mode is set. + * Otherwise we take just the protected virtual methods and non-static methods + * (potentially virtual methods) as well as constructors/destructors. * * ----------------------------------------------------------------------------- */ int Swig_need_protected(Node *n) { - /* First, 'n' looks like a function */ - /* if (!Swig_director_mode()) return 0; */ String *nodetype = nodeType(n); - if ((Equal(nodetype, "cdecl")) && SwigType_isfunction(Getattr(n, "decl"))) { - String *storage = Getattr(n, "storage"); - /* and the function is declared like virtual, or it has no - storage. This eliminates typedef, static and so on. */ - return !storage || Equal(storage, "virtual"); - } else if (Equal(nodetype, "constructor") || Equal(nodetype, "destructor")) { - return 1; + if (checkAttribute(n, "access", "protected")) { + if ((Equal(nodetype, "cdecl"))) { + if (Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode()) { + return 1; + } + if (SwigType_isfunction(Getattr(n, "decl"))) { + String *storage = Getattr(n, "storage"); + /* The function is declared virtual, or it has no storage. This eliminates typedef, static etc. */ + return !storage || Equal(storage, "virtual"); + } + } else if (Equal(nodetype, "constructor") || Equal(nodetype, "destructor")) { + return 1; + } } - return 0; } diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 80c6c7d9b..f58ebea96 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -172,7 +172,7 @@ extern "C" { extern SwigType *SwigType_template_deftype(const SwigType *type, Symtab *tscope); /* --- Type-system managment --- */ - extern void SwigType_typesystem_init(); + extern void SwigType_typesystem_init(void); extern int SwigType_typedef(SwigType *type, String_or_char *name); extern int SwigType_typedef_class(String_or_char *name); extern int SwigType_typedef_using(String_or_char *qname); @@ -182,7 +182,7 @@ extern "C" { extern void SwigType_using_scope(Typetab *t); extern void SwigType_new_scope(const String_or_char *name); extern void SwigType_inherit_scope(Typetab *scope); - extern Typetab *SwigType_pop_scope(); + extern Typetab *SwigType_pop_scope(void); extern Typetab *SwigType_set_scope(Typetab *h); extern void SwigType_print_scope(Typetab *t); extern SwigType *SwigType_typedef_resolve(SwigType *t); @@ -200,15 +200,15 @@ extern "C" { /* --- Symbol table module --- */ - extern void Swig_symbol_init(); + extern void Swig_symbol_init(void); extern void Swig_symbol_setscopename(const String_or_char *name); - extern String *Swig_symbol_getscopename(); + extern String *Swig_symbol_getscopename(void); extern String *Swig_symbol_qualifiedscopename(Symtab *symtab); - extern Symtab *Swig_symbol_newscope(); + extern Symtab *Swig_symbol_newscope(void); extern Symtab *Swig_symbol_setscope(Symtab *); extern Symtab *Swig_symbol_getscope(const String_or_char *symname); - extern Symtab *Swig_symbol_current(); - extern Symtab *Swig_symbol_popscope(); + extern Symtab *Swig_symbol_current(void); + extern Symtab *Swig_symbol_popscope(void); extern Node *Swig_symbol_add(String_or_char *symname, Node *node); extern void Swig_symbol_cadd(String_or_char *symname, Node *node); extern Node *Swig_symbol_clookup(String_or_char *symname, Symtab *tab); @@ -258,7 +258,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern String *Swig_name_destroy(const String_or_char *classname); extern String *Swig_name_disown(const String_or_char *classname); - extern void Swig_naming_init(); + extern void Swig_naming_init(void); extern void Swig_name_namewarn_add(String *prefix, String *name, SwigType *decl, Hash *namewrn); extern Hash *Swig_name_namewarn_get(Node *n, String *prefix, String *name, SwigType *decl); extern void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *namewrn, ParmList *declaratorparms); @@ -298,7 +298,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern String *Swig_string_upper(String *s); extern String *Swig_string_title(String *s); - extern void Swig_init(); + extern void Swig_init(void); extern void Swig_warn(const char *filename, int line, const char *msg); extern int Swig_value_wrapper_mode(int mode); @@ -345,11 +345,12 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern int Swig_VargetToFunction(Node *n, int flags); extern int Swig_VarsetToFunction(Node *n, int flags); -#define CWRAP_EXTEND 0x01 -#define CWRAP_SMART_POINTER 0x02 -#define CWRAP_NATURAL_VAR 0x04 -#define CWRAP_DIRECTOR_ONE_CALL 0x08 -#define CWRAP_DIRECTOR_TWO_CALLS 0x10 +#define CWRAP_EXTEND 0x01 +#define CWRAP_SMART_POINTER 0x02 +#define CWRAP_NATURAL_VAR 0x04 +#define CWRAP_DIRECTOR_ONE_CALL 0x08 +#define CWRAP_DIRECTOR_TWO_CALLS 0x10 +#define CWRAP_ALL_PROTECTED_ACCESS 0x20 /* --- Director Helpers --- */ extern Node *Swig_methodclass(Node *n); @@ -358,13 +359,13 @@ extern int ParmList_is_compactdefargs(ParmList *p); /* --- Legacy Typemap API (somewhat simplified, ha!) --- */ - extern void Swig_typemap_init(); + extern void Swig_typemap_init(void); extern void Swig_typemap_register(const String_or_char *op, ParmList *pattern, String_or_char *code, ParmList *locals, ParmList *kwargs); extern int Swig_typemap_copy(const String_or_char *op, ParmList *srcpattern, ParmList *pattern); extern void Swig_typemap_clear(const String_or_char *op, ParmList *pattern); extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat); extern void Swig_typemap_clear_apply(ParmList *pattern); - extern void Swig_typemap_debug(); + extern void Swig_typemap_debug(void); extern Hash *Swig_typemap_search(const String_or_char *op, SwigType *type, const String_or_char *pname, SwigType **matchtype); extern Hash *Swig_typemap_search_multi(const String_or_char *op, ParmList *parms, int *nmatch); @@ -373,8 +374,8 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern String *Swig_typemap_lookup_new(const String_or_char *op, Node *n, const String_or_char *lname, Wrapper *f); extern void Swig_typemap_attach_kwargs(Hash *tm, const String_or_char *op, Parm *p); - extern void Swig_typemap_new_scope(); - extern Hash *Swig_typemap_pop_scope(); + extern void Swig_typemap_new_scope(void); + extern Hash *Swig_typemap_pop_scope(void); extern void Swig_typemap_attach_parms(const String_or_char *op, ParmList *parms, Wrapper *f); @@ -382,14 +383,19 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern void Swig_fragment_register(Node *fragment); extern void Swig_fragment_emit(String *name); + extern void Swig_fragment_clear(String *section); /* hacks defined in C++ ! */ - extern int Swig_director_mode(); + extern int Swig_director_mode(void); + extern int Swig_director_protected_mode(void); + extern int Swig_all_protected_mode(void); extern void Wrapper_director_mode_set(int); + extern void Wrapper_director_protected_mode_set(int); + extern void Wrapper_all_protected_mode_set(int); /* -- template init -- */ - extern void SwigType_template_init(); + extern void SwigType_template_init(void); #ifdef __cplusplus