langhooks.h (struct lang_hooks_for_tree_inlining): Add start_inlining, end_inlining.
authorJason Merrill <jason@redhat.com>
Wed, 5 Dec 2001 23:48:19 +0000 (18:48 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 5 Dec 2001 23:48:19 +0000 (18:48 -0500)
        * langhooks.h (struct lang_hooks_for_tree_inlining): Add
        start_inlining, end_inlining.
        * tree-inline.c (expand_call_inline): Call them.
        * langhooks-def.h (LANG_HOOKS_TREE_INLINING_START_INLINING): Define.
        (LANG_HOOKS_TREE_INLINING_END_INLINING): Define.
        (LANG_HOOKS_TREE_INLINING_INITIALIZER): Add them.
        * langhooks.c (lhd_tree_inlining_start_inlining): New fn.
        (lhd_tree_inlining_end_inlining): New fn.

        * cp-lang.c (LANG_HOOKS_TREE_INLINING_START_INLINING): Define.
        (LANG_HOOKS_TREE_INLINING_END_INLINING): Define.
        * tree.c (cp_start_inlining, cp_end_inlining): New fns.
        * pt.c (push_tinst_level): No longer static.
        * cp-tree.h: Declare them.

        * init.c (resolve_offset_ref): Don't check access for the base
        conversion to access a FIELD_DECL.

        * cp-tree.h (TYPE_REFFN_P): New macro.
        * decl.c (bad_specifiers): Check it, too.

        * rtti.c (create_pseudo_type_info): Set CLASSTYPE_INTERFACE_ONLY
        on the __*_type_info type if we haven't seen a definition.

From-SVN: r47703

16 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-lang.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/tree.c
gcc/langhooks-def.h
gcc/langhooks.c
gcc/langhooks.h
gcc/testsuite/g++.dg/eh/spec1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/inherit/access1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/recurse.C [new file with mode: 0644]
gcc/tree-inline.c

index 941d79568fa778f83ac1d286a2d9a0e0d2ca9af6..d5adcfad67b15afd68b0898e5f4857eeb8cd49eb 100644 (file)
@@ -1,3 +1,14 @@
+2001-12-04  Jason Merrill  <jason@redhat.com>
+
+       * langhooks.h (struct lang_hooks_for_tree_inlining): Add
+       start_inlining, end_inlining.
+       * tree-inline.c (expand_call_inline): Call them.
+       * langhooks-def.h (LANG_HOOKS_TREE_INLINING_START_INLINING): Define.
+       (LANG_HOOKS_TREE_INLINING_END_INLINING): Define.
+       (LANG_HOOKS_TREE_INLINING_INITIALIZER): Add them.
+       * langhooks.c (lhd_tree_inlining_start_inlining): New fn.
+       (lhd_tree_inlining_end_inlining): New fn.
+
 2001-12-05  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * c-common.c (shadow_warning): New function, moved from cp/decl.c.
index a0a3f49fb14de418f6651fdf396954cebdeed51a..443f07fe7be2194ddf6e71aebb7233d9a5f9e259 100644 (file)
@@ -1,3 +1,20 @@
+2001-12-05  Jason Merrill  <jason@redhat.com>
+
+       * cp-lang.c (LANG_HOOKS_TREE_INLINING_START_INLINING): Define.
+       (LANG_HOOKS_TREE_INLINING_END_INLINING): Define.
+       * tree.c (cp_start_inlining, cp_end_inlining): New fns.
+       * pt.c (push_tinst_level): No longer static.
+       * cp-tree.h: Declare them.
+
+       * init.c (resolve_offset_ref): Don't check access for the base
+       conversion to access a FIELD_DECL.
+
+       * cp-tree.h (TYPE_REFFN_P): New macro.
+       * decl.c (bad_specifiers): Check it, too.
+
+       * rtti.c (create_pseudo_type_info): Set CLASSTYPE_INTERFACE_ONLY
+       on the __*_type_info type if we haven't seen a definition.
+
 2001-12-05  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * decl.c: Include c-common.h.
index 598c3fc5c7452ad6e882f87744b0874589cd2c2e..c40330bc319a39d2ecddd99a4b407262b1ecb9d4 100644 (file)
@@ -83,6 +83,10 @@ static HOST_WIDE_INT cxx_get_alias_set 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_START_INLINING
+#define LANG_HOOKS_TREE_INLINING_START_INLINING cp_start_inlining
+#undef LANG_HOOKS_TREE_INLINING_END_INLINING
+#define LANG_HOOKS_TREE_INLINING_END_INLINING cp_end_inlining
 #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
 #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree
 #undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN
index 4b6dd33ff79fdd2c3dce7586b102964488f792cb..420e2d9fed04ae1f700a775aeccff7f5d91ddf07 100644 (file)
@@ -2487,6 +2487,9 @@ extern int flag_new_for_scope;
 #define TYPE_PTRFN_P(NODE)                             \
   (TREE_CODE (NODE) == POINTER_TYPE                    \
    && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE)
+#define TYPE_REFFN_P(NODE)                             \
+  (TREE_CODE (NODE) == REFERENCE_TYPE                  \
+   && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE)
 
 /* Nonzero for _TYPE node means that this type is a pointer to member
    function type.  */
@@ -3968,6 +3971,7 @@ extern void do_decl_instantiation         PARAMS ((tree, tree, tree));
 extern void do_type_instantiation              PARAMS ((tree, tree, int));
 extern tree instantiate_decl                   PARAMS ((tree, int));
 extern tree get_bindings                       PARAMS ((tree, tree, tree));
+extern int push_tinst_level                    PARAMS ((tree));
 extern void pop_tinst_level                    PARAMS ((void));
 extern int more_specialized_class              PARAMS ((tree, tree));
 extern int is_member_template                   PARAMS ((tree));
@@ -4240,6 +4244,8 @@ extern int cp_is_overload_p PARAMS ((tree));
 extern int cp_auto_var_in_fn_p PARAMS ((tree,tree));
 extern tree cp_copy_res_decl_for_inlining PARAMS ((tree, tree, tree, void*,
                                                   int*, void*));
+extern int cp_start_inlining                   PARAMS ((tree));
+extern void cp_end_inlining                    PARAMS ((tree));
 
 /* in typeck.c */
 extern int string_conv_p                       PARAMS ((tree, tree, int));
index 2df8b229182227ec3aae3ceb4dc9677eb973422a..66aa70d89c692c5170a30e23fd1fc8b5f8acd4c3 100644 (file)
@@ -8750,6 +8750,7 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
   if (raises
       && (TREE_CODE (object) == TYPE_DECL
          || (!TYPE_PTRFN_P (TREE_TYPE (object))
+             && !TYPE_REFFN_P (TREE_TYPE (object))
              && !TYPE_PTRMEMFUNC_P (TREE_TYPE (object)))))
     cp_error_at ("`%D' declared with an exception specification", object);
 }
