Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLANG including struct names when looking up namespace name candidates #44561

Closed
llvmbot opened this issue Mar 16, 2020 · 6 comments
Closed

CLANG including struct names when looking up namespace name candidates #44561

llvmbot opened this issue Mar 16, 2020 · 6 comments
Labels
bugzilla Issues migrated from bugzilla c++11 invalid Resolved as invalid, i.e. not a bug

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 16, 2020

Bugzilla Link 45216
Resolution INVALID
Resolved on Mar 19, 2020 13:46
Version unspecified
OS All
Reporter LLVM Bugzilla Contributor
CC @DougGregor,@zygoloid

Extended Description

The below code compiles on GCC but not on CLANG. Looks like CLANG is looking up struct identifier names as ns_name candidates in addition to namespace names in "using ns_name::name;".

https://wandbox.org/permlink/zG6JvMtNwxXK4yPn

////////////////////////////////////////////////////////////////////////////
#include<stdio.h>

namespace N1 {
const char* f() {
return "NamespaceN1::f()";
}
}

namespace N2 {
struct N1 {
static const char* f() {
return "NamespaceN2::StructN1::f()";
}
};
}

using namespace N2;
using N1::f;

int main()
{
printf("%s\n", f());
return 0;
}

////////////////////////////////////////////////////////////////////////////
Compilation Error on CLANG:

prog.cc:18:7: error: reference to 'N1' is ambiguous
using N1::f;
^
prog.cc:3:11: note: candidate found by name lookup is 'N1'
namespace N1 {
^
prog.cc:10:10: note: candidate found by name lookup is 'N2::N1'
struct N1 {
^
prog.cc:22:20: error: use of undeclared identifier 'f'; did you mean 'N1::f'?
printf("%s\n", f());
^
N1::f
prog.cc:4:16: note: 'N1::f' declared here
const char* f() {
^
2 errors generated.

////////////////////////////////////////////////////////////////////////////
Result on GCC:

NamespaceN1::f()

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Mar 17, 2020

This is a GCC bug. The lookup for the name on the left of :: "considers only namespaces, types, and templates whose specializations are types" according to the C++ standard, so following the normal unqualified lookup rules it should find both the namespace ::N1 and the struct N2::N1.

Modified example showing why lookup to the left of :: should consider types:

namespace N1 {
const char* f();
}

namespace N2 {
struct X {
static const char* f();
};
using N1 = X;
}

using namespace N2;

using N1::f; // Clang: ambiguous, GCC: N1::f (OK)
struct Q : N2::N1 {
using N1::f; // Clang: ambiguous, GCC: N1::f (error)
};

@llvmbot
Copy link
Collaborator Author

llvmbot commented Mar 19, 2020

"When looking up a namespace-name in a using-directive, only namespace names are considered, see [basic.lookup.udir]. — end note" - http://eel.is/c++draft/namespace.udir

So shouldn't the lookup for the name on the left of the :: scope resolution operator when used in the context of a using-declaration 'using ns_name::name;' look up only namespace names?

Ref:
using ns_name::name; (6) - https://en.cppreference.com/w/cpp/language/namespace

  1. using-declaration: makes the symbol name from the namespace ns_name accessible for unqualified lookup as if declared in the same class scope, block scope, or namespace as where this using-declaration appears.

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Mar 19, 2020

"When looking up a namespace-name in a using-directive, only namespace names
are considered, see [basic.lookup.udir]. — end note"

A using-directive is a declaration of the form

using namespace NS;

The case in this bug report is a using-declaration, not a using-directive, so that rule doesn't apply.

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Mar 19, 2020

@llvmbot
Copy link
Collaborator Author

llvmbot commented Mar 19, 2020

The case in this bug report is a using-declaration, not a using-directive. Agreed.

One last question:
Shouldn't the left-most identifier in the nested-name-specifier in the using declaration always be a namespace name [or empty to refer to the global namespace]? Since a class name cannot be used here, shouldn't it be unambiguous to the compiler?

////////////////////////////////////////////////////////////////////////////
struct N1 {
static const char* f() {
return "StructN1::f()";
}
};

using N1::f;

#include<stdio.h>
int main()
{
printf("%s\n", f());
return 0;
}
////////////////////////////////////////////////////////////////////////////
Compilation Error on CLANG:

...
prog.cc:7:11: error: using declaration cannot refer to class member
using N1::f;
~~~~^
...
////////////////////////////////////////////////////////////////////////////

Refs:
http://eel.is/c++draft/namespace.memdef

"using typename(optional) nested-name-specifier unqualified-id ; (until C++17)"
nested-name-specifier - a sequence of names and scope resolution operators ::, ending with a scope resolution operator. A single :: refers to the global namespace.
https://en.cppreference.com/w/cpp/language/namespace#Using-declarations

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Mar 19, 2020

Shouldn't the left-most identifier in the nested-name-specifier in the using
declaration always be a namespace name [or empty to refer to the global namespace]?
Since a class name cannot be used here, shouldn't it be unambiguous to the compiler?

A class name can be used as the left-most identifier in a using-declaration. For example:

struct A { int x; };
struct B : A { using A::x; };

struct C { enum { e }; };
using C::e; // ok since C++20

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla c++11 invalid Resolved as invalid, i.e. not a bug
Projects
None yet
Development

No branches or pull requests

1 participant