[cfe-dev] Extern ref from method defined outside its namespace

Robinson, Paul Paul.Robinson at am.sony.com
Thu Dec 20 11:20:53 PST 2012


Here's a case where Clang and GCC both do the same thing but I don't see
why it is correct.

--------------------------------------
namespace aaa {
  class Klass {
  public:
    Klass() {}
    void Method();
  };
}

class Klass2 {
public:
  void Method() {}
};

Klass2 k2;

using namespace aaa;

void Klass::Method() {
  extern Klass2 k2; // <-- refers to what name?
  k2.Method();
}

int main() {
  Klass k;
  k.Method();
  return 0;
}
--------------------------------------
So "k2" is defined in the global namespace and has external linkage.
"using namespace aaa;" unpeels aaa and makes Klass available in the
global namespace.
This means the definition of "Klass::Method" actually refers to
"aaa::Klass::Method". So far so good.

If I omit the "extern Klass2 k2;" then the reference to k2.Method
correctly finds k2 in the global namespace.

But, adding the "extern" declaration causes Clang to treat "k2" as
a reference to "aaa::k2" rather than "::k2".  I think that's wrong.

3.5 [basic.link] p6
The name of a function declared in block scope and the name of a variable
declared by a block scope "extern" declaration have linkage. If there is
a visible declaration of an entity with linkage having the same name and
type, ignoring entities declared outside the innermost enclosing namespace
scope, the block scope declaration declares that same entity and receives
the linkage of the previous declaration.

Clearly ::k2 is visible for normal unqualified lookup, because if we omit
the "extern" declaration the compiler is able to see it.
The "using namespace aaa;" doesn't introduce a namespace scope, so the
method definition's innermost enclosing namespace scope would be the
global namespace, which is where ::k2 lives.

I don't see that the member-function definition of Klass::Method would
implicitly open a scope for namespace aaa.  Therefore, the global
namespace is still the innermost enclosing namespace scope of this
method's definition.

If we had this:

namespace aaa {
  void Klass::Method() {
    extern Klass2 k2;
    k2.Method();
  }
}
then sure, "k2" would be "aaa::k2" by the innermost-enclosing-namespace
rule.  But we don't have that here, AFAICT.

So is this a bug?  If not, what am I missing?
Thanks,
--paulr




More information about the cfe-dev mailing list