[C++ PATCH] Fix PR13092 (semantic checking of non-dependent SCOPE_REF)

Kriang Lerdsuwanakij lerdsuwa@users.sourceforge.net
Fri Feb 27 18:35:00 GMT 2004


Hi

This is the revised version of my earlier patch to fix PR13092.

  http://gcc.gnu.org/ml/gcc-patches/2004-01/msg01785.html

The original version dealt with two-phase lookup of SCOPE_REF (reject-legal)
and access checking (accept-illegal) issues but only two-phase problem is 
addressed in this patch.  Here is the summary of the changes:

- In init.c: This is straightforward, building SCOPE_REF with non-null
  TREE_TYPE when the name is non-dependent.

- Diagnostic fix when the operand 1 of SCOPE_REF is not IDENTIFIER_NODE
  (such as a FIELD_DECL).  Previously the scope is incorrectly displayed twice,
  like 'A::A::B' since dump_* first outputs the scope (like 'A') and then
  the name.  But when the name is a *_DECL node, its context is also outputed
  again (producing qualified ID for the name like 'A::B').  The result is
  duplicate scope.

- The change to type_dependent_expression_p to take into account SCOPE_REF
  may contain BASELINK as operand 1.  Its TREE_TYPE is unknown_type_node
  for this case.

For access checking problem, this is nasty (as can be seen from the original
patch).  We need to resolve name early to perform semantic check while still 
preserve the SCOPE_REF until the instantiation time.  TYPENAME_TYPE and
UNBOUND_CLASS_TEMPLATE that are non-dependent also have this problem.
This needs some major restructure and I'd rather consider this work for 3.5.

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

--Kriang


2004-02-27  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 (type_dependent_expression_p): Handle SCOPE_REF with
	unknown_type_node as its TREE_TYPE.
	* cxx-pretty_print.c (pp_cxx_unqualified_id): Handle BASELINK.
	* error.c (dump_decl) <SCOPE_REF case>: Use pp_expression.
	(dump_expr) <SCOPE_REF case>: Likewise.

2004-02-27  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.


diff -cprN gcc-34-save/gcc/cp/cxx-pretty-print.c gcc-34-new/gcc/cp/cxx-pretty-print.c
*** gcc-34-save/gcc/cp/cxx-pretty-print.c	Tue Dec 23 22:15:38 2003
--- gcc-34-new/gcc/cp/cxx-pretty-print.c	Tue Feb 24 21:21:56 2004
*************** pp_cxx_unqualified_id (cxx_pretty_printe
*** 177,182 ****
--- 177,186 ----
        pp_cxx_template_id (pp, t);
        break;
  
+     case BASELINK:
+       pp_cxx_unqualified_id (pp, BASELINK_FUNCTIONS (t));
+       break;
+ 
      case RECORD_TYPE:
      case UNION_TYPE:
      case ENUMERAL_TYPE:
diff -cprN gcc-34-save/gcc/cp/error.c gcc-34-new/gcc/cp/error.c
*** gcc-34-save/gcc/cp/error.c	Sat Feb 14 18:46:10 2004
--- gcc-34-new/gcc/cp/error.c	Tue Feb 24 21:21:56 2004
*************** dump_decl (tree t, int flags)
*** 814,822 ****
        break;
  
      case SCOPE_REF:
!       dump_decl (TREE_OPERAND (t, 0), flags & ~TFF_DECL_SPECIFIERS);
!       pp_colon_colon (cxx_pp); 
!       dump_decl (TREE_OPERAND (t, 1), flags);
        break;
  
      case ARRAY_REF:
--- 814,820 ----
        break;
  
      case SCOPE_REF:
!       pp_expression (cxx_pp, t);
        break;
  
      case ARRAY_REF:
*************** dump_expr (tree t, int flags)
*** 1723,1731 ****
        break;
  
      case SCOPE_REF:
!       dump_type (TREE_OPERAND (t, 0), flags);
!       pp_colon_colon (cxx_pp);
!       dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
        break;
  
      case CAST_EXPR:
--- 1721,1727 ----
        break;
  
      case SCOPE_REF:
!       pp_expression (cxx_pp, t);
        break;
  
      case CAST_EXPR:
diff -cprN gcc-34-save/gcc/cp/init.c gcc-34-new/gcc/cp/init.c
*** gcc-34-save/gcc/cp/init.c	Thu Feb  5 18:03:57 2004
--- gcc-34-new/gcc/cp/init.c	Tue Feb 24 21:21:56 2004
*************** build_offset_ref (tree type, tree name, 
*** 1371,1377 ****
    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)
--- 1371,1377 ----
    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, 
*** 1453,1458 ****
--- 1453,1466 ----
        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-34-save/gcc/cp/pt.c gcc-34-new/gcc/cp/pt.c
*** gcc-34-save/gcc/cp/pt.c	Sat Feb 14 18:49:59 2004
--- gcc-34-new/gcc/cp/pt.c	Tue Feb 24 21:21:56 2004
*************** convert_nontype_argument (tree type, tre
*** 3183,3189 ****
       --a pointer to member expressed as described in _expr.unary.op_.  */
  
    /* An integral constant-expression can include const variables or
! .     enumerators.  Simplify things by folding them to their values,
       unless we're about to bind the declaration to a reference
       parameter.  */
    if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE)
--- 3183,3189 ----
       --a pointer to member expressed as described in _expr.unary.op_.  */
  
    /* An integral constant-expression can include const variables or
!      enumerators.  Simplify things by folding them to their values,
       unless we're about to bind the declaration to a reference
       parameter.  */
    if (INTEGRAL_TYPE_P (expr_type) && TREE_CODE (type) != REFERENCE_TYPE)
*************** type_dependent_expression_p (tree expres
*** 11849,11858 ****
  	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)
--- 11849,11858 ----
  	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-34-save/gcc/testsuite/g++.dg/template/non-dependent5.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent5.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent5.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent5.C	Tue Feb 24 21:21:56 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-34-save/gcc/testsuite/g++.dg/template/non-dependent6.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent6.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent6.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent6.C	Tue Feb 24 21:21:56 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-34-save/gcc/testsuite/g++.dg/template/non-dependent7.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent7.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent7.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent7.C	Tue Feb 24 21:21:56 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-34-save/gcc/testsuite/g++.dg/template/non-dependent8.C gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent8.C
*** gcc-34-save/gcc/testsuite/g++.dg/template/non-dependent8.C	Thu Jan  1 07:00:00 1970
--- gcc-34-new/gcc/testsuite/g++.dg/template/non-dependent8.C	Tue Feb 24 21:21:56 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" }
+ };



More information about the Gcc-patches mailing list