This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH for 3.4] Fix PR18681 (access checking for typedef types)Part 1 of 2


Hi

This is the 3.4 version. Tested on i686-pc-linux-gnu with no regressions. OK for 3.4 branch?

--Kriang


2004-12-12  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/18681
	* cp-tree.h (struct saved_scope): Add x_processing_typedef field.
	(processing_typedef, TREE_NO_ACCESS_CHECK_P): New macros.
	* decl.c (typename_compare): Compare TREE_NO_ACCESS_CHECK_P.
	(build_typename_type, make_unbound_class_template): Set
	TREE_NO_ACCESS_CHECK_P for code appearing inside typedef.
	(grokdeclarator): Set TREE_NO_ACCESS_CHECK_P for typedef to
	previuosly declared typedef type.
	* parser.c (cp_parser_decl_specifier_seq): Set processing_typedef
	when typedef keyword is encountered.
	* pt.c (instantiate_class_template): Set processing_typedef
	when tsubst'ing typedef.  Handle TREE_NO_ACCESS_CHECK_P.
	(tsubst <case TYPENAME_TYPE, UNBOUND_CLASS_TEMPLATE>): Handle
	TREE_NO_ACCESS_CHECK_P.
	(tsubst_qualified_id): Handle TREE_NO_ACCESS_CHECK_P.

2004-12-12  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/18681
	* g++.dg/template/access-typedef1.C: New test.
	* g++.dg/template/access-typedef2.C: Likewise.
	* g++.dg/template/access-typedef3.C: Likewise.
	* g++.dg/template/access-typedef4.C: Likewise.
	* g++.dg/template/access-typedef5.C: Likewise.


diff -cprN gcc-34-save/gcc/cp/cp-tree.h gcc-34-new/gcc/cp/cp-tree.h
*** gcc-34-save/gcc/cp/cp-tree.h	Tue Oct 12 22:57:59 2004
--- gcc-34-new/gcc/cp/cp-tree.h	Sat Dec 11 18:09:17 2004
*************** struct diagnostic_context;
*** 77,82 ****
--- 77,84 ----
        IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
     5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
        DECL_VTABLE_OR_VTT_P (in VAR_DECL)
+       TREE_NO_ACCESS_CHECK_P (in TYPENAME_TYPE, UNBOUND_CLASS_TEMPLATE,
+ 			      SCOPE_REF, or TYPE_DECL)
     6: For future expansion
  
     Usage of TYPE_LANG_FLAG_?:
*************** struct saved_scope GTY(())
*** 704,709 ****
--- 706,712 ----
    HOST_WIDE_INT x_processing_template_decl;
    int x_processing_specialization;
    bool x_processing_explicit_instantiation;
+   bool x_processing_typedef;
    int need_pop_function_context;
  
    struct stmt_tree_s x_stmt_tree;
*************** struct saved_scope GTY(())
*** 751,756 ****
--- 754,788 ----
  #define processing_specialization scope_chain->x_processing_specialization
  #define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation
  
+ /* For typedef inside class template, we need to be careful about access
+    checking.  For example:
+ 
+      template <classs T> class A {
+        typedef typename T::X XX1;     // #1
+        class B {
+ 	 typedef XX1 XX2;             // #2
+ 	 void f1(XX1);                // #3
+ 	 void f2(XX2);                // #4
+ 	 void f3(typename T::X);      // #5
+        };
+      };
+ 
+    In cases 3 to 5, we have function parameter with type TYPENAME_TYPE.
+    However access checking should be performed only for case 5.  To
+    distinguish TYPENAME_TYPE, UNBOUND_CLASS_TEMPLATE, and SCOPE_REF
+    between those coming from typedef and those declared directly, we set
+    processing_typedef when we encounter typedef during parsing
+    in cp_parser_decl_specifier_seq.  Then the TREE_NO_ACCESS_CHECK_P
+    created for those tree nodes are set during creation in
+    build_typename_type and make_unbound_class_template.  Access checking
+    will be disabled in tsubst for code 3 and 4.
+ 
+    For typedef, we need to check access of case 1 but not case 2.  This
+    is accomplished by setting TREE_NO_ACCESS_CHECK_P for the TYPE_DECL
+    of case 2 in grokdeclarator.  This turn off access checking in
+    instantiate_class_template.  */
+ #define processing_typedef scope_chain->x_processing_typedef
+ 
  /* _TYPE: the previous type that was a class */
  
  #define previous_class_type scope_chain->x_previous_class_type
