Bug 109126 (cwg2387) - [DR2387] Linkage of const-qualified variable template
Summary: [DR2387] Linkage of const-qualified variable template
Status: RESOLVED FIXED
Alias: cwg2387
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 13.0
: P3 normal
Target Milestone: ---
Assignee: Jakub Jelinek
URL:
Keywords: wrong-code
: 116077 (view as bug list)
Depends on:
Blocks: c++-core-issues
  Show dependency treegraph
 
Reported: 2023-03-14 10:27 UTC by Jonathan Wakely
Modified: 2024-09-20 20:00 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2024-07-24 00:00:00


Attachments
gcc15-pr109126.patch (798 bytes, patch)
2024-08-07 10:20 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2023-03-14 10:27:49 UTC
Variable templates with const-qualified types should not default to internal linkage.

https://cplusplus.github.io/CWG/issues/2387.html
Comment 1 Andrew Pinski 2024-07-24 17:43:40 UTC
*** Bug 116077 has been marked as a duplicate of this bug. ***
Comment 2 Andrew Pinski 2024-07-24 17:43:58 UTC
.
Comment 3 Jakub Jelinek 2024-08-07 10:20:48 UTC
Created attachment 58858 [details]
gcc15-pr109126.patch

Untested implementation.
Comment 4 GCC Commits 2024-08-07 17:08:59 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:82cd63a63eaa61a4ed5c4029a1869be7446ecb3c

commit r15-2798-g82cd63a63eaa61a4ed5c4029a1869be7446ecb3c
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Aug 7 19:08:07 2024 +0200

    c++: Implement CWG2387 - Linkage of const-qualified variable template [PR109126]
    
    The following patch attempts to implement DR2387 by making variable
    templates including their specialization TREE_PUBLIC when at file
    scope and they don't have static storage class.
    
    2024-08-07  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/109126
            * decl.cc (grokvardecl): Implement CWG 2387 - Linkage of
            const-qualified variable template.  Set TREE_PUBLIC on variable
            templates with const qualified types unless static is present.
    
            * g++.dg/DRs/dr2387.C: New test.
            * g++.dg/DRs/dr2387-aux.cc: New file.
Comment 5 Jakub Jelinek 2024-08-07 17:12:05 UTC
Implemented for 15.1+.
Comment 6 Jonathan Wakely 2024-09-20 19:31:44 UTC
It looks like explicit specializations are not given vague linkage. Is that the correct behaviour?

/usr/bin/ld: /tmp/ccjbP7xI.o:/tmp/t.h:2: multiple definition of `var<int>'; /tmp/ccMCRAVO.o:/tmp/t.h:2: first defined here


Given these two TUs:

template<typename T> constexpr bool var = true;
template<> constexpr bool var<int> = false;
bool foo();
int main() { return var<int> != foo(); }

template<typename T> constexpr bool var = true;
template<> constexpr bool var<int> = false;
bool foo() { return var<int>; }


It works if I add 'inline' to the explicit specialization.
Comment 7 Andrew Pinski 2024-09-20 19:34:02 UTC
(In reply to Jonathan Wakely from comment #6)
> It looks like explicit specializations are not given vague linkage. Is that
> the correct behaviour?

I wonder if that is related to PR 116746 .
Comment 8 Jakub Jelinek 2024-09-20 19:42:51 UTC
Is there a reason why this should be treated any differently from non-const variable templates and their explicit specializations?
If I try
template<typename T> bool var = true;
template<> bool var<int> = false;
bool *p = &var<char>;
with older clang++, older g++ or older ICC, all those have comdat _Z3varIcE and non-comdat global non-weak _Z3varIiE.
So the DR just turns the same for const/constexpr variable templates and their specializations too.
Comment 9 Jakub Jelinek 2024-09-20 19:45:01 UTC
(In reply to Jonathan Wakely from comment #6)
> It works if I add 'inline' to the explicit specialization.

Or static.  inline will only work for C++17, while variable templates are in C++14 already.  And the DR applies to all.
Comment 10 Jonathan Wakely 2024-09-20 19:47:11 UTC
(In reply to Jakub Jelinek from comment #8)
> So the DR just turns the same for const/constexpr variable templates and
> their specializations too.

Yeah, I guess it's consistent.
Comment 11 Jakub Jelinek 2024-09-20 19:48:18 UTC
And
template <int N> int foo (void) { return N; }
template <> int foo <42> (void) { return -42; }
int a = foo<15> ();
int b = foo<42> ();
works the same, _Z3fooILi15EEiv is comdat exported weak, _Z3fooILi42EEiv is non-weak global non-comdat.
Comment 12 Jonathan Wakely 2024-09-20 20:00:08 UTC
Yes but for the function template case if I want to use it in constexpr I add 'constexpr' and it's implicitly inline. For the variable template specialisation it's already constexpr, and I can't define it non-inline in another TU because it needs to be in a header to use in other constexpr functions.

So it has to be inline (or static, which can cause odr violations in headers).

But this seems like a language problem not a gcc one.