* 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
+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
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) \
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));
arg = get_temp_name (argtype);
else
{
+ maybe_push_cleanup_level (argtype);
arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
DECL_ARTIFICIAL (arg) = 1;
}
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. */
&& 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
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;
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?
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);
{
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)
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;
}
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)
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
/* 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. */
&& 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;
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;
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 *));
&& 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
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))
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);
}
--- /dev/null
+// 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
--- /dev/null
+// 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
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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);
+}