Bug 24243 - [4.0 regression] lookup fails to match to function call, const-sensitive
Summary: [4.0 regression] lookup fails to match to function call, const-sensitive
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-06 19:20 UTC by David Fang
Modified: 2006-06-04 19:41 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
test case triggering bug (818 bytes, text/plain)
2005-10-06 19:22 UTC, David Fang
Details
corrected header file (1.40 KB, text/plain)
2005-10-06 23:38 UTC, David Fang
Details

Note You need to log in before you can comment on or make changes to this bug.
Description David Fang 2005-10-06 19:20:34 UTC
command: g++-4 -v -save-temps -c lookup-bug.cc

keywords: rejects-valid

expecting: (success)

program output:
Using built-in specs.
Target: powerpc-apple-darwin7
Configured with: ../configure --prefix=/sw --prefix=/sw/lib/gcc4 --enable-languages=c,c++,f95,objc,java --infodir=/share/info --with-gmp=/sw --with-included-gettext --host=powerpc-apple-darwin7 --with-as=/sw/lib/odcctools/bin/as --with-ld=/sw/lib/odcctools/bin/ld
Thread model: posix
gcc version 4.0.2
 /sw/lib/gcc4/libexec/gcc/powerpc-apple-darwin7/4.0.2/cc1plus -E -quiet -v -D__DYNAMIC__ -D__APPLE_CC__=1 lookup-bug.cc -fPIC -fpch-preprocess -o lookup-bug.ii
ignoring nonexistent directory "/sw/lib/gcc4/lib/gcc/powerpc-apple-darwin7/4.0.2/../../../../powerpc-apple-darwin7/include"
#include "..." search starts here:
#include <...> search starts here:
 /sw/lib/gcc4/lib/gcc/powerpc-apple-darwin7/4.0.2/../../../../include/c++/4.0.2
 /sw/lib/gcc4/lib/gcc/powerpc-apple-darwin7/4.0.2/../../../../include/c++/4.0.2/powerpc-apple-darwin7
 /sw/lib/gcc4/lib/gcc/powerpc-apple-darwin7/4.0.2/../../../../include/c++/4.0.2/backward
 /usr/local/include
 /sw/lib/gcc4/include
 /sw/lib/gcc4/lib/gcc/powerpc-apple-darwin7/4.0.2/include
 /usr/include
 /System/Library/Frameworks
 /Library/Frameworks
End of search list.
 /sw/lib/gcc4/libexec/gcc/powerpc-apple-darwin7/4.0.2/cc1plus -fpreprocessed lookup-bug.ii -fPIC -quiet -dumpbase lookup-bug.cc -auxbase lookup-bug -version -o lookup-bug.s
GNU C++ version 4.0.2 (powerpc-apple-darwin7)
        compiled by GNU C version 3.3 20030304 (Apple Computer, Inc. build 1640).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
lookup-bug.cc: In member function 'std::ostream& foo::name_space::dump(std::ostream&) const':
lookup-bug.cc:249: error: no matching function for call to 'mem_fun(std::ostream& (foo::instance_collection_base::*)(std::ostream&)const, const util::memory::never_ptr<const foo::instance_collection_base>&)'

known to work: gcc-4.0.1 (built likewise)

remarks:
Note that this is not std::mem_fun, but rather, a custom extension for pointer-classes, defined in namespace util.
In the attached .ii, changing the static member declaration:
    static const never_ptr<const instance_collection_base> null;
to
    static const never_ptr<instance_collection_base> null;
is sufficient to compile successfully.
Comment 1 David Fang 2005-10-06 19:22:10 UTC
Created attachment 9912 [details]
test case triggering bug
Comment 2 Andrew Pinski 2005-10-06 19:48:46 UTC
Here is the reduced testcase:
template <class R, template <class> class P, class T, class A>
 inline int  mem_fun(R (T::*f)(A), const P<T>& null) {}

template <class T> class never_ptr {};

struct instance_collection_base {
  int&  pair_dump(int&) const;
  static const never_ptr<const instance_collection_base> null;
};

int& dump(int& o) {
mem_fun(&instance_collection_base::pair_dump,   instance_collection_base::null);
}

