aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/typeck2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/typeck2.c')
-rw-r--r--gcc/cp/typeck2.c410
1 files changed, 200 insertions, 210 deletions
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index a00a4f13ffc..76a30b202d6 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1,6 +1,6 @@
/* Report error messages, build initializers, and perform
some front-end optimizations for C++ compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -38,6 +38,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
static tree process_init_constructor PROTO((tree, tree, tree *));
+static void ack PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1;
extern int errorcount;
extern int sorrycount;
@@ -80,11 +81,11 @@ binfo_or_else (parent_or_type, type)
void
readonly_error (arg, string, soft)
tree arg;
- char *string;
+ const char *string;
int soft;
{
- char *fmt;
- void (*fn)();
+ const char *fmt;
+ void (*fn) PVPROTO ((const char *, ...));
if (soft)
fn = cp_pedwarn;
@@ -133,30 +134,8 @@ abstract_virtuals_error (decl, type)
tree type;
{
tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
- int has_abstract_virtuals, needs_final_overriders;
tree tu;
- /* Count how many abstract methods need to be defined. */
- for (has_abstract_virtuals = 0, tu = u; tu; tu = TREE_CHAIN (tu))
- {
- if (DECL_ABSTRACT_VIRTUAL_P (TREE_VALUE (tu))
- && ! DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
- {
- has_abstract_virtuals = 1;
- break;
- }
- }
-
- /* Count how many virtual methods need a final overrider. */
- for (needs_final_overriders = 0, tu = u; tu; tu = TREE_CHAIN (tu))
- {
- if (DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
- {
- needs_final_overriders = 1;
- break;
- }
- }
-
if (decl)
{
if (TREE_CODE (decl) == RESULT_DECL)
@@ -185,44 +164,12 @@ abstract_virtuals_error (decl, type)
{
TREE_PURPOSE (u) = error_mark_node;
- if (has_abstract_virtuals)
- error (" since the following virtual functions are abstract:");
- tu = u;
- while (tu)
- {
- if (DECL_ABSTRACT_VIRTUAL_P (TREE_VALUE (tu))
- && ! DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
- cp_error ("\t%#D", TREE_VALUE (tu));
- tu = TREE_CHAIN (tu);
- }
-
- if (needs_final_overriders)
- {
- if (has_abstract_virtuals)
- error (" and the following virtual functions need a final overrider:");
- else
- error (" since the following virtual functions need a final overrider:");
- }
- tu = u;
- while (tu)
- {
- if (DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
- cp_error ("\t%#D", TREE_VALUE (tu));
- tu = TREE_CHAIN (tu);
- }
+ error (" since the following virtual functions are abstract:");
+ for (tu = u; tu; tu = TREE_CHAIN (tu))
+ cp_error_at ("\t%#D", TREE_VALUE (tu));
}
else
- {
- if (has_abstract_virtuals)
- {
- if (needs_final_overriders)
- cp_error (" since type `%T' has abstract virtual functions and must override virtual functions", type);
- else
- cp_error (" since type `%T' has abstract virtual functions", type);
- }
- else
- cp_error (" since type `%T' must override virtual functions", type);
- }
+ cp_error (" since type `%T' has abstract virtual functions", type);
}
/* Print an error message for invalid use of a signature type.
@@ -267,73 +214,89 @@ incomplete_type_error (value, type)
tree value;
tree type;
{
- char *errmsg = 0;
-
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
return;
- if (value != 0 && (TREE_CODE (value) == VAR_DECL
- || TREE_CODE (value) == PARM_DECL))
- cp_error ("`%D' has incomplete type", value);
- else
- {
- retry:
- /* We must print an error message. Be clever about what it says. */
-
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- errmsg = "invalid use of undefined type `%#T'";
- break;
+retry:
+ /* We must print an error message. Be clever about what it says. */
- case VOID_TYPE:
- error ("invalid use of void expression");
- return;
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ cp_error ("invalid use of undefined type `%#T'", type);
+ cp_error_at ("forward declaration of `%#T'", type);
+ break;
- case ARRAY_TYPE:
- if (TYPE_DOMAIN (type))
- {
- type = TREE_TYPE (type);
- goto retry;
- }
- error ("invalid use of array with unspecified bounds");
- return;
+ case VOID_TYPE:
+ cp_error ("invalid use of void expression");
+ break;
- case OFFSET_TYPE:
- error ("invalid use of member type (did you forget the `&' ?)");
- return;
+ case ARRAY_TYPE:
+ if (TYPE_DOMAIN (type))
+ {
+ type = TREE_TYPE (type);
+ goto retry;
+ }
+ cp_error ("invalid use of array with unspecified bounds");
+ break;
- case TEMPLATE_TYPE_PARM:
- error ("invalid use of template type parameter");
- return;
+ case OFFSET_TYPE:
+ bad_member:
+ cp_error ("invalid use of member (did you forget the `&' ?)");
+ break;
- default:
- my_friendly_abort (108);
- }
+ case TEMPLATE_TYPE_PARM:
+ cp_error ("invalid use of template type parameter");
+ break;
- cp_error (errmsg, type);
+ case UNKNOWN_TYPE:
+ if (value && TREE_CODE (value) == COMPONENT_REF)
+ goto bad_member;
+ else if (value && TREE_CODE (value) == ADDR_EXPR)
+ cp_error ("address of overloaded function with no contextual type information");
+ else if (value && TREE_CODE (value) == OVERLOAD)
+ cp_error ("overloaded function with no contextual type information");
+ else
+ cp_error ("insufficient contextual information to determine type");
+ break;
+
+ default:
+ my_friendly_abort (108);
}
+
+ if (value != 0 && (TREE_CODE (value) == VAR_DECL
+ || TREE_CODE (value) == PARM_DECL))
+ cp_error_at ("incomplete `%D' defined here", value);
}
/* Like error(), but don't call report_error_function(). */
static void
-ack (s, v, v2)
- char *s;
- HOST_WIDE_INT v;
- HOST_WIDE_INT v2;
+ack VPROTO ((const char *msg, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char *msg;
+#endif
+ va_list ap;
extern char * progname;
+ VA_START (ap, msg);
+
+#ifndef ANSI_PROTOTYPES
+ msg = va_arg (ap, const char *);
+#endif
+
if (input_filename)
fprintf (stderr, "%s:%d: ", input_filename, lineno);
else
fprintf (stderr, "%s: ", progname);
- fprintf (stderr, s, v, v2);
+ vfprintf (stderr, msg, ap);
+ va_end (ap);
+
fprintf (stderr, "\n");
}
@@ -352,19 +315,14 @@ ack (s, v, v2)
59 is, so they can understand how to work around it, should they
ever run into it.
- Note, there will be no more calls in the C++ front end to abort,
- because the C++ front end is so unreliable still. The C front end
- can get away with calling abort, because for most of the calls to
- abort on most machines, it, I suspect, can be proven that it is
- impossible to ever call abort. The same is not yet true for C++,
- one day, maybe it will be.
-
We used to tell people to "fix the above error[s] and try recompiling
the program" via a call to fatal, but that message tended to look
silly. So instead, we just do the equivalent of a call to fatal in the
- same situation (call exit). */
+ same situation (call exit).
-/* First used: 0 (reserved), Last used: 369. Free: */
+ We used to assign sequential numbers for the aborts; now we use an
+ encoding of the date the abort was added, since that has more meaning
+ when we only see the error message. */
static int abortcount = 0;
@@ -385,7 +343,8 @@ my_friendly_abort (i)
ack ("Internal compiler error.");
else
ack ("Internal compiler error %d.", i);
- ack ("Please submit a full bug report to `egcs-bugs@cygnus.com'.");
+ ack ("Please submit a full bug report to `egcs-bugs@egcs.cygnus.com'.");
+ ack ("See <URL:http://egcs.cygnus.com/faq.html#bugreport> for details.");
}
else
error ("confused by earlier errors, bailing out");
@@ -399,7 +358,8 @@ my_friendly_abort (i)
else
error ("Internal compiler error %d.", i);
- fatal ("Please submit a full bug report to `egcs-bugs@cygnus.com'.");
+ error ("Please submit a full bug report to `egcs-bugs@egcs.cygnus.com'.");
+ fatal ("See <URL:http://egcs.cygnus.com/faq.html#bugreport> for details.");
}
void
@@ -650,13 +610,6 @@ store_init_value (decl, init)
else
init = TREE_VALUE (init);
}
- else if (TREE_TYPE (init) != 0
- && TREE_CODE (TREE_TYPE (init)) == OFFSET_TYPE)
- {
- /* Use the type of our variable to instantiate
- the type of our initializer. */
- init = instantiate_type (type, init, 1);
- }
else if (TREE_CODE (init) == TREE_LIST
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
@@ -767,6 +720,9 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type)
+ return init;
+
raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
if (raw_constructor
@@ -937,6 +893,7 @@ process_init_constructor (type, init, elts)
/* List of the elements of the result constructor,
in reverse order. */
register tree members = NULL;
+ register tree next1;
tree result;
int allconstant = 1;
int allsimple = 1;
@@ -971,42 +928,62 @@ process_init_constructor (type, init, elts)
else
len = -1; /* Take as many as there are */
- for (i = 0; (len < 0 || i < len) && tail != 0; i++)
+ for (i = 0; len < 0 || i < len; i++)
{
- register tree next1;
-
- if (TREE_PURPOSE (tail)
- && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
- || TREE_INT_CST_LOW (TREE_PURPOSE (tail)) != i))
- sorry ("non-trivial labeled initializers");
-
- if (TREE_VALUE (tail) != 0)
+ if (tail)
{
- tree tail1 = tail;
- next1 = digest_init (TREE_TYPE (type),
- TREE_VALUE (tail), &tail1);
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))
- && TYPE_MAIN_VARIANT (TREE_TYPE (type)) != TYPE_MAIN_VARIANT (TREE_TYPE (next1)))
+ if (TREE_PURPOSE (tail)
+ && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
+ || TREE_INT_CST_LOW (TREE_PURPOSE (tail)) != i))
+ sorry ("non-trivial labeled initializers");
+
+ if (TREE_VALUE (tail) != 0)
{
- /* The fact this needs to be done suggests this code needs
- to be totally rewritten. */
- next1 = convert_for_initialization (NULL_TREE, TREE_TYPE (type), next1, LOOKUP_NORMAL, "initialization", NULL_TREE, 0);
+ tree tail1 = tail;
+ next1 = digest_init (TREE_TYPE (type),
+ TREE_VALUE (tail), &tail1);
+ if (next1 == error_mark_node)
+ return next1;
+ my_friendly_assert
+ (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (next1))),
+ 981123);
+ my_friendly_assert (tail1 == 0
+ || TREE_CODE (tail1) == TREE_LIST, 319);
+ if (tail == tail1 && len < 0)
+ {
+ error ("non-empty initializer for array of empty elements");
+ /* Just ignore what we were supposed to use. */
+ tail1 = NULL_TREE;
+ }
+ tail = tail1;
}
- my_friendly_assert (tail1 == 0
- || TREE_CODE (tail1) == TREE_LIST, 319);
- if (tail == tail1 && len < 0)
+ else
{
- error ("non-empty initializer for array of empty elements");
- /* Just ignore what we were supposed to use. */
- tail1 = NULL_TREE;
+ next1 = error_mark_node;
+ tail = TREE_CHAIN (tail);
}
- tail = tail1;
}
- else
+ else if (len < 0)
+ /* We're done. */
+ break;
+ else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
{
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
+ /* If this type needs constructors run for
+ default-initialization, we can't rely on the backend to do it
+ for us, so build up TARGET_EXPRs. If the type in question is
+ a class, just build one up; if it's an array, recurse. */
+
+ if (IS_AGGR_TYPE (TREE_TYPE (type)))
+ next1 = build_functional_cast (TREE_TYPE (type), NULL_TREE);
+ else
+ next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
+ next1 = digest_init (TREE_TYPE (type), next1, 0);
}
+ else
+ /* The default zero-initialization is fine for us; don't
+ add anything to the CONSTRUCTOR. */
+ break;
if (next1 == error_mark_node)
erroneous = 1;
@@ -1017,7 +994,7 @@ process_init_constructor (type, init, elts)
members = expr_tree_cons (NULL_TREE, next1, members);
}
}
- if (TREE_CODE (type) == RECORD_TYPE)
+ else if (TREE_CODE (type) == RECORD_TYPE)
{
register tree field;
@@ -1042,12 +1019,10 @@ process_init_constructor (type, init, elts)
}
}
- for (field = TYPE_FIELDS (type); field && tail;
+ for (field = TYPE_FIELDS (type); field;
field = TREE_CHAIN (field))
{
- register tree next1;
-
- if (! DECL_NAME (field))
+ if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field))
{
members = expr_tree_cons (field, integer_zero_node, members);
continue;
@@ -1056,25 +1031,67 @@ process_init_constructor (type, init, elts)
if (TREE_CODE (field) != FIELD_DECL)
continue;
- if (TREE_PURPOSE (tail)
- && TREE_PURPOSE (tail) != field
- && TREE_PURPOSE (tail) != DECL_NAME (field))
- sorry ("non-trivial labeled initializers");
+ if (tail)
+ {
+ if (TREE_PURPOSE (tail)
+ && TREE_PURPOSE (tail) != field
+ && TREE_PURPOSE (tail) != DECL_NAME (field))
+ sorry ("non-trivial labeled initializers");
+
+ if (TREE_VALUE (tail) != 0)
+ {
+ tree tail1 = tail;
- if (TREE_VALUE (tail) != 0)
+ next1 = digest_init (TREE_TYPE (field),
+ TREE_VALUE (tail), &tail1);
+ my_friendly_assert (tail1 == 0
+ || TREE_CODE (tail1) == TREE_LIST, 320);
+ tail = tail1;
+ }
+ else
+ {
+ next1 = error_mark_node;
+ tail = TREE_CHAIN (tail);
+ }
+ }
+ else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
{
- tree tail1 = tail;
+ /* If this type needs constructors run for
+ default-initialization, we can't rely on the backend to do it
+ for us, so build up TARGET_EXPRs. If the type in question is
+ a class, just build one up; if it's an array, recurse. */
+
+ if (IS_AGGR_TYPE (TREE_TYPE (field)))
+ next1 = build_functional_cast (TREE_TYPE (field),
+ NULL_TREE);
+ else
+ next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE,
+ NULL_TREE);
+ next1 = digest_init (TREE_TYPE (field), next1, 0);
- next1 = digest_init (TREE_TYPE (field),
- TREE_VALUE (tail), &tail1);
- my_friendly_assert (tail1 == 0
- || TREE_CODE (tail1) == TREE_LIST, 320);
- tail = tail1;
+ /* Warn when some struct elements are implicitly initialized. */
+ if (extra_warnings)
+ cp_warning ("missing initializer for member `%D'", field);
}
else
{
- next1 = error_mark_node;
- tail = TREE_CHAIN (tail);
+ if (TREE_READONLY (field))
+ cp_error ("uninitialized const member `%D'", field);
+ else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field))
+ && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
+ cp_error ("member `%D' with uninitialized const fields",
+ field);
+ else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
+ cp_error ("member `%D' is uninitialized reference", field);
+
+ /* Warn when some struct elements are implicitly initialized
+ to zero. */
+ if (extra_warnings)
+ cp_warning ("missing initializer for member `%D'", field);
+
+ /* The default zero-initialization is fine for us; don't
+ add anything to the CONSTRUCTOR. */
+ continue;
}
if (next1 == error_mark_node)
@@ -1085,45 +1102,10 @@ process_init_constructor (type, init, elts)
allsimple = 0;
members = expr_tree_cons (field, next1, members);
}
- for (; field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- /* Does this field have a default initialization? */
- if (DECL_INITIAL (field))
- {
- register tree next1 = DECL_INITIAL (field);
- if (TREE_CODE (next1) == ERROR_MARK)
- erroneous = 1;
- else if (!TREE_CONSTANT (next1))
- allconstant = 0;
- else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
- allsimple = 0;
- members = expr_tree_cons (field, next1, members);
- }
- else if (TREE_READONLY (field))
- error ("uninitialized const member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field))
- && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
- error ("member `%s' with uninitialized const fields",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
- error ("member `%s' is uninitialized reference",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- /* Warn when some struct elements are implicitly initialized
- to zero. */
- else if (extra_warnings)
- warning ("missing initializer for member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- }
}
-
- if (TREE_CODE (type) == UNION_TYPE)
+ else if (TREE_CODE (type) == UNION_TYPE)
{
register tree field = TYPE_FIELDS (type);
- register tree next1;
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
@@ -1152,8 +1134,8 @@ process_init_constructor (type, init, elts)
if (temp)
field = temp, win = 1;
else
- error ("no field `%s' in union being initialized",
- IDENTIFIER_POINTER (TREE_PURPOSE (tail)));
+ cp_error ("no field `%D' in union being initialized",
+ TREE_PURPOSE (tail));
}
if (!win)
TREE_VALUE (tail) = error_mark_node;
@@ -1392,8 +1374,7 @@ build_m_component_ref (datum, component)
}
else
{
- component = build_indirect_ref (component, NULL_PTR);
- type = TREE_TYPE (component);
+ type = TREE_TYPE (TREE_TYPE (component));
rettype = TREE_TYPE (type);
}
@@ -1504,6 +1485,11 @@ build_functional_cast (exp, parms)
cp_error ("type `%T' is not yet defined", type);
return error_mark_node;
}
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
+ {
+ abstract_virtuals_error (NULL_TREE, type);
+ return error_mark_node;
+ }
if (parms && TREE_CHAIN (parms) == NULL_TREE)
return build_c_cast (type, TREE_VALUE (parms));
@@ -1659,11 +1645,15 @@ report_case_error (code, type, new_value, old_value)
}
#endif
+/* Complain about defining new types in inappropriate places. We give an
+ exception for C-style casts, to accommodate GNU C stylings. */
+
void
check_for_new_type (string, inptree)
- char *string;
+ const char *string;
flagged_type_tree inptree;
{
- if (pedantic && inptree.new_type_flag)
+ if (inptree.new_type_flag
+ && (pedantic || strcmp (string, "cast") != 0))
pedwarn ("ANSI C++ forbids defining types within %s",string);
}