*************** struct lang_type GTY(())
*** 1199,1204 ****
--- 1231,1240 ----
     convenient, don't reprocess any methods that appear in its redefinition.  */
  #define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined)
  
+ /* Tree means access checking should be performed for this NODE after
+    template substitution.  */
+ #define TREE_NO_ACCESS_CHECK_P(NODE) TREE_LANG_FLAG_5 (NODE)
+ 
  /* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
     multiple inheritance.  If this is 0 for the root of a type
     hierarchy, then we can use more efficient search techniques.  */
diff -cprN gcc-34-save/gcc/cp/decl.c gcc-34-new/gcc/cp/decl.c
*** gcc-34-save/gcc/cp/decl.c	Tue Nov 30 21:04:39 2004
--- gcc-34-new/gcc/cp/decl.c	Sat Dec 11 18:12:07 2004
*************** typename_compare (const void * k1, const
*** 2546,2552 ****
  	  && ((TREE_TYPE (t1) != NULL_TREE)
  	      == (TREE_TYPE (t2) != NULL_TREE))
  	  && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
! 	  && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
  }
  
  /* Build a TYPENAME_TYPE.  If the type is `typename T::t', CONTEXT is
--- 2546,2553 ----
  	  && ((TREE_TYPE (t1) != NULL_TREE)
  	      == (TREE_TYPE (t2) != NULL_TREE))
  	  && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
! 	  && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2)
! 	  && TREE_NO_ACCESS_CHECK_P (t1) == TREE_NO_ACCESS_CHECK_P (t2));
  }
  
  /* Build a TYPENAME_TYPE.  If the type is `typename T::t', CONTEXT is
*************** build_typename_type (tree context, tree 
*** 2576,2581 ****
--- 2577,2583 ----
    t = make_aggr_type (TYPENAME_TYPE);
    TYPE_CONTEXT (t) = FROB_CONTEXT (context);
    TYPENAME_TYPE_FULLNAME (t) = fullname;
+   TREE_NO_ACCESS_CHECK_P (t) = processing_typedef;
  
    /* Build the corresponding TYPE_DECL.  */
    d = build_decl (TYPE_DECL, name, t);
