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

Multiple variable definition with Clang 9 #158

Closed
Dwarfobserver opened this issue Oct 15, 2019 · 11 comments
Closed

Multiple variable definition with Clang 9 #158

Dwarfobserver opened this issue Oct 15, 2019 · 11 comments
Labels
Milestone

Comments

@Dwarfobserver
Copy link

When compiling with Clang 9, I got

multiple definition of `cppsort::detail::iterator_category_value<std::__1::input_iterator_tag>'
multiple definition of `cppsort::detail::iterator_category_value<std::__1::forward_iterator_tag>'
multiple definition of `cppsort::detail::iterator_category_value<std::__1::bidirectional_iterator_tag>'
multiple definition of `cppsort::detail::iterator_category_value<std::__1::random_access_iterator_tag>'

because it seems that Clang 9 does not treat template specializations of constexpr variables inline anymore. Because the library is in C++14, the specializations cannot be marked inline so I think they should be static instead.

@Morwenn Morwenn added the bug label Oct 15, 2019
@Morwenn
Copy link
Owner

Morwenn commented Oct 15, 2019

Thanks for the report!

I thought that this variable template wasn't ODR-used since it is only used as a non-type template parameter, but apparently I'm still unable to predict ODR issues. I guess that I will do as you say and make it static in C++14, and inline when the C++17 support is sufficient.

@Morwenn
Copy link
Owner

Morwenn commented Oct 15, 2019

I can also remove the std::input_iterator_tag spacialisation now that I think of it, since it doesn't make sense for a sorter to handle input iterators.

@Dwarfobserver
Copy link
Author

Dwarfobserver commented Oct 15, 2019

You're welcome :)

Mmmh, it seems Clang allows to do a declaration of the specialized variable, and so always generates it (when not inlined): https://godbolt.org/z/NfvWzn

@Morwenn
Copy link
Owner

Morwenn commented Oct 15, 2019

Interestingly enough GCC allows to forward-declare the variable template as constexpr - which I thought would be forbidden - but not Clang. I keep getting surprised by all the details ^^'

@Dwarfobserver
Copy link
Author

Haha yes, me too !

I didn't succeed with template <class T> extern constexpr int i; 🤔
Did you write template <class T> constexpr int i; ? This one defines the variable like for int i; (C syntax 🤢).

@Morwenn
Copy link
Owner

Morwenn commented Oct 15, 2019

I did try that, haha.

Apparently both compilers allow inline or __inline variables as an extension in C++14 mode, but there is no way to detect that since __cpp_inline_variables is only defined in C++17 mode. I guess that I will just put them in an anonymous namespace for cpp-sort 1.x and properly use inline variables in the 2.x branch instead of trying to work around it; I have bigger issues than a few additional symbols in the binary.

@Dwarfobserver
Copy link
Author

Yup, I think it's the best way to do it, and static variables have good chances to be optimized away anyway. I didn't know about the inline extension.

Morwenn added a commit that referenced this issue Oct 15, 2019
Also remove the specialization for std::input_iterator_tag since it
doesn't make sense to call in-place sorting algorithms on input
iterators. This notably allows to reduce the index of the other
specializations.
@Morwenn
Copy link
Owner

Morwenn commented Oct 15, 2019

The tests passed but I can't really test the fix with Clang 9 since it's not on Travis AFAIK. I'll close the issue for now, don't hesitate to reopen if needed :)

@Morwenn Morwenn closed this as completed Oct 15, 2019
@Morwenn Morwenn added this to the 1.6.0 milestone Oct 15, 2019
@Morwenn
Copy link
Owner

Morwenn commented Oct 16, 2019

I just found the recent CWG2433 (the link is probably not available yet) which says:

The list of entities in 6.2 [basic.def.odr] paragraph 12 that can have multiple definitions across translation units does not, but should, include variable templates.

Apparently this DR is tentatively ready for the next meeting, and it looks like it directly concerns our issue here.

@Dwarfobserver
Copy link
Author

Nice ! I don't have access to the link but it should correct this issue indeed :)

Morwenn added a commit that referenced this issue Nov 13, 2019
Also remove the specialization for std::input_iterator_tag since it
doesn't make sense to call in-place sorting algorithms on input
iterators. This notably allows to reduce the index of the other
specializations.
Morwenn added a commit that referenced this issue Aug 19, 2022
While there haven't been lots of ODR issues so far with namespace-scope
constexpr variables (#158 being the exceptions), I would rather be safe
than sorry. This commit either puts constexpr variables in functions or
marks them inline to avoid ODR issues.

While variable templates are supposed to be inline as per CWG2433, GCC
and Clang document the DR support status as "unknown", so I decided to
be conservative and to mark constexpr variable templates inline too.
@Morwenn
Copy link
Owner

Morwenn commented Aug 19, 2022

I gave this issue another look for the C++20 branch of the project, but it seems that the status of CWG2433 support is still unknown/undocumented:

As a result I decided to be conservative and to mark all namespace-scope constexpr variables inline in the library, even the variable templates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants