Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

using declaration hides local declaration?

1 view
Skip to first unread message

Chris Uzdavinis

unread,
Nov 26, 2009, 1:07:07 AM11/26/09
to
Hi,
I was surprised to find that g++ (as of 4.3 and 4.4) rejects this
code:

void f() {}

namespace A {
void f(int);
using ::f; /// <<<< seems to hide above declaration
}

// The following line generates this message [g++]
// /tmp/asdf.cpp:8: error: 'void A::f(int)' should have been declared
inside 'A'
void A::f(int a) {}

int main() {
A::f(1);
}

In my opinion, it clearly is declared inside 'A', but the "using ::f"
declaration causes g++ to not see it. I reported this as a bug (gcc
bug 38799) but it was closed as "this is how it should behave." When
I reverse the order of those statements (such that the ::using comes
first, then g++ accepts the code without error.

I've not found any conclusive (to me) language in the standard about
this, but do notice that Comeau accepts this code, with and without c+
+0x extensions. I place a great deal of faith in Comeau/EDG, and
usually find that when I think I've found a bug in Comeau, it usually
turns into an opportunity for me to learn something new.

Can someone explain which compiler is correct, and if this error as
reported by g++ really is the intended behavior of the language,
please explain the motivation for it?

Thanks!

Chris

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Balog Pal

unread,
Nov 27, 2009, 8:34:57 AM11/27/09
to
"Chris Uzdavinis" <cuz...@gmail.com>

> I was surprised to find that g++ (as of 4.3 and 4.4) rejects this
> code:
>
> void f() {}
>
> namespace A {
> void f(int);
> using ::f; /// <<<< seems to hide above declaration
> }

> In my opinion, it clearly is declared inside 'A', but the "using ::f"


> declaration causes g++ to not see it. I reported this as a bug (gcc
> bug 38799) but it was closed as "this is how it should behave." When
> I reverse the order of those statements (such that the ::using comes
> first, then g++ accepts the code without error.
>
> I've not found any conclusive (to me) language in the standard about
> this, but do notice that Comeau accepts this code, with and without c+
> +0x extensions. I place a great deal of faith in Comeau/EDG, and
> usually find that when I think I've found a bug in Comeau, it usually
> turns into an opportunity for me to learn something new.

As I read the standard [7.3.4], Cameau is right.
using declaration most of the time works exactly like a normal declaration,
with the similar effect. The one exception I found is with member functions
where collision is processed as 'hide' instead of 'conflict'. What makes
sense.

Otherwise, function declarations made at the *same* declaration scope never
hide each other -- hiding applies only to declarations of an outer scope.

Your example would translate to

namespace A {
void f(int);
void f(); // mapping to ::f()
// note: if multiple functions are there all are dragged in
}
that is a good overload set. The order of the declarations is not important
for this case.

If you change ::f to be f(int), Cameat flags a conflict, as is should too.
(And the conflict goes away if code turned to member functions).

In summary IMO g++ guys are wrong. Did they say where their idea of hiding
*siblings* comes from?

Johannes Schaub (litb)

unread,
Nov 28, 2009, 3:38:34 AM11/28/09
to
Balog Pal wrote:

> "Chris Uzdavinis" <cuz...@gmail.com>
>
>> I was surprised to find that g++ (as of 4.3 and 4.4) rejects this
>> code:
>>
>> void f() {}
>>
>> namespace A {
>> void f(int);
>> using ::f; /// <<<< seems to hide above declaration
>> }
>
>> In my opinion, it clearly is declared inside 'A', but the "using ::f"
>> declaration causes g++ to not see it. I reported this as a bug (gcc
>> bug 38799) but it was closed as "this is how it should behave." When
>> I reverse the order of those statements (such that the ::using comes
>> first, then g++ accepts the code without error.
>>
>> I've not found any conclusive (to me) language in the standard about
>> this, but do notice that Comeau accepts this code, with and without c+
>> +0x extensions. I place a great deal of faith in Comeau/EDG, and
>> usually find that when I think I've found a bug in Comeau, it usually
>> turns into an opportunity for me to learn something new.
>

> Your example would translate to
>
> namespace A {
> void f(int);
> void f(); // mapping to ::f()
> // note: if multiple functions are there all are dragged in
> }
> that is a good overload set. The order of the declarations is not
> important for this case.
>
> If you change ::f to be f(int), Cameat flags a conflict, as is should
> too. (And the conflict goes away if code turned to member functions).
>
> In summary IMO g++ guys are wrong. Did they say where their idea of hiding
> *siblings* comes from?
>
>

Maybe they are reading 8.3/1 as saying that the qualified-id in that
declaration outside the namespace may not refer to an overload set
containing a using declaration? 8.3/1 says:

"... the declaration shall refer to a previously declared member of the
class or namespace to which the qualifier refers, and the member shall not
have been introduced by a using-declaration in the scope of the class or
namespace nominated by the nested-name-specifier of the declarator-id."

The declaration arguably does only refer to one function, but its qualified-
id when looked-up before considering context refers to both functions in
"A". Maybe GCC is making the test before or during declaration matching, and
not afterwards? I think they seem to do it *during* matching using a simple
loop: If the using declaration is found first, they error out. But if the
matching non-using declaration is found first, they stop that loop.

Balog Pal

unread,
Nov 28, 2009, 9:18:46 PM11/28/09
to
"Johannes Schaub (litb)" <schaub-...@web.de>

That makes sense, but does not apply in the case.

void f() {}
namespace A {
void f(int);
using ::f; /// <<<< seems to hide above declaration
}

void A::f(int a) {}

here f is a member of A and f(int) is a genuine thing. This would make
things

void A::f() {} // f is member but introduced with using
void A::g() {} // not member

Btw any argument about 'hiding' gets fishy with a qualified-id. hiding is a
feature applied to unqualified lookup.

> The declaration arguably does only refer to one function, but its
> qualified-
> id when looked-up before considering context refers to both functions in
> "A".

Sure. That doesn't make them not-declared. ;)

> Maybe GCC is making the test before or during declaration matching, and
> not afterwards? I think they seem to do it *during* matching using a
> simple
> loop: If the using declaration is found first, they error out.

Aha, that is technically possible -- when they process using, mark
everything. Or do some other kind of mis-booking, on f(int).

> But if the
> matching non-using declaration is found first, they stop that loop.

I'm sure the compiler doesn't work like that -- it is not looking source
text any longer, but has a symbol table built. When true-member f comes
last, it is put correctly in the table. With the other sequence some info
is corrupted, manifesting in the bug.

0 new messages