Commit graph

22,805 commits

Author SHA1 Message Date
Vadim Zeitlin
a335fff2ec Avoid errors due to generating identical overloads
Add typecheck typemaps for primitive types and string and call
Swig_overload_check() to ensure that we don't generate two wrappers
functions taking the same "const char*" type if we have overloads taking
it and "std::string" (or a reference) in the original code.
2021-12-05 20:49:20 +01:00
Vadim Zeitlin
4a3ae6f8d3 Don't generate C++ wrappers for overridden virtual functions
This is harmless, but also useless, as the implementation is the same as
the existing one in the base class anyhow.
2021-12-05 20:24:38 +01:00
Vadim Zeitlin
aacc930023 Streamline and improve std::string typemaps
Avoid unnecessary heap allocations, just use temporary variables.

Actually update the string parameters passed by pointer/non-const
reference. This requires the pointers passed to actually be non-const,
so update the C-specific unit test runme to use a char buffer instead of
a literal string.

Also simplify the code copying the string contents to just use strdup()
(if there are ever any platforms where this POSIX functions is not
available, we could just define it ourselves once instead of using
strlen() + malloc() + memcpy() manually twice).
2021-12-05 03:31:35 +01:00
Vadim Zeitlin
628e2cf6d2 Make std::{set,map} has() and has_key() methods const
They don't modify the object, so should be callable on const objects.
2021-12-04 17:47:27 +01:00
Vadim Zeitlin
c4187f495f Fix definition of move assignment operator for wrapper classes
Classes not deriving from another class in the hierarchy must take care
of freeing their current pointer before reassigning it.

This should have been part of 3f3438093 (Define move ctor and assignment
operator for C++ wrappers, 2021-11-24).
2021-12-03 03:53:36 +01:00
Vadim Zeitlin
bfc6623bbd Make SWIG_CException dtor public to fix memory leak
The actual dtor was never called when the wrapper object was destroyed
before, due to dtor being private.
2021-12-03 03:38:33 +01:00
Vadim Zeitlin
19e0ecbb9d Don't leak the pointer returned by SWIG_CException::get_pending()
This pointer is always new (if non-null) and so must be deleted.
2021-12-03 03:38:04 +01:00
Vadim Zeitlin
d33e76e045 Fix bug with deleting even non-owned pointers in C++ wrappers
Only take ownership of the objects returned from functions that are
explicitly annotated with %newobject or from functions returning objects
by value -- as in this case nothing else can own the returned object
anyhow.

This required changing the code slightly to let do_resolve_type() access
the function node pointer, as the information we need is only available
in it and not in the dummy node passed to us when we're called from
inside Swig_typemap_lookup() due to $typemap() expansion.
2021-12-03 03:00:17 +01:00
Vadim Zeitlin
efdfad6565 Avoid redundant casts for function result in generated code
No real changes, just avoid somewhat ridiculously looking consecutive
casts to the same type in the generated code.
2021-12-02 00:31:33 +01:00
Vadim Zeitlin
e4bb84f3bd Represent scoped enums as scoped enums in C++ wrappers
This is better than turning them into unscoped enums with a prefix for
the elements.
2021-11-30 02:30:46 +01:00
Vadim Zeitlin
a031ec3474 Enable two previously failing tests that pass now
This is just the result of rerunning "make check-failing".
2021-11-30 02:29:31 +01:00
Vadim Zeitlin
579c343d5f Represent enums as enums, not int, if possible
Use enum types instead of int for the enum-valued parameters and
function return values, this is more type-safe and clear for the users
of the library.

Change cpp_enum unit test to use C++ to check that C++ enum wrappers
can at least be compiled, but still use C API in it.

Note that enum whose underlying type is bigger than int still don't
work, but this is no different from what it was before, so just document
this limitation but don't do anything else about it for now.

This commit is best viewed ignoring whitespace-only changes.
2021-11-30 02:22:25 +01:00
Vadim Zeitlin
815c7c0361 Don't call getEnumName() with NULL node
No real changes, just a tiny refactoring in preparation for the upcoming
changes.

This commit is best viewed ignoring whitespace-only changes.
2021-11-30 01:57:59 +01:00
Vadim Zeitlin
06c651431c Fix enum names for renamed typedefs
Also use sym:name even for typedefs for enums themselves, as they can
%renamed as well.

