Inaccessible base class despite friendship

The problem is that the conversion from B* to A* (the one which requires friendship) does not happen in a member function of C, but in the context of the code containing b and c (i.e. the unrelated function bar()).

It would work fine if you created a member function in C accepting a B*, and then called foo() from within it. That would have the conversion happen within the context of C which has the necessary access rights (thanks to friendship).

Your code is equivalent to this:

B b;
C c;
A * a = &b; // <- This cast produces the error;

You cannot cast &b as A* since the base class is protected, regardless of the friendship of C.