index 169bc8c07a0bdbcdba2577d7c0dd46bc7996f2d2..098697fa5a7c309206f1d7f40c2559d1b8f9f4f3 100644 (file)
@@ -1831,9 +1831,12 @@ resolve_offset_ref (exp)
       if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
        base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type));
 
-      basetype = lookup_base (TREE_TYPE (base), basetype, ba_check, NULL);
+      /* Don't check access on the conversion; we might be after a member
+        promoted by an access- or using-declaration, and we have already
+        checked access for the member itself.  */
+      basetype = lookup_base (TREE_TYPE (base), basetype, ba_ignore, NULL);
       expr = build_base_path (PLUS_EXPR, base, basetype, 1);
-      
+
       if (expr == error_mark_node)
        return error_mark_node;
 
index f383127edd96bfe407cd21b17229a7b7c9fae7c9..8e620bea2c5747911e43f5104ad439703b30dfad 100644 (file)
@@ -98,7 +98,6 @@ static int try_one_overload PARAMS ((tree, tree, tree, tree, tree,
                                   unification_kind_t, int));
 static int unify PARAMS ((tree, tree, tree, tree, int));
 static void add_pending_template PARAMS ((tree));
-static int push_tinst_level PARAMS ((tree));
 static void reopen_tinst_level PARAMS ((tree));
 static tree classtype_mangled_name PARAMS ((tree));
 static char *mangle_class_name_for_template PARAMS ((const char *, tree, tree));
@@ -4460,7 +4459,7 @@ static int last_template_error_tick;
 /* We're starting to instantiate D; record the template instantiation context
    for diagnostics and to restore it later.  */
 
