[cfe-dev] Template default arg : Friend function cannot access private member

John McCall rjmccall at apple.com
Wed Sep 25 00:58:32 PDT 2013


On Sep 19, 2013, at 12:16 AM, suyog sarda <sardask01 at gmail.com> wrote:
> This is regarding a test case which involves default argument deduction/substitution. The test case can be summarized as :
> 
> 
> template <class T, class = typename T::I>h(T){}
> 
> template <class T, class = typename T::I>j(T){}
> 
> class A
> {
> typedef int I;
> friend void h<A>(A);
> 
> };
> 
> int main()
> {
> A a;
> h(a);
> j(a);
> }
> 
> gcc-4.8.1 throws error for function j, since it has been not been declared friend nor it is private to class A and hence violates access rule for
> 
> private member I(which is valid). gcc does not throw error for function h since it has been declared as friend to class A and hence can access
> 
> private member I.
> 
> Clang throws error for both the functions. Error for function j (not declared friend is valid and as expected), but it throws error even for
> 
> friend function h (error : deduction of default arg failed since I is a private member of class A). This violates the accessibility of the friend
> 
> function.
> 
> The standard says - (At 14.8.2 pt 8)
> 
> 
> "If a substitution results in an invalid type or expression, type deduction fails. An in valid type or expression
> 
> is one that would be ill-formed if written using the substituted arguments. [ Note: Access checking is done as
> 
> part of the substitution process. —end note ]"
> 
> 
> Can someone please provide inputs as to how to check where the access rights are being checked in clang?  I am using QT creator to debug clang 

Clang is actually rejecting the friend function declaration, not the call to h.

The relevant bit from the standard is [class.access]p9:
  The names in a default template-argument have their access checked in the context in which they appear rather than at any points of use of the default template-argument.

This is the resolution to DR 401:
  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2609.html#401

Note in particular this quote, which illuminates the reasoning behind the somewhat confusing standard wording:
  We decided that template parameter default arguments should have their access checked in the context where they appear without special access for the entity declared…

The context in which the template parameter default argument appears is the global context, which has no special access rights to A.  So Clang is correct to reject this.

GCC is probably mistakenly checking access from the context which uses the default argument.  I can’t imagine that they’re really doing the heroics necessary to check access from the context of h<A> **in order to validate the declaration which makes that access well-formed**.

John.



More information about the cfe-dev mailing list