]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/6994 (ICE in find_function_data)
authorZack Weinberg <zack@codesourcery.com>
Fri, 25 Oct 2002 22:11:19 +0000 (22:11 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Fri, 25 Oct 2002 22:11:19 +0000 (22:11 +0000)
PR middle-end/6994
* c-objc-common.c (inline_forbidden_p): Can not inline
functions containing structures or unions containing VLAs.
* tree-inline.c (walk_tree): For all class 't' nodes, walk
TYPE_SIZE and TYPE_SIZE_UNIT. #undef WALK_SUBTREE_TAIL at end.
(copy_tree_r): Copy types if they are variably modified.

* hooks.c (hook_tree_bool_false): New.
* hooks.h: Prototype it.
* langhooks.h (struct lang_hooks_for_tree_inlining): Add
var_mod_type_p.
* langhooks-def.h: Default for tree_inlining.var_mod_type_p is
hook_tree_bool_false.

* tree.c (variably_modified_type_p): Moved here from
cp/tree.c.  Use lang_hooks.tree_inlining.var_mod_type_p for
language-specific cases.  Due to this, must weaken some 'if
and only if' checks to merely 'if'.
* tree.h: Prototype variably_modified_type_p.

cp:
* cp-lang.c (cp_var_mod_type_p): New: C++ hook for
variably_modified_type_p.
* cp-tree.h: Remove prototype of variably_modified_type_p.
* tree.c (variably_modified_type_p): Remove; now implemented
in language-independent code.

PR c++/7266
* decl.c (grokdeclarator): Check that TREE_OPERAND 0 of a
SCOPE_REF is not null before dereferencing it.

testsuite:
* g++.dg/ext/vla1.C, gcc.dg/vla-2.c,
g++.dg/template/typename3.C: New tests.

From-SVN: r58542

15 files changed:
gcc/ChangeLog
gcc/c-objc-common.c
gcc/cp/ChangeLog
gcc/cp/cp-lang.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/tree.c
gcc/hooks.c
gcc/hooks.h
gcc/langhooks-def.h
gcc/langhooks.h
gcc/testsuite/ChangeLog
gcc/tree-inline.c
gcc/tree.c
gcc/tree.h

index a9f03f10d7b4686ddae946a7a51b570430afb558..c5f7db3a8ce30f36cf077c84ae514075f0fbb8ae 100644 (file)
@@ -1,3 +1,25 @@
+2002-10-25  Zack Weinberg  <zack@codesourcery.com>
+
+       PR middle-end/6994
+       * c-objc-common.c (inline_forbidden_p): Can not inline
+       functions containing structures or unions containing VLAs.
+       * tree-inline.c (walk_tree): For all class 't' nodes, walk
+       TYPE_SIZE and TYPE_SIZE_UNIT. #undef WALK_SUBTREE_TAIL at end.
+       (copy_tree_r): Copy types if they are variably modified.
+
+       * hooks.c (hook_tree_bool_false): New.
+       * hooks.h: Prototype it.
+       * langhooks.h (struct lang_hooks_for_tree_inlining): Add
+       var_mod_type_p.
+       * langhooks-def.h: Default for tree_inlining.var_mod_type_p is
+       hook_tree_bool_false.
+
+       * tree.c (variably_modified_type_p): Moved here from
+       cp/tree.c.  Use lang_hooks.tree_inlining.var_mod_type_p for
+       language-specific cases.  Due to this, must weaken some 'if
+       and only if' checks to merely 'if'.
+       * tree.h: Prototype variably_modified_type_p.
+
 2002-10-22  Jim Wilson  <wilson@redhat.com>
 
        * config/i386/i386.md (subdi3_1): Add call to ix86_binary_operator_ok.
index 43ec820599bc5bd1164f4a4216526154d371685d..d2bc5c1a391b217226af458b5a882d8693593335 100644 (file)
@@ -131,6 +131,22 @@ inline_forbidden_p (nodep, walk_subtrees, fn)
 
       break;
 
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      /* We cannot inline a function of the form
+
+          void F (int i) { struct S { int ar[i]; } s; }
+
+        Attempting to do so produces a catch-22 in tree-inline.c.
+        If walk_tree examines the TYPE_FIELDS chain of RECORD_TYPE/
+        UNION_TYPE nodes, then it goes into infinite recursion on a
+        structure containing a pointer to its own type.  If it doesn't,
+        then the type node for S doesn't get adjusted properly when
+        F is inlined, and we abort in find_function_data.  */
+      for (t = TYPE_FIELDS (node); t; t = TREE_CHAIN (t))
+       if (variably_modified_type_p (TREE_TYPE (t)))
+         return node;
+
     default:
       break;
     }
