14
votes
namespace X {
    void f();
}

void X::f() {
    void g();
    g();
}

Have I declared ::g, or X::g?

clang 3.5 will compile and link this if I add a definition of X::g:

namespace X {
    void f();
}

void X::f() {
    void g();
    g();
}

void X::g() { }

gcc 4.9.1 rejects the definition with the message:

error: ‘void X::g()’ should have been declared inside ‘X’

but if I define g in the global namespace instead, gcc seems to change it's mind and complain about the opposite:

Undefined symbols for architecture x86_64:
  "X::g()", referenced from:
      X::f()     in ccABCDEF.o

Because it is also illegal to declare void ::g() inside of f, it seems that it isn't possible to have a function-scope forward declaration of global function in a namespace function. Am I missing something? What exactly are the scoping rules here?

g++ (GCC) 4.9.1; Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)

1

1 Answers

6
votes

Function declarations at block scope have linkage. [basic.link]/6:

The name of a function declared in block scope and [..] have linkage.

But such block scope declarations with linkage do not introduce any names into enclosing namespaces. [basic.link]/7:

When a block scope declaration of an entity with linkage is not found to refer to some other declaration, then that entity is a member of the innermost enclosing namespace. However such a declaration does not introduce the member name in its namespace scope.

You have therefore neither declared ::g nor X::g. Defining it via

void X::g() {}

is ill-formed.