[cfe-dev] Template parameters of friend declarations.

John McCall rjmccall at apple.com
Tue Jan 22 15:16:55 PST 2013

On Jan 22, 2013, at 3:07 PM, Enea Zaffanella <zaffanella at cs.unipr.it> wrote:
> On 01/22/2013 08:34 PM, John McCall wrote:
>> On Jan 21, 2013, at 12:42 AM, Enea Zaffanella <zaffanella at cs.unipr.it> wrote:
>>> In clang AST, we currently have two nodes representing friend declarations, namely FriendDecl and FriendTemplateDecl. The documentation for the second class says that it is currently unused:
>>> /// \note This class is not currently in use.  All of the above
>>> /// will yield a FriendDecl, not a FriendTemplateDecl.
>>> Hence, all friend declarations having template parameter lists end up building a FriendDecl node. Currently, these FriendDecl nodes have no way to store the (optional) template parameter lists.
>>> For source-code fidelity purposes *only*, would it be OK if FriendDecl is changed so as to also store this missing info?
>>> Currently, the FriendDecl node uses a pointer union:
>>>  typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
>>> A possibility would be to add an ExtInfo inner class (similar to what was done for DeclaratorDecl) and then change the union above to become:
>>>  typedef llvm::PointerUnion3<NamedDecl*,TypeSourceInfo*,ExtInfo*> FriendUnion;
>>> This way, we would incur a memory space penalty only when there actually are template parameter lists. Are you willing to accept patches following this approach?
>> Are the template parameter lists not attached to the target declaration?
>> John.
> I am actually referring to a friend *type* declaration such as
> class C {
>  template<class T> friend struct S<T>::B;
> };
> That is, I am interested in the "outer" template parameter lists (such as those of out-of-line definitions of non-template members of class templates). Afaict, this kind of friend declarations is handled in
>  Sema::ActOnTemplatedFriendTag
> where I see the comment:
>  // [...] TODO: for source fidelity, remember the headers.

Ah, yes, I see.  This is actually the "unsupported friend" case, for which
we do not actually implement correct semantic analysis at all — which
should be obvious from the fact that we drop the template parameter
lists, which would otherwise be necessary for correctness.

These outer template parameter lists can be present for both cases of a
friend declaration:
  template <class T> class A<T>::B;
  template <class T> void A<T>::B::foo();

So I don't suggest adding this as ExtInfo in the FriendUnion.  Fortunately,
FriendDecl has no subclasses, and we know how many outer template
parameter lists there are when parsing it, so you can actually just store
the number of parameter lists in the class and tail-allocate the array of
template parameter lists.


More information about the cfe-dev mailing list