After some experiment, using typename for internal representation is not enough. It cannot distinguish between the following two cases:
template <class T> struct D { ... };
template <class T> class C {
friend class D<T>::X; // use typename here?
template <class U> friend class D<U>::Y; // also use typename?
};
My latest idea is to invent a new tree node to represent the second friend.