-static int
+int
 push_tinst_level (d)
      tree d;
 {
index 3510cc10b380f3eeebb7574c6cd079aaa9af91da..a1b665e592735ceffc73787fc307f8ba25b8bcae 100644 (file)
@@ -1162,6 +1162,15 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
   
   /* Get the vtable decl. */
   real_type = xref_tag (class_type_node, get_identifier (real_name), 1);
+  if (! TYPE_SIZE (real_type))
+    {
+      /* We never saw a definition of this type, so we need to tell the
+        compiler that this is an exported class, as indeed all of the
+        __*_type_info classes are.  */
+      SET_CLASSTYPE_INTERFACE_KNOWN (real_type);
+      CLASSTYPE_INTERFACE_ONLY (real_type) = 1;
+    }
+
   vtable_decl = get_vtable_decl (real_type, /*complete=*/1);
   vtable_decl = build_unary_op (ADDR_EXPR, vtable_decl, 0);
 
@@ -1185,12 +1194,12 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
   pseudo_type = make_aggr_type (RECORD_TYPE);
   finish_builtin_type (pseudo_type, pseudo_name, fields, ix, ptr_type_node);
   TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
-  VA_CLOSE (ap);
 
   result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
   TINFO_VTABLE_DECL (result) = vtable_decl;
   TINFO_PSEUDO_TYPE (result) = pseudo_type;
   
+  VA_CLOSE (ap);
   return result;
 }
 
index 600c6e3746d3c3cede8e1df26790724d3fdac440..1d0c32475ad3e818a6eef1f58a19f5966d58ca31 100644 (file)
@@ -2230,6 +2230,30 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
   return var;
 }
 
+/* Record that we're about to start inlining FN, and return non-zero if
+   that's OK.  Used for lang_hooks.tree_inlining.start_inlining.  */
+
+int
+cp_start_inlining (fn)
+     tree fn;
+{
+  if (DECL_TEMPLATE_INSTANTIATION (fn))
+    return push_tinst_level (fn);
+  else
+    return 1;
+}
+
+/* Record that we're done inlining FN.  Used for
+   lang_hooks.tree_inlining.end_inlining.  */
+
+void
+cp_end_inlining (fn)
+     tree fn ATTRIBUTE_UNUSED;
+{
+  if (DECL_TEMPLATE_INSTANTIATION (fn))
+    pop_tinst_level ();
+}
+
 /* Initialize tree.c.  */
 
 void
index 910d1f543594609bfe192d8e398e41d8e4ac4101..ca55a82797da9cfb676e62384cec099716e76dc2 100644 (file)
@@ -60,6 +60,8 @@ tree lhd_tree_inlining_copy_res_decl_for_inlining PARAMS ((tree, tree,
                                                           tree, void *,
                                                           int *, void *));
 int lhd_tree_inlining_anon_aggr_type_p         PARAMS ((tree));
+int lhd_tree_inlining_start_inlining           PARAMS ((tree));
+void lhd_tree_inlining_end_inlining            PARAMS ((tree));
 
 #define LANG_HOOKS_NAME                        "GNU unknown"
 #define LANG_HOOKS_IDENTIFIER_SIZE     sizeof (struct lang_identifier)
@@ -97,6 +99,10 @@ int lhd_tree_inlining_anon_aggr_type_p               PARAMS ((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_START_INLINING \
+  lhd_tree_inlining_start_inlining
+#define LANG_HOOKS_TREE_INLINING_END_INLINING \
+  lhd_tree_inlining_end_inlining
 
 #define LANG_HOOKS_TREE_INLINING_INITIALIZER { \
   LANG_HOOKS_TREE_INLINING_WALK_SUBTREES, \
@@ -106,7 +112,9 @@ int lhd_tree_inlining_anon_aggr_type_p              PARAMS ((tree));
   LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P, \
   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_ANON_AGGR_TYPE_P, \
+  LANG_HOOKS_TREE_INLINING_START_INLINING, \
+  LANG_HOOKS_TREE_INLINING_END_INLINING \
 } \
 
 /* Tree dump hooks.  */
index 5e0098680e35e8508d2aed251c395c4f84d6d5d1..e2e72826bb3caabba5c714ade1a811ceb276a8b5 100644 (file)
@@ -240,6 +240,27 @@ lhd_tree_inlining_anon_aggr_type_p (t)
   return 0;
 }
 
