Bug 19809 - [4.0/4.1 Regression] Multiple definitions of friend functions in template classes
Summary: [4.0/4.1 Regression] Multiple definitions of friend functions in template cla...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.1.2
Assignee: Jason Merrill
URL:
Keywords: accepts-invalid
: 33150 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-02-07 18:13 UTC by Stefan Straßer
Modified: 2007-08-22 19:06 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 3.3.4 4.2.0
Known to fail: 3.4.4 4.0.0
Last reconfirmed: 2006-09-05 23:26:57


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan Straßer 2005-02-07 18:13:29 UTC
This report is based on <16899453.0502060835.6c893401@posting.google.com>

given this testcase:

#include <iostream>
template<int i>
struct n{
  friend void foo(){
    std::cerr << i << std::endl;;
  }
};

int main(){
  n<1> n1;
  n<2> n2;
  n<3> n3;
  foo();
}

there must be a bug here, though I'm not sure what exactly it is.

a) it could be a multiple definition of foo, which is reported by version 3.3.4,
but not by 4.0.0 and 3.4.3.

b) std note 14.5.3.3 could mean that it's not a multiple definition:

<<<3 When a function is defined in a friend function declaration in a class
template, the function is defined when the class template is first instantiated.
The function is defined even if it is never used.>>>

so if it's _only_ defined on the first instantiation this is not a multiple
definition - but then I don't think it is legal to use the template arguments of
struct n in the function definition

c) even if b) is wrong and usage of template arguments is allowed, there's still
a bug, because the result of the testcase above is "3", so the _last_
instantiation is used.


comeau C++ chooses a), so does 3.3.4.
Comment 1 Giovanni Bajo 2005-02-07 19:46:46 UTC
My understanding is that this should create one definition *per* instantiation 
so there is an ODR conflict if the signatures match. Notice that it is still 
useful to do something as:

template <class T>
struct A {
   friend void foo(A<T> t) { .... }
};

template class A<int>;
template class A<float>;

thus different overloads are injected into the global namespace.

Now, the standard says that we are not forced to detect ODR violations. On the 
other hand, we used to do so for this case, so I qualify this as a QoI 
regression.

