diff options
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/cp/cp-lang.c | 4 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 1 | ||||
-rw-r--r-- | gcc/cp/init.c | 7 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 11 | ||||
-rw-r--r-- | gcc/cp/tree.c | 24 | ||||
-rw-r--r-- | gcc/langhooks-def.h | 10 | ||||
-rw-r--r-- | gcc/langhooks.c | 21 | ||||
-rw-r--r-- | gcc/langhooks.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/spec1.C | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/inherit/access1.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/recurse.C | 22 | ||||
-rw-r--r-- | gcc/tree-inline.c | 5 |
16 files changed, 162 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 941d795..d5adcfa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a0a3f49..443f07f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 598c3fc..c40330b 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4b6dd33..420e2d9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2df8b22..66aa70d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 169bc8c..098697f 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f383127..8e620be 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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; { diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 3510cc1..a1b665e 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -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; } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 600c6e3..1d0c324 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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 diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index 910d1f5..ca55a82 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -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. */ diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 5e00986..e2e7282 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -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. */ diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 8ce5674..81ae71b 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -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 index 0000000..0bd0cbc --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/spec1.C @@ -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 index 0000000..7f2ec68 --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/access1.C @@ -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 index 0000000..61b9409 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/recurse.C @@ -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" } +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index f82c8c9..1444edf 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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; } |