Bug 70413 - Class template names in anonymous namespaces are not globally unique
Summary: Class template names in anonymous namespaces are not globally unique
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.3.0
: P3 normal
Target Milestone: 14.0
Assignee: Patrick Palka
URL:
Keywords: ABI, wrong-code
: 101695 111423 (view as bug list)
Depends on:
Blocks:
 
Reported: 2016-03-25 18:42 UTC by Fabian Knorr
Modified: 2023-12-21 18:58 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 5.4.0, 6.2.0, 7.0, 8.2.1
Last reconfirmed: 2021-08-06 00:00:00


Attachments
Example Source Code (372 bytes, application/gzip)
2016-03-25 18:42 UTC, Fabian Knorr
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Fabian Knorr 2016-03-25 18:42:00 UTC
Created attachment 38099 [details]
Example Source Code

If a class template is defined twice with the same name inside of anonymous namespaces in different translation units and then used as a template template parameter, the two templates are not treated as having globally unique names.

Example:

invoke.hh:
    #include <iostream>
    void invoke_foo(), invoke_bar();

    template<template<int> class T>
    void invoke_print() {
        T<0>{}.print();
    }

foo.cc:
    #include "invoke.hh"
    namespace {
        template<int> struct s {
            void print() { std::cout << "foo\n"; }
        };
    }    
    void invoke_foo() { invoke_print<s>(); }

bar.cc:
    #include "invoke.hh"
    namespace {
        template<int> struct s {
            void print() { std::cout << "bar\n"; }
        };
    }    
    void invoke_bar() { invoke_print<s>(); }

main.cc:
    #include "invoke.hh"
    int main() {
        invoke_foo();
        invoke_bar();
    }

Compile with
    g++ -obug main.cc foo.cc bar.cc -std=c++11

Expected output:
    foo
    bar

Actual output:
    foo
    foo

Tested with GCC 5.3.0 on x86_64. Clang 3.7.1 gets this right.
The source files are attached.
Comment 1 ethortsen 2017-04-05 19:54:35 UTC
Bumping this.

We ran into a similar issue in GCC 6.3.0 on x86_64.

We've ran the example provided by Fabian under GCC 6.3.0 on x86_64 and see the same unexpected result.
Comment 2 Markus Trippelsdorf 2017-04-05 20:44:09 UTC
Confirmed.

The problem is that _Z12invoke_printIN12_GLOBAL__N_11sEEvv is wrongly marked as comdat.
Comment 3 Markus Trippelsdorf 2017-04-06 06:36:33 UTC
This gets wrongly set here:

decl2.c:

2912   else if (DECL_TEMPLOID_INSTANTIATION (decl))                                                                                                                                
2913     {                                                                                                                                                                         
2914       /* DECL is an implicit instantiation of a function or static                                                                                                            
2915          data member.  */                                                                                                                                                     
2916       if ((flag_implicit_templates                                                                                                                                            
2917            && !flag_use_repository)                                                                                                                                           
2918           || (flag_implicit_inline_templates                                                                                                                                  
2919               && TREE_CODE (decl) == FUNCTION_DECL                                                                                                                            
2920               && DECL_DECLARED_INLINE_P (decl)))                                                                                                                              
2921         comdat_p = true;                                                                                                                                                      
2922       else 

But for instantiations with types defined in anon namespace this is wrong
and  "TREE_PUBLIC (decl) = 0" should be used instead.
Comment 4 Jeffrey Walton 2019-07-24 02:54:32 UTC
Bumping this.

We ran into a similar issue in GCC 6.3.0 on ARM with -flto. openSUSE enabled LTO by default, so we added a test case for all platforms which support LTO (including Debian with its stale packages that never get updated).
Comment 5 Jonathan Wakely 2021-08-06 10:32:07 UTC
*** Bug 101695 has been marked as a duplicate of this bug. ***
Comment 6 Andrew Pinski 2022-12-29 03:07:41 UTC
*** Bug 107906 has been marked as a duplicate of this bug. ***
Comment 7 Patrick Palka 2023-09-15 14:17:48 UTC
*** Bug 111423 has been marked as a duplicate of this bug. ***
Comment 8 GCC Commits 2023-12-21 18:53:51 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:7226f825db049517b64442a40a6387513febb8f9

commit r14-6789-g7226f825db049517b64442a40a6387513febb8f9
Author: Patrick Palka <ppalka@redhat.com>
Date:   Thu Dec 21 13:53:43 2023 -0500

    c++: visibility wrt template and ptrmem targs [PR70413]
    
    When constraining the visibility of an instantiation, we weren't
    properly considering the visibility of PTRMEM_CST and TEMPLATE_DECL
    template arguments.
    
    This patch fixes this.  It turns out we don't maintain the relevant
    visibility flags for alias templates (e.g. TREE_PUBLIC is never set),
    so continue to ignore alias template template arguments for now.
    
            PR c++/70413
            PR c++/107906
    
    gcc/cp/ChangeLog:
    
            * decl2.cc (min_vis_expr_r): Handle PTRMEM_CST and TEMPLATE_DECL
            other than those for alias templates.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/template/linkage2.C: New test.
            * g++.dg/template/linkage3.C: New test.
            * g++.dg/template/linkage4.C: New test.
            * g++.dg/template/linkage4a.C: New test.
Comment 9 Patrick Palka 2023-12-21 18:58:09 UTC
Fixed for GCC 14 (other than the alias template template argument case which PR107906 tracks).