Bug: name lookup ambiguities in class scope

Carlos Pita cpitaar@yahoo.com.ar
Wed Jul 18 05:21:00 GMT 2001


g++ 3.0 compiles (with -pedantic) the following code without complaining.
But according to the ISO standard (final, not the draft) the program is
ill-formed because of #1 and #2 (marked in the comments):

struct A {
        void f(int) {};
        void f(char) {};
};

struct B {
        void f(double);
};

struct C:public A,B {
      using A::f;
      using B::f;
      void g() { f(1); }; // <-- this shouldn't work (#1)
};

struct D:public A,B {
      using A::f;
      void g() { f(1); }; // <-- this shouldn't work (#2)
};

struct E:public A,B {
      using A::f;
      using B::f;
      void f(int) {};
      void g() { f(1); }; // <-- this is fine
};

struct F:public A,B {
      using A::f;
      void f(int) {};
      void g() { f(1); }; // <-- this is fine
};

int main() {
 C c;
 D d;
 E e;
 F f;
 //...
 return 0;
}

The related standard sections are 10.2.2, 7.3.3.12 and 7.3.3.13. I'm
partially quoting them below:

"""
10.2.2  The following steps define the result of name lookup in a class
scope, C.   First,  every  declaration for the name in the class and in each
of its base class  sub-objects is considered. A member name f in one
subobject B hides a member  name  f  in a sub-object A if A is a base class
sub-object of B. Any declarations  that  are so hidden are eliminated from
consideration. Each of these  declarations that was introduced by a
using-declaration is considered to  be  from  each  sub-object  of  C  that
is  of  the type containing the declaration  designated by the
using-declaration.*96*) If the resulting set of declarations are not all
from sub-objects of the same type, or the set has a nonstatic member and
includes members from distinct sub-objects, there is an ambiguity and the
program is ill-formed. Otherwise that set is the result of the lookup.

Note *96* says: Note that  using-declarations  cannot  be used to resolve
inherited member ambiguities...

7.3.3.12  When  a  using-declaration brings names from a base class into a
derived class  scope,  member  functions  in  the derived class override
and/or hide member  functions  with  the  same  name and parameter types in
a base class (rather than conflicting). [Example....

7.3.3.13  For  the  purpose  of  overload  resolution,  the  functions
which  are introduced  by  a  using-declaration into a derived class will be
treated as though  they  were members of the derived class.
"""


Following 10.2.2 neither A::f nor B::f is hidden by a declaration of a
member f in C so there is an ambiguity in the body of C::g. The same can be
said for D. The ambiguity is eliminated in E and F because of the
declarations of E::f and F::f respectively. Then, according 7.3.3.12 and
7.3.3.13, overloading will be done for E::f in order to select one function
from the set {A::f(char), B::f(double), E::f(int)}. Similarly, the set for
F::f will be {A::f(char), B::f(double), F::f(int)}. So classes E and F don't
make the program ill-formed.

I'll submit this as a bug 5 days after posting it here except in case that
anyone of you think (and convincingly explain why :) ) this is not a bug
before the fifth day. I prefer some discussion before submitting bugs
related to ISO conformace bacause of the vaguety and complexity that
sometimes obscures the standard text.

See you,
 Carlos


_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com




More information about the Gcc-bugs mailing list