From: Mark Mitchell Date: Fri, 11 Oct 2002 22:42:21 +0000 (+0000) Subject: re PR c++/5661 (Gcc 3.0.3 Seg faults compiling bad code) X-Git-Tag: releases/gcc-3.2.1~171 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=791238161dd02e43f9b720440c79f9d98029cfaa;p=thirdparty%2Fgcc.git re PR c++/5661 (Gcc 3.0.3 Seg faults compiling bad code) PR c++/5661 * g++.dg/ext/vlm1.C: New test. * g++.dg/ext/vlm2.C: Likewise. 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. From-SVN: r58070 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d47dcc70b78f..622dca534fc1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2002-10-11 Mark Mitchell + + 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 Jason Molenda * init.c (build_field_list): Provide uses_unions_p with a default diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4bd08799e6fd..43a9817d7836 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4200,6 +4200,7 @@ extern void end_input PARAMS ((void)); /* in tree.c */ 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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5fb7849eda5a..46cff952b4ed 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10710,19 +10710,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; @@ -11210,6 +11197,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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8fc9f743e1e0..b8e95455b577 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3430,6 +3430,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; + } } } } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 748ab9a0b9ad..fb32a71303df 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1898,6 +1898,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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1bf6f987c42c..f3008b0d9661 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2002-10-11 Mark Mitchell + + PR c++/5661 + * g++.dg/ext/vlm1.C: New test. + * g++.dg/ext/vlm2.C: Likewise. + 2002-10-09 Zack Weinberg PR c/7353