index 068f43dd0f3cea4246e6bd43f33b6a6fa85d344f..90e209b52935a0c36f912ada0967a406ffe77d4a 100644 (file)
@@ -1,3 +1,16 @@
+2002-10-25  Zack Weinberg  <zack@codesourcery.com>
+
+       PR middle-end/6994
+       * cp-lang.c (cp_var_mod_type_p): New: C++ hook for
+       variably_modified_type_p.
+       * cp-tree.h: Remove prototype of variably_modified_type_p.
+       * tree.c (variably_modified_type_p): Remove; now implemented
+       in language-independent code.
+
+       PR c++/7266
+       * decl.c (grokdeclarator): Check that TREE_OPERAND 0 of a
+       SCOPE_REF is not null before dereferencing it.
+
 2002-10-24  David Edelsohn  <edelsohn@gnu.org>
 
        PR c++/7228
index b573cce317b12fa7d889f9903b645e85c7833366..1464ef6af19a848908f52e1e4a55b692ff300ec7 100644 (file)
@@ -30,6 +30,7 @@ Boston, MA 02111-1307, USA.  */
 
 static HOST_WIDE_INT cxx_get_alias_set         PARAMS ((tree));
 static tree cp_expr_size                       PARAMS ((tree));
+static bool cp_var_mod_type_p                  PARAMS ((tree));
 
 #undef LANG_HOOKS_NAME
 #define LANG_HOOKS_NAME "GNU C++"
@@ -84,6 +85,8 @@ static tree cp_expr_size                      PARAMS ((tree));
   cp_copy_res_decl_for_inlining
 #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
 #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p
+#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
+#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P cp_var_mod_type_p
 #undef LANG_HOOKS_TREE_INLINING_START_INLINING
 #define LANG_HOOKS_TREE_INLINING_START_INLINING cp_start_inlining
 #undef LANG_HOOKS_TREE_INLINING_END_INLINING
@@ -130,3 +133,21 @@ cp_expr_size (exp)
     /* Use the default code.  */
     return lhd_expr_size (exp);
 }
+
+/* Returns true if T is a variably modified type, in the sense of C99.
+   This routine needs only check cases that cannot be handled by the
+   language-independent logic in tree-inline.c.  */
+
+static bool
+cp_var_mod_type_p (tree 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)));
+
+  /* All other types are not variably modified.  */
+  return false;
+}
+
index 77a066cc8c8e01380c860d18378a23d13d68d752..9e8199f9faf8ea72ce933d586221553c0bf1e201 100644 (file)
@@ -4213,7 +4213,6 @@ 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));
index 095008d1b7841addc8406d7bf5fbb237eafb9f26..5eb410ce53b59aa426021560dd5f9d7c22fe0aab 100644 (file)
@@ -11022,8 +11022,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
              pop_decl_namespace ();
            else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
              /* Don't fall out into global scope. Hides real bug? --eichin */ ;
-           else if (! IS_AGGR_TYPE_CODE
-                    (TREE_CODE (TREE_OPERAND (declarator, 0))))
+           else if (!TREE_OPERAND (declarator, 0)
+                    || !IS_AGGR_TYPE_CODE
+                         (TREE_CODE (TREE_OPERAND (declarator, 0))))
              ;
            else if (TREE_COMPLEXITY (declarator) == current_class_depth)
              {
index 8868e6cf0b89e61564e16c66403d737f1dbb11c1..65dca00360669e15ba758cbf226432214a17e1d2 100644 (file)
@@ -1898,72 +1898,6 @@ 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 3fd876a208c042c7f08ff0294a9720ecffb6a3aa..2f71873e68cb5af8d6334d7ac62d5ceec2d68fd8 100644 (file)
@@ -38,3 +38,11 @@ hook_void_bool_false ()
 {
   return false;
 }
+
+/* Generic hook that takes (tree) and returns false.  */
+bool
+hook_tree_bool_false (a)
+     tree a ATTRIBUTE_UNUSED;
+{
+  return false;
+}
index 763ab8efc2ed888cc446be92e8865e7f820ebabf..d91aca8474a0dd35efdc9c4f1c67df2736e29312 100644 (file)
@@ -24,5 +24,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 bool hook_void_bool_false PARAMS ((void));
 void hook_void_void PARAMS ((void));
+bool hook_tree_bool_false PARAMS ((tree));
 
 #endif
index e80b798798ae08f62c82bff0019e1b406ca2975e..013211746d1f8df04305035b3b99722ce0ea5685 100644 (file)
@@ -104,6 +104,8 @@ tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
   lhd_tree_inlining_copy_res_decl_for_inlining
 #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
   lhd_tree_inlining_anon_aggr_type_p
+#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
+  hook_tree_bool_false
 #define LANG_HOOKS_TREE_INLINING_START_INLINING \
   lhd_tree_inlining_start_inlining
 #define LANG_HOOKS_TREE_INLINING_END_INLINING \
@@ -120,6 +122,7 @@ tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
   LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
   LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, \
   LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P, \
+  LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P, \
   LANG_HOOKS_TREE_INLINING_START_INLINING, \
   LANG_HOOKS_TREE_INLINING_END_INLINING, \
   LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
index 7a3c3bd0201e3348f4ecec1427730c87abbf57b5..a77ddeeb4d6606d887eb0ef915f9af3b6cce6fa1 100644 (file)
@@ -46,6 +46,7 @@ struct lang_hooks_for_tree_inlining
                                                          void *, int *,
                                                          void *));
   int (*anon_aggr_type_p) PARAMS ((union tree_node *));
