Bug 695567

Summary: "cannot be used as a function" error when calling pointer-to-member functions in a template
Product: [Fedora] Fedora Reporter: r6144 <rainy6144>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED UPSTREAM QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 14CC: jakub, jason
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2011-04-14 10:21:14 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Attachments:
Description Flags
File demonstrating the problem
none
rh695567.C none

Description r6144 2011-04-12 02:45:48 UTC
Created attachment 491398 [details]
File demonstrating the problem

Description of problem:

The attached phoenix-bug.cpp does not compile with g++.  Specifically, (vp->*push_back_)(tria1) gives the error "vp->*push_back_ cannot be used as a function", although assigning vp->*push_back_ to a local variable fp and calling fp(tria1) does work.  If the function f() is not a template, there is no problem.  clang has no problem compiling the code either.

Version-Release number of selected component (if applicable):
gcc-c++-4.5.1-4.fc14.x86_64
boost-devel-1.44.0-7.fc14.x86_64
clang-2.8-10.fc14.x86_64

How reproducible:
Always

Steps to Reproduce:
1. g++ -o phoenix-bug phoenix-bug.cpp
  
Actual results:
phoenix-bug.cpp: In function ‘void f(T)’:
phoenix-bug.cpp:20:26: error: ‘vp->*push_back_’ cannot be used as a function

Expected results:
Should compile.

This program does compile correctly with clang:
clang -o phoenix-bug phoenix-bug.cpp -lstdc++


Additional info:

Comment 1 Jakub Jelinek 2011-04-12 11:21:51 UTC
Jason, is this valid?

#include <vector>
#include <boost/spirit/include/phoenix.hpp>
namespace ph = boost::phoenix;
struct Triangle {};
extern ph::actor<ph::value<std::vector<Triangle> *> > vp;
#ifndef WORKS2
template<typename T>
#endif
void foo ()
{
  void (std::vector<Triangle>::*const p)(const Triangle&)
    = &std::vector<Triangle>::push_back;
  Triangle tria1;
#ifdef WORKS
   auto fp = vp->*p;
   fp(tria1);
#else
   (vp->*p)(tria1);
#endif
}
#ifndef WORKS2
void bar ()
{
  foo<int> ();
}
#endif

Comment 2 Jakub Jelinek 2011-04-12 11:23:46 UTC
Created attachment 491460 [details]
rh695567.C

Somewhat delta reduced, hope I haven't elided anything important for the testcase.

Comment 3 Jakub Jelinek 2011-04-12 11:33:17 UTC
Failed that way already in r130000 and already in r90000 (up to r129XXX ) failed with
error: ‘#‘member_ref’ not supported by dump_expr#<expression error>’ cannot be used as a function
error instead of
error: ‘vp->*p’ cannot be used as a function
But compiles fine with g++ 3.2-RH and 3.3.

Comment 4 Jason Merrill 2011-04-13 18:28:35 UTC
This is indeed a bug.  Reduced:

struct A { } a;

typedef void (*pfn)();
pfn operator->* (A, int);

template <class T>
void f()
{  
  (a->*1)();
}