C++ PATCH for templates/const confusion

Mark Mitchell mark@codesourcery.com
Tue Apr 13 21:15:00 GMT 1999


Pity the poor user who writes something like:

   #include <map>
   void f() {
     map<int, double> m1, m2;
    
     map<int, double>::iterator i = m1.begin();
     map<int, double>::iterator j = m2.begin();
     while (i != m1.end()) {
       *j = *i;
       ++i; 
       ++j;
     }
   }

This code looks like it copies one map to another, but its not legal.
(What's the bug?  The type of `*j' is `pair<const int, double>', not
`double', as one might expect.  It would be utterly bogus to assign
these, and the `const int' is supposed to prevent that.)

We, however, did not flag the error.  There were two bugs: we were not
marking template FIELD_DECLs TREE_READONLY when we should have, and we
were checking TREE_READONLY when we should have been checking the
const-ness of types.  TREE_READONLY is for communication with the
middle-end and says what can and cannot be modified; CP_TYPE_CONST_P
is for the linguistic notion of "const".

Here's the fix.

-- 
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-04-13  Mark Mitchell  <mark@codesourcery.com>

	* class.c (finish_struct_1): Look at the const-ness of the field's
	type, not the TREE_READONLY-ness of the declaration.
	* method.c (synthesize_method): Likewise.
	* pt.c (tsubst_decl): Call c_apply_type_quals_to_decl when
	creating new declarations.
Index: testsuite/g++.old-deja/g++.pt/assign1.C
===================================================================
RCS file: assign1.C
diff -N assign1.C
*** /dev/null	Sat Dec  5 20:30:03 1998
--- assign1.C	Tue Apr 13 21:12:23 1999
***************
*** 0 ****
--- 1,14 ----
+ // Build don't link:
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ template <class T>
+ struct S {
+   S();
+   T t;
+ };
+ 
+ void f()
+ {
+   S<const int> s;
+   s = s; // ERROR - generated assignment operator is illegal
+ }
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.142
diff -c -p -r1.142 class.c
*** class.c	1999/04/05 12:34:17	1.142
--- class.c	1999/04/14 04:06:48
*************** finish_struct_1 (t, warn_anon)
*** 3360,3366 ****
          has_mutable = 1;
  
        /* If any field is const, the structure type is pseudo-const.  */
!       if (TREE_READONLY (x))
  	{
  	  C_TYPE_FIELDS_READONLY (t) = 1;
  	  if (DECL_INITIAL (x) == NULL_TREE)
--- 3360,3366 ----
          has_mutable = 1;
  
        /* If any field is const, the structure type is pseudo-const.  */
!       if (CP_TYPE_CONST_P (TREE_TYPE (x)))
  	{
  	  C_TYPE_FIELDS_READONLY (t) = 1;
  	  if (DECL_INITIAL (x) == NULL_TREE)
Index: cp/method.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/method.c,v
retrieving revision 1.96
diff -c -p -r1.96 method.c
*** method.c	1999/04/02 15:36:19	1.96
--- method.c	1999/04/14 04:06:58
*************** do_build_assign_ref (fndecl)
*** 2341,2347 ****
  	  if (TREE_CODE (field) != FIELD_DECL)
  	    continue;
  
! 	  if (TREE_READONLY (field))
  	    {
  	      if (DECL_NAME (field))
  		cp_error ("non-static const member `%#D', can't use default assignment operator", field);
--- 2341,2347 ----
  	  if (TREE_CODE (field) != FIELD_DECL)
  	    continue;
  
! 	  if (CP_TYPE_CONST_P (TREE_TYPE (field)))
  	    {
  	      if (DECL_NAME (field))
  		cp_error ("non-static const member `%#D', can't use default assignment operator", field);
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.282
diff -c -p -r1.282 pt.c
*** pt.c	1999/04/11 00:34:02	1.282
--- pt.c	1999/04/14 04:07:08
*************** tsubst_decl (t, args, type, in_decl)
*** 5687,5692 ****
--- 5687,5694 ----
        {
  	r = copy_node (t);
  	TREE_TYPE (r) = type;
+ 	c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
+ 
  	if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
  	  DECL_INITIAL (r) = TREE_TYPE (r);
  	else
*************** tsubst_decl (t, args, type, in_decl)
*** 5709,5720 ****
      case FIELD_DECL:
        {
  	r = copy_node (t);
- 	TREE_TYPE (r) = type;
  	copy_lang_decl (r);
! #if 0
! 	DECL_FIELD_CONTEXT (r) = tsubst (DECL_FIELD_CONTEXT (t), args, 
! 					 /*complain=*/1, in_decl);
! #endif
  	DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
  					/*complain=*/1, in_decl);
  	TREE_CHAIN (r) = NULL_TREE;
--- 5711,5722 ----
      case FIELD_DECL:
        {
  	r = copy_node (t);
  	copy_lang_decl (r);
! 	TREE_TYPE (r) = type;
! 	c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
! 
! 	/* We don't have to set DECL_CONTEXT here; it is set by
! 	   finish_member_declaration.  */
  	DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
  					/*complain=*/1, in_decl);
  	TREE_CHAIN (r) = NULL_TREE;
*************** tsubst_decl (t, args, type, in_decl)
*** 5760,5765 ****
--- 5762,5768 ----
  
  	r = copy_node (t);
  	TREE_TYPE (r) = type;
+ 	c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
  	DECL_CONTEXT (r) = ctx;
  	if (TREE_STATIC (r))
  	  DECL_ASSEMBLER_NAME (r)


More information about the Gcc-patches mailing list