+/* lang_hooks.tree_inlining.start_inlining and end_inlining perform any
+   language-specific bookkeeping necessary for processing
+   FN. start_inlining returns non-zero if inlining should proceed, zero if
+   not.
+
+   For instance, the C++ version keeps track of template instantiations to
+   avoid infinite recursion.  */
+
+int
+lhd_tree_inlining_start_inlining (fn)
+     tree fn ATTRIBUTE_UNUSED;
+{
+  return 1;
+}
+
+void
+lhd_tree_inlining_end_inlining (fn)
+     tree fn ATTRIBUTE_UNUSED;
+{
+}
+
 /* lang_hooks.tree_dump.dump_tree:  Dump language-specific parts of tree 
    nodes.  Returns non-zero if it does not want the usual dumping of the 
    second argument.  */
index 8ce5674ebe9d5c4fe1ca8f2e03493d090c8fcdc9..81ae71b4dc0d0794ef4fdc4769bc2c8edc21fb16 100644 (file)
@@ -46,6 +46,8 @@ struct lang_hooks_for_tree_inlining
                                                          void *, int *,
                                                          void *));
   int (*anon_aggr_type_p) PARAMS ((union tree_node *));
+  int (*start_inlining) PARAMS ((union tree_node *));
+  void (*end_inlining) PARAMS ((union tree_node *));
 };
 
 /* The following hooks are used by tree-dump.c.  */
diff --git a/gcc/testsuite/g++.dg/eh/spec1.C b/gcc/testsuite/g++.dg/eh/spec1.C
new file mode 100644 (file)
index 0000000..0bd0cbc
--- /dev/null
@@ -0,0 +1,5 @@
+// Check that we allow an exception specification on a reference-to-function.
+// { dg-do compile }
+
+void f () throw ();
+void (&fp)() throw () = f;
diff --git a/gcc/testsuite/g++.dg/inherit/access1.C b/gcc/testsuite/g++.dg/inherit/access1.C
new file mode 100644 (file)
index 0000000..7f2ec68
--- /dev/null
@@ -0,0 +1,19 @@
+// Test that we can access a member from an inaccessible base if it has
+// been promoted with a using-declaration.
+
+// { dg-do compile }
+
+struct A
+{
+  int i;
+};
+
+struct B: private A
+{
+  using A::i;
+};
+
+struct C: public B
+{
+  void f () { B::i = 0; }
+};
diff --git a/gcc/testsuite/g++.dg/template/recurse.C b/gcc/testsuite/g++.dg/template/recurse.C
new file mode 100644 (file)
index 0000000..61b9409
--- /dev/null
@@ -0,0 +1,22 @@
+// Test for handling of excessive template recursion.
+// { dg-options "-ftemplate-depth-50 -O" }
+
+template <int I> struct F
+{
+  int operator()()
+    {
+      F<I+1> f;                        // { dg-error "" "" }
+      return f()*I;
+    }
+};
+
+template <> struct F<52>
+{
+  int operator()() { return 0; }
+};
+
+int main ()
+{
+  F<1> f;
+  return f();          // { dg-error "instantiate" "excessive recursion" }
+}
index f82c8c90ae5de7df78ded6a9983279b611664e92..1444edf10ea03d4a91729f24f5ca74af96cae3d8 100644 (file)
@@ -812,6 +812,9 @@ expand_call_inline (tp, walk_subtrees, data)
   if (!inlinable_function_p (fn, id))
     return NULL_TREE;
 
+  if (! (*lang_hooks.tree_inlining.start_inlining) (fn))
+    return NULL_TREE;
+
   /* Set the current filename and line number to the function we are
      inlining so that when we create new _STMT nodes here they get
      line numbers corresponding to the function we are calling.  We
@@ -951,6 +954,8 @@ expand_call_inline (tp, walk_subtrees, data)
   /* Don't walk into subtrees.  We've already handled them above.  */
   *walk_subtrees = 0;
 
+  (*lang_hooks.tree_inlining.end_inlining) (fn);
+
   /* Keep iterating.  */
   return NULL_TREE;
 }