diff --git a/CHANGES.current b/CHANGES.current index c88ffcb98..7ec9a304b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -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(). diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 25a05ba71..16ef7fdc7 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -2440,6 +2440,27 @@ above: +
  • +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: + +

    +
    +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
    +};
    +
    +
    +
  • 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>)

    -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.

    @@ -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); + ... }; @@ -3957,8 +3979,7 @@ conflicts in the input, there will be no conflicts in the generated code.

    -Note: Namespaces have a subtle effect on the wrapping of conversion operators. For -instance, suppose you had an interface like this: +Note: 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:

    @@ -3976,7 +3997,7 @@ namespace foo {

    -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:

    @@ -3986,9 +4007,7 @@ To wrap the conversion function, you might be inclined to write this:

    -The only problem is that it doesn't work. The reason it doesn't work is that -bar 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:

    @@ -3997,14 +4016,113 @@ instead:
    +

    +Note, however, that if the operator is defined using a qualifier in its name, then the feature must use it too... +

    + +
    +
    +%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();
    +        ...
    +   };
    +}
    +
    +
    + +

    +Compatibility Note: 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. +

    + +

    Note: 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.

    +

    Renaming templated types in namespaces

    +

    +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 bbb and the fully qualified type is used to rename to ccc. +

    + +
    +
    +%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>;
    +
    +
    + +

    +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. +

    + +
    +
    +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>;
    +
    +
    + +

    +Note that ddd 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. +

    + +
    +
    +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>;
    +
    +
    +

    6.20 Exception specifications

    diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c index 14c25e4d9..9433eb9f7 100644 --- a/Source/CParse/cscanner.c +++ b/Source/CParse/cscanner.c @@ -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); } } diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx index 701e933ff..40da47b95 100644 --- a/Source/Modules/typepass.cxx +++ b/Source/Modules/typepass.cxx @@ -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"); diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c index de21dca69..54b4e6a28 100644 --- a/Source/Swig/naming.c +++ b/Source/Swig/naming.c @@ -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);