-
Notifications
You must be signed in to change notification settings - Fork 13.6k
C++ import std still puts things in global namespace? #90101
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
Comments
@llvm/issue-subscribers-clang-modules Author: None (rnikander)
This code fails to compile. Shouldn't it work?
```
import std;
namespace ns {
double fog(double d) { return d; }
}
int fog; // Okay - no conflict with ns::fog
int log; // Fails - conflicts with std::log
```
I notice this because I'm always trying to declare these file-local |
I'm not finding the docs (if there are any) on how to prepare the |
It fails for me too. Can you post your compiler output; I'd like to make sure we look at the same failure. |
Here:
By the way, MS's compiler is doing the same thing to me. It seems to me that the right thing to do here would be to have |
This is slightly complex to explain. But my conclusion is, the behavior of the compiler to the reproducer is "correct" and I don't know how libc++ can fix this. Let's talk about the compiler first and the library second. For this issue, the compiler are saying "you're defining two different '::log', this violates the ODR rule". This is correct. The reproducer defines two different entities with the same name in the same program (the std library is part of that program). Here the This may be annoying but image this in the header's era, if we include For libc++, it is hard to fix. The fundamental reason is that, the implementation of |
Also if you're interested, you can take a look at #90154 for a similar case |
If we wanted to fix this, I think we could relatively easily. We're already defining our own set of the math functions, which we could include directly and avoid the libcs math.h altogether. Then we'd change using ::log to using std::__math::log. I'm just not sure we really want to do that, since it's trivial to regress on this. |
I am not sure the standard as specified is implementable because of the fact aliases don't introduce new names? https://eel.is/c++draft/support.c.headers#other-1.sentence-2 It is unspecified whether these names are first declared or defined within namespace scope ([basic.scope.namespace]) of the namespace std and are then injected into the global namespace scope by explicit using-declarations ([namespace.udecl]) https://eel.is/c++draft/library#std.modules-2 The named module std exports declarations in namespace std that are provided by the importable C++ library headers (Table 24 or the subset provided by a freestanding implementation) and the C++ headers for C library facilities (Table 25). It additionally exports declarations in the global namespace for the storage allocation and deallocation functions that are provided by . The intent behind the std.compat split is that import std would not add names to the global namespace, but can we achieve that reliably? @philnik777 solution would probably work but would not that cause ABI issues? |
@cor3ntin As I understand it, if you |
I guess what @cor3ntin says is, since that solution may change the implementation of |
The intent was not to pollute the global namespace at all. Presumably (in part) so that users could then put their own names there. The other motivation if i recall was to avoid ADL issues (which we achieve).
You suggested putting the definition in eg |
I'm a bit surprised this is considered "as intended". I thought modules were intended to encapsulate dependencies and not leak them to those who import modules. Should the module's I don't think moving things to |
Yes, but that is for declarations in module purview. For example,
In the above example, the definition of But it is a different story of std modules in libc++ now since they actually a wrapper of headers.
From the current implementation of libc++, the
|
I am wondering if we can fix it by:
Then point is, we don't need to touch Do you think if this is feasible? Or otherwise we can only say this may not be implementable and raise some complaints in WG21. |
I'm pretty sure you've misunderstood what I suggested. We already have inline |
@philnik777 Oh! excellent. Then it might be a good (or at least conforming) way forward |
Thanks that makes it clear why this happens. I'm still not convinced the I want to investigate further what's possible. |
I did some additional tests, including adding a layer of indirection. That however did not work. |
We may have that by |
If my memory is correct, GMF decls can be elided if they are unused so whether ::log is reachable might not be the concern? |
But if we're |
yes, indeed - in that case it cannot be elided. |
I had no real design. I just wanted to experiment with a separate library while reading the Standard to better understand what the real issue was. I just noticed some parts that were not reachable also caused compilation errors. These issues were indeed fixed by So I agree the current design works as intended and I don't see anything libc++ or clang can do to fix this. |
But the reported case |
yes as far as I can see it should be. Therefore I closed the report. I was just very surprised by this behaviour, so I wanted to look at bit closer at the details and the exact wording in the Standard. |
I am very unclear that this is the case. Let me ask LWG |
I am not sure if I read correctly. I mean, if we enabled I just tried myself. With In this case, I think we shouldn't close the issue. Especially we're still not very clear what's the standard behavior from the spec. (Although personally I think we should accept the reproducer.) |
Since our implementation is conforming (which is reaffirmed on the reflector) I feel we can keep this closed. Discarding unreachable declarations does not fix the issue. It requires changing the Standard. (I still feel it would be great if this worked.) |
Can you explain this a bit more? I've been using C++ a lot lately, but I don't understand it as deeply as you all do. I don't fully understand all the terms used in these posts. To me it feels like I have a thing with a "public" interface – the To me, that should be hidden. I shouldn't have to think about it. Is that accurate, or would you describe it differently? |
Can you elaborate on that? For example, I didn't see relevant discussion in EWG's reflector. Also it will be helpful to share the text about why it is conforming and why we need to change the Standard if we want to do that. |
That might be nice, but it's not the case. Modules cannot prevent all conflicts -- in order to prevent conflicts, implementations must (still) use unique names for their global functions (generally achieved by putting everything into a unique namespace). Perhaps in an ideal world, the C++ standard library would also only depend on names in the "std" namespace, and not global names -- leaving the global names available for users. But, in the world we have, the C++ library is built upon a foundation laid by the C library -- and the C library defines a lot of names in the global namespace (such as "log"). So, even if the code in the initial example were to successfully compile, it would be broken at link-time/runtime, because your global variable symbol "log" would conflict with the C library's global function symbol "log". Nothing good can come of that. |
The discussion was on the LWG reflector. The relevant part in the Standard is [extern.names]/4
So basically the program below is not conforming:
I expect this to work properly in practice, but it's not conforming. Which GCC is happy to tell you. I hope that makes it clear to you @rnikander . |
Oh, fine enough. So we can see modules help clang to implement this check : ) |
This code fails to compile. Shouldn't it work?
I notice this because I'm always trying to declare these file-local
log
objects (writing messages to a file, not the mathematical function) and I hit this conflict.The text was updated successfully, but these errors were encountered: