public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/49609] New: No code emitted for address-taken instances of function templates
@ 2011-07-01 15:48 srk31 at srcf dot ucam.org
  2011-07-01 16:20 ` [Bug c++/49609] " redi at gcc dot gnu.org
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: srk31 at srcf dot ucam.org @ 2011-07-01 15:48 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

           Summary: No code emitted for address-taken instances of
                    function templates
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: srk31@srcf.ucam.org


In the following code

template <typename From, typename To>
inline
void *
value_convert_function(From *from, To *to)
{
    return 0;
}

void *(*my_table[])(void *, void *) = {
    reinterpret_cast<void*(*)(void*,void*)>(&(value_convert_function<double,
double>)),
    0
};    

void *(*my_function_ptr)(void*, void *)
 = reinterpret_cast<void*(*)(void*,void*)>(&(value_convert_function<float,
float>));

void *(*my_uncast_function_ptr)(bool *, bool *)
 = &(value_convert_function<bool, bool>);


... I expect to see code output for each of the three template instances that I
take the address of. But only the last one is actually generated. 

$ objdump -t test.o | c++filt

test.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test.cc
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .text._Z22value_convert_functionIbbEPvPT_PT0_ 
0000000000000000 .text._Z22value_convert_functionIbbEPvPT_PT0_
0000000000000000 l    d  .note.GNU-stack        0000000000000000
.note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000 l    d  .group 0000000000000000 .group
0000000000000000 g     O .data  0000000000000010 my_table
0000000000000000         *UND*  0000000000000000 void*
value_convert_function<double, double>(double*, double*)
0000000000000010 g     O .data  0000000000000008 my_function_ptr
0000000000000000         *UND*  0000000000000000 void*
value_convert_function<float, float>(float*, float*)
0000000000000018 g     O .data  0000000000000008 my_uncast_function_ptr
0000000000000000  w    F .text._Z22value_convert_functionIbbEPvPT_PT0_ 
0000000000000013 void* value_convert_function<bool, bool>(bool*, bool*)


I notice that in g++ 4.4, the code for the first two is rejected with a clearly
bogus error ("address of overloaded function with no contextual type
information").  In 4.5.1 and later, it is accepted but yields an undefined
symbol (causing link errors in my actual use-case). This also happens in the
latest sources I've tried, which are a fairly recent subversion checkout:

$ g++ --version | head -n1
g++  (GCC) 4.7.0 20110417 (experimental)

One attempted workaround was to type my table entries as void *, insert no cast
and compile with -fpermissive (to get the implicit conversion to void*). But
that reverts to the 4.4-style bogus error, even in later versions:

void *my_voidptr_table[] = { &value_convert_function<char, char>, 0 };

test.cc:20: error: cannot resolve overloaded function ‘value_convert_function’
based on conversion to type ‘void*’

My workaround for now is to separately instantiate everything I want to put in
the table, by defining a bunch of static function pointers. 

Thanks for reading!


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/49609] No code emitted for address-taken instances of function templates
  2011-07-01 15:48 [Bug c++/49609] New: No code emitted for address-taken instances of function templates srk31 at srcf dot ucam.org
@ 2011-07-01 16:20 ` redi at gcc dot gnu.org
  2011-07-01 16:34 ` redi at gcc dot gnu.org
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2011-07-01 16:20 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> 2011-07-01 16:19:27 UTC ---
The C++ standard lists the contexts in which an overloaded function name can be
used without arguments, and reinterpret_cast is not one of them.

Based on that, I would think G++ 4.4 was correct to reject the code.  I note
that clang++ gives the same behaviour as G++ 4.7 (accepts the code but does not
instantiate the function template)

You can make it work by using an explicit type conversion to the correct type
before doing the reinterpret_cast:

void *(*my_function_ptr)(void*, void *)
 = reinterpret_cast<void*(*)(void*,void*)>(
    (void*(*)(float*,float*))&(value_convert_function<float, float>) );


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/49609] No code emitted for address-taken instances of function templates
  2011-07-01 15:48 [Bug c++/49609] New: No code emitted for address-taken instances of function templates srk31 at srcf dot ucam.org
  2011-07-01 16:20 ` [Bug c++/49609] " redi at gcc dot gnu.org
@ 2011-07-01 16:34 ` redi at gcc dot gnu.org
  2011-07-01 17:55 ` jason at gcc dot gnu.org
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2011-07-01 16:34 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> 2011-07-01 16:34:32 UTC ---
(In reply to comment #1)
> The C++ standard lists the contexts in which an overloaded function name can be
> used without arguments, and reinterpret_cast is not one of them.
> 
> Based on that, I would think G++ 4.4 was correct to reject the code.  I note
> that clang++ gives the same behaviour as G++ 4.7 (accepts the code but does not
> instantiate the function template)

Ah, I think this behaviour is covered by the new text added to 13.4 p2 by
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#115

That paragraph says that if template argument deduction succeeds then an
instantiation is generated. In your case deduction doesn't succeed because the
target type is not available.  The note added by DR 115 says that the
specialization can be identified if there's a template argument list, which is
what happens in your example, but it doesn't say that the function template is
instantiated in that case.

> You can make it work by using an explicit type conversion to the correct type
> before doing the reinterpret_cast:
> 
> void *(*my_function_ptr)(void*, void *)
>  = reinterpret_cast<void*(*)(void*,void*)>(
>     (void*(*)(float*,float*))&(value_convert_function<float, float>) );

You can also make it work by not specifying an explicit template argument list
and letting them be deduced:

void *(*my_function_ptr)(void*, void *)
  = reinterpret_cast<void*(*)(void*,void*)>(
    (void*(*)(float*,float*))&value_convert_function);

As 13.4 p2 says, that causes the template to be instantiated.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/49609] No code emitted for address-taken instances of function templates
  2011-07-01 15:48 [Bug c++/49609] New: No code emitted for address-taken instances of function templates srk31 at srcf dot ucam.org
  2011-07-01 16:20 ` [Bug c++/49609] " redi at gcc dot gnu.org
  2011-07-01 16:34 ` redi at gcc dot gnu.org
@ 2011-07-01 17:55 ` jason at gcc dot gnu.org
  2011-07-01 18:09 ` srk31 at srcf dot ucam.org
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: jason at gcc dot gnu.org @ 2011-07-01 17:55 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

Jason Merrill <jason at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |jason at gcc dot gnu.org
         Resolution|                            |DUPLICATE

--- Comment #3 from Jason Merrill <jason at gcc dot gnu.org> 2011-07-01 17:54:27 UTC ---
That's a pretty strained reading.  Even if that were pedantically what the
standard says, it would clearly be an oversight.

*** This bug has been marked as a duplicate of bug 48883 ***


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/49609] No code emitted for address-taken instances of function templates
  2011-07-01 15:48 [Bug c++/49609] New: No code emitted for address-taken instances of function templates srk31 at srcf dot ucam.org
                   ` (2 preceding siblings ...)
  2011-07-01 17:55 ` jason at gcc dot gnu.org
