Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I believe this is a bug in clang++ related to the access to a class's public member function

The following doesn't compile in clang:

#include <iostream>

void f() { std::cout << "f()\n"; }

struct S {
    typedef void(*p)();
    operator p() { return f; }
};

int main()
{
    S s;
    s.operator p()();
}

Yields:

main.cpp:13:16: error: unknown type name 'p'; did you mean 'S::p'?
    s.operator p()();
               ^
               S::p

main.cpp:6:19: note: 'S::p' declared here
    typedef void(*p)();
                  ^

But it should, as the expression s.operator p()() accesses a public member function of the object S::s. Am I missing something?

If I'm wrong, I would appreciate a quote from the Standard supporting the answer.

like image 772
Alexander Avatar asked Jun 10 '17 15:06

Alexander


1 Answers

This appears to be a bug in Clang. I believe the code is correct.

Clang 4.0.0 reports:

<source>:13:16: error: unknown type name 'p'; did you mean 'S::p'?
    s.operator p()();
           ^

However, from C++14 3.4.5/7 [basic.lookup.classref]

If the id-expression is a conversion-function-id, its conversion-type-id is first looked up in the class of the object expression and the name, if found, is used. Otherwise it is looked up in the context of the entire postfix-expression. In each of these lookups, only names that denote types or templates whose specializations are types are considered.

[ Example:

struct A { };
namespace N {
struct A {
    void g() { }
    template <class T> operator T();
};
}


int main() {
    N::A a;
    a.operator A();
       // calls N::A::operator N::A
}

— end example ]

In your example, the type p should have been found in the class without requiring qualification.

like image 150
Vaughn Cato Avatar answered Nov 15 '22 14:11

Vaughn Cato