In C++ a base class' name is a member of the base (its injected class name) and so
is visible from within a derived class, named either unqualified ('Base') or scope
qualified through the derived class ('Derived::Base'). SWIG did not model this, so
a base in a namespace named without its namespace qualifier was not resolved: a
using declaration through such a typedef gave a spurious Warning 315 and dropped the
member, and the base named as a type was either unresolved or treated as a distinct
type from the base named directly.
namespace Space { struct Base { ... }; }
struct Derived : Space::Base {
typedef Base base_type; // Base, not Space::Base
using base_type::method; // no longer Warning 315
Base m(Base b); // 'Base' resolves to Space::Base
};
Derived::Base f(Derived::Base); // 'Derived::Base' resolves to Space::Base
This is handled in three places, mirroring the same C++ rule:
- Swig_symbol_inherit() adds the base class' name to the derived class' C symbol
table, so the symbol table resolves the base named from within the derived class.
The node added is the base's own entry in its enclosing scope, where every class
is registered; it does not clash, as the derived class' constructors carry the
derived name.
- The type system (typepass) aliases the base class' name to the base's own scope
within the derived class, so a base named unqualified as a type resolves to the
base's own type.
- SwigType_typedef_qualified() resolves a scope qualified name that itself names a
scope (such as Derived::Base) to that scope's canonical name, so the base named
through the derived class resolves to the same type as the base named directly.
Closes#2659
Assisted-by: Claude Opus 4.8 (1M context)