diff --git a/CHANGES.current b/CHANGES.current index f0c044c76..2f6185581 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-02-26: wsfulton + #655 #1840 Add new warning WARN_LANG_USING_NAME_DIFFERENT to warn when a + method introduced by a using declaration in a derived class cannot + be used due to a conflict in names. + 2022-02-24: olly #1465 An invalid preprocessor expression is reported as a pair of warnings with the second giving a more detailed message from the diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index d480f61f3..9820a1800 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -1125,7 +1125,7 @@ customization features.
SWIG wraps class members that are public following the C++ conventions, i.e., by explicit public declaration or by the use of - the using directive. In general, anything specified in a + using declarations. In general, anything specified in a private or protected section will be ignored, although the internal code generator sometimes looks at the contents of the private and protected sections so that it can properly generate code for default @@ -2083,7 +2083,6 @@ or for statically typed languages like Java:
example.i:4: Warning 516: Overloaded method foo(long) ignored, example.i:3: Warning 516: using foo(int) instead. -at example.i:3 used.@@ -2330,8 +2329,8 @@ also apply to %ignore. For example:
%ignore foo(double); // Ignore all foo(double) -%ignore Spam::foo; // Ignore foo in class Spam -%ignore Spam::foo(double); // Ignore foo(double) in class Spam +%ignore Spam::foo; // Ignore foo in class Spam (and foo in any derived classes) +%ignore Spam::foo(double); // Ignore foo(double) in class Spam (and foo in any derived classes) %ignore *::foo(double); // Ignore foo(double) in all classes
+Renaming a class member, using an unparameterized but qualified name, such as Spam::foo, also applies to members in all derived classes +that have members with the same name. +This can be used to simply rename a method, across an entire class hierarchy for all overloaded and non-overloaded methods. +This also applies to methods introduced via using declarations, see +Using declarations and inheritance. +For example: + +
+%rename(foo_new) Spam::foo;
+
+class Spam {
+public:
+ virtual void foo(int); // Renamed to foo_new
+};
+
+class Bar : public Spam {
+public:
+ virtual void foo(int); // Renamed to foo_new
+ void foo(bool, short, int); // Renamed to foo_new
+};
+
+class Grok : public Bar {
+public:
+ virtual void foo(int); // Renamed to foo_new
+ void foo(bool, int); // Renamed to foo_new
+ void foo(const char *); // Renamed to foo_new
+ void foo(Bar *); // Renamed to foo_new
+};
+
+class Spok : public Grok {
+public:
+ void foo(); // Renamed to foo_new
+};
+
+class Knock : public Spok {
+public:
+ using Grok::foo; // Introduced methods renamed to foo_new
+};
+
+The order in which %rename directives are defined does not matter as long as they appear before the declarations to be renamed. Thus, there is no difference @@ -4073,23 +4119,23 @@ math::Complex c;
At this level, namespaces are relatively easy to manage. However, things start to get very ugly when you throw in the other ways a namespace can be used. For example, -selective symbols can be exported from a namespace with using. +selective symbols can be exported from a namespace with a using declaration:
-using math::Complex; +using math::Complex; // Using declaration double magnitude(Complex *c); // Namespace prefix stripped
-Similarly, the contents of an entire namespace can be made available like this: +Similarly, the contents of an entire namespace can be made available via a using directive:
-using namespace math; +using namespace math; // Using directive double x = sin(1.0); double magnitude(Complex *c);@@ -4246,9 +4292,11 @@ Similarly, %ignore can be used to ignore declarations.
-using declarations do not have any effect on the generated wrapper -code. They are ignored by SWIG language modules and they do not result in any -code. However, these declarations are used by the internal type +C++ using directives and using declarations +do not add any code to the generated wrapper code. +However, there is an exception in one context, see Using declarations and inheritance +for introducing members of a base class into a derived class definition. +C++ using declarations and directives are used by the internal type system to track type-names. Therefore, if you have code like this:
@@ -5172,7 +5220,7 @@ exit # 'a' is released, SWIG unref 'a' called in the destructor wra-using declarations are sometimes used to adjust access to members of +C++ using declarations are sometimes used to introduce members of base classes. For example:
@@ -5180,7 +5228,7 @@ base classes. For example:
class Foo {
public:
- int blah(int x);
+ int blah(int x);
};
class Bar {
@@ -5228,7 +5276,8 @@ you wrap this code in Python, the module works just like you would expect:
-using declarations can also be used to change access when applicable. For example: +C++ using declarations can also be used to change access when applicable. +For example, protected methods in a base class can be made public in a derived class:
Because a using declaration does not provide fine-grained -control over the declarations that get imported, it may be difficult +control over the declarations that get imported, because a single using declaration +may introduce multiple methods, it may be difficult to manage such declarations in applications that make heavy use of SWIG customization features. If you can't get using to work -correctly, you can always change the interface to the following: +correctly, you can always modify the C++ code to handle SWIG differently such as:
-
class FooBar : public Foo, public Bar {
public:
#ifndef SWIG
@@ -5285,13 +5334,36 @@ public:
+If the C++ code being wrapped cannot be changed, make judicious usage of %extend and %rename +to ignore and unignore declarations. The example below is effectively the same as above: +
+ +
+%extend FooBar {
+ int blah(int x) { return $self->Foo::blah(x); }
+ double blah(double x) { return $self->Bar::blah(x); }
+}
+%ignore FooBar::blah; // ignore all FooBar::blah below
+%rename("") FooBar::blah(const char *x); // parameterized unignore
+
+class FooBar : public Foo, public Bar {
+public:
+ using Foo::blah;
+ using Bar::blah;
+ char *blah(const char *x);
+};
+
+Notes:
If a derived class redefines a method defined in a base class, then a using declaration -won't cause a conflict. For example:
+If a derived class introduces a method defined in a base class via a using declaration, +there won't be a conflict due to incorrect additional methods. For example:
@@ -5303,14 +5375,14 @@ public:
class Bar : public Foo {
public:
- using Foo::blah; // Only imports blah(double);
+ using Foo::blah; // Only introduces blah(double);
int blah(int);
};
Resolving ambiguity in overloading may prevent declarations from being -imported by using. For example: +
Renaming methods may prevent methods from being +introduced into the derived class via using declarations. For example:
+The problem here is Foo::blah is renamed to blah_long in the target language, but +the using declaration in Bar is not renamed in the target language and thinks all introduced methods should simply +be called blah. +It is not clear what target language names should be used in Bar and so the conflicting names are effectively ignored +as they are not introduced into the derived class for the target language wrappers. +In such situations SWIG will emit a warning: +
+ ++example.i:15: Warning 526: Using declaration Foo::blah, with name 'blah', is not actually using +example.i:10: Warning 526: the method from Foo::blah(long), with name 'blah_long', as the names are different. ++
+Compatibility Note: +This warning message was introduced in SWIG-4.1.0. +Prior versions also effectively ignored the using declaration for the same reasons, but were silent about it. +
+ ++If methods really need different names, please use of combinations of %rename, %ignore and %extend to achieve the desired outcome. +
+