On Saturday, September 7, 2019 2:18:40 PM MDT Jonathan M Davis via Digitalmars-d-learn wrote: > On Saturday, September 7, 2019 8:53:54 AM MDT Max Samukha via > Digitalmars-d- > learn wrote: > > extern(C++, "ns1") { > > > > extern(C++, ns2) { > > > > extern(C++, "ns3") { > > > > extern(C++, ns4) { > > > > void foo(); > > > > } > > > > } > > > > } > > > > } > > > > pragma(msg, foo.mangleof); // _ZN3ns23ns43ns13ns33fooEv > > > > That produces 'ns2::ns4::ns1::ns3::foo' path instead of the > > intuitively expected 'ns1::ns2::ns3::ns4::foo'. The identifier > > namespaces are grouped before the string ones. Bug or feature? > > Given that the string version of extern(C++) is supposed to only affect > mangling, whereas the other version does some other weird stuff, I'm not > sure that you can really expect something sane if you try to mix them. > That being said, unless the language disallows mixing them, the compiler > should be doing something at least semi-sane. Either way, I don't see how > having the result be anything other than ns1:ns2:ns3:ns4 is defensible. > The type of weirdness that I would expect would resolve around the kind > of issues that led to the string version being added in the first place > (e.g. having to put the entire namespace in a single module). I'd suggest > that you report it as a bug. It wouldn't surprise me if dmd doesn't even > have any tests that try to mix the two types of extern(C++), since that > really wasn't an intended use case. If anything, I expect that the hope > was that the non-string version would eventually be deprecated, though I > wouldn't bet on that actually happening.
Actually, thinking on this further, I would have thought that only the extern(C++, ns4) would be applied. No other D attributes have any kind of nesting. Applying incompatible attributes either results in one overriding the other or in an error (usually, one overrides the other when attributes are mass-applied, whereas you get an error if you put them directly on the symbol). If we allow nesting like this with extern(C++), then I would expect that the nesting would work in the same order as you'd get in C++, which would be ns1:ns2:ns3:ns4 in this case, but I would have expected that you'd have to apply the entire namespace in one go rather than have multiple extern(C++) declarations - e.g. extern(C++, "ns1:ns2:ns3:ns4") or extern(C++, ns1, ns2, ns3, ns4) for the non-string version IIRC (I've avoided the non-string extern(C++) like the plague though, since it makes no sense, and fortunately, most of the C++ that I've interacted with from D has not had namespaces). In any case, I would consider the current behavior to be nonsensical, and I have a hard time believing that it's on purpose. With that example, I would expect that you'd either get only ns4 applied or that you'd get ns1:ns2:ns3:ns4. Getting only ns4 would be consistent with the rest of D, whereas ns1:ns2:ns3:ns4 would be more consistent with what someone would expect if they were coming from C++ and translating the C++ declarations to D declarations directly. - Jonathan M Davis