@ 2011-07-01 18:09 ` srk31 at srcf dot ucam.org
  2011-07-01 18:56 ` redi at gcc dot gnu.org
  2011-07-01 20:26 ` jason at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: srk31 at srcf dot ucam.org @ 2011-07-01 18:09 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

--- Comment #4 from Stephen Kell <srk31 at srcf dot ucam.org> 2011-07-01 18:09:07 UTC ---
(In reply to comment #2)
> That paragraph says that if template argument deduction succeeds then an
> instantiation is generated. In your case deduction doesn't succeed because the
> target type is not available.  The note added by DR 115 says that the
> specialization can be identified if there's a template argument list, which is
> what happens in your example, but it doesn't say that the function template is
> instantiated in that case.

Ah, I see... I was thinking that the error was spurious because I hadn't
overloaded the function, but I guess the template argument-dependence defines a
family of overloads.

> > You can make it work by using an explicit type conversion to the correct type
> > before doing the reinterpret_cast:
> > 
> > void *(*my_function_ptr)(void*, void *)
> >  = reinterpret_cast<void*(*)(void*,void*)>(
> >     (void*(*)(float*,float*))&(value_convert_function<float, float>) );
> 
> You can also make it work by not specifying an explicit template argument list
> and letting them be deduced:
> 
> void *(*my_function_ptr)(void*, void *)
>   = reinterpret_cast<void*(*)(void*,void*)>(
>     (void*(*)(float*,float*))&value_convert_function);

Cool -- thanks for this! That teaches me for thinking I can get away without
ever using C-style casts in C++....


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/49609] No code emitted for address-taken instances of function templates
  2011-07-01 15:48 [Bug c++/49609] New: No code emitted for address-taken instances of function templates srk31 at srcf dot ucam.org
                   ` (3 preceding siblings ...)
  2011-07-01 18:09 ` srk31 at srcf dot ucam.org
@ 2011-07-01 18:56 ` redi at gcc dot gnu.org
  2011-07-01 20:26 ` jason at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2011-07-01 18:56 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> 2011-07-01 18:56:19 UTC ---
(In reply to comment #3)
> That's a pretty strained reading.  Even if that were pedantically what the
> standard says, it would clearly be an oversight.

ok, good!  I would have assumed it was meant to work except that clang gives
exactly the same behaviour, so I started looking for reasons why.


(In reply to comment #4)
> > You can also make it work by not specifying an explicit template argument list
> > and letting them be deduced:
> > 
> > void *(*my_function_ptr)(void*, void *)
> >   = reinterpret_cast<void*(*)(void*,void*)>(
> >     (void*(*)(float*,float*))&value_convert_function);
> 
> Cool -- thanks for this! That teaches me for thinking I can get away without
> ever using C-style casts in C++....

You can do it without -style casts, using static_cast:

void *(*my_function_ptr)(void*, void *)
  = reinterpret_cast<void*(*)(void*,void*)>(
    static_cast<void*(*)(float*,float*)>(&value_convert_function));

or with a functional-style cast:

typedef void*(*func_type)(float*,float*);

void *(*my_function_ptr)(void*, void *)
  = reinterpret_cast<void*(*)(void*,void*)>(
    func_type(&value_convert_function));


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/49609] No code emitted for address-taken instances of function templates
  2011-07-01 15:48 [Bug c++/49609] New: No code emitted for address-taken instances of function templates srk31 at srcf dot ucam.org
                   ` (4 preceding siblings ...)
  2011-07-01 18:56 ` redi at gcc dot gnu.org
@ 2011-07-01 20:26 ` jason at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: jason at gcc dot gnu.org @ 2011-07-01 20:26 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

--- Comment #6 from Jason Merrill <jason at gcc dot gnu.org> 2011-07-01 20:24:15 UTC ---
Author: jason
Date: Fri Jul  1 20:24:08 2011
New Revision: 175764

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=175764
Log:
    PR c++/48883
    PR c++/49609
    * pt.c (resolve_nondeduced_context): Call mark_used.

Added:
    trunk/gcc/testsuite/g++.dg/template/explicit-args4.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/pt.c
    trunk/gcc/testsuite/ChangeLog


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-07-01 20:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-01 15:48 [Bug c++/49609] New: No code emitted for address-taken instances of function templates srk31 at srcf dot ucam.org
2011-07-01 16:20 ` [Bug c++/49609] " redi at gcc dot gnu.org
2011-07-01 16:34 ` redi at gcc dot gnu.org
2011-07-01 17:55 ` jason at gcc dot gnu.org
2011-07-01 18:09 ` srk31 at srcf dot ucam.org
2011-07-01 18:56 ` redi at gcc dot gnu.org
2011-07-01 20:26 ` jason at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).