[cfe-dev] (Unexpected) Method type

Sebastian Redl sebastian.redl at getdesigned.at
Sun Jan 10 14:44:26 CST 2010


Abramo Bagnara wrote:
> Il 10/01/2010 16:07, Sebastian Redl ha scritto:
>   
>> It's deliberate. I saw no reason to give it a distinct type. A
>> MemberPointerType to FunctionProtoType is a pointer to member function.
>> The only place where a member function can appear without a pointer to
>> it is in call expressions. You can't do anything with the function in
>> these cases except call it, so the type system gets along just fine.
>>
>> The bug here is that the validation code for & takes a wrong path and
>> returns a normal PointerType to FunctionProtoType.
>>     
>
> To tell you the truth, I'm a bit perplexed: I think that a non static
> method type is something very different from an ordinary function type
> and that they should not share the same type.
>   
But they do! Look at this snippet; GCC accepts it:

typedef void FuncType();
FuncType func; // Declare a normal function called func, no return value
or parameters.
void func() { // Define func.
}
struct A {
  FuncType mfunc; // Declare a member function called mfunc, no return
value or parameters.
};
void A::mfunc() { // Define mfunc.
}

> If we use the same type, comparison of canonical type of a non static
> method and canonical type of an ordinary function could wrongly succeeds
> and I expect other problems following this path.
>   
There is no way in valid C++ to create a situation where this is
relevant. If we have some bugs in this area, it's because we're not
intercepting invalid code early enough, as your two code examples show.
> Also under a C++ standard perspective I don't see how a non static
> method could be considered to have the same type of ordinary function,
> they don't have neither the same arguments (because implicit "this"
> argument).
>   
What the standard says is only a minor consideration in the design of
Clang's data structures. More important is that using FunctionProtoType
directly simplifies a lot of code. Also, the implicit this doesn't
matter - take a look at the one important place where it could: the
standard explicitly says that it is ignored. I'm talking about overload
resolution, of course.

struct B {
  static void fn(int);
  void fn(double);
};
void test() {
  B b;
  b.fn(1); // Calls fn(int), ignoring the object argument
  b.fn(1.0); // Calls fn(double), ignoring the object argument
}
> The following C++ source (wrongly compiled by clang) is another small
> snippet that shows the problems of current approach:
>
> template <typename T>
> void p(T, T);
>
> void g();
>
> struct c {
>   void h();
>   void f() {
>     __typeof(h) i;
>     return p(i, g);
>   }
> };
>   
But again, this is (or in the case of Clang, should be) rejected far
earlier, namely at __typeof(h). GCC complains that the type of the
member function is unknown. In other words, you're not allowed to apply
typeof to a member function. I'll have to check what C++0x says about
decltype, but I suspect it's the same thing.

Sebastian


More information about the cfe-dev mailing list