[C++ PATCH for 4.0] Fix PR18681 (access checking for typedef types using different approach)

Kriang Lerdsuwanakij lerdsuwa@users.sourceforge.net
Tue Dec 21 15:49:00 GMT 2004


Hi

This patch fixes PR18681 (a regression) for GCC 4.0 using a different
approach than my previous version:

  http://gcc.gnu.org/ml/gcc-patches/2004-12/msg00854.html

This is also a complete fix and solves the problems mentioned in the
follow up mails of the patch above.


For the code like:

  class C {
    typedef int X;
    template <class T> friend class A;
  };

  template <classs T> class A {
    typedef typename T::X XX;
    class B {
      void f(XX);	// should be allowed, currently issue error
			// message that C::X is private
    };
  };

  template class A<C>;

the type node of the typedef (such as 'XX' above) is copied (via
build_variant_type_copy in grokdeclarator) and marked it with
TYPE_NO_ACCESS_CHECK_P flag.  When tsubst encounter a type with
this flag marked, access checking is turned off.  In the old
approach, TYPENAME_TYPE, UNBOUND_CLASS_TEMPLATE and SCOPE_REF would
be marked instead.


As in the previous version, the tricky part is about access checking
in the typedef declaration itself when the class template containing
this typedef is instantiated:

1. Even though we don't want to check any occurrent of 'XX', we still
   want to perform access checking for the declaration

     typedef typename T::X XX;

   i.e., whether T::X is accessible, when the enclosing class template
   is instantiated.

   The type of typedef, which is TYPENANE_TYPE in this case, is marked.
   So we clear TYPE_NO_ACCESS_CHECK_P before the tsubst call, enabling
   access checking.  During tsubst, the access of the qualified ID 'T::X'
   is checked in make_typename_type.  This marker is later set back after
   tsubst finishes.
   

2. Second tricky issue is that we don't want to check access for

     typedef XX* XX1; // Prior typedef of 'XX' is assumed.

   This is handled exactly the same way as case 1.  We clear
   TYPE_NO_ACCESS_CHECK_P of the type node which is a POINTER_TYPE.
   Nested inside this POINTER_TYPE is a TYPENAME_TYPE node inherited
   from 'XX' declaration which is still marked with TYPE_NO_ACCESS_CHECK_P.
   So no access checking for 'XX'.

   The same applies with cases like

     typedef D<XX, typename T::X> XX2;

   The TYPE_NO_ACCESS_CHECK_P is cleared for the RECORD_TYPE (for D<...>).
   Inside this RECORD_TYPE, we find 2 TYPENAME_TYPE nodes.
   - One is 'XX', inherited from a previous typedef so it is marked
     and no checking is performed.
   - The other is the 'T::X', not inherited, so it is not marked and
     access checking is done.

   Those cases work because the type of 'XX1' and 'XX2' is different tree
   node from 'XX'.


3. We still require to deal with the special case.

     typedef XX XX2;

   the type of 'XX2' and the inherited type 'XX' is exactly the same node.
   We need to avoid clearing TYPE_NO_ACCESS_CHECK_P in the first place.
   So an additional DECL_NO_ACCESS_CHECK_P flag is utilized on the TYPE_DECL
   for this purpose.


Tested on i686-pc-linux-gnu.  OK for the mainline?

--Kriang


-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: diff-typedef-access-b3.txt
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20041221/cd8cacb8/attachment.txt>


More information about the Gcc-patches mailing list