diff options
| author | Mark Mitchell <mark@codesourcery.com> | 2002-10-11 19:55:21 +0000 |
|---|---|---|
| committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2002-10-11 19:55:21 +0000 |
| commit | dac45b5c091237cb7e8f723e75b3897a8f763432 (patch) | |
| tree | 4a570b2a83e5295f39745305c4a521b00d6df0f7 /gcc/cp/tree.c | |
| parent | 46dd38849ba39f228f467edab38cfd60e6809b6e (diff) | |
| download | gcc-dac45b5c091237cb7e8f723e75b3897a8f763432.zip gcc-dac45b5c091237cb7e8f723e75b3897a8f763432.tar.gz gcc-dac45b5c091237cb7e8f723e75b3897a8f763432.tar.bz2 | |
re PR c++/5661 (Gcc 3.0.3 Seg faults compiling bad code)
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
Diffstat (limited to 'gcc/cp/tree.c')
| -rw-r--r-- | gcc/cp/tree.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 4b1142b..ddc1ce1 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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. */ |
