From bd0d5d4a5e3ecf01c4f5d2c537ad4b3a10d94777 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 8 Feb 2001 10:54:39 -0500 Subject: [PATCH] search.c (shared_member_p): New function. * search.c (shared_member_p): New function. (lookup_field_r): Use it. * cp-tree.h (SHARED_MEMBER_P): Remove. * method.c (process_overload_item): Handle template-dependent array bounds. * pt.c (type_unification_real): If we end up with undeduced nontype parms, try again. * decl.c (lookup_name_real): Tweak warning to refer to decls, not types. * typeck2.c (friendly_abort): Don't say anything if we have earlier errors or sorries. * decl.c (check_tag_decl): Notice attempts to redefine bool and wchar_t. Ignore if in_system_header. * decl.c (maybe_push_cleanup_level): New fn... (start_decl_1): ...split out from here. * cvt.c (build_up_reference): Use it. * cp-tree.h: Declare it. From-SVN: r39540 --- gcc/cp/ChangeLog | 25 +++++++++ gcc/cp/cp-tree.h | 7 +-- gcc/cp/cvt.c | 1 + gcc/cp/decl.c | 52 ++++++++++++------ gcc/cp/method.c | 16 ++++-- gcc/cp/pt.c | 55 ++++++++++++++----- gcc/cp/search.c | 34 +++++++++++- gcc/cp/typeck2.c | 12 ++-- gcc/testsuite/g++.old-deja/g++.ext/syshdr1.C | 11 ++++ gcc/testsuite/g++.old-deja/g++.other/dtor12.C | 15 +++++ gcc/testsuite/g++.old-deja/g++.other/goto4.C | 26 +++++++++ .../g++.old-deja/g++.other/lookup21.C | 16 ++++++ gcc/testsuite/g++.old-deja/g++.pt/deduct4.C | 11 ++++ 13 files changed, 232 insertions(+), 49 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.ext/syshdr1.C create mode 100644 gcc/testsuite/g++.old-deja/g++.other/dtor12.C create mode 100644 gcc/testsuite/g++.old-deja/g++.other/goto4.C create mode 100644 gcc/testsuite/g++.old-deja/g++.other/lookup21.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/deduct4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6f756a4976c..feb01772622 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,28 @@ +2001-02-08 Jason Merrill + + * search.c (shared_member_p): New function. + (lookup_field_r): Use it. + * cp-tree.h (SHARED_MEMBER_P): Remove. + + * method.c (process_overload_item): Handle template-dependent array + bounds. + * pt.c (type_unification_real): If we end up with undeduced nontype + parms, try again. + + * decl.c (lookup_name_real): Tweak warning to refer to decls, not + types. + + * typeck2.c (friendly_abort): Don't say anything if we have + earlier errors or sorries. + + * decl.c (check_tag_decl): Notice attempts to redefine bool and + wchar_t. Ignore if in_system_header. + + * decl.c (maybe_push_cleanup_level): New fn... + (start_decl_1): ...split out from here. + * cvt.c (build_up_reference): Use it. + * cp-tree.h: Declare it. + 2001-02-07 Mark Mitchell * lang-specs.h: Use CPLUSPLUS_CPP_SPEC for the preprocessor diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d473006f24e..43a97143e25 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2070,12 +2070,6 @@ struct lang_decl member function. */ #define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function) -/* Nonzero for a class member means that it is shared between all objects - of that class. */ -#define SHARED_MEMBER_P(NODE) \ - (TREE_CODE (NODE) == VAR_DECL || TREE_CODE (NODE) == TYPE_DECL \ - || TREE_CODE (NODE) == CONST_DECL) - /* Nonzero for FUNCTION_DECL means that this decl is a non-static member function. */ #define DECL_NONSTATIC_MEMBER_FUNCTION_P(NODE) \ @@ -3785,6 +3779,7 @@ extern void keep_next_level PARAMS ((int)); extern int kept_level_p PARAMS ((void)); extern int template_parm_scope_p PARAMS ((void)); extern void set_class_shadows PARAMS ((tree)); +extern void maybe_push_cleanup_level PARAMS ((tree)); extern void begin_scope PARAMS ((scope_kind)); extern void finish_scope PARAMS ((void)); extern void note_level_for_for PARAMS ((void)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index ff7d4bc4cea..9fa2a665e15 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -380,6 +380,7 @@ build_up_reference (type, arg, flags) arg = get_temp_name (argtype); else { + maybe_push_cleanup_level (argtype); arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype)); DECL_ARTIFICIAL (arg) = 1; } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 13e3094e791..dcf84e6ddac 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -863,6 +863,24 @@ pushlevel (tag_transparent) keep_next_level_flag = 0; } +/* We're defining an object of type TYPE. If it needs a cleanup, but + we're not allowed to add any more objects with cleanups to the current + scope, create a new binding level. */ + +void +maybe_push_cleanup_level (type) + tree type; +{ + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) + && current_binding_level->more_cleanups_ok == 0) + { + keep_next_level (2); + pushlevel (1); + clear_last_expr (); + add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1); + } +} + /* Enter a new scope. The KIND indicates what kind of scope is being created. */ @@ -5993,10 +6011,9 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) && TREE_CODE (val) == TYPE_DECL && ! same_type_p (TREE_TYPE (from_obj), TREE_TYPE (val))) cp_pedwarn ("\ -lookup of `%D' in the scope of `%#T' (`%#T') \ -does not match lookup in the current scope (`%#T')", - name, got_object, TREE_TYPE (from_obj), - TREE_TYPE (val)); +lookup of `%D' in the scope of `%#T' (`%#D') \ +does not match lookup in the current scope (`%#D')", + name, got_object, from_obj, val); /* We don't change val to from_obj if got_object depends on template parms because that breaks implicit typename for @@ -6864,14 +6881,23 @@ check_tag_decl (declspecs) register tree value = TREE_VALUE (link); if (TYPE_P (value) + || TREE_CODE (value) == TYPE_DECL || (TREE_CODE (value) == IDENTIFIER_NODE && IDENTIFIER_GLOBAL_VALUE (value) - && TYPE_P (IDENTIFIER_GLOBAL_VALUE (value)))) + && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (value)) == TYPE_DECL)) { ++found_type; - if ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value)) - || TREE_CODE (value) == ENUMERAL_TYPE) + if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE) + { + if (! in_system_header) + cp_pedwarn ("redeclaration of C++ built-in type `%T'", value); + return NULL_TREE; + } + + if (TYPE_P (value) + && ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value)) + || TREE_CODE (value) == ENUMERAL_TYPE)) { my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261); t = value; @@ -7194,17 +7220,7 @@ start_decl_1 (decl) if (type == error_mark_node) return; - /* If this type of object needs a cleanup, but we're not allowed to - add any more objects with cleanups to the current scope, create a - new binding level. */ - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) - && current_binding_level->more_cleanups_ok == 0) - { - keep_next_level (2); - pushlevel (1); - clear_last_expr (); - add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1); - } + maybe_push_cleanup_level (type); if (initialized) /* Is it valid for this decl to have an initializer at all? diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 30ede1b600a..72702b402f1 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1359,8 +1359,12 @@ process_overload_item (parmtype, extra_Gcode) tree length = array_type_nelts (parmtype); if (TREE_CODE (length) != INTEGER_CST || flag_do_squangling) { - length = fold (build (PLUS_EXPR, TREE_TYPE (length), - length, integer_one_node)); + if (TREE_CODE (length) == MINUS_EXPR + && TREE_OPERAND (length, 1) == integer_one_node) + length = TREE_OPERAND (length, 0); + else + length = fold (build (PLUS_EXPR, TREE_TYPE (length), + length, integer_one_node)); STRIP_NOPS (length); } build_overload_value (sizetype, length, 1); @@ -1964,7 +1968,8 @@ hack_identifier (value, name) { if (current_class_name) { - tree fields = lookup_fnfields (TYPE_BINFO (current_class_type), name, 1); + tree fields = lookup_fnfields (TYPE_BINFO (current_class_type), + name, 1); if (fields == error_mark_node) return error_mark_node; if (fields) @@ -2091,8 +2096,9 @@ hack_identifier (value, name) else if (TREE_CODE (value) == TREE_LIST && TREE_TYPE (value) == error_mark_node) { - error ("request for member `%s' is ambiguous in multiple inheritance lattice", - IDENTIFIER_POINTER (name)); + cp_error ("\ +request for member `%D' is ambiguous in multiple inheritance lattice", + name); print_candidates (value); return error_mark_node; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e85ec792d05..181a00eb77b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7930,25 +7930,28 @@ maybe_adjust_types_for_deduction (strict, parm, arg) template). */ static int -type_unification_real (tparms, targs, parms, args, subr, - strict, allow_incomplete, len) - tree tparms, targs, parms, args; +type_unification_real (tparms, targs, xparms, xargs, subr, + strict, allow_incomplete, xlen) + tree tparms, targs, xparms, xargs; int subr; unification_kind_t strict; - int allow_incomplete, len; + int allow_incomplete, xlen; { tree parm, arg; int i; int ntparms = TREE_VEC_LENGTH (tparms); int sub_strict; + int saw_undeduced = 0; + tree parms, args; + int len; my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289); - my_friendly_assert (parms == NULL_TREE - || TREE_CODE (parms) == TREE_LIST, 290); + my_friendly_assert (xparms == NULL_TREE + || TREE_CODE (xparms) == TREE_LIST, 290); /* ARGS could be NULL (via a call from parse.y to build_x_function_call). */ - if (args) - my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291); + if (xargs) + my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291); my_friendly_assert (ntparms > 0, 292); switch (strict) @@ -7974,9 +7977,14 @@ type_unification_real (tparms, targs, parms, args, subr, my_friendly_abort (0); } - if (len == 0) + if (xlen == 0) return 0; + again: + parms = xparms; + args = xargs; + len = xlen; + while (parms && parms != void_list_node && args @@ -8056,7 +8064,7 @@ type_unification_real (tparms, targs, parms, args, subr, /* Are we done with the interesting parms? */ if (--len == 0) - return 0; + goto done; } /* Fail if we've reached the end of the parm list, and more args are present, and the parm list isn't variadic. */ @@ -8067,10 +8075,23 @@ type_unification_real (tparms, targs, parms, args, subr, && parms != void_list_node && TREE_PURPOSE (parms) == NULL_TREE) return 1; + + done: if (!subr) for (i = 0; i < ntparms; i++) if (TREE_VEC_ELT (targs, i) == NULL_TREE) { + tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i)); + + /* If this is an undeduced nontype parameter that depends on + a type parameter, try another pass; its type may have been + deduced from a later argument than the one from which + this parameter can be deduced. */ + if (TREE_CODE (tparm) == PARM_DECL + && uses_template_parms (TREE_TYPE (tparm)) + && !saw_undeduced++) + goto again; + if (!allow_incomplete) error ("incomplete type unification"); return 2; @@ -8742,13 +8763,17 @@ unify (tparms, targs, parm, arg, strict) template-parameter exactly, except that a template-argument deduced from an array bound may be of any integral type. The non-type parameter might use already deduced type parameters. */ - if (same_type_p (TREE_TYPE (arg), - tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE))) - /* OK */; + tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE); + if (same_type_p (TREE_TYPE (arg), tparm)) + /* OK */; else if ((strict & UNIFY_ALLOW_INTEGER) - && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE - || TREE_CODE (TREE_TYPE (parm)) == BOOLEAN_TYPE)) + && (TREE_CODE (tparm) == INTEGER_TYPE + || TREE_CODE (tparm) == BOOLEAN_TYPE)) /* OK */; + else if (uses_template_parms (tparm)) + /* We haven't deduced the type of this parameter yet. Try again + later. */ + return 0; else return 1; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 1699c325f66..620d7592085 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -119,6 +119,7 @@ static tree bfs_walk PARAMS ((tree, tree (*) (tree, void *), tree (*) (tree, void *), void *)); static tree lookup_field_queue_p PARAMS ((tree, void *)); +static int shared_member_p PARAMS ((tree)); static tree lookup_field_r PARAMS ((tree, void *)); static tree canonical_binfo PARAMS ((tree)); static tree shared_marked_p PARAMS ((tree, void *)); @@ -1312,6 +1313,37 @@ template_self_reference_p (type, decl) && DECL_NAME (decl) == constructor_name (type)); } + +/* Nonzero for a class member means that it is shared between all objects + of that class. + + [class.member.lookup]:If the resulting set of declarations are not all + from sub-objects of the same type, or the set has a nonstatic member + and includes members from distinct sub-objects, there is an ambiguity + and the program is ill-formed. + + This function checks that T contains no nonstatic members. */ + +static int +shared_member_p (t) + tree t; +{ + if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == TYPE_DECL \ + || TREE_CODE (t) == CONST_DECL) + return 1; + if (is_overloaded_fn (t)) + { + for (; t; t = OVL_NEXT (t)) + { + tree fn = OVL_CURRENT (t); + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) + return 0; + } + return 1; + } + return 0; +} + /* DATA is really a struct lookup_field_info. Look for a field with the name indicated there in BINFO. If this function returns a non-NULL value it is the result of the lookup. Called from @@ -1392,7 +1424,7 @@ lookup_field_r (binfo, data) hide the old one, we might have an ambiguity. */ if (lfi->rval_binfo && !is_subobject_of_p (lfi->rval_binfo, binfo, lfi->type)) { - if (nval == lfi->rval && SHARED_MEMBER_P (nval)) + if (nval == lfi->rval && shared_member_p (nval)) /* The two things are really the same. */ ; else if (is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type)) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index a7e71e59ded..c62949ef405 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -261,11 +261,15 @@ friendly_abort (where, file, line, func) int line; const char *func; { - if (where > 0) - error ("Internal error #%d.", where); + if (errorcount > 0 || sorrycount > 0) + /* Say nothing. */; + else if (where > 0) + { + error ("Internal error #%d.", where); - /* Uncount this error, so finish_abort will do the right thing. */ - --errorcount; + /* Uncount this error, so internal_error will do the right thing. */ + --errorcount; + } fancy_abort (file, line, func); } diff --git a/gcc/testsuite/g++.old-deja/g++.ext/syshdr1.C b/gcc/testsuite/g++.old-deja/g++.ext/syshdr1.C new file mode 100644 index 00000000000..69d0c7aabc0 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.ext/syshdr1.C @@ -0,0 +1,11 @@ +// Test that we don't complain about trying to define bool or wchar_t in a +// system header. + +// Special g++ Options: +// Build don't link: + +# 1 "syshdr1.C" +# 1 "syshdr1.h" 1 3 +typedef int bool; +typedef int wchar_t; +# 2 "syshdr1.C" 2 diff --git a/gcc/testsuite/g++.old-deja/g++.other/dtor12.C b/gcc/testsuite/g++.old-deja/g++.other/dtor12.C new file mode 100644 index 00000000000..1a9d58a5a8e --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/dtor12.C @@ -0,0 +1,15 @@ +// Test that we don't complain about calling a destructor on a const object. + +#include + +struct A +{ + ~A() {} +}; + +const A a = {}; +int main() +{ + a.~A(); + a.A::~A(); // gets bogus error - const violation +} diff --git a/gcc/testsuite/g++.old-deja/g++.other/goto4.C b/gcc/testsuite/g++.old-deja/g++.other/goto4.C new file mode 100644 index 00000000000..75461d44d84 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/goto4.C @@ -0,0 +1,26 @@ +// Test that we clean up temporaries bound to references properly when +// jumping out of their scope. + +int ret = 1; + +struct A +{ + ~A() { ret = 0; } +}; + +void f() +{ + if (0) + { + out: + return; + } + const A& a = A(); + goto out; +} + +int main() +{ + f(); + return ret; +} diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup21.C b/gcc/testsuite/g++.old-deja/g++.other/lookup21.C new file mode 100644 index 00000000000..09b3123b2fc --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/lookup21.C @@ -0,0 +1,16 @@ +// Check that we don't complain about ambiguity between the same static +// member function in different subobjects. + +struct A { + static void f() {} +}; + +struct B: public A { }; +struct C: public A { }; +struct D: public B, public C { }; + +int main() +{ + D d; + d.f(); +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/deduct4.C b/gcc/testsuite/g++.old-deja/g++.pt/deduct4.C new file mode 100644 index 00000000000..b80a932f7a4 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/deduct4.C @@ -0,0 +1,11 @@ +// Test that we can deduce t even though T is deduced from a later argument. + +template struct A { }; + +template void f (A &, T) { } + +int main () +{ + A<42> a; + f (a, 24); +} -- 2.30.2