aboutsummaryrefslogtreecommitdiff
path: root/Source/Modules/lang.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Modules/lang.cxx')
-rw-r--r--Source/Modules/lang.cxx736
1 files changed, 313 insertions, 423 deletions
diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx
index f7979b611..92f0cebd3 100644
--- a/Source/Modules/lang.cxx
+++ b/Source/Modules/lang.cxx
@@ -4,7 +4,7 @@
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
- * and at http://www.swig.org/legal.html.
+ * and at https://www.swig.org/legal.html.
*
* lang.cxx
*
@@ -16,13 +16,18 @@
#include <ctype.h>
/* default mode settings */
+static int directors_allowed = 0;
+static int director_language = 0;
static int director_mode = 0;
static int director_protected_mode = 1;
static int all_protected_mode = 0;
static int naturalvar_mode = 0;
Language *Language::this_ = 0;
-/* Set director_protected_mode */
+int Swig_directors_enabled() {
+ return director_language && CPlusPlus && (directors_allowed || director_mode);
+}
+
void Wrapper_director_mode_set(int flag) {
director_mode = flag;
}
@@ -74,9 +79,11 @@ String *input_file = 0;
int SmartPointer = 0;
static Hash *classhash;
-extern int GenerateDefault;
extern int ForceExtern;
extern int AddExtern;
+extern "C" {
+ extern int UseWrapperSuffix;
+}
/* import modes */
@@ -219,104 +226,149 @@ int Dispatcher::emit_children(Node *n) {
int Dispatcher::defaultHandler(Node *) {
return SWIG_OK;
}
+
int Dispatcher::extendDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::applyDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::clearDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::constantDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::fragmentDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::importDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::includeDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::insertDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::moduleDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::nativeDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::pragmaDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::typemapDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::typemapitemDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::typemapcopyDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::typesDirective(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::cDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::externDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::enumDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::enumvalueDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::enumforwardDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::classDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::templateDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::lambdaDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::classforwardDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::constructorDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::destructorDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::accessDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::usingDeclaration(Node *n) {
return defaultHandler(n);
}
+
int Dispatcher::namespaceDeclaration(Node *n) {
return defaultHandler(n);
}
+Dispatcher::AccessMode Dispatcher::accessModeFromString(String *access) {
+ Dispatcher::AccessMode mode = PUBLIC;
+ if (Cmp(access, "public") == 0) {
+ mode = PUBLIC;
+ } else if (Cmp(access, "private") == 0) {
+ mode = PRIVATE;
+ } else if (Cmp(access, "protected") == 0) {
+ mode = PROTECTED;
+ } else {
+ assert(0);
+ }
+ return mode;
+}
+
+
/* Allocators */
Language::Language():
none_comparison(NewString("$arg != 0")),
director_ctor_code(NewString("")),
director_prot_ctor_code(0),
+director_multiple_inheritance(1),
+doxygenTranslator(NULL),
symtabs(NewHash()),
overloading(0),
multiinput(0),
-cplus_runtime(0),
-directors(0) {
+cplus_runtime(0) {
symbolAddScope(""); // create top level/global symbol table scope
argc_template_string = NewString("argc");
argv_template_string = NewString("argv[%d]");
@@ -324,17 +376,8 @@ directors(0) {
/* Default director constructor code, passed to Swig_ConstructorToFunction */
Printv(director_ctor_code, "if ( $comparison ) { /* subclassed */\n", " $director_new \n", "} else {\n", " $nondirector_new \n", "}\n", NIL);
- /*
- Default director 'protected' constructor code, disabled by
- default. Each language that needs it, has to define it.
- */
- director_prot_ctor_code = 0;
- director_multiple_inheritance = 1;
- director_language = 0;
assert(!this_);
this_ = this;
-
- doxygenTranslator = NULL;
}
Language::~Language() {
@@ -418,7 +461,7 @@ static Parm *nonvoid_parms(Parm *p) {
* Returns the alternative value type needed in C++ for class value
* types. When swig is not sure about using a plain $ltype value,
* since the class doesn't have a default constructor, or it can't be
- * assigned, you will get back 'SwigValueWrapper<type >'.
+ * assigned, you will get back 'SwigValueWrapper<(type)>'.
*
* ----------------------------------------------------------------------------- */
@@ -445,12 +488,7 @@ static Node *first_nontemplate(Node *n) {
void swig_pragma(char *lang, char *name, char *value) {
if (strcmp(lang, "swig") == 0) {
- if ((strcmp(name, "make_default") == 0) || ((strcmp(name, "makedefault") == 0))) {
- GenerateDefault = 1;
- } else if ((strcmp(name, "no_default") == 0) || ((strcmp(name, "nodefault") == 0))) {
- Swig_warning(WARN_DEPRECATED_NODEFAULT, "SWIG", 1, "dangerous, use %%nodefaultctor, %%nodefaultdtor instead.\n");
- GenerateDefault = 0;
- } else if (strcmp(name, "attributefunction") == 0) {
+ if (strcmp(name, "attributefunction") == 0) {
String *nvalue = NewString(value);
char *s = strchr(Char(nvalue), ':');
if (!s) {
@@ -722,23 +760,23 @@ int Language::typemapDirective(Node *n) {
String *code = Getattr(n, "code");
Parm *kwargs = Getattr(n, "kwargs");
Node *items = firstChild(n);
- static int namewarn = 0;
+ static int nameerror = 0;
if (code && (Strstr(code, "$source") || (Strstr(code, "$target")))) {
- Swig_warning(WARN_TYPEMAP_SOURCETARGET, Getfile(n), Getline(n), "Deprecated typemap feature ($source/$target).\n");
- if (!namewarn) {
- Swig_warning(WARN_TYPEMAP_SOURCETARGET, Getfile(n), Getline(n), "The use of $source and $target in a typemap declaration is deprecated.\n\
+ Swig_error(Getfile(n), Getline(n), "Obsolete typemap feature ($source/$target).\n");
+ if (!nameerror) {
+ Swig_error(Getfile(n), Getline(n), "The use of $source and $target in a typemap declaration is no longer supported.\n\
For typemaps related to argument input (in,ignore,default,arginit,check), replace\n\
$source by $input and $target by $1. For typemaps related to return values (out,\n\
argout,ret,except), replace $source by $1 and $target by $result. See the file\n\
Doc/Manual/Typemaps.html for complete details.\n");
- namewarn = 1;
+ nameerror = 1;
}
}
if (Strcmp(method, "except") == 0) {
- Swig_warning(WARN_DEPRECATED_EXCEPT_TM, Getfile(n), Getline(n), "%%typemap(except) is deprecated. Use the %%exception directive.\n");
+ Swig_error(Getfile(n), Getline(n), "%%typemap(except) is no longer supported. Use the %%exception directive.\n");
}
if (Strcmp(method, "in") == 0) {
@@ -765,16 +803,7 @@ Doc/Manual/Typemaps.html for complete details.\n");
}
if (Strcmp(method, "ignore") == 0) {
- Swig_warning(WARN_DEPRECATED_IGNORE_TM, Getfile(n), Getline(n), "%%typemap(ignore) has been replaced by %%typemap(in,numinputs=0).\n");
-
- Clear(method);
- Append(method, "in");
- Hash *k = NewHash();
- Setattr(k, "name", "numinputs");
- Setattr(k, "value", "0");
- set_nextSibling(k, kwargs);
- Setattr(n, "kwargs", k);
- kwargs = k;
+ Swig_error(Getfile(n), Getline(n), "%%typemap(ignore) is no longer supported. Use %%typemap(in,numinputs=0).\n");
}
/* Replace $descriptor() macros */
@@ -879,11 +908,11 @@ int Language::cDeclaration(Node *n) {
/* discards nodes following the access control rules */
if (cplus_mode != PUBLIC || !is_public(n)) {
/* except for friends, they are not affected by access control */
- int isfriend = Cmp(storage, "friend") == 0;
+ int isfriend = (Strstr(storage, "friend") != NULL);
if (!isfriend) {
/* 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)) || isNonVirtualProtectedAccess(n)))) {
+ if (!(Swig_directors_enabled() && ((is_member_director(CurrentClass, n) && need_nonpublic_member(n)) || isNonVirtualProtectedAccess(n)))) {
return SWIG_NOWRAP;
}
// Prevent wrapping protected overloaded director methods more than once -
@@ -1029,17 +1058,6 @@ int Language::cDeclaration(Node *n) {
}
}
}
- if (!SwigType_ismutable(ty)) {
- SetFlag(n, "feature:immutable");
- }
- /* If an array and elements are const, then read-only */
- if (SwigType_isarray(ty)) {
- SwigType *tya = SwigType_array_type(ty);
- if (SwigType_isconst(tya)) {
- SetFlag(n, "feature:immutable");
- }
- Delete(tya);
- }
DohIncref(type);
Setattr(n, "type", ty);
variableHandler(n);
@@ -1058,7 +1076,7 @@ int Language::cDeclaration(Node *n) {
int Language::functionHandler(Node *n) {
String *storage = Getattr(n, "storage");
- int isfriend = CurrentClass && Cmp(storage, "friend") == 0;
+ int isfriend = CurrentClass && Strstr(storage, "friend");
int isstatic = CurrentClass && Swig_storage_isstatic(n) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"));
Parm *p = Getattr(n, "parms");
if (GetFlag(n, "feature:del")) {
@@ -1084,7 +1102,7 @@ int Language::functionHandler(Node *n) {
// This is a member function, set a flag so the documentation type is correct
SetFlag(n, "memberfunction");
Node *explicit_n = 0;
- if (directorsEnabled() && is_member_director(CurrentClass, n) && !extraDirectorProtectedCPPMethodsRequired()) {
+ if (Swig_directors_enabled() && is_member_director(CurrentClass, n) && !extraDirectorProtectedCPPMethodsRequired()) {
bool virtual_but_not_pure_virtual = (!(Cmp(storage, "virtual")) && (Cmp(Getattr(n, "value"), "0") != 0));
if (virtual_but_not_pure_virtual) {
// Add additional wrapper which makes an explicit call to the virtual method (ie not a virtual call)
@@ -1148,7 +1166,20 @@ int Language::globalfunctionHandler(Node *n) {
String *extendname = Getattr(n, "extendname");
String *call = Swig_cfunction_call(extendname ? extendname : name, parms);
String *cres = Swig_cresult(type, Swig_cresult_name(), call);
- Setattr(n, "wrap:action", cres);
+ String *friendusing = Getattr(n, "friendusing");
+ if (friendusing) {
+ // Add a using directive to avoid having to possibly fully qualify the call to the friend function.
+ // Unconventional for SWIG generation, but the alternative is to implement Argument Dependent Lookup
+ // as friend functions are quirky and not visible, except for ADL. An ADL implementation would be needed
+ // in order to work out when the friend function is visible or not, in order to determine whether to
+ // rely on ADL (with no qualification) or to fully qualify the call to the friend function made
+ // visible via a matching declaration at namespace scope.
+ String *action = NewStringf("%s\n%s", friendusing, cres);
+ Setattr(n, "wrap:action", action);
+ Delete(action);
+ } else {
+ Setattr(n, "wrap:action", cres);
+ }
Delete(cres);
Delete(call);
functionWrapper(n);
@@ -1261,7 +1292,7 @@ int Language::memberfunctionHandler(Node *n) {
}
int DirectorExtraCall = 0;
- if (directorsEnabled() && is_member_director(CurrentClass, n) && !SmartPointer)
+ if (Swig_directors_enabled() && is_member_director(CurrentClass, n) && !SmartPointer)
if (extraDirectorProtectedCPPMethodsRequired())
DirectorExtraCall = CWRAP_DIRECTOR_TWO_CALLS;
@@ -1307,29 +1338,36 @@ int Language::staticmemberfunctionHandler(Node *n) {
else
cname = NewStringf("%s::%s", sname, name);
} else {
- String *mname = Swig_name_mangle(ClassName);
+ String *classname_str = SwigType_namestr(ClassName);
+ String *mname = Swig_name_mangle_string(classname_str);
cname = Swig_name_member(NSpace, mname, name);
Delete(mname);
+ Delete(classname_str);
}
mrename = Swig_name_member(NSpace, ClassPrefix, symname);
if (Extend) {
String *code = Getattr(n, "code");
String *defaultargs = Getattr(n, "defaultargs");
- String *mangled = Swig_name_mangle(mrename);
+ String *mangled = Swig_name_mangle_string(mrename);
Delete(mrename);
mrename = mangled;
- if (Getattr(n, "sym:overloaded") && code) {
- Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
- }
+ if (code) {
+ // See Swig_MethodToFunction() for the explanation of this code.
+ if (Getattr(n, "sym:overloaded")) {
+ Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
+ } else if (UseWrapperSuffix) {
+ Append(cname, "__SWIG");
+ }
- if (!defaultargs && code) {
- /* Hmmm. An added static member. We have to create a little wrapper for this */
- String *mangled_cname = Swig_name_mangle(cname);
- Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0);
- Setattr(n, "extendname", mangled_cname);
- Delete(mangled_cname);
+ if (!defaultargs) {
+ /* Hmmm. An added static member. We have to create a little wrapper for this */
+ String *mangled_cname = Swig_name_mangle_string(cname);
+ Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0);
+ Setattr(n, "extendname", mangled_cname);
+ Delete(mangled_cname);
+ }
}
}
@@ -1428,7 +1466,7 @@ int Language::membervariableHandler(Node *n) {
/* Create a function to set the value of the variable */
- int assignable = is_assignable(n);
+ int assignable = !is_immutable(n);
if (SmartPointer) {
if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
@@ -1481,8 +1519,6 @@ int Language::membervariableHandler(Node *n) {
} else {
String *pname0 = Swig_cparm_name(0, 0);
String *pname1 = Swig_cparm_name(0, 1);
- Replace(tm, "$source", pname1, DOH_REPLACE_ANY);
- Replace(tm, "$target", target, DOH_REPLACE_ANY);
Replace(tm, "$input", pname1, DOH_REPLACE_ANY);
Replace(tm, "$self", pname0, DOH_REPLACE_ANY);
Setattr(n, "wrap:action", tm);
@@ -1793,6 +1829,8 @@ int Language::typedefHandler(Node *n) {
*/
SwigType *name = Getattr(n, "name");
SwigType *decl = Getattr(n, "decl");
+ Setfile(name, Getfile(n));
+ Setline(name, Getline(n));
if (!SwigType_ispointer(decl) && !SwigType_isreference(decl)) {
SwigType *pname = Copy(name);
SwigType_add_pointer(pname);
@@ -1842,20 +1880,82 @@ static String *vtable_method_id(Node *n) {
String *tmp = SwigType_pop_function(local_decl);
Delete(local_decl);
local_decl = tmp;
- Node *method_id = NewStringf("%s|%s", name, local_decl);
+ String *method_id = NewStringf("%s|%s", name, local_decl);
Delete(local_decl);
return method_id;
}
+/* ----------------------------------------------------------------------
+ * Language::unrollOneVirtualMethod()
+ * ---------------------------------------------------------------------- */
+
+void Language::unrollOneVirtualMethod(String *classname, Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase) {
+ if (!checkAttribute(n, "storage", "virtual"))
+ return;
+ if (GetFlag(n, "final"))
+ return;
+
+ String *nodeType = Getattr(n, "nodeType");
+
+ /* we need to add methods(cdecl) and destructor (to check for throw decl) */
+ int is_destructor = (Cmp(nodeType, "destructor") == 0);
+ if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
+ String *decl = Getattr(n, "decl");
+ /* extra check for function type and proper access */
+ if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(n)) || need_nonpublic_member(n))) {
+ String *name = Getattr(n, "name");
+ String *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(n);
+ /* Make sure that the new method overwrites the existing: */
+ int len = Len(vm);
+ const int DO_NOT_REPLACE = -1;
+ int replace = DO_NOT_REPLACE;
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vm, i);
+ String *check_vmid = Getattr(item, "vmid");
+
+ if (Strcmp(method_id, check_vmid) == 0) {
+ replace = i;
+ break;
+ }
+ }
+ /* filling a new method item */
+ String *fqdname = NewStringf("%s::%s", classname, name);
+ Hash *item = NewHash();
+ Setattr(item, "fqdname", fqdname);
+ Node *m = Copy(n);
+
+ /* Store the complete return type - needed for non-simple return types (pointers, references etc.) */
+ SwigType *ty = NewString(Getattr(m, "type"));
+ SwigType_push(ty, decl);
+ if (SwigType_isqualifier(ty)) {
+ Delete(SwigType_pop(ty));
+ }
+ Delete(SwigType_pop_function(ty));
+ Setattr(m, "returntype", ty);
+
+ String *mname = NewStringf("%s::%s", Getattr(parent, "name"), name);
+ /* apply the features of the original method found in the base class */
+ Swig_features_get(Swig_cparse_features(), 0, mname, Getattr(m, "decl"), m);
+ Setattr(item, "methodNode", m);
+ Setattr(item, "vmid", method_id);
+ if (replace == DO_NOT_REPLACE)
+ Append(vm, item);
+ else
+ Setitem(vm, replace, item);
+ Setattr(n, "directorNode", m);
+
+ Delete(mname);
+ }
+ if (is_destructor) {
+ virtual_destructor = 1;
+ }
+ }
+}
/* ----------------------------------------------------------------------
* Language::unrollVirtualMethods()
* ---------------------------------------------------------------------- */
-int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_director, int &virtual_destructor, int protectedbase) {
- Node *ni;
- String *nodeType;
- String *classname;
- String *decl;
+int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase) {
bool first_base = false;
// recurse through all base classes to build the vtable
List *bl = Getattr(n, "bases");
@@ -1864,10 +1964,11 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance)
break;
- unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor);
+ unrollVirtualMethods(bi.item, parent, vm, virtual_destructor);
first_base = true;
}
}
+
// recurse through all protected base classes to build the vtable, as needed
bl = Getattr(n, "protectedbases");
if (bl) {
@@ -1875,88 +1976,28 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
for (bi = First(bl); bi.item; bi = Next(bi)) {
if (first_base && !director_multiple_inheritance)
break;
- unrollVirtualMethods(bi.item, parent, vm, default_director, virtual_destructor, 1);
+ unrollVirtualMethods(bi.item, parent, vm, virtual_destructor, 1);
first_base = true;
}
}
+
// find the methods that need directors
- classname = Getattr(n, "name");
- for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+ String *classname = Getattr(n, "name");
+ for (Node *ni = firstChild(n); ni; ni = nextSibling(ni)) {
/* we only need to check the virtual members */
- nodeType = Getattr(ni, "nodeType");
- int is_using = (Cmp(nodeType, "using") == 0);
- Node *nn = is_using ? firstChild(ni) : ni; /* assume there is only one child node for "using" nodes */
- if (is_using) {
- if (nn)
- nodeType = Getattr(nn, "nodeType");
- else
- continue; // A private "using" node
- }
- if (!checkAttribute(nn, "storage", "virtual"))
- continue;
- if (GetFlag(nn, "final"))
- continue;
- /* we need to add methods(cdecl) and destructor (to check for throw decl) */
- int is_destructor = (Cmp(nodeType, "destructor") == 0);
- if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
- decl = Getattr(nn, "decl");
- /* extra check for function type and proper access */
- if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(nn)) || need_nonpublic_member(nn))) {
- String *name = Getattr(nn, "name");
- Node *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(nn);
- /* Make sure that the new method overwrites the existing: */
- int len = Len(vm);
- const int DO_NOT_REPLACE = -1;
- int replace = DO_NOT_REPLACE;
- for (int i = 0; i < len; i++) {
- Node *item = Getitem(vm, i);
- String *check_vmid = Getattr(item, "vmid");
-
- if (Strcmp(method_id, check_vmid) == 0) {
- replace = i;
- break;
- }
- }
- /* filling a new method item */
- String *fqdname = NewStringf("%s::%s", classname, name);
- Hash *item = NewHash();
- Setattr(item, "fqdname", fqdname);
- Node *m = Copy(nn);
-
- /* Store the complete return type - needed for non-simple return types (pointers, references etc.) */
- SwigType *ty = NewString(Getattr(m, "type"));
- SwigType_push(ty, decl);
- if (SwigType_isqualifier(ty)) {
- Delete(SwigType_pop(ty));
- }
- Delete(SwigType_pop_function(ty));
- Setattr(m, "returntype", ty);
-
- String *mname = NewStringf("%s::%s", Getattr(parent, "name"), name);
- /* apply the features of the original method found in the base class */
- Swig_features_get(Swig_cparse_features(), 0, mname, Getattr(m, "decl"), m);
- Setattr(item, "methodNode", m);
- Setattr(item, "vmid", method_id);
- if (replace == DO_NOT_REPLACE)
- Append(vm, item);
- else
- Setitem(vm, replace, item);
- Setattr(nn, "directorNode", m);
-
- Delete(mname);
- }
- if (is_destructor) {
- virtual_destructor = 1;
+ if (Equal(nodeType(ni), "using")) {
+ for (Node *nn = firstChild(ni); nn; nn = Getattr(nn, "sym:nextSibling")) {
+ unrollOneVirtualMethod(classname, nn, parent, vm, virtual_destructor, protectedbase);
}
}
+ unrollOneVirtualMethod(classname, ni, parent, vm, virtual_destructor, protectedbase);
}
/*
We delete all the nodirector methods. This prevents the
generation of 'empty' director classes.
- But this has to be done outside the previous 'for'
- and the recursive loop!.
+ Done once we've collated all the virtual methods into vm.
*/
if (n == parent) {
int len = Len(vm);
@@ -2035,7 +2076,6 @@ int Language::classDirectorDisown(Node *n) {
* ---------------------------------------------------------------------- */
int Language::classDirectorConstructors(Node *n) {
- Node *ni;
String *nodeType;
Node *parent = Swig_methodclass(n);
int default_ctor = Getattr(parent, "allocate:default_constructor") ? 1 : 0;
@@ -2043,31 +2083,42 @@ int Language::classDirectorConstructors(Node *n) {
int constructor = 0;
/* emit constructors */
- for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+ List *constructors = NewList();
+ for (Node *ni = firstChild(n); ni; ni = nextSibling(ni)) {
nodeType = Getattr(ni, "nodeType");
- if (Cmp(nodeType, "constructor") == 0) {
- if (GetFlag(ni, "feature:ignore"))
- continue;
+ if (Equal(nodeType, "constructor")) {
+ Append(constructors, ni);
+ } else if (Equal(nodeType, "using") && GetFlag(ni, "usingctor")) {
+ for (Node *ui = firstChild(ni); ui; ui = nextSibling(ui)) {
+ Append(constructors, ui);
+ }
+ }
+ }
+ for (Iterator it = First(constructors); it.item; it = Next(it)) {
+ Node *ni = it.item;
+ if (GetFlag(ni, "feature:ignore"))
+ continue;
- Parm *parms = Getattr(ni, "parms");
- if (is_public(ni)) {
- /* emit public constructor */
+ Parm *parms = Getattr(ni, "parms");
+ if (is_public(ni)) {
+ /* emit public constructor */
+ classDirectorConstructor(ni);
+ constructor = 1;
+ if (default_ctor)
+ default_ctor = !ParmList_numrequired(parms);
+ } else {
+ /* emit protected constructor if needed */
+ if (need_nonpublic_ctor(ni)) {
classDirectorConstructor(ni);
constructor = 1;
+ protected_ctor = 1;
if (default_ctor)
default_ctor = !ParmList_numrequired(parms);
- } else {
- /* emit protected constructor if needed */
- if (need_nonpublic_ctor(ni)) {
- classDirectorConstructor(ni);
- constructor = 1;
- protected_ctor = 1;
- if (default_ctor)
- default_ctor = !ParmList_numrequired(parms);
- }
}
}
}
+ Delete(constructors);
+
/* emit default constructor if needed */
if (!constructor) {
if (!default_ctor) {
@@ -2193,13 +2244,13 @@ int Language::classDirector(Node *n) {
}
List *vtable = NewList();
int virtual_destructor = 0;
- unrollVirtualMethods(n, n, vtable, 0, virtual_destructor);
+ unrollVirtualMethods(n, n, vtable, 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");
+ String *nodeType = nodeType(ni);
if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) {
String *classtype = Getattr(n, "classtype");
SWIG_WARN_NODE_BEGIN(ni);
@@ -2210,13 +2261,18 @@ int Language::classDirector(Node *n) {
Delete(using_protected_members_code);
return SWIG_OK;
}
- bool cdeclaration = (Cmp(nodeType, "cdecl") == 0);
- if (cdeclaration && !GetFlag(ni, "feature:ignore")) {
- if (isNonVirtualProtectedAccess(ni)) {
- Node *overloaded = Getattr(ni, "sym:overloaded");
+ Node *nn = ni;
+ bool cdeclaration = Equal(nodeType, "cdecl");
+ if (!cdeclaration && Equal(nodeType, "using")) {
+ nn = Getattr(ni, "firstChild");
+ cdeclaration = nn && Equal(nodeType(nn), "cdecl") ? true : false;
+ }
+ if (cdeclaration && !GetFlag(nn, "feature:ignore")) {
+ if (isNonVirtualProtectedAccess(nn)) {
+ Node *overloaded = Getattr(nn, "sym:overloaded");
// emit the using base::member statement (but only once if the method is overloaded)
- if (!overloaded || (overloaded && (overloaded == ni)))
- Printf(using_protected_members_code, " using %s::%s;\n", SwigType_namestr(ClassName), Getattr(ni, "name"));
+ if (!overloaded || (overloaded && (overloaded == nn)))
+ Printf(using_protected_members_code, " using %s::%s;\n", SwigType_namestr(ClassName), Getattr(nn, "name"));
}
}
}
@@ -2249,164 +2305,6 @@ int Language::classDirector(Node *n) {
* Language::classDeclaration()
* ---------------------------------------------------------------------- */
-static void addCopyConstructor(Node *n) {
- Node *cn = NewHash();
- set_nodeType(cn, "constructor");
- Setattr(cn, "access", "public");
- Setfile(cn, Getfile(n));
- Setline(cn, Getline(n));
-
- String *cname = Getattr(n, "name");
- SwigType *type = Copy(cname);
- String *name = Swig_scopename_last(cname);
- String *cc = NewStringf("r.q(const).%s", type);
- String *decl = NewStringf("f(%s).", cc);
- String *oldname = Getattr(n, "sym:name");
-
- if (Getattr(n, "allocate:has_constructor")) {
- // to work properly with '%rename Class', we must look
- // for any other constructor in the class, which has not been
- // renamed, and use its name as oldname.
- Node *c;
- for (c = firstChild(n); c; c = nextSibling(c)) {
- const char *tag = Char(nodeType(c));
- if (strcmp(tag, "constructor") == 0) {
- String *cname = Getattr(c, "name");
- String *csname = Getattr(c, "sym:name");
- String *clast = Swig_scopename_last(cname);
- if (Equal(csname, clast)) {
- oldname = csname;
- break;
- }
- }
- }
- }
-
- String *symname = Swig_name_make(cn, cname, name, decl, oldname);
- if (Strcmp(symname, "$ignore") != 0) {
- Parm *p = NewParm(cc, "other", n);
-
- Setattr(cn, "name", name);
- Setattr(cn, "sym:name", symname);
- SetFlag(cn, "feature:new");
- Setattr(cn, "decl", decl);
- Setattr(cn, "parentNode", n);
- Setattr(cn, "parms", p);
- Setattr(cn, "copy_constructor", "1");
-
- Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
- Node *on = Swig_symbol_add(symname, cn);
- Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
- Swig_symbol_setscope(oldscope);
-
- if (on == cn) {
- Node *access = NewHash();
- set_nodeType(access, "access");
- Setattr(access, "kind", "public");
- appendChild(n, access);
- appendChild(n, cn);
- Setattr(n, "has_copy_constructor", "1");
- Setattr(n, "copy_constructor_decl", decl);
- Setattr(n, "allocate:copy_constructor", "1");
- Delete(access);
- }
- }
- Delete(cn);
- Delete(name);
- Delete(decl);
- Delete(symname);
-}
-
-static void addDefaultConstructor(Node *n) {
- Node *cn = NewHash();
- set_nodeType(cn, "constructor");
- Setattr(cn, "access", "public");
- Setfile(cn, Getfile(n));
- Setline(cn, Getline(n));
-
- String *cname = Getattr(n, "name");
- String *name = Swig_scopename_last(cname);
- String *decl = NewString("f().");
- String *oldname = Getattr(n, "sym:name");
- String *symname = Swig_name_make(cn, cname, name, decl, oldname);
- if (Strcmp(symname, "$ignore") != 0) {
- Setattr(cn, "name", name);
- Setattr(cn, "sym:name", symname);
- SetFlag(cn, "feature:new");
- Setattr(cn, "decl", decl);
- Setattr(cn, "parentNode", n);
- Setattr(cn, "default_constructor", "1");
- Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
- Node *on = Swig_symbol_add(symname, cn);
- Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
- Swig_symbol_setscope(oldscope);
-
- if (on == cn) {
- Node *access = NewHash();
- set_nodeType(access, "access");
- Setattr(access, "kind", "public");
- appendChild(n, access);
- appendChild(n, cn);
- Setattr(n, "has_default_constructor", "1");
- Setattr(n, "allocate:default_constructor", "1");
- Delete(access);
- }
- }
- Delete(cn);
- Delete(name);
- Delete(decl);
- Delete(symname);
-}
-
-static void addDestructor(Node *n) {
- Node *cn = NewHash();
- set_nodeType(cn, "destructor");
- Setattr(cn, "access", "public");
- Setfile(cn, Getfile(n));
- Setline(cn, Getline(n));
-
- String *cname = Getattr(n, "name");
- String *name = Swig_scopename_last(cname);
- Insert(name, 0, "~");
- String *decl = NewString("f().");
- String *symname = Swig_name_make(cn, cname, name, decl, 0);
- if (Strcmp(symname, "$ignore") != 0) {
- String *possible_nonstandard_symname = NewStringf("~%s", Getattr(n, "sym:name"));
-
- Setattr(cn, "name", name);
- Setattr(cn, "sym:name", symname);
- Setattr(cn, "decl", "f().");
- Setattr(cn, "parentNode", n);
-
- Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
- Node *nonstandard_destructor = Equal(possible_nonstandard_symname, symname) ? 0 : Swig_symbol_clookup(possible_nonstandard_symname, 0);
- Node *on = Swig_symbol_add(symname, cn);
- Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
- Swig_symbol_setscope(oldscope);
-
- if (on == cn) {
- // SWIG accepts a non-standard named destructor in %extend that uses a typedef for the destructor name
- // For example: typedef struct X {} XX; %extend X { ~XX() {...} }
- // Don't add another destructor if a nonstandard one has been declared
- if (!nonstandard_destructor) {
- Node *access = NewHash();
- set_nodeType(access, "access");
- Setattr(access, "kind", "public");
- appendChild(n, access);
- appendChild(n, cn);
- Setattr(n, "has_destructor", "1");
- Setattr(n, "allocate:destructor", "1");
- Delete(access);
- }
- }
- Delete(possible_nonstandard_symname);
- }
- Delete(cn);
- Delete(name);
- Delete(decl);
- Delete(symname);
-}
-
int Language::classDeclaration(Node *n) {
String *ochildren = Getattr(n, "feature:onlychildren");
if (ochildren) {
@@ -2479,44 +2377,19 @@ int Language::classDeclaration(Node *n) {
/* Call classHandler() here */
if (!ImportMode) {
- if (directorsEnabled()) {
+ if (Swig_directors_enabled()) {
int ndir = GetFlag(n, "feature:director");
int nndir = GetFlag(n, "feature:nodirector");
/* 'nodirector' has precedence over 'director' */
dir = (ndir || nndir) ? (ndir && !nndir) : 0;
}
- int abstract = !dir && abstractClassTest(n);
- int odefault = (GenerateDefault && !GetFlag(n, "feature:nodefault"));
-
- /* default constructor */
- if (!abstract && !GetFlag(n, "feature:nodefaultctor") && odefault) {
- if (!Getattr(n, "has_constructor") && !Getattr(n, "allocate:has_constructor") && (Getattr(n, "allocate:default_constructor"))) {
- addDefaultConstructor(n);
- }
- }
- /* copy constructor */
- if (CPlusPlus && !abstract && GetFlag(n, "feature:copyctor")) {
- if (!Getattr(n, "has_copy_constructor") && !Getattr(n, "allocate:has_copy_constructor")
- && (Getattr(n, "allocate:copy_constructor"))
- && (!GetFlag(n, "feature:ignore"))) {
- addCopyConstructor(n);
- }
- }
- /* default destructor */
- if (!GetFlag(n, "feature:nodefaultdtor") && odefault) {
- if (!Getattr(n, "has_destructor") && (!Getattr(n, "allocate:has_destructor"))
- && (Getattr(n, "allocate:default_destructor"))
- && (!GetFlag(n, "feature:ignore"))) {
- addDestructor(n);
- }
- }
if (dir) {
DirectorClassName = directorClassName(n);
classDirector(n);
}
- /* check for abstract after resolving directors */
+ /* check for abstract after resolving directors */
Abstract = abstractClassTest(n);
classHandler(n);
} else {
@@ -2674,19 +2547,24 @@ int Language::constructorDeclaration(Node *n) {
Setattr(CurrentClass, "sym:cleanconstructor", "1");
}
- if ((cplus_mode != PUBLIC)) {
+ if (!is_public(n)) {
/* check only for director classes */
if (!Swig_directorclass(CurrentClass) || !need_nonpublic_ctor(n))
return SWIG_NOWRAP;
}
- /* Name adjustment for %name */
+ // Name adjustment of constructor when a class has been renamed with %rename
Swig_save("constructorDeclaration", n, "sym:name", NIL);
{
String *base = Swig_scopename_last(name);
- if ((Strcmp(base, symname) == 0) && (Strcmp(symname, ClassPrefix) != 0)) {
- Setattr(n, "sym:name", ClassPrefix);
+ // Note that it is possible for the constructor to have a different name to the class name in
+ // some target languages, where it is wrapped as a factory type function instead of a constructor.
+ if (Equal(base, symname) && !Equal(symname, ClassPrefix)) {
+ // Adjust name, except when the constructor's name comes from a templated constructor,
+ // where the name passed to %template is used instead.
+ if (!Getattr(n, "template"))
+ Setattr(n, "sym:name", ClassPrefix);
}
Delete(base);
}
@@ -2752,7 +2630,6 @@ int Language::constructorDeclaration(Node *n) {
constructorHandler(n);
}
}
- Setattr(CurrentClass, "has_constructor", "1");
Swig_restore(n);
return SWIG_OK;
@@ -2869,16 +2746,29 @@ int Language::destructorDeclaration(Node *n) {
Setattr(n, "sym:name", ClassPrefix);
}
- String *expected_name = ClassName;
- String *scope = Swig_scopename_check(ClassName) ? Swig_scopename_prefix(ClassName) : 0;
- String *actual_name = scope ? NewStringf("%s::%s", scope, name) : NewString(name);
- Delete(scope);
- Replace(actual_name, "~", "", DOH_REPLACE_FIRST);
+ String *nprefix = 0;
+ String *nlast = 0;
+ String *tprefix;
+ Swig_scopename_split(ClassName, &nprefix, &nlast);
+ tprefix = SwigType_templateprefix(nlast);
+ String *expected_name = NewStringf("~%s", tprefix);
+
+ String *actual_name = Copy(name);
if (!Equal(actual_name, expected_name) && !(Getattr(n, "template"))) {
bool illegal_name = true;
if (Extend) {
// Check for typedef names used as a destructor name in %extend. This is deprecated except for anonymous
// typedef structs which have had their symbol names adjusted to the typedef name in the parser.
+ Replace(actual_name, "~", "", DOH_REPLACE_FIRST);
+ Replace(expected_name, "~", "", DOH_REPLACE_FIRST);
+ if (Len(nprefix) > 0) {
+ String *old_actual_name = actual_name;
+ String *old_expected_name = expected_name;
+ actual_name = NewStringf("%s::%s", nprefix, actual_name);
+ expected_name = NewStringf("%s::%s", nprefix, expected_name);
+ Delete(old_expected_name);
+ Delete(old_actual_name);
+ }
SwigType *name_resolved = SwigType_typedef_resolve_all(actual_name);
SwigType *expected_name_resolved = SwigType_typedef_resolve_all(expected_name);
@@ -2900,6 +2790,11 @@ int Language::destructorDeclaration(Node *n) {
if (illegal_name) {
Swig_warning(WARN_LANG_ILLEGAL_DESTRUCTOR, input_file, line_number, "Illegal destructor name %s. Ignored.\n", Swig_name_decl(n));
Swig_restore(n);
+ Delete(tprefix);
+ Delete(nlast);
+ Delete(nprefix);
+ Delete(expected_name);
+ Delete(actual_name);
return SWIG_NOWRAP;
}
}
@@ -2907,6 +2802,11 @@ int Language::destructorDeclaration(Node *n) {
Setattr(CurrentClass, "has_destructor", "1");
Swig_restore(n);
+ Delete(tprefix);
+ Delete(nlast);
+ Delete(nprefix);
+ Delete(expected_name);
+ Delete(actual_name);
return SWIG_OK;
}
@@ -2939,14 +2839,7 @@ int Language::destructorHandler(Node *n) {
* ---------------------------------------------------------------------- */
int Language::accessDeclaration(Node *n) {
- String *kind = Getattr(n, "kind");
- if (Cmp(kind, "public") == 0) {
- cplus_mode = PUBLIC;
- } else if (Cmp(kind, "private") == 0) {
- cplus_mode = PRIVATE;
- } else if (Cmp(kind, "protected") == 0) {
- cplus_mode = PROTECTED;
- }
+ cplus_mode = accessModeFromString(Getattr(n, "kind"));
return SWIG_OK;
}
@@ -3028,7 +2921,7 @@ int Language::variableWrapper(Node *n) {
}
/* If no way to set variables. We simply create functions */
- int assignable = is_assignable(n);
+ int assignable = !is_immutable(n);
int flags = use_naturalvar_mode(n);
if (!GetFlag(n, "wrappedasconstant"))
flags = flags | Extend;
@@ -3049,8 +2942,6 @@ int Language::variableWrapper(Node *n) {
}
} else {
String *pname0 = Swig_cparm_name(0, 0);
- Replace(tm, "$source", pname0, DOH_REPLACE_ANY);
- Replace(tm, "$target", name, DOH_REPLACE_ANY);
Replace(tm, "$input", pname0, DOH_REPLACE_ANY);
Setattr(n, "wrap:action", tm);
Delete(tm);
@@ -3127,8 +3018,8 @@ void Language::main(int argc, char *argv[]) {
* ----------------------------------------------------------------------------- */
int Language::addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope) {
- //Printf( stdout, "addSymbol: %s %s\n", s, scope );
- Hash *symbols = Getattr(symtabs, scope ? scope : "");
+ //Printf( stdout, "addSymbol: %s %s %s:%d\n", s, scope, Getfile(n), Getline(n) );
+ Hash *symbols = symbolScopeLookup(scope);
if (!symbols) {
symbols = symbolAddScope(scope);
} else {
@@ -3175,15 +3066,15 @@ int Language::addInterfaceSymbol(const String *interface_name, Node *n, const_St
* Language::symbolAddScope()
*
* Creates a scope (symbols Hash) for given name. This method is auxiliary,
- * you don't have to call it - addSymbols will lazily create scopes automatically.
+ * you don't have to call it - addSymbol will lazily create scopes automatically.
* If scope with given name already exists, then do nothing.
* Returns newly created (or already existing) scope.
* ----------------------------------------------------------------------------- */
-Hash* Language::symbolAddScope(const_String_or_char_ptr scope) {
+Hash *Language::symbolAddScope(const_String_or_char_ptr scope/*, Node *n*/) {
Hash *symbols = symbolScopeLookup(scope);
- if(!symbols) {
+ if (!symbols) {
// The order in which the following code is executed is important. In the Language
- // constructor addScope("") is called to create a top level scope.
+ // constructor symbolAddScope("") is called to create a top level scope.
// Thus we must first add a symbols hash to symtab and only then add pseudo
// symbols to the top-level scope.
@@ -3195,8 +3086,22 @@ Hash* Language::symbolAddScope(const_String_or_char_ptr scope) {
// Alternatively the target language must add it in before attempting to add symbols into the scope.
const_String_or_char_ptr top_scope = "";
Hash *topscope_symbols = Getattr(symtabs, top_scope);
- Hash *pseudo_symbol = NewHash();
- Setattr(pseudo_symbol, "sym:scope", "1");
+
+ // TODO:
+ // Stop using pseudo scopes, the symbol Node containing the new scope should be passed into this function.
+ // This will require explicit calls to symbolScopeLookup() in each language and removing the call from addSymbol().
+ // addSymbol() should then instead assert that the scope exists.
+ // All this just to fix up the file/line numbering of the scopes for error reporting.
+ //Node *symbol = n;
+ Node *symbol = Getattr(topscope_symbols, scope);
+
+ Hash *pseudo_symbol = 0;
+ if (symbol) {
+ pseudo_symbol = symbol;
+ } else {
+ pseudo_symbol = NewHash();
+ Setattr(pseudo_symbol, "sym:scope", "1");
+ }
Setattr(topscope_symbols, scope, pseudo_symbol);
}
return symbols;
@@ -3208,7 +3113,7 @@ Hash* Language::symbolAddScope(const_String_or_char_ptr scope) {
* Lookup and returns a symtable (hash) representing given scope. Hash contains
* all symbols in this scope.
* ----------------------------------------------------------------------------- */
-Hash* Language::symbolScopeLookup( const_String_or_char_ptr scope ) {
+Hash *Language::symbolScopeLookup(const_String_or_char_ptr scope) {
Hash *symbols = Getattr(symtabs, scope ? scope : "");
return symbols;
}
@@ -3227,7 +3132,7 @@ Hash* Language::symbolScopeLookup( const_String_or_char_ptr scope ) {
* There is no difference from symbolLookup() method except for signature
* and return type.
* ----------------------------------------------------------------------------- */
-Hash* Language::symbolScopePseudoSymbolLookup( const_String_or_char_ptr scope )
+Hash *Language::symbolScopePseudoSymbolLookup(const_String_or_char_ptr scope)
{
/* Getting top scope */
const_String_or_char_ptr top_scope = "";
@@ -3254,6 +3159,7 @@ void Language::dumpSymbols() {
while (it.key) {
String *symname = it.key;
Printf(stdout, " %s\n", symname);
+ //Printf(stdout, " %s (%s:%d)\n", symname, Getfile(it.item), Getline(it.item));
it = Next(it);
}
}
@@ -3477,19 +3383,19 @@ int Language::cplus_runtime_mode() {
}
/* -----------------------------------------------------------------------------
- * Language::allow_directors()
+ * Language::directorLanguage()
* ----------------------------------------------------------------------------- */
-void Language::allow_directors(int val) {
- directors = val;
+void Language::directorLanguage(int val) {
+ director_language = val;
}
/* -----------------------------------------------------------------------------
- * Language::directorsEnabled()
+ * Language::allow_directors()
* ----------------------------------------------------------------------------- */
-int Language::directorsEnabled() const {
- return director_language && CPlusPlus && (directors || director_mode);
+void Language::allow_directors(int val) {
+ directors_allowed = val;
}
/* -----------------------------------------------------------------------------
@@ -3513,7 +3419,7 @@ void Language::allow_allprotected(int val) {
* ----------------------------------------------------------------------------- */
int Language::dirprot_mode() const {
- return directorsEnabled() ? director_protected_mode : 0;
+ return Swig_directors_enabled() ? director_protected_mode : 0;
}
/* -----------------------------------------------------------------------------
@@ -3549,7 +3455,7 @@ int Language::need_nonpublic_ctor(Node *n) {
members, and use %ignore for the method you don't want to add in
the director class.
*/
- if (directorsEnabled()) {
+ if (Swig_directors_enabled()) {
if (is_protected(n)) {
if (dirprot_mode()) {
/* when using dirprot mode, the protected constructors are
@@ -3582,7 +3488,7 @@ int Language::need_nonpublic_ctor(Node *n) {
* Language::need_nonpublic_member()
* ----------------------------------------------------------------------------- */
int Language::need_nonpublic_member(Node *n) {
- if (directorsEnabled() && DirectorClassName) {
+ if (Swig_directors_enabled() && DirectorClassName) {
if (is_protected(n)) {
if (dirprot_mode()) {
/* when using dirprot mode, the protected members are always needed. */
@@ -3624,15 +3530,20 @@ String *Language::makeParameterName(Node *n, Parm *p, int arg_num, bool setter)
// Check if parameter name is a duplicate.
int count = 0;
+ Parm *first_duplicate_parm = 0;
ParmList *plist = Getattr(n, "parms");
while (plist) {
- if ((Cmp(pn, Getattr(plist, "name")) == 0))
+ if ((Cmp(pn, Getattr(plist, "name")) == 0)) {
+ if (!first_duplicate_parm)
+ first_duplicate_parm = plist;
count++;
+ }
plist = nextSibling(plist);
}
// If the parameter has no name at all or has a non-unique name, replace it with "argN".
- if (!pn || count > 1) {
+ // On the assumption that p is pointer/element in plist, only replace the 2nd and subsequent duplicates
+ if (!pn || (count > 1 && p != first_duplicate_parm)) {
arg = NewStringf("arg%d", arg_num);
} else {
// Otherwise, try to use the original C name, but modify it if necessary to avoid conflicting with the language keywords.
@@ -3742,10 +3653,10 @@ String *Language::getClassType() const {
}
/* -----------------------------------------------------------------------------
- * Language::abstractClassTest()
+ * Dispatcher::abstractClassTest()
* ----------------------------------------------------------------------------- */
//#define SWIG_DEBUG
-int Language::abstractClassTest(Node *n) {
+int Dispatcher::abstractClassTest(Node *n) {
/* check for non public operator new */
if (GetFlag(n, "feature:notabstract"))
return 0;
@@ -3774,7 +3685,7 @@ int Language::abstractClassTest(Node *n) {
#endif
if (!labs)
return 0; /*strange, but need to be fixed */
- if (abstracts && !directorsEnabled())
+ if (abstracts && !Swig_directors_enabled())
return 1;
if (!GetFlag(n, "feature:director"))
return 1;
@@ -3787,7 +3698,7 @@ int Language::abstractClassTest(Node *n) {
#endif
for (int i = 0; i < labs; i++) {
Node *ni = Getitem(abstracts, i);
- Node *method_id = vtable_method_id(ni);
+ String *method_id = vtable_method_id(ni);
if (!method_id)
continue;
bool exists_item = false;
@@ -3837,29 +3748,8 @@ void Language::setOverloadResolutionTemplates(String *argc, String *argv) {
argv_template_string = Copy(argv);
}
-int Language::is_assignable(Node *n) {
- if (GetFlag(n, "feature:immutable"))
- return 0;
- SwigType *type = Getattr(n, "type");
- Node *cn = 0;
- SwigType *ftd = SwigType_typedef_resolve_all(type);
- SwigType *td = SwigType_strip_qualifiers(ftd);
- if (SwigType_type(td) == T_USER) {
- cn = Swig_symbol_clookup(td, 0);
- if (cn) {
- if ((Strcmp(nodeType(cn), "class") == 0)) {
- if (Getattr(cn, "allocate:noassign")) {
- SetFlag(n, "feature:immutable");
- Delete(ftd);
- Delete(td);
- return 0;
- }
- }
- }
- }
- Delete(ftd);
- Delete(td);
- return 1;
+int Language::is_immutable(Node *n) {
+ return GetFlag(n, "feature:immutable");
}
String *Language::runtimeCode() {