Note that this means that "tdname" itself should probably be never used
at all at this level, but it's still used for structs in C mode, which
is almost certainly wrong.
2021-11-30 01:43:22 +01:00
Vadim Zeitlin
1c06a43e35 Do use sym:name for the enum names themselves
Ever since fb4d70027 (Represent enums as themselves in generated code,
2016-04-14) the code used "name" attribute for the enums themselves
instead of "sym:name". The reason for this was documented in the comment
added in f4ee8e536 (Fix names of enums and their elements, 2021-11-04),
but this explanation was only half-correct: although we indeed shouldn't
use sym:name for typedefs, we should use it for the enums themselves, as
otherwise renaming them didn't work and enums were generated in the
wrappers with the wrong names.

Fix this by using sym:name for non typedef'd enums.
2021-11-30 00:17:27 +01:00
Vadim Zeitlin
6fb95e7e97 Fix wording of another error message
Don't use "reference return type" for the typemap used for returning
objects by value.
2021-11-29 15:45:38 +01:00
Vadim Zeitlin
4a3f4ba896 Improve error given for unsupported typemap in C++ wrappers
This error message should never happen, normally, but still make it more
informative if it does, as it could be just completely useless if there
was no sym:name attribute on the node (as is often the case for the
function parameters, for example).
2021-11-29 15:33:53 +01:00
Vadim Zeitlin
9a974040fa Fix naming scoped enums elements in C++ wrappers
For now still use prefix for them, as otherwise enum element names may
conflict with the other names defined in the same scope.

The upcoming commits will handle them as scoped enums in the wrappers
too.
2021-11-27 18:51:13 +01:00
Vadim Zeitlin
059f615a61 Generate C++ wrapper enums for nested enums too
This doesn't seem to be more difficult to do, just ensure that the
nested enums use the proper indentation and output them in the section
containing the class declaration, rather than the global ones.
2021-11-27 18:51:13 +01:00
Vadim Zeitlin
8643dcf426 Generate C++ enum wrappers
They are almost identical to C enums, but are more convenient to use
from C++ code, as the (possibly long) prefix doesn't need to be fully
specified if namespace using directive is used.

For now restrict the wrapper enums generation to global enums only.
2021-11-27 18:51:11 +01:00
Vadim Zeitlin
e8cb7cc952 Simplify code dealing with enum prefix
Use enum_prefix_, ending with "_" if it's not empty, as it can be used
unconditionally instead of having to check whether it's null every time
first.

No real changes, this is just a simplification.
2021-11-27 18:50:23 +01:00
Vadim Zeitlin
30bbb6ae1c Slightly simplify code in enumDeclaration()
Don't bother with maybe_owned_dohptr, we can just use tdname directly at
the cost of a single "if" at the end, so do it like this as it's more
clear and shorter.
2021-11-27 16:02:14 +01:00
Vadim Zeitlin
1087e250d6 Fix long-standing confusion between Files and Strings
Don't use "f_" prefix and "File *" type for the variables that are
strings and not files. Use "sect_" prefix, which means "section", and
"String *" for them.

This finally stops using misleading types (even if they all map to
"void*" anyhow) for the variables, which could result in using file-only
functions with non-files or string-only functions (e.g. Append()) with
two "f_" variables, only for it to work with one of them but not the
other (which was a real file, unlike the first one).

No real changes, this just clarifies the types.
2021-11-27 15:48:02 +01:00
Vadim Zeitlin
c02738270b Rename cxx_wrappers::f_fwd_decls to f_types
This section will contain other types declarations too soon, so rename
it in preparation for it.

No real changes so far.
2021-11-27 15:40:47 +01:00
Vadim Zeitlin
55dc976b9f Use "noexcept for internal ctor and special move operators
No real changes, but just make the trivial non-throwing members
explicitly noexcept.
2021-11-27 15:35:39 +01:00
Vadim Zeitlin
aa0df5faa0 Make swig_check() inline as it should have always been
Fix link errors when including the generated header from more than one
translation unit.
2021-11-27 01:03:12 +01:00
Vadim Zeitlin
c3b262c2f7 Merge branch 'master' into C
Merge with the latest master to resolve (trivial) conflict in the
GitHub workflow file.
2021-11-27 00:20:19 +01:00
Vadim Zeitlin
38b76bb7c6 Make global SWIG_CException::PendingException thread-local
This allows different threads to use the same library concurrently
without corrupting each other's exceptions.

