aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2001-02-08 10:54:39 -0500
committerJason Merrill <jason@gcc.gnu.org>2001-02-08 10:54:39 -0500
commitbd0d5d4a5e3ecf01c4f5d2c537ad4b3a10d94777 (patch)
treef2dedc12f81ff4a7ee22feea5cba093301e449cb /gcc
parent0c1cf241c4a4fa72ead663cf55e443f6084eacae (diff)
downloadgcc-bd0d5d4a5e3ecf01c4f5d2c537ad4b3a10d94777.zip
gcc-bd0d5d4a5e3ecf01c4f5d2c537ad4b3a10d94777.tar.gz
gcc-bd0d5d4a5e3ecf01c4f5d2c537ad4b3a10d94777.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/cp-tree.h7
-rw-r--r--gcc/cp/cvt.c1
-rw-r--r--gcc/cp/decl.c52
-rw-r--r--gcc/cp/method.c16
-rw-r--r--gcc/cp/pt.c55
-rw-r--r--gcc/cp/search.c34
-rw-r--r--gcc/cp/typeck2.c12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ext/syshdr1.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/dtor12.C15
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/goto4.C26
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/lookup21.C16
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/deduct4.C11
13 files changed, 232 insertions, 49 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6f756a4..feb0177 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@
+2001-02-08 Jason Merrill <jason@redhat.com>
+
+ * 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 <mark@codesourcery.com>
* 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 d473006..43a9714 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 ff7d4bc..9fa2a66 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 13e3094..dcf84e6 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 30ede1b..72702b4 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 e85ec792..181a00e 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 1699c32..620d759 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 a7e71e5..c62949e 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 0000000..69d0c7a
--- /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 0000000..1a9d58a
--- /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 <new>
+
+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 0000000..75461d4
--- /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 0000000..09b3123
--- /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 0000000..b80a932
--- /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 <int I> struct A { };
+
+template <class T, T t> void f (A<t> &, T) { }
+
+int main ()
+{
+ A<42> a;
+ f (a, 24);
+}