But I think this is invalid as "const instance_collection_base" is not the same as instance_collection_base.  so T cannot be matched to "const instance_collection_base" as it was before 4.1.0/4.0.2.

ICC and Comeau rejects the same code too for the same reason.
Comment 3 David Fang 2005-10-06 20:30:30 UTC
Subject: Re:  [4.0 regression] lookup fails to match to function
 call, const-sensitive

> ------- Comment #2 from pinskia at gcc dot gnu dot org  2005-10-06 19:48 -------
> Here is the reduced testcase:
> template <class R, template <class> class P, class T, class A>
>  inline int  mem_fun(R (T::*f)(A), const P<T>& null) {}
>
> template <class T> class never_ptr {};
>
> struct instance_collection_base {
>   int&  pair_dump(int&) const;
>   static const never_ptr<const instance_collection_base> null;
> };
>
> int& dump(int& o) {
> mem_fun(&instance_collection_base::pair_dump,
> instance_collection_base::null);
> }
>
> But I think this is invalid as "const instance_collection_base" is not
> the same as instance_collection_base.  so T cannot be matched to
> "const instance_collection_base" as it was before 4.1.0/4.0.2.
>
> ICC and Comeau rejects the same code too for the same reason.

True, const T != T, but shouldn't const-volatile qualifiers be disregarded
when trying to match member functions of T?

Perhaps irrelevant, but in the context of my test-case I wanted to
be precise about member-function constness.

Comment 4 David Fang 2005-10-06 21:28:26 UTC
Subject: Re:  [4.0 regression] lookup fails to match to function
 call, const-sensitive

Something else puzzling to me, that I noticed from your reduction:
Why is the compiler always matching the non-const version of mem_fun, when
the member-function I'm passing in (pair_dump) is const? Isn't the const a
closer match?  In fact, if I remove the non-const mem_fun() definition,
then I get "no match found" from g++-3.3 to 4.0 -- doesn't even accept the
const version.  I've seen some old PRs on this matter, but don't recall
what their resolution was.

> mem_fun(&instance_collection_base::pair_dump,
> instance_collection_base::null);

// prefers this:
template <class R, template <class> class P, class T, class A>
inline
mem_fun1_p_t<R, P, T, A>
mem_fun(R (T::*f)(A), const P<T>& null) {
        return mem_fun1_p_t<R, P, T, A>(f);
}

// over this:
template <class R, template <class> class P, class T, class A>
inline
const_mem_fun1_p_t<R, P, T, A>
mem_fun(R (T::*f)(A) const, const P<T>& null) {
        return const_mem_fun1_p_t<R, P, T, A>(f);
}


Comment 5 Richard Biener 2005-10-06 21:41:47 UTC
I have seen this issue one time and the solution is to cast the argument to memfun to the appropriate type - f.i. the const member function, or to specify the template parameters to memfun.  In case you have both const and non-const member functions you'll have an ambiguous match otherwise.

This really is invalid.
Comment 6 David Fang 2005-10-06 21:47:05 UTC
I now second your opinions that this is invalid.
Upon closer examination, what I *should've* written to make this code valid is the following:

template <class R, template <class> class P, class T, class A>
inline
const_mem_fun1_p_t<R, P, T, A>
mem_fun(R (T::*f)(A) const, const P<const T>& null) {
        return const_mem_fun1_p_t<R, P, T, A>(f);
}

To be more correct, I changed "const P<T>" to "const P<const T>" in the function parameter list.
Now gcc-3.3 to 4.0.x find the right match and accept it.  
(So really, the previous versions 'accepts-invalid.')

Thanks for being patient with me on this.  
Comment 7 David Fang 2005-10-06 23:38:08 UTC
Created attachment 9913 [details]
corrected header file

Just as a follow-up, here's what the new valid header file looks like, with all the various mem_fun definitions corrected in the const cases.  (Perhaps this might be useful for reference in future test cases?)
Comment 8 David Fang 2006-03-11 22:10:56 UTC
Housekeeping: re-classify as invalid?
I wasn't able to find an "accepts-invalid" version of this bug in the database for reference.  
That bug would've been fixed sometime between 4.0.1 and 4.0.2.  
Comment 9 Mark Mitchell 2006-06-04 19:41:07 UTC
Submitter agrees code is invalid.