Note that this requires C++11 support for wrapper compilation too. If
this really turns out to be a problem, we could always just #define
thread_local as compiler-specific equivalent such as "__thread" for gcc
or "__declspec(thread)" for MSVC, which are available since forever.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
c7fa9126ce Use a unique prefix for SWIG_CException_Raise()
This allows using different modules generated by SWIG in the same
process without conflicts.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
9dd1301ec4 Improve the fix for exceptions support with multiple modules
The approach of the parent commit almost worked, but broke down if the
main module itself redefined typemaps for SWIGTYPE, as this broke
generation of SWIG_CException wrappers when we finally did it at the
end.

This probably could be salvaged by explicitly defining the typemaps for
SWIG_CException itself and also "int" and "char*", used for its
functions, but this just seems too fragile so switch to a different
approach instead: examine the parse tree immediately when starting
generation to check if it contains any %imports, and decide whether we
need to generate exceptions support in this module based on this.

New version seems more robust and easier to understand, and is probably
not noticeably slower.

Still keep the one in the previous commit just in case we need/want to
return to it later -- but keep in min the typemap redefinition problem
described above if we do it.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
727a65c0e8 Fix using exception in modules importing other modules
Ensure that we have only a single SWIG_CException_Raise() function
across all modules instead of having per-module functions and, worse,
per-module PendingException variables, which resulted in compile-time
errors and couldn't work anyhow because function checking for the
current exception didn't necessarily use the same "global" variable
where it was stored. More formally, old version resulted in ODR
violations and undefined behaviour.

The way we avoid it now is rather ugly and consists in excluding
SWIG_CException from wrapping using the hack in the source code which
postpones wrapping this class until the very end and checks if we had
encountered any %import directives and simply doesn't wrap it if we did.

The same code is used to define the special SWIG_CException_DEFINED
preprocessor symbol which is then used in the generated code to prevent
the SWIG_CException class declaration from being compiled as part of the
wrapper too (because this still happens due to %inline being used for
its definition, and there doesn't seem to be any better way to avoid
this).

This is definitely not pretty, but at least adding "throw(char*)" to a
couple of functions in mod_[ab].i test suite files works now instead of
failing (even without linking and running) as before. This commit
doesn't modify the test suite to avoid possible problems with the other
languages, however.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
9a8ebbb998 Throw SWIG_CException from C++ wrappers automatically
Check for the pending exception after every call to a wrapper function
not marked "noexcept" and throw a C++ exception if necessary.

Add C++ version of the exception example to show how this works.

Also change SWIG_CException to use member functions for checking for and
resetting pending exceptions, this seems better than having separate
functions for it and will make it easier to customize exception handling
later by just replacing SWIG_CException class with something else.

Note that we still use a global (and not a member) function for raising
the exception, but this one is not exported at all, and needs to be a
function in order to be easily callable from other modules (see the
upcoming commit).
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
52f8412a46 Simplify importDirective() code
Don't bother finding the "top" node when we can just save the contents
of its "outfile_h" attribute in top(), where we already use it (and we
already save the module name).

No real changes, just make the code simpler and marginally faster.

This commit is best viewed ignoring whitespace-only changes.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
17fbb0a528 Include required headers for %imported modules
We need the types from the imported modules, so #include the header
generated for it.

Unfortunately we have to half-guess the name used for that header, as
it's not available anywhere (and can't really be, as it could be changed
by a command line option used for another SWIG invocation that was used
to compile that module), but this seems to work well enough in practice.

In particular, this fixes failures in multi cpp tests, so that we don't
need FAILING_MULTI_CPP_TESTS any longer.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
f7f59f4648 Rename module_prefix to just module_name
It is used as a prefix, but it's really just the name of the module, so
the new name is less confusing.

There also doesn't seem to be any need to copy/delete it, just keep a
pointer, it's not going to change.

No real changes.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
43c7aefeb1 Don't leak namespace prefix variable
No real changes, just delete a local variable.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
f42b0eaa71 Use different executable names for C and C++ examples
Trying to create the same "runme" executable for both C and C++ examples
could result in errors when using parallel make, as one of the targets
could fail to write to the file being currently executed.

