3
votes

Per C++ 03 standard 7.3.3/4. The code below is well-formed since the function g has C linkage. A::g() and B::g() should refer to the same entity.

namespace A {
    extern "C" void  g();
}

namespace B {
    extern "C" void g();
}

using namespace A;
using namespace B;

int main(){
    g(); // Error (Apple LLVM 2.1): Call to 'g' is ambiguous.

    return 0;
}

extern "C" void  g(){ }

When I compile the C++ code with Xcode 4.1, there are different behaviors when selecting different compilers. If Apple LLVM 2.1 is selected, there is compile error, say "Call to 'g' is ambiguous". If select GCC 4.2 or LLVM GCC 4.2, it can compile successfully.

Is it a defect of CLang or I'm wrong somewhere?

The Apple LLVM 2.1 is actually that Clang is the front-end and LLVM is the back-end, right?

==========================================================================

The corresponding description of C++ standard is:

If name lookup finds a declaration for a name in two different namespaces, and the declarations do not declare the same entity and do not declare functions, the use of the name is ill-formed. [Note: in particular, the name of an object, function or enumerator does not hide the name of a class or enumeration declared in a different namespace. For example,

namespace A {
    class X { };
    extern "C"   int g();
    extern "C++" int h();
}
namespace B {
    void X(int);
    extern "C"   int g();
    extern "C++" int h();
}

using namespace A;
using namespace B;

void f() {
  X(1); // error: name X found in two namespaces

  g();  // okay: name g refers to the same entity

  h();  // error: name h found in two namespaces
}

—end note]

1

1 Answers

2
votes

It seems likely, given the quote, that it is a Clang bug.

Most probably, Clang considers the two entities distinct because they were declared in different scopes (namespace A and namespace B), and does not realise that extern "C" subverts the scope rules.

I would advise against puting extern "C" declarations within namespaces, since namespaces are irrelevant for those, and thus, even if applicable, it will only confuse the developers (and occasionally compilers :p)