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 PR 5661


This patch implements the consensus reached regarding variably
modified types as template arguments -- namely that they shouldn't be
template arguments.

It turns out that the C++ front end (unlike the C front end) already
tried to prevent VLMs from being used as data members -- but didn't
quite succeed.  I tightened up that check.

Tested on i686-pc-linux-gnu, applied on the mainline.  

I will apply it on the branch shortly as well; crashing on the code in
vlm1.C is a regression.

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

2002-10-11  Mark Mitchell  <mark@codesourcery.com>

	PR c++/5661
	* cp-tree.h (variably_modified_type_p): New function.
	(grokdeclarator) Tighten check for variably modified types as
	fields.
	* pt.c (convert_template_argument): Do not allow variably modified
	types as template arguments.
	* tree.c (variably_modified_type_p): New function.	

2002-10-11  Mark Mitchell  <mark@codesourcery.com>

	PR c++/5661
	* g++.dg/ext/vlm1.C: New test.
	* g++.dg/ext/vlm2.C: Likewise.

Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.757
diff -c -5 -p -r1.757 cp-tree.h
*** cp/cp-tree.h	11 Oct 2002 16:50:40 -0000	1.757
--- cp/cp-tree.h	11 Oct 2002 19:44:57 -0000
*************** extern void lang_check_failed			PARAMS (
*** 4177,4186 ****
--- 4177,4187 ----
  extern tree stabilize_expr			PARAMS ((tree, tree *));
  extern tree cxx_unsave_expr_now			PARAMS ((tree));
  extern tree cxx_maybe_build_cleanup		PARAMS ((tree));
  extern void init_tree			        PARAMS ((void));
  extern int pod_type_p				PARAMS ((tree));
+ extern bool variably_modified_type_p            (tree);
  extern int zero_init_p				PARAMS ((tree));
  extern tree canonical_type_variant              PARAMS ((tree));
  extern void unshare_base_binfos			PARAMS ((tree));
  extern int member_p				PARAMS ((tree));
  extern cp_lvalue_kind real_lvalue_p		PARAMS ((tree));
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.946
diff -c -5 -p -r1.946 decl.c
*** cp/decl.c	11 Oct 2002 16:50:40 -0000	1.946
--- cp/decl.c	11 Oct 2002 19:45:00 -0000
*************** grokdeclarator (declarator, declspecs, d
*** 10917,10939 ****
  
  	    declarator = TREE_OPERAND (declarator, 0);
  
  	    type = create_array_type_for_decl (dname, type, size);
  
- 	    /* VLAs never work as fields.  */
- 	    if (decl_context == FIELD && !processing_template_decl
- 		&& TREE_CODE (type) == ARRAY_TYPE
- 		&& TYPE_DOMAIN (type) != NULL_TREE
- 		&& !TREE_CONSTANT (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
- 	      {
- 		error ("size of member `%D' is not constant", dname);
- 		/* Proceed with arbitrary constant size, so that offset
- 		   computations don't get confused.  */
- 		type = create_array_type_for_decl (dname, TREE_TYPE (type),
- 						   integer_one_node);
- 	      }
- 
  	    ctype = NULL_TREE;
  	  }
  	  break;
  
  	case CALL_EXPR:
--- 10917,10926 ----
*************** grokdeclarator (declarator, declspecs, d
*** 11406,11415 ****
--- 11393,11410 ----
        && TREE_OVERFLOW (TYPE_SIZE (type)))
      {
        error ("size of array `%s' is too large", name);
        /* If we proceed with the array type as it is, we'll eventually
  	 crash in tree_low_cst().  */
+       type = error_mark_node;
+     }
+ 
+   if (decl_context == FIELD 
+       && !processing_template_decl 
+       && variably_modified_type_p (type))
+     {
+       error ("data member may not have variably modified type `%T'", type);
        type = error_mark_node;
      }
  
    if (explicitp == 1 || (explicitp && friendp))
      {
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.623
diff -c -5 -p -r1.623 pt.c
*** cp/pt.c	8 Oct 2002 22:52:14 -0000	1.623
--- cp/pt.c	11 Oct 2002 19:45:01 -0000
*************** convert_template_argument (parm, arg, ar
*** 3465,3474 ****
--- 3465,3484 ----
  		    error
  		      ("template-argument `%T' uses local type `%T'",
  		       val, t);
  		  return error_mark_node;
  		}
+ 
+ 	      /* In order to avoid all sorts of complications, we do
+ 		 not allow variably-modified types as template
+ 		 arguments.  */
+ 	      if (variably_modified_type_p (val))
+ 		{
+ 		  error ("template-argument `%T' is a variably modified type",
+ 			 val);
+ 		  return error_mark_node;
+ 		}
  	    }
  	}
      }
    else
      {
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.303
diff -c -5 -p -r1.303 tree.c
*** cp/tree.c	30 Sep 2002 19:33:05 -0000	1.303
--- cp/tree.c	11 Oct 2002 19:45:02 -0000
*************** pod_type_p (t)
*** 1956,1965 ****
--- 1956,2031 ----
    if (CLASSTYPE_NON_POD_P (t))
      return 0;
    return 1;
  }
  
+ /* Returns true if T is a variably modified type, in the sense of
+    C99.
+ 
+    In C99, a struct type is never variably modified because a VLA may
+    not appear as a structure member.  However, in GNU C code like:
+     
+      struct S { int i[f()]; };
+ 
+    is valid.  Even though GNU C++ does not allow that, this function
+    may sometimes be used in the C front end, so it treats any type
+    with variable size in the same way that C99 treats VLAs.
+ 
+    In particular, a variably modified type is one that involves a type
+    with variable size.  */
+ 
+ bool
+ variably_modified_type_p (tree type)
+ {
+   /* If TYPE itself has variable size, it is variably modified.  
+ 
+      We do not yet have a representation of the C99 '[*]' syntax.
+      When a representation is chosen, this function should be modified
+      to test for that case as well.  */
+   if (TYPE_SIZE (type) 
+       && TYPE_SIZE (type) != error_mark_node
+       && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+     return true;
+ 
+   /* If TYPE is a pointer or reference, it is variably modified if and
+      only if the type pointed to is variably modified.  */
+   if (TYPE_PTR_P (type)
+       || TREE_CODE (type) == REFERENCE_TYPE)
+     return variably_modified_type_p (TREE_TYPE (type));
+   
+   /* If TYPE is an array, it is variably modified if the array
+      elements are.  (Note that the VLA case has alredy been checked
+      above).  */
+   if (TREE_CODE (type) == ARRAY_TYPE)
+     return variably_modified_type_p (TREE_TYPE (type));
+ 
+   /* If TYPE is a pointer-to-member, it is variably modified if either
+      the class or the member are variably modified.  */
+   if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
+     return (variably_modified_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
+ 	    || variably_modified_type_p (TYPE_PTRMEM_POINTED_TO_TYPE (type)));
+ 
+   /* If TYPE Is a function type, it is variably modified if any of the
+      parameters or the return type are variably modified.  */
+   if (TREE_CODE (type) == FUNCTION_TYPE
+       || TREE_CODE (type) == METHOD_TYPE)
+     {
+       tree parm;
+ 
+       if (variably_modified_type_p (TREE_TYPE (type)))
+ 	return true;
+       for (parm = TYPE_ARG_TYPES (type); 
+ 	   parm && parm != void_list_node; 
+ 	   parm = TREE_CHAIN (parm))
+ 	if (variably_modified_type_p (TREE_VALUE (parm)))
+ 	  return true;
+     }
+ 
+   /* All other types are not variably modified.  */
+   return false;
+ }
+ 
  /* Returns 1 iff zero initialization of type T means actually storing
     zeros in it.  */
  
  int
  zero_init_p (t)
Index: testsuite/g++.dg/ext/vlm1.C
===================================================================
RCS file: testsuite/g++.dg/ext/vlm1.C
diff -N testsuite/g++.dg/ext/vlm1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/vlm1.C	11 Oct 2002 19:45:04 -0000
***************
*** 0 ****
--- 1,13 ----
+ // { dg-options "" }
+ 
+ template <class T> struct A {};
+  
+ struct B {
+   static const int s;
+   A<int[s]> a; // { dg-error "variably modified|no type" }
+ };
+  
+ const int B::s=16;
+  
+ B b;
+  
Index: testsuite/g++.dg/ext/vlm2.C
===================================================================
RCS file: testsuite/g++.dg/ext/vlm2.C
diff -N testsuite/g++.dg/ext/vlm2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/vlm2.C	11 Oct 2002 19:45:04 -0000
***************
*** 0 ****
--- 1,13 ----
+ // { dg-options "" }
+ 
+ int n;
+ 
+ struct Y
+ {
+   void f () {
+     typedef int X[n];
+     struct Z {
+       X x; // { dg-error "variably modified" }
+     };
+   }
+ };


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