www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Should an 'extern(C++, "ns"):' override previous ones in the same

reply Max Samukha <maxsamukha gmail.com> writes:
extern(C++, "ns1"):
extern(C++, "ns2"): // Not in nested scope. Should it supersede?
void foo();

pragma(msg, foo.mangleof); // _ZN3ns13ns23fooEv instead of 
expected _ZN3ns23fooEv

Is that by design?
Sep 07 2019
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, September 7, 2019 9:15:44 AM MDT Max Samukha via Digitalmars-d-
learn wrote:
 extern(C++, "ns1"):
 extern(C++, "ns2"): // Not in nested scope. Should it supersede?
 void foo();

 pragma(msg, foo.mangleof); // _ZN3ns13ns23fooEv instead of
 expected _ZN3ns23fooEv

 Is that by design?
If you have safe: system: then system overrides safe. And you can't have a C++ symbol that lives in multiple namespaces. So, I would consider it a bug if your example doesn't put foo in the namespace ns2, overriding ns1. IMHO, overriding is the only behavior that makes sense, and anything else would be inconsistent with how other, incompatible attributes are applied. Certainly, treating extern(C++, "ns1"): extern(C++, "ns2"): as equivalent to extern(C++, "ns1::ns2"): makes no sense whatsoever IMHO. IIRC, this version of extern(C++) didn't go through the DIP process and was simply added via a PR. So, it wouldn't surprise me if the person who implemented it didn't even think about the extern(C++, "ns1"): extern(C++, "ns2"): case and didn't test for it properly. - Jonathan M Davis
Sep 07 2019
next sibling parent Exil <Exil gmall.com> writes:
On Saturday, 7 September 2019 at 17:22:07 UTC, Jonathan M Davis 
wrote:
 makes no sense whatsoever IMHO. IIRC, this version of 
 extern(C++) didn't go through the DIP process and was simply 
 added via a PR.
The original extern(C++) worked the same way. Since it was implemented in v2.066.0 by the looks of it. IIRC the only thing the PR did was basically remove the code that added new objects. So it's to be expected they behave the same way. https://run.dlang.io/is/v1vFeZ extern(C++, ns1): extern(C++, ns2): void foo(); pragma(msg, foo.mangleof); void main() { } Since 2.066.0: Success with output: _ZN3ns13ns23fooEv
Sep 07 2019
prev sibling parent reply Exil <Exil gmall.com> writes:
On Saturday, 7 September 2019 at 17:22:07 UTC, Jonathan M Davis 
wrote:
  safe:
  system:

 then  system overrides  safe.
Just to add onto this, you can't do: safe system void foo(); // error but you can do: extern(C++, ns1) extern(C++, ns2) void foo(); // ok
Sep 07 2019
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Saturday, September 7, 2019 3:40:58 PM MDT Exil via Digitalmars-d-learn 
wrote:
 On Saturday, 7 September 2019 at 17:22:07 UTC, Jonathan M Davis

 wrote:
  safe:
  system:

 then  system overrides  safe.
Just to add onto this, you can't do: safe system void foo(); // error but you can do: extern(C++, ns1) extern(C++, ns2) void foo(); // ok
It makes no sense to apply multiple namespaces to the same symbol. I expect that this behavior is due to a lack of testing (the same with the out of order weirdness in the other post). It's the sort of thing that you test when you're trying to make sure that the feature does the right thing when people use it incorrectly, not the sort of thing when you're trying to make sure that the feature works as intended, so it's easy to forget. My guess is that this behavior leaked its way in due to the fact that you need to be able to put multiple extern(C++) declarations on a symbol when you use extern(C++, struct) or extern(C++, class) in addition to the extern(C++) for the namespace. - Jonathan M Davis
Sep 07 2019
next sibling parent reply Max Samukha <maxsamukha gmail.com> writes:
On Saturday, 7 September 2019 at 22:19:48 UTC, Jonathan M Davis 
wrote:
 On Saturday, September 7, 2019 3:40:58 PM MDT Exil via 
 Digitalmars-d-learn wrote:
 On Saturday, 7 September 2019 at 17:22:07 UTC, Jonathan M Davis

 wrote:
  safe:
  system:

 then  system overrides  safe.
Just to add onto this, you can't do: safe system void foo(); // error but you can do: extern(C++, ns1) extern(C++, ns2) void foo(); // ok
It makes no sense to apply multiple namespaces to the same symbol. I expect that this behavior is due to a lack of testing (the same with the out of order weirdness in the other post). It's the sort of thing that you test when you're trying to make sure that the feature does the right thing when people use it incorrectly, not the sort of thing when you're trying to make sure that the feature works as intended, so it's easy to forget. My guess is that this behavior leaked its way in due to the fact that you need to be able to put multiple extern(C++) declarations on a symbol when you use extern(C++, struct) or extern(C++, class) in addition to the extern(C++) for the namespace. - Jonathan M Davis
I wonder how that undocumented and not well thought-through (or having some unobvious justifications) feature made it into a stable release. Anyway, thank you for your help. I will probably file a bug report when I have time.
Sep 08 2019
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, September 8, 2019 3:03:31 AM MDT Max Samukha via Digitalmars-d-
learn wrote:
 On Saturday, 7 September 2019 at 22:19:48 UTC, Jonathan M Davis

 wrote:
 On Saturday, September 7, 2019 3:40:58 PM MDT Exil via

 Digitalmars-d-learn wrote:
 On Saturday, 7 September 2019 at 17:22:07 UTC, Jonathan M Davis

 wrote:
  safe:
  system:

 then  system overrides  safe.