+  bool (*var_mod_type_p) PARAMS ((union tree_node *));
   int (*start_inlining) PARAMS ((union tree_node *));
   void (*end_inlining) PARAMS ((union tree_node *));
   union tree_node *(*convert_parm_for_inlining) PARAMS ((union tree_node *,
index ccd13075c7ae622099daf4f1bf3f6bf6cd2d77ce..40df0f47b12a587601842b407d10b8466ca6ce47 100644 (file)
@@ -1,3 +1,8 @@
+2002-10-25  Zack Weinberg  <zack@codesourcery.com>
+
+       * g++.dg/ext/vla1.C, gcc.dg/vla-2.c,
+       g++.dg/template/typename3.C: New tests.
+
 2002-10-24  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.c-torture/execute/20021024-1.c: New test.
@@ -11,7 +16,7 @@
 
        PR c++/7679
        * g++.dg/parse/inline1.C: New test.
-       
+
 2002-10-22  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/6579
index 79f4c52f0b40b5d9685d2552e66f6e067108d119..307c35c2bb1b2e4b1f496819f2cb7251a668f146 100644 (file)
@@ -1224,6 +1224,12 @@ walk_tree (tp, func, data, htab_)
     {
       WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
     }
+  else if (TREE_CODE_CLASS (code) == 't')
+    {
+      WALK_SUBTREE (TYPE_SIZE (*tp));
+      WALK_SUBTREE (TYPE_SIZE_UNIT (*tp));
+      /* Also examine various special fields, below.  */
+    }
 
   result = (*lang_hooks.tree_inlining.walk_subtrees) (tp, &walk_subtrees, func,
                                                      data, htab);
@@ -1320,6 +1326,7 @@ walk_tree (tp, func, data, htab_)
   return NULL_TREE;
 
 #undef WALK_SUBTREE
+#undef WALK_SUBTREE_TAIL
 }
 
 /* Like walk_tree, but does not walk duplicate nodes more than 
@@ -1378,8 +1385,8 @@ copy_tree_r (tp, walk_subtrees, data)
       if (TREE_CODE (*tp) == SCOPE_STMT)
        SCOPE_STMT_BLOCK (*tp) = NULL_TREE;
     }
-  else if (TREE_CODE_CLASS (code) == 't')
-    /* There's no need to copy types, or anything beneath them.  */
+  else if (TREE_CODE_CLASS (code) == 't' && !variably_modified_type_p (*tp))
+    /* Types only need to be copied if they are variably modified.  */
     *walk_subtrees = 0;
 
   return NULL_TREE;
index dd222a3b5df82af64eb7f61c30735d90263ed99e..5ffb01006f63ab1a333f172775eeef80298a367e 100644 (file)
@@ -4335,6 +4335,65 @@ int_fits_type_p (c, type)
     }
 }
 
+/* Returns true if T is, contains, or refers to a type with variable
+   size.  This concept is more general than that of C99 'variably
+   modified types': 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, and other languages may define similar constructs.  */
+
+bool
+variably_modified_type_p (type)
+     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 
+     the type pointed to is variably modified.  */
+  if ((TREE_CODE (type) == POINTER_TYPE
+       || TREE_CODE (type) == REFERENCE_TYPE)
+      && variably_modified_type_p (TREE_TYPE (type)))
+    return true;
+  
+  /* If TYPE is an array, it is variably modified if the array
+     elements are.  (Note that the VLA case has already been checked
+     above.)  */
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && variably_modified_type_p (TREE_TYPE (type)))
+    return true;
+
+  /* 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;
+    }
+
+  /* The current language may have other cases to check, but in general,
+     all other types are not variably modified.  */
+  return (*lang_hooks.tree_inlining.var_mod_type_p) (type);
+}
+
 /* Given a DECL or TYPE, return the scope in which it was declared, or
    NULL_TREE if there is no containing scope.  */
 
index 084c3065cbd323d577b685105180ed028c94616d..03724e1818a763da24d65b21020322367a8cae73 100644 (file)
@@ -2938,6 +2938,7 @@ struct obstack;
 /* In tree.c */
 extern int really_constant_p           PARAMS ((tree));
 extern int int_fits_type_p             PARAMS ((tree, tree));
+extern bool variably_modified_type_p    PARAMS ((tree));
 extern int tree_log2                   PARAMS ((tree));
 extern int tree_floor_log2             PARAMS ((tree));
 extern void preserve_data              PARAMS ((void));