swig-fortran / swig

This fork of SWIG creates Fortran wrapper code from C++ headers.
http://www.swig.org
Other
42 stars 11 forks source link

Improve conflict detection and renaming behavior #114

Closed sethrj closed 5 years ago

sethrj commented 5 years ago
aprokop commented 5 years ago

Enum values will be ignored (and generate a warning) when they conflict.

Can you please elaborate?

Member functions whose names conflict with other class functions will be ignored.

I don't quite understand that. If they have the same name, isn't it an overload?

Member functions that hide (shadow) base class functions will be ignored.

Would not that make the Fortran behave very differently from a similar C++ code?

sethrj commented 5 years ago

@aprokop The key is that Fortran's namespace/scope is different from C++: it's all lowercase, and there's no namspace. Currently, in most SWIG languages, if you have

namespace a {
class Foo {};
}
namespace b {
class Foo {};
}

the other SWIG languages will error out, but Fortran arbitrarily renames the second one. With enums, we also arbitrarily rename conflicts:

enum Foo {
 FOO
};

generates symbols foo and foo1 because they're both foo in Fortran's lowercase namespace. The Go language sometimes changes the case of symbols and ignores if they're duplicates rather than erroring. So again we'll be replicating that behavior.

Finally, regarding overloading and hiding: Fortran and C++ behave very differently with regards to "overloading". With Fortran, as I understand it, the basic idea is to apply the same operation to different types: daughter classes can extend the interface if the base class declares it generic. The result is that there are a ton of restrictions on what can be overloaded:

...and a thousand others. Right now we generate a lot of invalid Fortran code with overloaded and overridden functions; the proposed change will make these overloads ignored by default since the semantic meaning of C++ overloading and Fortran generics are almost completely at odds.

%module derp

%inline %{

class Base {
public:
 int func();
 int func(int a);
 virtual int func(int a, int b);
 // void func(int, int, int); // ERROR: can't overload subroutine with functions
 void another();
};

class Derived : public Base {
 public:
  // using Base::func; // ERROR: generates functions ambiguous with base class
  double func(double b); // ERROR unless we have another overloading function
                         // so that the daughter function is labeled generic
  double func(double, double);
  // virtual int func(int x, int y); // ERROR: different parameter names
  // virtual int func(int a, int b); // ERROR: ambiguous with base class
  void another();
  // int another(int);
  // double another(double); // ERROR: generic in daughter class but not in parent
};

%}

Anyway, the result of the change is a lot of warnings but users will have to %rename the overloads.

aprokop commented 5 years ago

Thank you for the thorough comment! I did not realize the existence of all those nuances.

sethrj commented 5 years ago

Yeah, Fortran is fun 🙄

sethrj commented 5 years ago

This merge ticks a few boxes in #59 , fixing the following tests:

Some new tests fail:

Most failing tests are due to conflicting symbols in the target language module and should be trivial to fix.