*************** make_unbound_class_template (tree contex
*** 2764,2769 ****
--- 2766,2772 ----
    t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
    TYPE_CONTEXT (t) = FROB_CONTEXT (context);
    TREE_TYPE (t) = NULL_TREE;
+   TREE_NO_ACCESS_CHECK_P (t) = processing_typedef;
  
    /* Build the corresponding TEMPLATE_DECL.  */
    d = build_decl (TEMPLATE_DECL, name, t);
*************** grokdeclarator (tree declarator,
*** 7979,7984 ****
--- 7982,7989 ----
  	  /* FIXME remangle member functions; member functions of a
  	     type with external linkage have external linkage.  */
  	}
+       else if (typedef_decl)
+ 	TREE_NO_ACCESS_CHECK_P (decl) = 1;
  
        if (quals)
  	{
diff -cprN gcc-34-save/gcc/cp/parser.c gcc-34-new/gcc/cp/parser.c
*** gcc-34-save/gcc/cp/parser.c	Thu Dec  2 18:45:15 2004
--- gcc-34-new/gcc/cp/parser.c	Sat Dec 11 18:14:36 2004
*************** cp_parser_decl_specifier_seq (cp_parser*
*** 6706,6711 ****
--- 6706,6712 ----
  	  /* The representation of the specifier is simply the
  	     appropriate TREE_IDENTIFIER node.  */
  	  decl_spec = token->value;
+ 	  processing_typedef = true;
  	  /* Consume the token.  */
  	  cp_lexer_consume_token (parser->lexer);
  	  /* A constructor declarator cannot appear in a typedef.  */
*************** cp_parser_decl_specifier_seq (cp_parser*
*** 6812,6817 ****
--- 6813,6819 ----
  	  if (!(flags & CP_PARSER_FLAGS_OPTIONAL))
  	    {
  	      cp_parser_error (parser, "expected decl specifier");
+ 	      processing_typedef = false;
  	      return error_mark_node;
  	    }
  
*************** cp_parser_decl_specifier_seq (cp_parser*
*** 6827,6832 ****
--- 6829,6836 ----
        flags |= CP_PARSER_FLAGS_OPTIONAL;
      }
  
+   processing_typedef = false;
+ 
    /* Don't allow a friend specifier with a class definition.  */
    if (friend_p && (*declares_class_or_enum & 2))
      error ("class definition may not be declared a friend");
diff -cprN gcc-34-save/gcc/cp/pt.c gcc-34-new/gcc/cp/pt.c
*** gcc-34-save/gcc/cp/pt.c	Sat Dec  4 13:48:05 2004
--- gcc-34-new/gcc/cp/pt.c	Sat Dec 11 18:18:25 2004
*************** instantiate_class_template (tree type)
*** 5587,5595 ****
--- 5587,5614 ----
  
  		  if (TREE_CODE (t) == TEMPLATE_DECL)
  		    ++processing_template_decl;
+ 		  else if (TREE_CODE (t) == TYPE_DECL
+ 			   && !DECL_IMPLICIT_TYPEDEF_P (t)
+ 			   && !DECL_SELF_REFERENCE_P (t))
+ 		    {
+ 		      if (TREE_NO_ACCESS_CHECK_P (t))
+ 			push_deferring_access_checks (dk_no_check);
+ 		      processing_typedef = true;
+ 		    }
+ 
  		  r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
+ 
  		  if (TREE_CODE (t) == TEMPLATE_DECL)
  		    --processing_template_decl;
+ 		  else if (TREE_CODE (t) == TYPE_DECL
+ 			   && !DECL_IMPLICIT_TYPEDEF_P (t)
+ 			   && !DECL_SELF_REFERENCE_P (t))
+ 		    {
+ 		      if (TREE_NO_ACCESS_CHECK_P (t))
+ 			pop_deferring_access_checks ();
+ 		      processing_typedef = false;
+ 		    }
+ 
  		  if (TREE_CODE (r) == VAR_DECL)
  		    {
  		      tree init;
*************** tsubst (tree t, tree args, tsubst_flags_
*** 7212,7221 ****
--- 7231,7245 ----
  	      }
  	  }
  
+ 	if (TREE_NO_ACCESS_CHECK_P (t) && !processing_typedef)
+ 	  push_deferring_access_checks (dk_no_check);
  	f = make_typename_type (ctx, f,
  				(complain & tf_error) | tf_keep_type_decl);
+ 	if (TREE_NO_ACCESS_CHECK_P (t) && !processing_typedef)
+ 	  pop_deferring_access_checks ();
  	if (f == error_mark_node)
  	  return f;
+ 
   	if (TREE_CODE (f) == TYPE_DECL)
   	  {
  	    complain |= tf_ignore_bad_quals;
*************** tsubst (tree t, tree args, tsubst_flags_
*** 7235,7241 ****
  	if (ctx == error_mark_node || name == error_mark_node)
  	  return error_mark_node;
  
! 	return make_unbound_class_template (ctx, name, complain);
        }
  
      case INDIRECT_REF:
--- 7259,7271 ----
  	if (ctx == error_mark_node || name == error_mark_node)
  	  return error_mark_node;
  
! 	if (TREE_NO_ACCESS_CHECK_P (t) && !processing_typedef)
! 	  push_deferring_access_checks (dk_no_check);
! 	r = make_unbound_class_template (ctx, name, complain);
! 	if (TREE_NO_ACCESS_CHECK_P (t) && !processing_typedef)
! 	  pop_deferring_access_checks ();
! 
! 	return r;
        }
  
      case INDIRECT_REF:
*************** tsubst_qualified_id (tree qualified_id, 
*** 7424,7431 ****
      }
    
    if (DECL_P (expr))
!     check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
! 					 scope);
    
    /* Remember that there was a reference to this entity.  */
    if (DECL_P (expr))
--- 7454,7464 ----
      }
    
    if (DECL_P (expr))
!     {
!       if (!TREE_NO_ACCESS_CHECK_P (qualified_id) || processing_typedef)
! 	check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
! 					     scope);
!     }
    
    /* Remember that there was a reference to this entity.  */
    if (DECL_P (expr))
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef1.C gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef1.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef1.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef1.C	Sat Dec 11 18:06:12 2004
***************
*** 0 ****
--- 1,27 ----
+ // { dg-do compile }
+ 
+ // Origin: Wolfgang Roehrl <wolfgang.roehrl@de.gi-de.com>
+ 
+ // PR c++/18681: Access checking of typedef to type containing typename
+ //		 (Valid case)
+ 
+ template <typename> class C1;
+ 
+ template <typename T_>
+ class C2
+ {
+   typedef T_ T_PAR_TYPE;
+   friend class C1<T_>;
+ };
+ 
+ template <typename T_>
+ class C1
+ {
+   typedef typename C2<T_>::T_PAR_TYPE T_PAR;
+   struct S1
+   {
+     T_PAR par;
+   };
+ };
+ 
+ template class C1<int>;
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef2.C gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef2.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef2.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef2.C	Sat Dec 11 18:06:12 2004
***************
*** 0 ****
--- 1,24 ----
+ // { dg-do compile }
+ 
+ // Origin: Wolfgang Roehrl <wolfgang.roehrl@de.gi-de.com>
+ 
+ // PR c++/18681: Access checking of typedef to type containing typename
+ //		 (Invalid case)
+ 
+ template <typename T_>
+ class C2
+ {
+   typedef T_ T_PAR_TYPE;			// { dg-error "private" }
+ };
+ 
+ template <typename T_>
+ class C1
+ {
+   typedef typename C2<T_>::T_PAR_TYPE T_PAR;	// { dg-error "this context" }
+   struct S1
+   {
+     T_PAR par;
+   };
+ };
+ 
+ template class C1<int>;				// { dg-error "instantiated" }
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef3.C gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef3.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef3.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef3.C	Sat Dec 11 18:06:12 2004
***************
*** 0 ****
--- 1,26 ----
+ // { dg-do compile }
+ 
+ // Origin: Wolfgang Roehrl <wolfgang.roehrl@de.gi-de.com>
+ 
+ // PR c++/18681: Access checking of typedef to type containing typename
+ //		 (Invalid case)
+ 
+ template <typename> class C1;
+ 
+ template <typename T_> class C2
+ {
+   typedef T_ T_PAR_TYPE;			// { dg-error "private" }
+   friend class C1<T_>;
+ };
+ 
+ template <typename T_>
+ class C1
+ {
+   struct S1
+   {
+     typedef typename C2<T_>::T_PAR_TYPE T_PAR;	// { dg-error "this context" }
+     T_PAR par;
+   };
+ };
+ 
+ template class C1<int>;				// { dg-error "instantiated" }
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef4.C gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef4.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef4.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef4.C	Sat Dec 11 18:06:12 2004
***************
*** 0 ****
--- 1,28 ----
+ // { dg-do compile }
+ 
+ // Origin: Wolfgang Roehrl <wolfgang.roehrl@de.gi-de.com>
+ 
+ // PR c++/18681: Access checking of typedef to type containing typename
+ //		 (Invalid case)
+ 
+ template <typename> class C1;
+ 
+ template <typename T_>
+ class C2
+ {
+   typedef T_ T_PAR_TYPE;
+   friend class C1<T_>;
+ };
+ 
+ template <typename T_>
+ class C1
+ {
+   typedef typename C2<T_>::T_PAR_TYPE T_PAR;
+   struct S1
+   {
+     typedef T_PAR T_PAR2;
+     T_PAR2 par;
+   };
+ };
+ 
+ template class C1<int>;
diff -cprN gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef5.C gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef5.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/access-typedef5.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/access-typedef5.C	Sat Dec 11 18:06:12 2004
***************
*** 0 ****
--- 1,29 ----
+ // { dg-do compile }
+ 
+ // Origin: Wolfgang Roehrl <wolfgang.roehrl@de.gi-de.com>
+ 
+ // PR c++/18681: Access checking of typedef to type containing
+ //		 member template
+ 
+ template <typename> class C1;
+ 
+ template <typename T_>
+ class C2
+ {
+   template <typename U_> class D {};
+   friend class C1<T_>;
+ };
+ 
+ template <template <typename T_> class> class C3 {};
+ 
+ template <typename T_>
+ class C1
+ {
+   typedef C3<C2<T_>::template D> T_PAR;
+   struct S1
+   {
+     T_PAR par;
+   };
+ };
+ 
+ template class C1<int>;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]