Is it legal to friend a function via a using declaration? - c++

The following (LiveWorkspace here) is rejected by GCC 4.7.2, GCC 4.8.0, and ICC 13.0.1.
namespace A {
namespace B {
void C();
}
using B::C;
}
class D {
friend void A::C();
};
Additionally, it crashes Clang 3.2 (!). I've submitted a bug report and patch already, for the crash bug, but I'm not 100% sure if this code is really in error, because I can't find anything in §7.3.3 [namespace.udecl] or §11.3 [class.friend] that explicitly addresses this case, but maybe there's something in the definition of one of the various name specifier terms that I've missed.
Furthermore, it seems like all four compilers accept the following (LiveWorkspace here):
namespace A {
namespace B {
class C;
}
using B::C;
}
class D {
friend class A::C;
};
There doesn't seem to be anything fundamentally different about these two cases, so I'm curious what GCC and ICC's grounds to reject the first example but not this one are, if any. Can anyone more familiar with the standard find anything that addresses this?
It's definitely a minor issue at best, but since I'm patching it, I'd like to be sure I'm doing the right thing...
EDIT: This is patched now in clang/trunk!
NEW EDIT: Johannes's answer below explains why my original example is rejected, but it doesn't seem to explain why GCC and ICC also reject the following (LiveWorkspace here):
namespace A {
namespace B {
void C();
}
using B::C;
class D {
friend void C();
};
}

8.3p1:
When the declarator-id is qualified,
the declaration shall refer to a previously declared member of the class or namespace to which the qualifier
refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace (7.3.1))
or to a specialization thereof; the member shall not merely 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.
A class foo; or class foo::bar; does not contain a declarator-id, so it is not affected by this rule. Instead, the foo::bar is part of an elaborated-type-specifier (7.1.6.3).

Related

Why do I have to qualify the namespace for a function passed a typedef of the functions templated parameter type?

