mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-18 23:54:55 +08:00
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
This commit is contained in:
parent
0c1cf241c4
commit
bd0d5d4a5e
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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?
|
||||
|
@ -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;
|
||||
}
|
||||
|
55
gcc/cp/pt.c
55
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;
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
|
11
gcc/testsuite/g++.old-deja/g++.ext/syshdr1.C
Normal file
11
gcc/testsuite/g++.old-deja/g++.ext/syshdr1.C
Normal file
@ -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
|
15
gcc/testsuite/g++.old-deja/g++.other/dtor12.C
Normal file
15
gcc/testsuite/g++.old-deja/g++.other/dtor12.C
Normal file
@ -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
|
||||
}
|
26
gcc/testsuite/g++.old-deja/g++.other/goto4.C
Normal file
26
gcc/testsuite/g++.old-deja/g++.other/goto4.C
Normal file
@ -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;
|
||||
}
|
16
gcc/testsuite/g++.old-deja/g++.other/lookup21.C
Normal file
16
gcc/testsuite/g++.old-deja/g++.other/lookup21.C
Normal file
@ -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();
|
||||
}
|
11
gcc/testsuite/g++.old-deja/g++.pt/deduct4.C
Normal file
11
gcc/testsuite/g++.old-deja/g++.pt/deduct4.C
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user