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:
Jason Merrill 2001-02-08 10:54:39 -05:00 committed by Jason Merrill
parent 0c1cf241c4
commit bd0d5d4a5e
13 changed files with 232 additions and 49 deletions

View File

@ -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

View File

@ -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));

View File

@ -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;
}

View File

@ -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?

View File

@ -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;
}

View File

@ -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;

View File

@ -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))

View File

@ -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);
}

View 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

View 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
}

View 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;
}

View 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();
}

View 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);
}