In this example why do I need to qualify the function call B::F() with its namespace? As the typedef of QF should match the type Q as I thought it was an alias for it, not really a new type?
Is there an elegant way around this that doesn't require a using statement in every function body?
namespace A
{
template<class T> struct V {};
template<class T> struct Q {};
typedef Q<float> QF;
template<class T>
inline void F(V<T> v) {}
namespace B
{
template<class T>
inline void F(Q<T> q) {}
}
namespace C
{
void Test();
}
}
using namespace A;
using namespace A::B;
void A::C::Test()
{
QF q;
// using namespace A::B; // Uncomment will work
F(q); // Error, tries A::F() and can't find B::F()
B::F(q); // Ok it uses B::F() as intended
}
int main()
{
return 0;
}
I'll try to show in what ways clang interprets the draft differently than gcc and msvc. When you call F(q) inside the definition of void A::C::Test(), the compiler tries to look up the name F in the scopes in which that call is made, and will stop looking for larger scopes as soon as that name (name, not particular overload) is found. The body of void A::C::Test() is inside the namespace C which is inside A which is inside the global namespace. So when you write the using directive in the global scope, the relevant passage in the standard [basic.lookup.unqual]:
In all the cases listed in [basic.lookup.unqual], the scopes are searched for a declaration in the order listed in each of the
respective categories; name lookup ends as soon as a declaration is
found for the name. If no declaration is found, the program is
ill-formed.
The declarations from the namespace nominated by a using-directive become visible in a namespace enclosing the using-directive; see
[namespace.udir]. For the purpose of the unqualified name lookup rules
described in [basic.lookup.unqual], the declarations from the
namespace nominated by the using-directive are considered members of
that enclosing namespace.
by point 2 implies that the name F (coming from A::B::F) is visible as if it was declared in the global scope, but by point 1 name lookup will find a name F sooner, in namespace A and will not look further. So it only finds void F(V<T> v) and this declaration is not fit for the call.
The more interesting story is with the using directive put inside the body of the function. The difference in approach is whether the definition of void A::C::Test() (which is also a declaration) appears in the global namespace or in namespace A::C. If you take the view that this is the global namespace (as clang apparently does), then the namespace enclosing the using-directive written inside the function is the global namespace and we are back to the explanation above. But if you believe that it appears in namespace A::C, then you bring in (among others) the declaration of void F(Q<T>) into A::C and regular lookup finds it.
A bonus observation is why you would still be able to call F(V<double>{}) since now the declaration void F(Q<T>) is in a narrower scope - and the answer is argument-dependent lookup, the namespace where V<T> is declared is going to be looked at too.
That's a story to scare the learner, but if you want practical guidance, do not use the shortcut with namespaces, use
namespace A::C
{
void Test()
{
...
}
}
so that the namespace in which it is declared is not subject to debate and put using namespace A::B; either in namespace scope or in function scope.
(And I'll try to figure out what was the real intended scope of the void A::C::Test() declaration-definition with wiser people).

Neither clang nor g++ compile the snippet below. Why? [duplicate]

From [class.access]/7 we have the following sentence:
Similarly, the use of A::B as a base-specifier is well-formed
because D is derived from A, so checking of base-specifiers must
be deferred until the entire base-specifier-list has been seen.
class A {
protected:
struct B { };
};
struct D: A::B, A { };
See live example with clang. As a matter of fact, clang also complains about this snippet, where no deferment is necessary.
class A {
protected:
struct B { };
};
struct D: A, A::B { };
Why does this code not compile?
PS: gcc and VS21013 don't compile the codes either.
This is simply a compiler bug. The normative text of the standard supports the example. The fact that multiple compilers have the same bug means this is part of the standard is tricky to get right.
There are open bugs about this for GCC
and for clang. Note that a few related cases are actually subtle differences between C++03 and C++11, but as far as I can tell, not this one.
[class.access]/1.2 merely states
protected; that is, its name can be used only by members and friends of the class in which it is declared, by classes derived from that class, and by their friends (see 11.4).
and 11.4 does not expand on this. You are using the name B in a class D derived from that class A. That's fine.
I believe this to be a bug with clang. Ideone doesn't accept the code either: http://ideone.com/uiFl9L:
class A {
protected:
struct B { };
};
struct D: A::B, A { };
I checked with gcc-5.1.0, gcc-4.9 and clang-3.7(rc2). The standard explicitly states this as well-formed (see question) thus the compilers are at fault.
The example clearifies [class.access]/6:
All access controls in Clause 11 affect the ability to access a class member name from the declaration of a
particular entity, including parts of the declaration preceding the name of the entity being declared ...
This means, according to [class.access]/2 that a class has access to all base-classes, even before they are declared.

Maybe my understanding of [class.access]/7 isn't correct, but

From [class.access]/7 we have the following sentence:
Similarly, the use of A::B as a base-specifier is well-formed
because D is derived from A, so checking of base-specifiers must
be deferred until the entire base-specifier-list has been seen.
class A {
protected:
struct B { };
};
struct D: A::B, A { };
See live example with clang. As a matter of fact, clang also complains about this snippet, where no deferment is necessary.
class A {
protected:
struct B { };
};
struct D: A, A::B { };
Why does this code not compile?
PS: gcc and VS21013 don't compile the codes either.
This is simply a compiler bug. The normative text of the standard supports the example. The fact that multiple compilers have the same bug means this is part of the standard is tricky to get right.
There are open bugs about this for GCC
and for clang. Note that a few related cases are actually subtle differences between C++03 and C++11, but as far as I can tell, not this one.
[class.access]/1.2 merely states
protected; that is, its name can be used only by members and friends of the class in which it is declared, by classes derived from that class, and by their friends (see 11.4).
and 11.4 does not expand on this. You are using the name B in a class D derived from that class A. That's fine.
I believe this to be a bug with clang. Ideone doesn't accept the code either: http://ideone.com/uiFl9L:
class A {
protected:
struct B { };
};
struct D: A::B, A { };
I checked with gcc-5.1.0, gcc-4.9 and clang-3.7(rc2). The standard explicitly states this as well-formed (see question) thus the compilers are at fault.
The example clearifies [class.access]/6:
All access controls in Clause 11 affect the ability to access a class member name from the declaration of a
particular entity, including parts of the declaration preceding the name of the entity being declared ...
This means, according to [class.access]/2 that a class has access to all base-classes, even before they are declared.

Wherefore inline unnamed namespaces?

A quick one for the gurus: C++11 allows unnamed namespaces to be declared inline. This seems redundant to me; things declared in an unnamed namespace are already used as if they were declared in the enclosing namespace.
So my question is this: what does it mean to say
inline namespace /*anonymous*/ {
// stuff
}
and how is it different from the traditional
namespace /*anonymous*/ {
// stuff
}
that we know and love from C++98? Can anyone give an example of different behaviour when inline is used?
EDIT: Just to clarify, since this question has been marked as a duplicate: I'm not asking about named inline namespaces in general. I understand the use-case there, and I think they're great. I'm specifically asking what it means to declare an unnamed namespace as inline. Since unnamed namespaces are necessarily always local to a TU, the symbol versioning rational doesn't seem to apply, so I'm curious about what adding inline actually does.
As an aside, the standard [7.3.1.1], regarding unnamed namespaces, says:
inline appears if and only if it appears in the unnamed-namespace-definition
but this seems like a tautology to my non-language lawyer eyes -- "it appears in the definition iff it appears in the definition"! For bonus points, can anyone explain what this bit of standardese is actually saying?
EDIT: Cubbi claimed the bonus point in the comments:
the standard is saying that unnamed-namespace-definition behaves as if it were replaced by X where inline appears in X iff it appears in the unnamed-namespace-definition
I don't know whether it's the done thing to answer your own question on SO, but after some playing around my curiosity has been satisfied, so I may as well share it.
The definition of an inline namespace includes not only the hoisting of names into the enclosing namespace (which happens anyway for unnamed namespaces), but also allows templates defined within an inline namespace to be specialised outside it. It turns out that this applies to unnamed namespaces too:
inline // comment this out to change behaviour
namespace {
template <typename T> struct A {};
}
template <> struct A<int> {};
Without the inline, g++ complains about trying to specialise a template from a different namespace (though Clang does not). With inline, it compiles just fine. With both compilers, anything defined within the specialisation is still marked as having internal linkage (according to nm), as if it were within the unnamed namespace, but I guess this is to be expected. I can't really think of any reason why this would be useful, but there we go.
An arguably more useful effect comes from the change regarding argument-dependent lookup for inline namespaces, which also affects unnamed inline namespaces. Consider the following case:
namespace NS {
// Pretend this is defined in some header file
template <typename T>
void func(const T&) {}
// Some type definition private to this TU
inline namespace {
struct A {};
}
} // end namespace NS
int main()
{
NS::A a;
func(a);
}
Without inline, ADL fails and we have to explicitly write NS::func(a). Of course, if we defined the unnamed namespace at the toplevel (as one normally would), then we wouldn't get ADL whether it was inline or not, but still...
Here is one use that I have found:
namespace widgets { inline namespace {
void foo();
} } // namespaces
void widgets::foo()
{
}
In this example, foo has internal linkage and we can define the function later on by using the namespace::function syntax to ensure that the function's signature is correct. If you were to not use the widgets namespace then the void foo() definition would define a totally different function. You also don't need to re-open the namespace saving you a level of indentation.
If there is another function called foo in the widgets namespace already then this will give you an ambiguity instead rather than a nasty ODR violation.

Obviously ambiguous call does not cause a compilation error on GCC

I was surprised by the fact that GCC does not consider the call to foo() in the following program ambiguous:
#include <iostream>
struct B1 { bool foo(bool) { return true; } };
struct B2 { bool foo(bool) { return false; } };
struct C : public B1, public B2
{
using B1::foo;
using B2::foo;
};
int main()
{
C c;
// Compiles and prints `true` on GCC 4.7.2 and GCC 4.8.0 (beta);
// does not compile on Clang 3.2 and ICC 13.0.1;
std::cout << std::boolalpha << c.foo(true);
}
The above function call compiles and returns true on GCC 4.7.2 and GCC 4.8.0 (beta), while it won't compile (as I would expect) on Clang 3.2 and ICC 13.0.1.
Is this a case of "no diagnostic required", or is it a bug in GCC? References to the C++11 Standard are encouraged.
§7.3.3/3:
In a using-declaration used as a member-declaration, the nested-name-specifier shall name a base class of the class being defined. If such a using-declaration names a constructor, the nested-name-specifier shall name a direct base class of the class being defined; otherwise it introduces the set of declarations found by member name lookup (10.2, 3.4.3.1).
¶14:
… [ Note: Two using-declarations may introduce functions with the same name and the same parameter types. If, for a call to an unqualified function name, function overload resolution selects the functions introduced by such using-declarations, the function call is ill-formed.
¶16:
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.
So, the using declarations are legal, but the functions are peers in the same overload set, as you said, and the program is ill-formed.
The call to foo(true) in your program is, as you say, clearly ambiguous; furthermore, it is ambiguous according to the algorithm presented in §10.2 and consequently, it should be flagged on use. (Flagging the using declaration would be incorrect; 10.2(1) clearly states that ambiguous uses of names are flagged on lookup, not on declaration.)
It's interesting to contrast this program with a similar one, which is the subject of a a recognized gcc bug (slightly modified from that bug report to make the parallel clearer):
#include <iostream>
struct A {
static int foo() {return 1;}
static int foo(char) { return 2;}
};
struct B1 : A {
// using A::foo;
};
struct B2 : A {
// using A::foo;
};
struct C : B1, B2 {
// using B1::foo;
// using B2::foo;
};
int main()
{
std::cout << C::foo();
}
The above program is correct; despite the diamond inheritance, foo is a static member of A, so it is not ambiguous. In fact, gcc compiles it without trouble. However, uncommenting the two instances of using A::foo, which does not change anything about either foo, causes gcc to produce the oddly reduplicated error noted in the bug report. Uncommenting the two using declarations inside C, which presumably triggers the other bug which is the subject of this question, then masks the static function bug and causes the program to compile again.
clang seems to handle all possible variants of this program, for what it's worth.
Finally, note that an explicitly declared foo(bool) within C (in the original program) will win out over any foo(bool) brought into C's scope by using declarations. I suspect that both of these bugs are the result of bad bookkeeping while trying to keep track of the various function declarations in each class's scope and their individual provenance (as a sequence of using declarations and function declarations).