Using separate names works around this problem.
2021-11-27 00:19:05 +01:00
Vadim Zeitlin
d2546e23ff Don't use exception specification with C++ compiler in example
Support for the exception specifications using types was removed in
C++17 (and "throw ()" in C++20), so don't use them when using the C++
compiler any longer, as this broke the example with recent g++ versions
that use C++17 by default.

We still need them for SWIG, however, so use SWIG_THROW macro, defined
differently for SWIG and the compiler, to preserve the existing
behaviour.

Using %except might be a better idea, but would require more changes.
2021-11-24 20:16:42 +01:00
William S Fulton
a39c2695f2
Merge pull request #2100 from rex4539/typos
Fix typos
2021-11-24 18:41:26 +00:00
Vadim Zeitlin
43276f22a7 Enable testing some C++ wrappers code in the test suite
C++ wrappers still don't compile for about a hundred tests, but they do
compile for almost 500 more of them, so it's still valuable to be able
to check that there are no regressions for those that do work now.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
adb96f8b7a Always pass wrapper objects by const reference in C++ wrappers
Passing them by value doesn't seem to have any advantages, as the copy
will be made internally anyhow if the original function took them by
value and doing an extra one doesn't seem necessary, but does have a big
drawback of not compiling if the class doesn't define a copy ctor.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
3f3438093d Define move ctor and assignment operator for C++ wrappers
This can be done naturally and there doesn't seem to be any reason not
to do it.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
79e9d43c1b Disable broken default-generated copy ctor in C++ wrappers
We can't rely on the default-generated copy ctor because it simply
copies the (possibly) owned pointer, resulting in double destruction if
it's ever used, so disable it completely unless it is explicitly
declared in the original class, in which case we can wrap it using the C
function wrapper defined for it.

Note that we probably should also wrap default-generated copy ctor of
the original class, if it has any, but currently we don't do it even at
C wrappers level, and so can't do it for C++ wrappers neither.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
03c6099ac1 Define "classname" in cxx_class_wrapper dtor too
No changes, just a tiny refactoring before the upcoming commit.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
8d1fbbacb3 Use correct base class C proxy name even if it's not set yet
Replace C::getProxyName() with global get_c_proxy_name() and use it in
cxx_class_wrapper rather than relying on "proxyname" attribute being
already set because this might not be the case if the base class is
defined in another SWIG module just %import'ed from the current one: in
this case, the class is known, but no wrappers had been generated for it
yet, so "proxyname" for it is not set.

Note that, unlike getProxyName(), the new function doesn't bother with
always copying the string, as we may be sure it remains valid as it's
referenced by the node, as one of its attributes.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
b0c9991164 Separate forward declarations and implementations of C++ wrappers
This allows the generated code to compile when different classes depend
on each other, as the class must be forward-declared to be mentioned at
all (as either parameter or return type) and fully defined in order to
be used in either role, as we need to use its ctor or call swig_self()
on it.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
a13da1f8a9 Refactor code to use cxx_wrappers struct
No real changes, just prepare for adding more File objects to be used
for C++ wrappers generation: we can't generate all of them in a single
pass because there may be dependencies between classes.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
a980c036d6 Fix $typemap expansion for C++ wrappers
This required slightly changing the approach used for resolving types in
emit_member_function(), as we can't resolve the type and the casts
to/from it independently any more, but need to do both at once, as this
is required when it's done indirectly due to $typemap() expansion, and
we can't make "return" part of the returned wrapper as we could end with
multiple "returns".

So replace expr_wrapper with type_desc containing both the wrappers and
the type itself and add "return" in emit_member_function() itself for
non-void functions. Also use IIFE so that we can always just prepend
this "return" in the beginning.

Also connect things up so that C++-specific type resolution function is
used while C++ wrappers are being generated.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
e78f5dac45 Add temp_ptr_setter and use it with cxx_class_wrapper
The new helper class will be also useful in other places, so extract it
from cxx_class_wrapper.

No real changes, this is just a refactoring.
2021-11-24 02:41:33 +01:00
Vadim Zeitlin
7c6fb542d3 Convert li_boost_shared_ptr runtime test to C++ from C
It's simpler to write tests in C++ rather than C and checking the
generated C++ API also checks the C API it uses underneath, so there is
no need to have both.
2021-11-23 01:29:26 +01:00