CC'ing Kriang as he surely knows if this is fixable in the 4.0 timeframe.
Comment 2 Andrew Pinski 2005-02-16 15:02:36 UTC
: Search converges between 2004-02-01-trunk (#445) and 2004-03-01-trunk (#446).
: Search converges between 2004-03-01-3.4 (#2) and 2004-03-15-3.4 (#3).
Comment 3 Andrew Pinski 2005-07-22 21:13:27 UTC
Moving to 4.0.2 pre Mark.
Comment 4 Andrew Pinski 2005-10-13 21:00:08 UTC
I should note that foo is not declared anywhere so you cannot get access to it in main.
Comment 5 Mark Mitchell 2005-10-31 02:35:27 UTC
Leaving as P2; we should indeed try to fix this.

(I suspect we're not noticing the conflicts because we're correctly no longer trying to inject the functions into namespace scope.)
Comment 6 Mark Mitchell 2006-02-24 00:25:38 UTC
This issue will not be resolved in GCC 4.1.0; retargeted at GCC 4.1.1.
Comment 7 Mark Mitchell 2006-05-25 02:32:31 UTC
Will not be fixed in 4.1.1; adjust target milestone to 4.1.2.
Comment 8 Jason Merrill 2006-09-05 23:26:57 UTC
I'm not sure this is actually a bug.
Comment 9 Jason Merrill 2006-09-05 23:27:31 UTC
Actually, I am, didn't mean to add that comment.
Comment 10 Jason Merrill 2006-09-06 01:15:19 UTC
Subject: Bug 19809

Author: jason
Date: Wed Sep  6 01:15:09 2006
New Revision: 116709

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116709
Log:
        PR c++/26102
        * name-lookup.c (do_class_using_decl): Try to find the base even
        if bases_dependent_p.
        * pt.c (type_dependent_expression_p): A USING_DECL is dependent.

        PR c++/19809
        * pt.c (tsubst_friend_function): Set DECL_INITIAL before pushdecl.

Added:
    trunk/gcc/testsuite/g++.dg/template/friend47.C
    trunk/gcc/testsuite/g++.dg/template/using14.C
Modified:
    trunk/gcc/cp/name-lookup.c
    trunk/gcc/cp/pt.c

Comment 11 Jason Merrill 2006-09-06 01:15:47 UTC
Subject: Bug 19809

Author: jason
Date: Wed Sep  6 01:15:39 2006
New Revision: 116710

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116710
Log:
        PR c++/26102
        * name-lookup.c (do_class_using_decl): Try to find the base even
        if bases_dependent_p.
        * pt.c (type_dependent_expression_p): A USING_DECL is dependent.

        PR c++/19809
        * pt.c (tsubst_friend_function): Set DECL_INITIAL before pushdecl.

Modified:
    trunk/gcc/cp/ChangeLog

Comment 12 Jason Merrill 2006-09-07 22:27:26 UTC
Subject: Bug 19809

Author: jason
Date: Thu Sep  7 22:27:01 2006
New Revision: 116763

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116763
Log:
        PR c++/26195
        * decl.c (make_rtl_for_nonlocal_decl),
        (start_preparsed_function): Don't use lbasename on
        input_filename when calling get_fileinfo.
        * semantics.c (begin_class_definition): Likewise.
        * lex.c (cxx_make_type): Likewise.
        (handle_pragma_interface): Call get_fileinfo on input_filename,
        not on the parameter to the directive.

        PR c++/26696
        * cvt.c (convert_to_void): Replace a subexpression with no side
        effects with void_zero_node.
        * tree.c (is_overloaded_fn): Look through COMPONENT_REF.
        (get_first_fn): Ditto.
        * decl.c (grokdeclarator): No need to look through COMPONENT_REF.

        PR c++/26571
        * parser.c (cp_parser_diagnose_invalid_type_name): Handle the case
        where the name is a type used incorrectly.

        PR c++/26671
        * typeck.c (maybe_warn_about_returning_address_of_local): Look
        through COMPONENT_REF and ARRAY_REF.

        PR c++/26102
        * name-lookup.c (do_class_using_decl): Try to find the base even
        if bases_dependent_p.
        * pt.c (type_dependent_expression_p): A USING_DECL is dependent.

        PR c++/19809
        * pt.c (tsubst_friend_function): Set DECL_INITIAL before pushdecl.

Modified:
    branches/gcc-4_1-branch/gcc/cp/ChangeLog
    branches/gcc-4_1-branch/gcc/cp/cvt.c
    branches/gcc-4_1-branch/gcc/cp/decl.c
    branches/gcc-4_1-branch/gcc/cp/lex.c
    branches/gcc-4_1-branch/gcc/cp/name-lookup.c
    branches/gcc-4_1-branch/gcc/cp/parser.c
    branches/gcc-4_1-branch/gcc/cp/pt.c
    branches/gcc-4_1-branch/gcc/cp/semantics.c
    branches/gcc-4_1-branch/gcc/cp/tree.c
    branches/gcc-4_1-branch/gcc/cp/typeck.c

Comment 13 Jason Merrill 2006-09-07 22:38:21 UTC
Subject: Bug 19809

Author: jason
Date: Thu Sep  7 22:38:03 2006
New Revision: 116764

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116764
Log:
        PR c++/26195
        * decl.c (make_rtl_for_nonlocal_decl),
        (start_preparsed_function): Don't use lbasename on
        input_filename when calling get_fileinfo.
        * semantics.c (begin_class_definition): Likewise.
        * lex.c (cxx_make_type): Likewise.
        (handle_pragma_interface): Call get_fileinfo on input_filename,
        not on the parameter to the directive.

        PR c++/26696
        * cvt.c (convert_to_void): Replace a subexpression with no side
        effects with void_zero_node.
        * tree.c (is_overloaded_fn): Look through COMPONENT_REF.
        (get_first_fn): Ditto.
        * decl.c (grokdeclarator): No need to look through COMPONENT_REF.

        PR c++/26571
        * parser.c (cp_parser_diagnose_invalid_type_name): Handle the case
        where the name is a type used incorrectly.

        PR c++/26671
        * typeck.c (maybe_warn_about_returning_address_of_local): Look
        through COMPONENT_REF and ARRAY_REF.

        PR c++/19809
        * pt.c (tsubst_friend_function): Set DECL_INITIAL before pushdecl.

Modified:
    branches/gcc-4_0-branch/gcc/cp/ChangeLog
    branches/gcc-4_0-branch/gcc/cp/cvt.c
    branches/gcc-4_0-branch/gcc/cp/decl.c
    branches/gcc-4_0-branch/gcc/cp/lex.c
    branches/gcc-4_0-branch/gcc/cp/parser.c
    branches/gcc-4_0-branch/gcc/cp/pt.c
    branches/gcc-4_0-branch/gcc/cp/semantics.c
    branches/gcc-4_0-branch/gcc/cp/tree.c
    branches/gcc-4_0-branch/gcc/cp/typeck.c

Comment 14 Jason Merrill 2006-09-07 23:03:31 UTC
fixed
Comment 15 Andrew Pinski 2007-08-22 19:06:10 UTC
*** Bug 33150 has been marked as a duplicate of this bug. ***