conversion operator %rename improvements - the exact operator name must be specified now, rather than a fully qualified operator name
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9837 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
ec8d13b467
commit
3e5f30c94f
5 changed files with 199 additions and 44 deletions
|
|
@ -1,6 +1,34 @@
|
|||
Version 1.3.32 (in progress)
|
||||
============================
|
||||
|
||||
05/25/2007: wsfulton
|
||||
Fixed %rename inconsistency in conversion operators as reported by Zhong Ren. The matching
|
||||
is now done on the operator name in the same way as it is done for parameters. For example:
|
||||
|
||||
%rename(opABC) Space::ABC::operator ABC() const;
|
||||
%rename(methodABC) Space::ABC::method(ABC a) const;
|
||||
namespace Space {
|
||||
class ABC {
|
||||
public:
|
||||
void method(ABC a) const {}
|
||||
operator ABC() const { ABC a; return a; }
|
||||
};
|
||||
}
|
||||
|
||||
Note that qualifying the conversion operator previously may or may not have matched.
|
||||
Now it definitely won't, so this will not match:
|
||||
|
||||
%rename(opABC) Space::ABC::operator Space::ABC() const;
|
||||
|
||||
in the same that this does not match:
|
||||
|
||||
%rename(methodABC) Space::ABC::method(Space::ABC a) const;
|
||||
|
||||
The documentation has been improved with respect to %rename, namespaces and templates.
|
||||
Conversion operators documentation too.
|
||||
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
05/16/2007: mutandiz
|
||||
[allegrocl]
|
||||
Fix bad generation of local var ltype's in functionWrapper().
|
||||
|
|
|
|||
|
|
@ -2440,6 +2440,27 @@ above:
|
|||
|
||||
</li>
|
||||
|
||||
<li><p>
|
||||
Currently no resolution is performed in order to match function parameters. This means function parameter types must match exactly.
|
||||
For example, namespace qualifiers and typedefs will not work. The following usage of typedefs demonstrates this:
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
typedef int Integer;
|
||||
|
||||
%rename(foo_i) foo(int);
|
||||
|
||||
class Spam {
|
||||
public:
|
||||
void foo(Integer); // Stays 'foo' (not renamed)
|
||||
};
|
||||
class Ham {
|
||||
public:
|
||||
void foo(int); // Renamed to foo_i
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<li><p>
|
||||
The name matching rules also use default arguments for finer control when wrapping methods that have default arguments.
|
||||
Recall that methods with default arguments are wrapped as if the equivalent overloaded methods had been parsed
|
||||
|
|
@ -3144,7 +3165,7 @@ TEMPLATE_WRAP(PairStringInt, std::pair<string, int>)
|
|||
</div>
|
||||
|
||||
<p>
|
||||
Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in last example would not be possible.
|
||||
Note the use of a vararg macro for the type T. If this wasn't used, the comma in the templated type in the last example would not be possible.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -3482,10 +3503,11 @@ It is also possible to separate these declarations from the template class. For
|
|||
|
||||
...
|
||||
template<class T> class List {
|
||||
...
|
||||
public:
|
||||
List() { };
|
||||
...
|
||||
...
|
||||
public:
|
||||
List() { };
|
||||
T get(int index);
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -3957,8 +3979,7 @@ conflicts in the input, there will be no conflicts in the generated code.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
<b>Note:</b> Namespaces have a subtle effect on the wrapping of conversion operators. For
|
||||
instance, suppose you had an interface like this:
|
||||
<b>Note:</b> In the same way that no resolution is performed on parameters, a conversion operator name must match exactly to how it is defined. Do not change the qualification of the operator. For example, suppose you had an interface like this:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -3976,7 +3997,7 @@ namespace foo {
|
|||
</div>
|
||||
|
||||
<p>
|
||||
To wrap the conversion function, you might be inclined to write this:
|
||||
The following is how the feature is expected to be written for a successful match:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -3986,9 +4007,7 @@ To wrap the conversion function, you might be inclined to write this:
|
|||
</div>
|
||||
|
||||
<p>
|
||||
The only problem is that it doesn't work. The reason it doesn't work is that
|
||||
<tt>bar</tt> is not defined in the global scope. Therefore, to make it work, do this
|
||||
instead:
|
||||
The following does not work as no namespace resolution is performed in the matching of conversion operator names:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
|
@ -3997,14 +4016,113 @@ instead:
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Note, however, that if the operator is defined using a qualifier in its name, then the feature must use it too...
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%rename(tofoo) foo::spam::operator bar(); // will not match
|
||||
%rename(tofoo) foo::spam::operator foo::bar(); // will match
|
||||
namespace foo {
|
||||
class bar;
|
||||
class spam {
|
||||
public:
|
||||
...
|
||||
operator foo::bar();
|
||||
...
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<b>Compatibility Note:</b> Versions of SWIG prior to 1.3.32 were inconsistent in this approach. A fully qualified name was usually required, but would not work in some situations.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
<b>Note:</b> The flattening of namespaces is only intended to serve as
|
||||
a basic namespace implementation. Since namespaces are a new addition
|
||||
to SWIG, none of the target language modules are currently programmed
|
||||
a basic namespace implementation.
|
||||
None of the target language modules are currently programmed
|
||||
with any namespace awareness. In the future, language modules may or may not provide
|
||||
more advanced namespace support.
|
||||
</p>
|
||||
|
||||
<H2><a name="SWIGPlus_renaming_templated_types_namespaces"></a>Renaming templated types in namespaces</H2>
|
||||
<p>
|
||||
As has been mentioned, when %rename includes parameters, the parameter types must match exactly (no typedef or namespace resolution is performed).
|
||||
SWIG treats templated types slightly differently and has an additional matching rule so unlike non-templated types, an exact match is not always required.
|
||||
If the fully qualified templated type is specified, it will have a higher precedence over the generic template type.
|
||||
In the example below, the generic template type is used to rename to <tt>bbb</tt> and the fully qualified type is used to rename to <tt>ccc</tt>.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%rename(bbb) Space::ABC::aaa(T t); // will match but with lower precedence than ccc
|
||||
%rename(ccc) Space::ABC<Space::XYZ>::aaa(Space::XYZ t); // will match but with higher precedence than bbb
|
||||
|
||||
namespace Space {
|
||||
class XYZ {};
|
||||
template<typename T> struct ABC {
|
||||
void aaa(T t) {}
|
||||
};
|
||||
}
|
||||
%template(ABCXYZ) Space::ABC<Space::XYZ>;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
It should now be apparent that there are many ways to achieve a renaming with %rename. This is demonstrated
|
||||
by the following two examples, which are effectively the same as the above example.
|
||||
Below shows how %rename can be placed inside a namespace.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
namespace Space {
|
||||
%rename(bbb) ABC::aaa(T t); // will match but with lower precedence than ccc
|
||||
%rename(ccc) ABC<Space::XYZ>::aaa(Space::XYZ t); // will match but with higher precedence than bbb
|
||||
%rename(ddd) ABC<Space::XYZ>::aaa(XYZ t); // will not match
|
||||
}
|
||||
|
||||
namespace Space {
|
||||
class XYZ {};
|
||||
template<typename T> struct ABC {
|
||||
void aaa(T t) {}
|
||||
};
|
||||
}
|
||||
%template(ABCXYZ) Space::ABC<Space::XYZ>;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Note that <tt>ddd</tt> does not match as there is no namespace resolution for parameter types and the fully qualified type must be specified for template type expansion.
|
||||
The following example shows how %rename can be placed within %extend.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
namespace Space {
|
||||
%extend ABC {
|
||||
%rename(bbb) aaa(T t); // will match but with lower precedence than ccc
|
||||
}
|
||||
%extend ABC<Space::XYZ> {
|
||||
%rename(ccc) aaa(Space::XYZ t); // will match but with higher precedence than bbb
|
||||
%rename(ddd) aaa(XYZ t); // will not match
|
||||
}
|
||||
}
|
||||
|
||||
namespace Space {
|
||||
class XYZ {};
|
||||
template<typename T> struct ABC {
|
||||
void aaa(T t) {}
|
||||
};
|
||||
}
|
||||
%template(ABCXYZ) Space::ABC<Space::XYZ>;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
||||
<H2><a name="SWIGPlus_exception_specifications"></a>6.20 Exception specifications</H2>
|
||||
|
||||
|
|
|
|||
|
|
@ -702,8 +702,7 @@ int yylex(void) {
|
|||
needspace = 0;
|
||||
}
|
||||
}
|
||||
yylval.str = Swig_symbol_string_qualify(s,0);
|
||||
/* Printf(stdout,"OPERATOR '%s'\n", yylval.str); */
|
||||
yylval.str = s;
|
||||
if (!rename_active) {
|
||||
String *cs;
|
||||
char *t = Char(s) + 9;
|
||||
|
|
@ -737,7 +736,8 @@ int yylex(void) {
|
|||
return COPERATOR;
|
||||
}
|
||||
}
|
||||
if (termtoken) Scanner_pushtoken(scan, termtoken, termvalue);
|
||||
if (termtoken)
|
||||
Scanner_pushtoken(scan, termtoken, termvalue);
|
||||
return (OPERATOR);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -578,6 +578,14 @@ class TypePass:private Dispatcher {
|
|||
}
|
||||
normalize_parms(Getattr(n, "parms"));
|
||||
normalize_parms(Getattr(n, "throws"));
|
||||
if (GetFlag(n, "conversion_operator")) {
|
||||
/* The call to the operator in the generated wrapper must be fully qualified in order to compile */
|
||||
SwigType *name = Getattr(n, "name");
|
||||
SwigType *qualifiedname = Swig_symbol_string_qualify(name,0);
|
||||
Clear(name);
|
||||
Append(name, qualifiedname);
|
||||
Delete(qualifiedname);
|
||||
}
|
||||
|
||||
if (checkAttribute(n, "storage", "typedef")) {
|
||||
String *name = Getattr(n, "name");
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ String *Swig_name_get(const String_or_char *vname) {
|
|||
String *f;
|
||||
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_name_get: '%s'\n", vname);
|
||||
Printf(stdout, "Swig_name_get: '%s'\n", vname);
|
||||
#endif
|
||||
|
||||
r = NewStringEmpty();
|
||||
|
|
@ -387,7 +387,7 @@ void Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *obj
|
|||
DOH *n;
|
||||
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_name_object_set: '%s', '%s'\n", name, decl);
|
||||
Printf(stdout, "Swig_name_object_set: '%s', '%s'\n", name, decl);
|
||||
#endif
|
||||
n = Getattr(namehash, name);
|
||||
if (!n) {
|
||||
|
|
@ -455,7 +455,7 @@ DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType
|
|||
}
|
||||
*/
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_name_object_get: '%s', '%s'\n", name, decl);
|
||||
Printf(stdout, "Swig_name_object_get: '%s' '%s', '%s'\n", prefix, name, decl);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -520,7 +520,7 @@ DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType
|
|||
Delete(tname);
|
||||
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_name_object_get: found %d\n", rn ? 1 : 0);
|
||||
Printf(stdout, "Swig_name_object_get: found %d\n", rn ? 1 : 0);
|
||||
#endif
|
||||
|
||||
return rn;
|
||||
|
|
@ -601,7 +601,7 @@ static
|
|||
void features_get(Hash *features, String *tname, SwigType *decl, SwigType *ncdecl, Node *node) {
|
||||
Node *n = Getattr(features, tname);
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, " features_get: %s\n", tname);
|
||||
Printf(stdout, " features_get: %s\n", tname);
|
||||
#endif
|
||||
if (n) {
|
||||
merge_features(get_object(n, 0), node);
|
||||
|
|
@ -653,7 +653,7 @@ void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *d
|
|||
}
|
||||
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_features_get: %s %s %s\n", prefix, name, decl);
|
||||
Printf(stdout, "Swig_features_get: %s %s %s\n", prefix, name, decl);
|
||||
#endif
|
||||
|
||||
/* Global features */
|
||||
|
|
@ -730,7 +730,7 @@ void Swig_feature_set(Hash *features, const String_or_char *name, SwigType *decl
|
|||
Hash *fhash;
|
||||
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_feature_set: %s %s %s %s\n", name, decl, featurename, value);
|
||||
Printf(stdout, "Swig_feature_set: %s %s %s %s\n", name, decl, featurename, value);
|
||||
#endif
|
||||
|
||||
n = Getattr(features, name);
|
||||
|
|
@ -1037,7 +1037,7 @@ static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj) {
|
|||
Setattr(mi, "attrlist", attrlist);
|
||||
#ifdef SWIG_DEBUG
|
||||
if (isrxsmatch)
|
||||
Printf(stderr, "rxsmatch to use: %s %s %s\n", ckey, Getattr(kw, "value"), attrlist);
|
||||
Printf(stdout, "rxsmatch to use: %s %s %s\n", ckey, Getattr(kw, "value"), attrlist);
|
||||
#endif
|
||||
if (isnotmatch)
|
||||
SetFlag(mi, "notmatch");
|
||||
|
|
@ -1108,9 +1108,9 @@ static DOH *Swig_get_lattr(Node *n, List *lattr) {
|
|||
res = Getattr(n, nattr);
|
||||
#ifdef SWIG_DEBUG
|
||||
if (!res) {
|
||||
Printf(stderr, "missing %s %s %s\n", nattr, Getattr(n, "name"), Getattr(n, "member"));
|
||||
Printf(stdout, "missing %s %s %s\n", nattr, Getattr(n, "name"), Getattr(n, "member"));
|
||||
} else {
|
||||
Printf(stderr, "lattr %d %s %s\n", i, nattr, DohIsString(res) ? res : Getattr(res, "name"));
|
||||
Printf(stdout, "lattr %d %s %s\n", i, nattr, DohIsString(res) ? res : Getattr(res, "name"));
|
||||
}
|
||||
#endif
|
||||
n = res;
|
||||
|
|
@ -1136,7 +1136,7 @@ int Swig_name_rxsmatch_value(String *mvalue, String *value) {
|
|||
retval = regexec(&compiled, cvalue, 0, 0, 0);
|
||||
match = (retval == REG_NOMATCH) ? 0 : 1;
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "rxsmatch_value: %s %s %d\n", cvalue, cmvalue, match);
|
||||
Printf(stdout, "rxsmatch_value: %s %s %d\n", cvalue, cmvalue, match);
|
||||
#endif
|
||||
regfree(&compiled);
|
||||
return match;
|
||||
|
|
@ -1158,7 +1158,7 @@ int Swig_name_match_value(String *mvalue, String *value) {
|
|||
while (sep && !match) {
|
||||
match = strncmp(cvalue, cmvalue, sep - cmvalue) == 0;
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "match_value: %s %s %d\n", cvalue, cmvalue, match);
|
||||
Printf(stdout, "match_value: %s %s %d\n", cvalue, cmvalue, match);
|
||||
#endif
|
||||
cmvalue = sep + 1;
|
||||
sep = strchr(cmvalue, '|');
|
||||
|
|
@ -1166,7 +1166,7 @@ int Swig_name_match_value(String *mvalue, String *value) {
|
|||
if (!match) {
|
||||
match = strcmp(cvalue, cmvalue) == 0;
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "match_value: %s %s %d\n", cvalue, cmvalue, match);
|
||||
Printf(stdout, "match_value: %s %s %d\n", cvalue, cmvalue, match);
|
||||
#endif
|
||||
}
|
||||
return match;
|
||||
|
|
@ -1180,7 +1180,7 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
|
|||
int match = 1;
|
||||
List *matchlist = Getattr(rn, "matchlist");
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_name_match_nameobj: %s\n", Getattr(n, "name"));
|
||||
Printf(stdout, "Swig_name_match_nameobj: %s\n", Getattr(n, "name"));
|
||||
#endif
|
||||
if (matchlist) {
|
||||
int ilen = Len(matchlist);
|
||||
|
|
@ -1192,9 +1192,9 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
|
|||
int notmatch = GetFlag(mi, "notmatch");
|
||||
int rxsmatch = GetFlag(mi, "rxsmatch");
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "mi %d %s re %d not %d \n", i, nval, notmatch, rxsmatch);
|
||||
Printf(stdout, "mi %d %s re %d not %d \n", i, nval, notmatch, rxsmatch);
|
||||
if (rxsmatch) {
|
||||
Printf(stderr, "rxsmatch %s\n", lattr);
|
||||
Printf(stdout, "rxsmatch %s\n", lattr);
|
||||
}
|
||||
#endif
|
||||
match = 0;
|
||||
|
|
@ -1203,7 +1203,7 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
|
|||
match = rxsmatch ? Swig_name_rxsmatch_value(kwval, nval)
|
||||
: Swig_name_match_value(kwval, nval);
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "val %s %s %d %d \n", nval, kwval, match, ilen);
|
||||
Printf(stdout, "val %s %s %d %d \n", nval, kwval, match, ilen);
|
||||
#endif
|
||||
}
|
||||
if (notmatch)
|
||||
|
|
@ -1211,7 +1211,7 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
|
|||
}
|
||||
}
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_name_match_nameobj: %d\n", match);
|
||||
Printf(stdout, "Swig_name_match_nameobj: %d\n", match);
|
||||
#endif
|
||||
return match;
|
||||
}
|
||||
|
|
@ -1389,12 +1389,6 @@ void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *ne
|
|||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* String *Swig_name_make()
|
||||
*
|
||||
* Make a name after applying all the rename/namewarn objects
|
||||
*
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
/* Create a name applying rename/namewarn if needed */
|
||||
static String *apply_rename(String *newname, int fullname, String *prefix, String *name) {
|
||||
|
|
@ -1427,6 +1421,13 @@ static String *apply_rename(String *newname, int fullname, String *prefix, Strin
|
|||
return result;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* String *Swig_name_make()
|
||||
*
|
||||
* Make a name after applying all the rename/namewarn objects
|
||||
*
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType *decl, String *oldname) {
|
||||
String *nname = 0;
|
||||
String *result = 0;
|
||||
|
|
@ -1437,7 +1438,7 @@ String *Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType
|
|||
|
||||
/* very specific hack for template constructors/destructors */
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "SWIG_name_make: looking for %s %s %s %s\n", prefix, name, decl, oldname);
|
||||
Printf(stdout, "Swig_name_make: looking for %s %s %s %s\n", prefix, name, decl, oldname);
|
||||
#endif
|
||||
|
||||
if (name && n && SwigType_istemplate(name)) {
|
||||
|
|
@ -1461,7 +1462,7 @@ String *Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType
|
|||
rdecl = Copy(decl);
|
||||
Replaceall(rdecl, name, rname);
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "SWIG_name_make: use new name %s %s : %s %s\n", name, decl, rname, rdecl);
|
||||
Printf(stdout, "SWIG_name_make: use new name %s %s : %s %s\n", name, decl, rname, rdecl);
|
||||
#endif
|
||||
decl = rdecl;
|
||||
Delete(name);
|
||||
|
|
@ -1545,7 +1546,7 @@ String *Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType
|
|||
Delete(name);
|
||||
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stderr, "Swig_name_make: result '%s' '%s'\n", cname, result);
|
||||
Printf(stdout, "Swig_name_make: result '%s' '%s'\n", cname, result);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
|
@ -1559,7 +1560,7 @@ String *Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType
|
|||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void Swig_name_inherit(String *base, String *derived) {
|
||||
/* Printf(stderr,"base = '%s', derived = '%s'\n", base, derived); */
|
||||
/* Printf(stdout,"base = '%s', derived = '%s'\n", base, derived); */
|
||||
Swig_name_object_inherit(Swig_name_rename_hash(), base, derived);
|
||||
Swig_name_object_inherit(Swig_name_namewarn_hash(), base, derived);
|
||||
Swig_name_object_inherit(Swig_cparse_features(), base, derived);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue