[cfe-commits] r155303 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplate.cpp test/PCH/cxx-friends.cpp test/PCH/cxx-friends.h test/SemaTemplate/friend-template.cpp

Douglas Gregor dgregor at apple.com
Tue Nov 6 11:31:05 PST 2012


On Apr 21, 2012, at 7:13 PM, Richard Smith <richard-llvm at metafoo.co.uk> wrote:

> Author: rsmith
> Date: Sat Apr 21 21:13:50 2012
> New Revision: 155303
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=155303&view=rev
> Log:
> PR12585: When processing a friend template inside a class template, don't
> pretend there was no previous declaration -- that can lead us to injecting
> a class template (with no access specifier) into a class scope. Instead,
> just avoid the problematic checks.

This can lead to us breaking AST invariants that are hard to work around. For example, given this example:

class RecyclerTag {
    template <typename T> friend class Recycler;
};

template<typename TTag>
class CRN {
    template <typename T> friend class Recycler;
};

The first declaration of 'Recycler' as a template parameter list with a template type parameter of depth=0, index=0. The second declaration of 'Recycler' has a template parameter list with a template type parameter of depth=1, index=0. Those two template parameter lists aren't actually compatible; if one tried to (say) substitute one level of template arguments (which makes sense for the Recycler class) into the second declaration, we'd be in trouble.

I think the right approach here is to keep CRN's Recycler in some nonattached form of class template, then when we instantiate CRN<something>, match up the substituted template parameters of Recycler with the known class template Recycler and link it into the redeclaration chain at that point. This solution also deals with cases like:

template<int N> struct A { };

template<typename T>
struct B {
	template<T value> friend struct A;
};

where the template parameters of the friend class template depend on outer template parameters, and we can't detect whether this causes a problem until instantiation time.

	- Doug




More information about the cfe-commits mailing list