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] Fix PR13092 regression (non-dependent SCOPE_REF)


Hi

This is the patch to fix 3.4 regression PR13092.  SCOPE_REF representing 
nondependent names is not properly built with its TREE_TYPE set inside
build_offset_ref.  Changing this also requires adjustments to other
functions:

- convert_nontype_argument now has to deal with this kind of SCOPE_REF.
  We need to verify that the given template argument matches the parameter
  by resolving SCOPE_REF and checking while still returning this SCOPE_REF
  to the caller upon success.  Later during template substitution (in
  tsubst_qualified_id), we need this SCOPE_REF for correct access checking.

- Somehow a latent bug in friend_accessible_p is triggered.  It expects
  a RECORD_TYPE node for friend class and either FUNCTION_DECL or
  TEMPLATE_DECL for friend function.  But it manages to recurse itself
  with type of wrong argument.

The rests are minor tweak to add robustness to tsubst_qualified_id
(due to the new tsubst_copy_and_build call in convert_nontype_argument)
and type_dependent_exp (the type of SCOPE_REF can now be unknown_type_node
when operand 1 is a BASELINK).

Tested on i686-pc-linux-gnu with no regressions.  OK for 3.4 branch and
mainline?

--Kriang


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

	PR c++/13092
	* init.c (build_offset_ref): Build SCOPE_REF with non-null
	TREE_TYPE for non-dependent names.
	* pt.c (convert_nontype_argument): Handle non-dependent SCOPE_REF.
	(tsubst_qualified_id): Only use DECL_INITIAL when it is available.
	(type_dependent_expression_p): Handle SCOPE_REF with
	unknown_type_node as its TREE_TYPE.
	* search.c (friend_accessible_p): Correctly recurse when scope is
	a class template specialization.

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

	PR c++/13092
	* g++.dg/template/non-dependent5.C: New test.
	* g++.dg/template/non-dependent6.C: Likewise.
	* g++.dg/template/non-dependent7.C: Likewise.
	* g++.dg/template/non-dependent8.C: Likewise.
	* g++.dg/template/non-dependent9.C: Likewise.


diff -cprN gcc-main-save/gcc/cp/init.c gcc-main-new/gcc/cp/init.c
*** gcc-main-save/gcc/cp/init.c	Wed Jan 14 21:54:43 2004
--- gcc-main-new/gcc/cp/init.c	Sun Jan 18 16:38:44 2004
*************** build_offset_ref (tree type, tree name, 
*** 1368,1374 ****
    if (TREE_CODE (name) == TEMPLATE_DECL)
      return name;
  
!   if (processing_template_decl || uses_template_parms (type))
      return build_min_nt (SCOPE_REF, type, name);
  
    if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
--- 1368,1374 ----
    if (TREE_CODE (name) == TEMPLATE_DECL)
      return name;
  
!   if (dependent_type_p (type) || type_dependent_expression_p (name))
      return build_min_nt (SCOPE_REF, type, name);
  
    if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
*************** build_offset_ref (tree type, tree name, 
*** 1450,1455 ****
--- 1450,1463 ----
        return error_mark_node;
      }
  
+   if (processing_template_decl)
+     {
+       if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
+ 	return build_min (SCOPE_REF, TREE_TYPE (member), type, orig_name);
+       else
+ 	return build_min (SCOPE_REF, TREE_TYPE (member), type, name);
+     }
+ 
    if (TREE_CODE (member) == TYPE_DECL)
      {
        TREE_USED (member) = 1;
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c	Fri Jan 16 00:21:40 2004
--- gcc-main-new/gcc/cp/pt.c	Sun Jan 18 16:38:44 2004
*************** convert_nontype_argument (tree type, tre
*** 3199,3205 ****
  	}
  
        if (TREE_CODE (referent) == SCOPE_REF)
! 	referent = TREE_OPERAND (referent, 1);
  
        if (is_overloaded_fn (referent))
  	/* We'll check that it has external linkage later.  */
--- 3199,3222 ----
  	}
  
        if (TREE_CODE (referent) == SCOPE_REF)
! 	{
! 	  tree orig_expr = expr;
! 
! 	  /* Resolve the EXPR and check for validity of this non-type
! 	     template argument.  We still need to keep the SCOPE_REF
! 	     around for later access checking however.  */
! 	  int saved_processing_template_decl = processing_template_decl; 
! 	  processing_template_decl = 0;
! 	  expr = tsubst_copy_and_build (expr, /*args=*/NULL_TREE,
! 					tf_error, /*in_decl=*/NULL_TREE,
! 					/*function_p=*/false);
! 	  processing_template_decl = saved_processing_template_decl; 
! 
! 	  expr = convert_nontype_argument (type, expr);
! 	  if (expr == error_mark_node)
! 	    return error_mark_node;
! 	  return orig_expr;
! 	}
  
        if (is_overloaded_fn (referent))
  	/* We'll check that it has external linkage later.  */
*************** tsubst_qualified_id (tree qualified_id, 
*** 7242,7248 ****
    if (DECL_P (expr))
      {
        mark_used (expr);
!       if (!args && TREE_CODE (expr) == VAR_DECL)
  	expr = DECL_INITIAL (expr);
      }
  
--- 7259,7265 ----
    if (DECL_P (expr))
      {
        mark_used (expr);
!       if (!args && TREE_CODE (expr) == VAR_DECL && DECL_INITIAL (expr))
  	expr = DECL_INITIAL (expr);
      }
  
*************** type_dependent_expression_p (tree expres
*** 11743,11752 ****
  	return dependent_type_p (type);
      }
	  
!   if (TREE_CODE (expression) == SCOPE_REF
!       && dependent_scope_ref_p (expression,
! 				type_dependent_expression_p))
!     return true;
  
    if (TREE_CODE (expression) == FUNCTION_DECL
        && DECL_LANG_SPECIFIC (expression)
--- 11760,11771 ----
  	return dependent_type_p (type);
      }
  
!   if (TREE_CODE (expression) == SCOPE_REF)
!     {
!       return dependent_scope_ref_p (expression,
! 				    type_dependent_expression_p)
! 	     || dependent_type_p (TREE_TYPE (expression));
!     }
  
    if (TREE_CODE (expression) == FUNCTION_DECL
        && DECL_LANG_SPECIFIC (expression)
diff -cprN gcc-main-save/gcc/cp/search.c gcc-main-new/gcc/cp/search.c
*** gcc-main-save/gcc/cp/search.c	Tue Dec 23 22:15:41 2003
--- gcc-main-new/gcc/cp/search.c	Sun Jan 18 16:38:44 2004
*************** friend_accessible_p (tree scope, tree de
*** 888,895 ****
        if (DECL_TEMPLATE_INFO (scope))
  	return friend_accessible_p (DECL_TI_TEMPLATE (scope), decl, binfo);
      }
!   else if (CLASSTYPE_TEMPLATE_INFO (scope))
!     return friend_accessible_p (CLASSTYPE_TI_TEMPLATE (scope), decl, binfo);
  
    return 0;
  }
--- 888,897 ----
        if (DECL_TEMPLATE_INFO (scope))
  	return friend_accessible_p (DECL_TI_TEMPLATE (scope), decl, binfo);
      }
!   else if (CLASSTYPE_TEMPLATE_INFO (scope)
! 	   && CLASSTYPE_USE_TEMPLATE (scope))
!     return friend_accessible_p (TREE_TYPE (CLASSTYPE_TI_TEMPLATE (scope)),
! 				decl, binfo);
  
    return 0;
  }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent5.C gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent5.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent5.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent5.C	Sun Jan 18 16:38:44 2004