Just to add onto this, you can't do: safe system void foo(); // error but you can do: extern(C++, ns1) extern(C++, ns2) void foo(); // ok
It makes no sense to apply multiple namespaces to the same symbol. I expect that this behavior is due to a lack of testing (the same with the out of order weirdness in the other post). It's the sort of thing that you test when you're trying to make sure that the feature does the right thing when people use it incorrectly, not the sort of thing when you're trying to make sure that the feature works as intended, so it's easy to forget. My guess is that this behavior leaked its way in due to the fact that you need to be able to put multiple extern(C++) declarations on a symbol when you use extern(C++, struct) or extern(C++, class) in addition to the extern(C++) for the namespace. - Jonathan M Davis
I wonder how that undocumented and not well thought-through (or having some unobvious justifications) feature made it into a stable release. Anyway, thank you for your help. I will probably file a bug report when I have time.
The C++ support has been improved kind of piecemeal over time, and initially, none of it was documented. So, it wasn't exactly fully planned out when it was added. IIRC, it was added originally so that the dmd frontend could be moved to D. The DIP process was very different at that point, and it was much more common then for Walter or one of the other core developers to just propose a feature in a PR and get it merged. I expect that the oddities in the implementation stem from stuff that whoever implemented it didn't think to try. The whole process is much more rigorous now than it used to be. - Jonathan M Davis
Sep 08 2019
parent Max Samukha <maxsamukha gmail.com> writes:
On Sunday, 8 September 2019 at 09:35:03 UTC, Jonathan M Davis 
wrote:

 The C++ support has been improved kind of piecemeal over time, 
 and initially, none of it was documented. So, it wasn't exactly 
 fully planned out when it was added. IIRC, it was added 
 originally so that the dmd frontend could be moved to D. The 
 DIP process was very different at that point, and it was much 
 more common then for Walter or one of the other core developers 
 to just propose a feature in a PR and get it merged. I expect 
 that the oddities in the implementation stem from stuff that 
 whoever implemented it didn't think to try. The whole process 
 is much more rigorous now than it used to be.

 - Jonathan M Davis
Good to know, thank you.
Sep 08 2019
prev sibling parent reply Exil <Exil gmall.com> writes:
On Saturday, 7 September 2019 at 22:19:48 UTC, Jonathan M Davis 
wrote:
 On Saturday, September 7, 2019 3:40:58 PM MDT Exil via 
 Digitalmars-d-learn wrote:
 On Saturday, 7 September 2019 at 17:22:07 UTC, Jonathan M Davis

 wrote:
  safe:
  system:

 then  system overrides  safe.
Just to add onto this, you can't do: safe system void foo(); // error but you can do: extern(C++, ns1) extern(C++, ns2) void foo(); // ok
It makes no sense to apply multiple namespaces to the same symbol. I expect that this behavior is due to a lack of testing (the same with the out of order weirdness in the other post). It's the sort of thing that you test when you're trying to make sure that the feature does the right thing when people use it incorrectly, not the sort of thing when you're trying to make sure that the feature works as intended, so it's easy to forget. My guess is that this behavior leaked its way in due to the fact that you need to be able to put multiple extern(C++) declarations on a symbol when you use extern(C++, struct) or extern(C++, class) in addition to the extern(C++) for the namespace. - Jonathan M Davis
You don't need to make guesses or assumptions. It most definitely was intentional. https://github.com/dlang/dmd/commit/4b2578e208f2af9a02159fc2d8d87fb17b09005e#diff-62dcb5f0ffc3089b7565897d8beb3322R617 By the looks of it, this feature was also implemented before extern(C++, struct/class).
Sep 08 2019
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Sunday, September 8, 2019 12:12:53 PM MDT Exil via Digitalmars-d-learn 
wrote:
 On Saturday, 7 September 2019 at 22:19:48 UTC, Jonathan M Davis

 wrote:
 On Saturday, September 7, 2019 3:40:58 PM MDT Exil via

 Digitalmars-d-learn wrote:
 On Saturday, 7 September 2019 at 17:22:07 UTC, Jonathan M Davis

 wrote:
  safe:
  system:

 then  system overrides  safe.
Just to add onto this, you can't do: safe system void foo(); // error but you can do: extern(C++, ns1) extern(C++, ns2) void foo(); // ok
It makes no sense to apply multiple namespaces to the same symbol. I expect that this behavior is due to a lack of testing (the same with the out of order weirdness in the other post). It's the sort of thing that you test when you're trying to make sure that the feature does the right thing when people use it incorrectly, not the sort of thing when you're trying to make sure that the feature works as intended, so it's easy to forget. My guess is that this behavior leaked its way in due to the fact that you need to be able to put multiple extern(C++) declarations on a symbol when you use extern(C++, struct) or extern(C++, class) in addition to the extern(C++) for the namespace. - Jonathan M Davis
You don't need to make guesses or assumptions. It most definitely was intentional. https://github.com/dlang/dmd/commit/4b2578e208f2af9a02159fc2d8d87fb17b0900 5e#diff-62dcb5f0ffc3089b7565897d8beb3322R617 By the looks of it, this feature was also implemented before extern(C++, struct/class).
Well, it's inconsistent with the rest of the language and bad design IMHO. And even if it were desirable behavior, it clearly becomes a mess with the ordering once the attributes are no longer directly on the symbol. Of course, ideally, the whole extern(C++) feature with identifiers instead of strings for the namespace would be deprecated anyway. - Jonathan M Davis
Sep 08 2019