llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.02k stars 11.96k forks source link

inconsistent unqualified lookup for friend declaration #24462

Open llvmbot opened 9 years ago

llvmbot commented 9 years ago
Bugzilla Link 24088
Version 3.6
OS Windows NT
Reporter LLVM Bugzilla Contributor
CC @DougGregor,@tstellar,@jwakely

Extended Description

Consider the following code, courtesy of Belloc (http://stackoverflow.com/q/31348475/2069064):

struct Outer {
    void f() { }
    class C { };

    class Inner {
        friend class C;
        friend void f();
        static const int i = 0;
    };
};

void f() { int i = Outer::Inner::i; }
class C { int i = Outer::Inner::i; };

int main() { }

According to [namespace.memdef]/3,

the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.

There's some confusion as to what "outside" means in this context, but regardless both GCC and Clang are inconsistent in their interpretation. Either it means exclusively the innermost enclosing namespace (in which case both ::f and ::C should be friends) or it just means stop at the innermost enclosing namespace (in which case both Outer::f and Outer::C should be friends). But in this case, both GCC and Clang friend ::f and Outer::C, which is a bug in one direction or the other.

3a17e7c4-fca4-4827-b2a7-11a54d73d746 commented 7 years ago

As I said at https://gcc.gnu.org/#66836

Well friend void f(); can't match Outer::f because you can't declare a member function like that except in the class' own scope. What GCC and Clang do is what the standard intended to say but fails to say clearly, which is Core issue 138 https://wg21.link/cwg138