***************
*** 0 ****
--- 1,22 ----
+ // { dg-do compile }
+ 
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+ 
+ // PR c++/13092: ICE taking address of member which is non-dependent
+ 
+ struct S
+ {
+   int i;
+ };
+ 
+ template<int S::*p>
+ struct X
+ {};
+ 
+ template <class T>
+ struct Foo
+ {
+   X<&S::i> x;
+ };
+ 
+ template struct Foo<void>;
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent6.C gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent6.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent6.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent6.C	Sun Jan 18 16:38:44 2004
***************
*** 0 ****
--- 1,21 ----
+ // { dg-do compile }
+ 
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+ 
+ // Two-phase name lookup for address of member:
+ // Detecting error during parsing
+ 
+ struct S
+ {
+   char i;
+ };
+ 
+ template<int S::*p>
+ struct X
+ {};
+ 
+ template <class T>
+ struct Foo
+ {
+   X<&S::i> x;	// { dg-error "convert|no type" }
+ };
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent7.C gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent7.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent7.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent7.C	Sun Jan 18 16:38:44 2004
***************
*** 0 ****
--- 1,22 ----
+ // { dg-do compile }
+ 
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+ 
+ // Two-phase name lookup for address of member:
+ // Overloading function
+ 
+ struct S
+ {
+   int f();
+   int f(int);
+ };
+ 
+ template<int (S::*p)()>
+ struct X
+ {};
+ 
+ template <class T>
+ struct Foo
+ {
+   X<&S::f> x;
+ };
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent8.C gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent8.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent8.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent8.C	Sun Jan 18 16:38:44 2004
***************
*** 0 ****
--- 1,22 ----
+ // { dg-do compile }
+ 
+ // Origin: Giovanni Bajo <giovannibajo@libero.it>
+ 
+ // Two-phase name lookup for address of member:
+ // Detecting overloading function error during parsing
+ 
+ struct S
+ {
+   int f(char);
+   int f(int);
+ };
+ 
+ template<int (S::*p)()>
+ struct X
+ {};
+ 
+ template <class T>
+ struct Foo
+ {
+   X<&S::f> x;	// { dg-error "convert|no type" }
+ };
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent9.C gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent9.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/non-dependent9.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/non-dependent9.C	Sun Jan 18 16:38:44 2004
***************
*** 0 ****
--- 1,28 ----
+ // { dg-do compile }
+ 
+ // Two-phase name lookup for address of member:
+ // Protected member access
+ 
+ class B
+ {
+   protected:
+   int i;			// { dg-error "protected" }
+ };
+ 
+ template <class T> void fr ();
+ 
+ class D2 : public B
+ {
+   friend void fr<int> ();
+ };
+ 
+ template<int B::*> struct X
+ {};
+ 
+ template <class T> void fr ()
+ {
+   X<&B::i> x1;			// { dg-error "context" }
+   X<&D2::i> x2;			// { dg-error "context" }
+ }
+ 
+ template void fr<char>();	// { dg-error "instantiated" }


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