C++ operator overload miscompilation

For C++ code:

struct A {
    operator int();
};
bool f() {
    bool operator==(const A &, const A &);
    return A() == A();
}

clang emits calls to A::operator int() and then performs the == comparison on ints - which is incorrect, only a call to operator==(const A &, const A &) should be emitted.
Other compilers handle this correctly (gcc, icc, cl).

For C++ code:

struct A {
   operator int();
};
bool f() {
   bool operator==(const A &, const A &);
   return A() == A();
}

Any particular reason why you declare operator== inside f()? Normally, such declarations are put at the top level.

clang emits calls to A::operator int() and then performs the == comparison on ints - which is incorrect, only a call to operator==(const A &, const A &) should be emitted.

That said, it's weird that it doesn't find operator== here. I think it has something to do with declaring it inside the function, instead of at the top level.

-Dimitry

Yes, this is a bug. Looks like we're not correctly putting the operator==
function into IDNS_NonMemberOperator. We have this code in two places in
Sema:

   if (Function->isOverloadedOperator() && !DC->isRecord() &&
      PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
    PrincipalDecl->setNonMemberOperator();

... which is wrong -- the above declaration is in IDNS_LocalExtern, not
IDNS_Ordinary. If you're interested in putting together a patch for this,
the fix might be as simple as changing the IDNS_Ordinary in these two cases
to IDNS_Ordinary | IDNS_LocalExtern (you'll need to make sure that doesn't
make the operator visible to operator lookups *outside* f(), though).