]> gcc.gnu.org Git - gcc.git/commitdiff
re PR c++/5661 (Gcc 3.0.3 Seg faults compiling bad code)
authorMark Mitchell <mark@codesourcery.com>
Fri, 11 Oct 2002 19:55:21 +0000 (19:55 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 11 Oct 2002 19:55:21 +0000 (19:55 +0000)
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.

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

From-SVN: r58060

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/vlm1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/vlm2.C [new file with mode: 0644]

index 3246ea23705edfa8acb2059b57cd9fb52ea26bbf..5704c900663998934bbbd816fc2f4d9e5beed1fe 100644 (file)
 
 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.      
+
        * NEWS: Document removal of "new X = ..." extension.
        * class.c (initialize_array): Set TREE_HAS_CONSTRUCTOR on
        brace-enclosed initializers.
index 97b7177d14b9a373dfe3563c26c8c541e200a188..d3d064a0dadc948d18d5bb827768d8d7268528d3 100644 (file)
@@ -4179,6 +4179,7 @@ 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));
index f8202b46e46c453871bad54dc99e6f783b0d9b40..4401954adcbab8a6913d9e3f8c08b121eac405f4 100644 (file)
@@ -10928,19 +10928,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
            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;
@@ -11420,6 +11407,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       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))
     {
       /* [dcl.fct.spec] The explicit specifier shall only be used in
index 46d91abd301e5f321442e0162b044ad6f20509ca..ceff84f0a06583d1ab698a4e97c9215ae4674050 100644 (file)
@@ -3467,6 +3467,16 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
                       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;
+               }
            }
        }
     }
index 4b1142b11545a62851892cb6b2e7d888ba4ddd80..ddc1ce1001ae7b6ce98feddc2605d4f9c8cc632c 100644 (file)
@@ -1958,6 +1958,72 @@ pod_type_p (t)
   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.  */
 
index 882e0227acc6f14f4513691b8b2a935bf0761e3c..f04daad57d380701f8e7b98b4fbb4c71af14a46e 100644 (file)
@@ -1,5 +1,9 @@
 2002-10-11  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/5661
+       * g++.dg/ext/vlm1.C: New test.
+       * g++.dg/ext/vlm2.C: Likewise.
+       
        * g++.dg/init/array1.C: Remove invalid braces.
        * g++.dg/init/brace1.C: New test.
        * g++.dg/init/copy2.C: Likewise.
diff --git a/gcc/testsuite/g++.dg/ext/vlm1.C b/gcc/testsuite/g++.dg/ext/vlm1.C
new file mode 100644 (file)
index 0000000..61628e6
--- /dev/null
@@ -0,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;
diff --git a/gcc/testsuite/g++.dg/ext/vlm2.C b/gcc/testsuite/g++.dg/ext/vlm2.C
new file mode 100644 (file)
index 0000000..3a0b335
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-options "" }
+
+int n;
+
+struct Y
+{
+  void f () {
+    typedef int X[n];
+    struct Z {
+      X x; // { dg-error "variably modified" }
+    };
+  }
+};
This page took 0.131492 seconds and 5 git commands to generate.