summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/typeck2.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/typeck2.c')
-rw-r--r--contrib/gcc/cp/typeck2.c894
1 files changed, 293 insertions, 601 deletions
diff --git a/contrib/gcc/cp/typeck2.c b/contrib/gcc/cp/typeck2.c
index da98203..314685a 100644
--- a/contrib/gcc/cp/typeck2.c
+++ b/contrib/gcc/cp/typeck2.c
@@ -1,6 +1,7 @@
/* Report error messages, build initializers, and perform
some front-end optimizations for C++ compiler.
- Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -36,12 +37,10 @@ Boston, MA 02111-1307, USA. */
#include "cp-tree.h"
#include "flags.h"
#include "toplev.h"
+#include "output.h"
+#include "diagnostic.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;
+static tree process_init_constructor PARAMS ((tree, tree, tree *));
/* Print an error message stemming from an attempt to use
BASETYPE as a base class for TYPE. */
@@ -51,26 +50,22 @@ error_not_base_type (basetype, type)
tree basetype, type;
{
if (TREE_CODE (basetype) == FUNCTION_DECL)
- basetype = DECL_CLASS_CONTEXT (basetype);
- cp_error ("type `%T' is not a base type for type `%T'", basetype, type);
+ basetype = DECL_CONTEXT (basetype);
+ error ("type `%T' is not a base type for type `%T'", basetype, type);
return error_mark_node;
}
tree
-binfo_or_else (parent_or_type, type)
- tree parent_or_type, type;
+binfo_or_else (base, type)
+ tree base, type;
{
- tree binfo;
- if (TYPE_MAIN_VARIANT (parent_or_type) == TYPE_MAIN_VARIANT (type))
- return TYPE_BINFO (parent_or_type);
- if ((binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0)))
- {
- if (binfo == error_mark_node)
- return NULL_TREE;
- return binfo;
- }
- error_not_base_type (parent_or_type, type);
- return NULL_TREE;
+ tree binfo = lookup_base (type, base, ba_ignore, NULL);
+
+ if (binfo == error_mark_node)
+ return NULL_TREE;
+ else if (!binfo)
+ error_not_base_type (base, type);
+ return binfo;
}
/* According to ARM $7.1.6, "A `const' object may be initialized, but its
@@ -85,19 +80,19 @@ readonly_error (arg, string, soft)
int soft;
{
const char *fmt;
- void (*fn) PVPROTO ((const char *, ...));
+ void (*fn) PARAMS ((const char *, ...));
if (soft)
- fn = cp_pedwarn;
+ fn = pedwarn;
else
- fn = cp_error;
+ fn = error;
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
- fmt = "%s of member `%D' in read-only structure";
+ fmt = "%s of data-member `%D' in read-only structure";
else
- fmt = "%s of read-only member `%D'";
+ fmt = "%s of read-only data-member `%D'";
(*fn) (fmt, string, TREE_OPERAND (arg, 1));
}
else if (TREE_CODE (arg) == VAR_DECL)
@@ -125,84 +120,64 @@ readonly_error (arg, string, soft)
(*fn) ("%s of read-only location", string);
}
-/* Print an error message for invalid use of a type which declares
- virtual functions which are not inheritable. */
+/* If TYPE has abstract virtual functions, issue an error about trying
+ to create an object of that type. DECL is the object declared, or
+ NULL_TREE if the declaration is unavailable. Returns 1 if an error
+ occurred; zero if all was well. */
-void
+int
abstract_virtuals_error (decl, type)
tree decl;
tree type;
{
- tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
+ tree u;
tree tu;
+ if (!CLASS_TYPE_P (type) || !CLASSTYPE_PURE_VIRTUALS (type))
+ return 0;
+
+ if (!TYPE_SIZE (type))
+ /* TYPE is being defined, and during that time
+ CLASSTYPE_PURE_VIRTUALS holds the inline friends. */
+ return 0;
+
+ u = CLASSTYPE_PURE_VIRTUALS (type);
if (decl)
{
if (TREE_CODE (decl) == RESULT_DECL)
- return;
+ return 0;
if (TREE_CODE (decl) == VAR_DECL)
- cp_error ("cannot declare variable `%D' to be of type `%T'",
+ error ("cannot declare variable `%D' to be of type `%T'",
decl, type);
else if (TREE_CODE (decl) == PARM_DECL)
- cp_error ("cannot declare parameter `%D' to be of type `%T'",
+ error ("cannot declare parameter `%D' to be of type `%T'",
decl, type);
else if (TREE_CODE (decl) == FIELD_DECL)
- cp_error ("cannot declare field `%D' to be of type `%T'",
+ error ("cannot declare field `%D' to be of type `%T'",
decl, type);
else if (TREE_CODE (decl) == FUNCTION_DECL
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- cp_error ("invalid return type for method `%#D'", decl);
+ error ("invalid return type for member function `%#D'", decl);
else if (TREE_CODE (decl) == FUNCTION_DECL)
- cp_error ("invalid return type for function `%#D'", decl);
+ error ("invalid return type for function `%#D'", decl);
}
else
- cp_error ("cannot allocate an object of type `%T'", type);
+ error ("cannot allocate an object of type `%T'", type);
/* Only go through this once. */
if (TREE_PURPOSE (u) == NULL_TREE)
{
TREE_PURPOSE (u) = error_mark_node;
- error (" since the following virtual functions are abstract:");
+ error (" because the following virtual functions are abstract:");
for (tu = u; tu; tu = TREE_CHAIN (tu))
cp_error_at ("\t%#D", TREE_VALUE (tu));
}
else
- cp_error (" since type `%T' has abstract virtual functions", type);
-}
-
-/* Print an error message for invalid use of a signature type.
- Signatures are treated similar to abstract classes here, they
- cannot be instantiated. */
+ error (" since type `%T' has abstract virtual functions", type);
-void
-signature_error (decl, type)
- tree decl;
- tree type;
-{
- if (decl)
- {
- if (TREE_CODE (decl) == RESULT_DECL)
- return;
-
- if (TREE_CODE (decl) == VAR_DECL)
- cp_error ("cannot declare variable `%D' to be of signature type `%T'",
- decl, type);
- else if (TREE_CODE (decl) == PARM_DECL)
- cp_error ("cannot declare parameter `%D' to be of signature type `%T'",
- decl, type);
- else if (TREE_CODE (decl) == FIELD_DECL)
- cp_error ("cannot declare field `%D' to be of signature type `%T'",
- decl, type);
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- cp_error ("invalid return type for method `%#D'", decl);
- else if (TREE_CODE (decl) == FUNCTION_DECL)
- cp_error ("invalid return type for function `%#D'", decl);
- }
- else
- cp_error ("cannot allocate an object of signature type `%T'", type);
+ return 1;
}
/* Print an error message for invalid use of an incomplete type.
@@ -214,10 +189,18 @@ incomplete_type_error (value, type)
tree value;
tree type;
{
+ int decl = 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_at ("`%D' has incomplete type", value);
+ decl = 1;
+ }
retry:
/* We must print an error message. Be clever about what it says. */
@@ -226,12 +209,13 @@ retry:
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
- cp_error ("invalid use of undefined type `%#T'", type);
+ if (!decl)
+ error ("invalid use of undefined type `%#T'", type);
cp_error_at ("forward declaration of `%#T'", type);
break;
case VOID_TYPE:
- cp_error ("invalid use of void expression");
+ error ("invalid use of `%T'", type);
break;
case ARRAY_TYPE:
@@ -240,275 +224,34 @@ retry:
type = TREE_TYPE (type);
goto retry;
}
- cp_error ("invalid use of array with unspecified bounds");
+ error ("invalid use of array with unspecified bounds");
break;
case OFFSET_TYPE:
bad_member:
- cp_error ("invalid use of member (did you forget the `&' ?)");
+ error ("invalid use of member (did you forget the `&' ?)");
break;
case TEMPLATE_TYPE_PARM:
- cp_error ("invalid use of template type parameter");
+ error ("invalid use of template type parameter");
break;
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");
+ 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");
+ error ("overloaded function with no contextual type information");
else
- cp_error ("insufficient contextual information to determine type");
+ error ("insufficient contextual information to determine type");
break;
default:
- my_friendly_abort (108);
+ abort ();
}
-
- 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 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);
-
- vfprintf (stderr, msg, ap);
- va_end (ap);
-
- fprintf (stderr, "\n");
}
-
-/* There are times when the compiler can get very confused, confused
- to the point of giving up by aborting, simply because of previous
- input errors. It is much better to have the user go back and
- correct those errors first, and see if it makes us happier, than it
- is to abort on him. This is because when one has a 10,000 line
- program, and the compiler comes back with ``core dump'', the user
- is left not knowing even where to begin to fix things and no place
- to even try and work around things.
-
- The parameter is to uniquely identify the problem to the user, so
- that they can say, I am having problem 59, and know that fix 7 will
- probably solve their problem. Or, we can document what problem
- 59 is, so they can understand how to work around it, should they
- ever run into it.
-
- 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).
-
- 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;
-void
-my_friendly_abort (i)
- int i;
-{
- /* if the previous error came through here, i.e. report_error_function
- ended up calling us again, don't just exit; we want a diagnostic of
- some kind. */
- if (abortcount == 1)
- current_function_decl = NULL_TREE;
- else if (errorcount > 0 || sorrycount > 0)
- {
- if (abortcount > 1)
- {
- if (i == 0)
- ack ("Internal compiler error.");
- else
- ack ("Internal compiler error %d.", i);
- ack ("Please submit a full bug report.");
- ack ("See %s for instructions.", GCCBUGURL);
- }
- else
- error ("confused by earlier errors, bailing out");
-
- exit (34);
- }
- ++abortcount;
-
- if (i == 0)
- error ("Internal compiler error.");
- else
- error ("Internal compiler error %d.", i);
-
- error ("Please submit a full bug report.");
- fatal ("See %s for instructions.", GCCBUGURL);
-}
-
-void
-my_friendly_assert (cond, where)
- int cond, where;
-{
- if (cond == 0)
- my_friendly_abort (where);
-}
-
-/* Return nonzero if VALUE is a valid constant-valued expression
- for use in initializing a static variable; one that can be an
- element of a "constant" initializer.
-
- Return null_pointer_node if the value is absolute;
- if it is relocatable, return the variable that determines the relocation.
- We assume that VALUE has been folded as much as possible;
- therefore, we do not need to check for such things as
- arithmetic-combinations of integers. */
-
-tree
-initializer_constant_valid_p (value, endtype)
- tree value;
- tree endtype;
-{
- switch (TREE_CODE (value))
- {
- case CONSTRUCTOR:
- if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
- && TREE_CONSTANT (value))
- return
- initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)),
- endtype);
-
- return TREE_STATIC (value) ? null_pointer_node : 0;
-
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- case COMPLEX_CST:
- case PTRMEM_CST:
- return null_pointer_node;
-
- case ADDR_EXPR:
- return TREE_OPERAND (value, 0);
-
- case NON_LVALUE_EXPR:
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
- case CONVERT_EXPR:
- case NOP_EXPR:
- /* Allow conversions between pointer types. */
- if (POINTER_TYPE_P (TREE_TYPE (value))
- && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
- /* Allow conversions between real types. */
- if (TREE_CODE (TREE_TYPE (value)) == REAL_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == REAL_TYPE)
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
- /* Allow length-preserving conversions between integer types. */
- if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (value))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
-
- /* Allow conversions between other integer types only if
- explicit value. */
- if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
- {
- tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- if (inner == null_pointer_node)
- return null_pointer_node;
- return 0;
- }
-
- /* Allow (int) &foo provided int is as wide as a pointer. */
- if (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == POINTER_TYPE
- && (TYPE_PRECISION (TREE_TYPE (value))
- >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
-
- /* Likewise conversions from int to pointers, but also allow
- conversions from 0. */
- if (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (value, 0))) == INTEGER_TYPE)
- {
- if (integer_zerop (TREE_OPERAND (value, 0)))
- return null_pointer_node;
- else if (TYPE_PRECISION (TREE_TYPE (value))
- <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
- return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- }
-
- /* Allow conversions to union types if the value inside is okay. */
- if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
- return initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- return 0;
-
- case PLUS_EXPR:
- if ((TREE_CODE (endtype) == INTEGER_TYPE)
- && (TYPE_PRECISION (endtype) < POINTER_SIZE))
- return 0;
- {
- tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- endtype);
- /* If either term is absolute, use the other terms relocation. */
- if (valid0 == null_pointer_node)
- return valid1;
- if (valid1 == null_pointer_node)
- return valid0;
- return 0;
- }
-
- case MINUS_EXPR:
- if ((TREE_CODE (endtype) == INTEGER_TYPE)
- && (TYPE_PRECISION (endtype) < POINTER_SIZE))
- return 0;
- {
- tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- endtype);
- /* Win if second argument is absolute. */
- if (valid1 == null_pointer_node)
- return valid0;
- /* Win if both arguments have the same relocation.
- Then the value is absolute. */
- if (valid0 == valid1)
- return null_pointer_node;
- return 0;
- }
-
- default:
- break;
- }
-
- return 0;
-}
/* Perform appropriate conversions on the initial value of a variable,
store it in the declaration DECL,
@@ -551,21 +294,11 @@ store_init_value (decl, init)
{
if (! TYPE_HAS_TRIVIAL_INIT_REF (type)
&& TREE_CODE (init) != CONSTRUCTOR)
- my_friendly_abort (109);
+ abort ();
- /* Although we are not allowed to declare variables of signature
- type, we complain about a possible constructor call in such a
- declaration as well. */
- if (TREE_CODE (init) == TREE_LIST
- && IS_SIGNATURE (type))
- {
- cp_error ("constructor syntax cannot be used with signature type `%T'",
- type);
- init = error_mark_node;
- }
- else if (TREE_CODE (init) == TREE_LIST)
+ if (TREE_CODE (init) == TREE_LIST)
{
- cp_error ("constructor syntax used, but no constructor declared for type `%T'", type);
+ error ("constructor syntax used, but no constructor declared for type `%T'", type);
init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
}
#if 0
@@ -633,9 +366,15 @@ store_init_value (decl, init)
/* End of special C++ code. */
- /* Digest the specified initializer into an expression. */
-
- value = digest_init (type, init, (tree *) 0);
+ /* We might have already run this bracketed initializer through
+ digest_init. Don't do so again. */
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)
+ && TREE_TYPE (init)
+ && TYPE_MAIN_VARIANT (TREE_TYPE (init)) == TYPE_MAIN_VARIANT (type))
+ value = init;
+ else
+ /* Digest the specified initializer into an expression. */
+ value = digest_init (type, init, (tree *) 0);
/* Store the expression if valid; else report error. */
@@ -643,7 +382,7 @@ store_init_value (decl, init)
;
/* Other code expects that initializers for objects of types that need
constructing never make it into DECL_INITIAL, and passes 'init' to
- expand_aggr_init without checking DECL_INITIAL. So just return. */
+ build_aggr_init without checking DECL_INITIAL. So just return. */
else if (TYPE_NEEDS_CONSTRUCTING (type))
return value;
else if (TREE_STATIC (decl)
@@ -667,19 +406,17 @@ store_init_value (decl, init)
#if 0 /* No, that's C. jason 9/19/94 */
else
{
- if (pedantic && TREE_CODE (value) == CONSTRUCTOR
- /* Don't complain about non-constant initializers of
- signature tables and signature pointers/references. */
- && ! (TYPE_LANG_SPECIFIC (type)
- && (IS_SIGNATURE (type)
- || IS_SIGNATURE_POINTER (type)
- || IS_SIGNATURE_REFERENCE (type))))
+ if (pedantic && TREE_CODE (value) == CONSTRUCTOR)
{
if (! TREE_CONSTANT (value) || ! TREE_STATIC (value))
- pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions");
+ pedwarn ("ISO C++ forbids non-constant aggregate initializer expressions");
}
}
#endif
+
+ /* Store the VALUE in DECL_INITIAL. If we're building a
+ statement-tree we will actually expand the initialization later
+ when we output this function. */
DECL_INITIAL (decl) = value;
return NULL_TREE;
}
@@ -717,6 +454,17 @@ digest_init (type, init, tail)
&& TREE_VALUE (init) == error_mark_node))
return error_mark_node;
+ if (TREE_CODE (init) == ERROR_MARK)
+ /* __PRETTY_FUNCTION__'s initializer is a bogus expression inside
+ a template function. This gets substituted during instantiation. */
+ return init;
+
+ /* We must strip the outermost array type when completing the type,
+ because the its bounds might be incomplete at the moment. */
+ if (!complete_type_or_else (TREE_CODE (type) == ARRAY_TYPE
+ ? TREE_TYPE (type) : type, NULL_TREE))
+ return error_mark_node;
+
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
@@ -752,11 +500,7 @@ digest_init (type, init, tail)
}
typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if ((typ1 == char_type_node
- || typ1 == signed_char_type_node
- || typ1 == unsigned_char_type_node
- || typ1 == unsigned_wchar_type_node
- || typ1 == signed_wchar_type_node)
+ if (char_type_p (typ1)
&& ((init && TREE_CODE (init) == STRING_CST)
|| (element && TREE_CODE (element) == STRING_CST)))
{
@@ -800,10 +544,8 @@ digest_init (type, init, tail)
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == REFERENCE_TYPE
- || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
- || TYPE_PTRMEMFUNC_P (type)
- || (code == RECORD_TYPE && ! raw_constructor
- && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))))
+ || code == BOOLEAN_TYPE || code == COMPLEX_TYPE || code == VECTOR_TYPE
+ || TYPE_PTRMEMFUNC_P (type))
{
if (raw_constructor)
{
@@ -816,10 +558,10 @@ digest_init (type, init, tail)
}
while (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
{
- cp_pedwarn ("braces around scalar initializer for `%T'", type);
+ pedwarn ("braces around scalar initializer for `%T'", type);
init = CONSTRUCTOR_ELTS (init);
if (TREE_CHAIN (init))
- cp_pedwarn ("ignoring extra initializers for `%T'", type);
+ pedwarn ("ignoring extra initializers for `%T'", type);
init = TREE_VALUE (init);
}
@@ -829,18 +571,19 @@ digest_init (type, init, tail)
/* Come here only for records and arrays (and unions with constructors). */
- if (TYPE_SIZE (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
+ if (COMPLETE_TYPE_P (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
{
- cp_error ("variable-sized object of type `%T' may not be initialized",
+ error ("variable-sized object of type `%T' may not be initialized",
type);
return error_mark_node;
}
- if (code == ARRAY_TYPE || code == RECORD_TYPE || code == UNION_TYPE)
+ if (code == ARRAY_TYPE || IS_AGGR_TYPE_CODE (code))
{
- if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type))
+ if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type)
+ && TREE_HAS_CONSTRUCTOR (init))
{
- cp_error ("subobject of type `%T' must be initialized by constructor, not by `%E'",
+ error ("subobject of type `%T' must be initialized by constructor, not by `%E'",
type, init);
return error_mark_node;
}
@@ -935,7 +678,7 @@ process_init_constructor (type, init, elts)
{
if (TREE_PURPOSE (tail)
&& (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
- || TREE_INT_CST_LOW (TREE_PURPOSE (tail)) != i))
+ || compare_tree_int (TREE_PURPOSE (tail), i) != 0))
sorry ("non-trivial labeled initializers");
if (TREE_VALUE (tail) != 0)
@@ -946,8 +689,8 @@ process_init_constructor (type, init, elts)
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))),
+ (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (type), TREE_TYPE (next1)),
981123);
my_friendly_assert (tail1 == 0
|| TREE_CODE (tail1) == TREE_LIST, 319);
@@ -992,7 +735,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
- members = expr_tree_cons (NULL_TREE, next1, members);
+ members = tree_cons (size_int (i), next1, members);
}
}
else if (TREE_CODE (type) == RECORD_TYPE)
@@ -1003,17 +746,17 @@ process_init_constructor (type, init, elts)
{
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
- sorry ("initializer list for object of class with virtual baseclasses");
+ sorry ("initializer list for object of class with virtual base classes");
return error_mark_node;
}
if (TYPE_BINFO_BASETYPES (type))
{
- sorry ("initializer list for object of class with baseclasses");
+ sorry ("initializer list for object of class with base classes");
return error_mark_node;
}
- if (TYPE_VIRTUAL_P (type))
+ if (TYPE_POLYMORPHIC_P (type))
{
sorry ("initializer list for object using virtual functions");
return error_mark_node;
@@ -1025,7 +768,7 @@ process_init_constructor (type, init, elts)
{
if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field))
{
- members = expr_tree_cons (field, integer_zero_node, members);
+ members = tree_cons (field, integer_zero_node, members);
continue;
}
@@ -1066,29 +809,36 @@ process_init_constructor (type, init, elts)
next1 = build_functional_cast (TREE_TYPE (field),
NULL_TREE);
else
- next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE,
- NULL_TREE);
+ {
+ next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE,
+ NULL_TREE);
+ if (init)
+ TREE_HAS_CONSTRUCTOR (next1)
+ = TREE_HAS_CONSTRUCTOR (init);
+ }
next1 = digest_init (TREE_TYPE (field), next1, 0);
/* Warn when some struct elements are implicitly initialized. */
- if (extra_warnings)
- cp_warning ("missing initializer for member `%D'", field);
+ if (extra_warnings
+ && (!init || TREE_HAS_CONSTRUCTOR (init)))
+ warning ("missing initializer for member `%D'", field);
}
else
{
if (TREE_READONLY (field))
- cp_error ("uninitialized const member `%D'", field);
+ 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",
+ 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);
+ 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);
+ if (extra_warnings
+ && (!init || TREE_HAS_CONSTRUCTOR (init)))
+ warning ("missing initializer for member `%D'", field);
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@@ -1101,10 +851,12 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
- members = expr_tree_cons (field, next1, members);
+ members = tree_cons (field, next1, members);
}
}
- else if (TREE_CODE (type) == UNION_TYPE)
+ else if (TREE_CODE (type) == UNION_TYPE
+ /* If the initializer was empty, use default zero initialization. */
+ && tail)
{
register tree field = TYPE_FIELDS (type);
@@ -1135,7 +887,7 @@ process_init_constructor (type, init, elts)
if (temp)
field = temp, win = 1;
else
- cp_error ("no field `%D' in union being initialized",
+ error ("no field `%D' in union being initialized",
TREE_PURPOSE (tail));
}
if (!win)
@@ -1143,7 +895,7 @@ process_init_constructor (type, init, elts)
}
else if (field == 0)
{
- cp_error ("union `%T' with no named members cannot be initialized",
+ error ("union `%T' with no named members cannot be initialized",
type);
TREE_VALUE (tail) = error_mark_node;
}
@@ -1155,7 +907,7 @@ process_init_constructor (type, init, elts)
next1 = digest_init (TREE_TYPE (field),
TREE_VALUE (tail), &tail1);
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
- my_friendly_abort (357);
+ abort ();
tail = tail1;
}
else
@@ -1170,7 +922,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
allsimple = 0;
- members = expr_tree_cons (field, next1, members);
+ members = tree_cons (field, next1, members);
}
/* If arguments were specified as a list, just remove the ones we used. */
@@ -1210,7 +962,12 @@ process_init_constructor (type, init, elts)
x.A::ii refers to the ii member of the L part of
the A part of the C object named by X. In this case,
- DATUM would be x, and BASETYPE would be A. */
+ DATUM would be x, and BASETYPE would be A.
+
+ I used to think that this was nonconformant, that the standard specified
+ that first we look up ii in A, then convert x to an L& and pull out the
+ ii part. But in fact, it does say that we convert x to an A&; A here
+ is known as the "naming class". (jason 2000-12-19) */
tree
build_scoped_ref (datum, basetype)
@@ -1218,48 +975,21 @@ build_scoped_ref (datum, basetype)
tree basetype;
{
tree ref;
- tree type = TREE_TYPE (datum);
+ tree binfo;
if (datum == error_mark_node)
return error_mark_node;
+ binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- type = TYPE_MAIN_VARIANT (type);
-
- /* This is an easy conversion. */
- if (is_aggr_type (basetype, 1))
- {
- tree binfo = TYPE_BINFO (basetype);
- if (binfo != TYPE_BINFO (type))
- {
- binfo = get_binfo (binfo, type, 1);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (binfo == 0)
- return error_not_base_type (basetype, type);
- }
+ if (binfo == error_mark_node)
+ return error_mark_node;
+ if (!binfo)
+ return error_not_base_type (TREE_TYPE (datum), basetype);
+
+ ref = build_unary_op (ADDR_EXPR, datum, 0);
+ ref = build_base_path (PLUS_EXPR, ref, binfo, 1);
- switch (TREE_CODE (datum))
- {
- case NOP_EXPR:
- case CONVERT_EXPR:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_EXPR:
- ref = convert_pointer_to (binfo,
- build_unary_op (ADDR_EXPR, TREE_OPERAND (datum, 0), 0));
- break;
- default:
- ref = convert_pointer_to (binfo,
- build_unary_op (ADDR_EXPR, datum, 0));
- }
- return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
- }
- return error_mark_node;
+ return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
}
/* Build a reference to an object specified by the C++ `->' operator.
@@ -1319,7 +1049,7 @@ build_x_arrow (datum)
if (last_rval == NULL_TREE)
{
- cp_error ("base operand of `->' has non-pointer type `%T'", type);
+ error ("base operand of `->' has non-pointer type `%T'", type);
return error_mark_node;
}
@@ -1329,13 +1059,8 @@ build_x_arrow (datum)
else
last_rval = default_conversion (rval);
- /* Signature pointers are not dereferenced. */
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (last_rval))
- && IS_SIGNATURE_POINTER (TREE_TYPE (last_rval)))
- return last_rval;
-
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
- return build_indirect_ref (last_rval, NULL_PTR);
+ return build_indirect_ref (last_rval, NULL);
if (types_memoized)
error ("result of `operator->()' yields non-pointer result");
@@ -1361,55 +1086,75 @@ build_m_component_ref (datum, component)
tree datum, component;
{
tree type;
- tree objtype = TREE_TYPE (datum);
- tree rettype;
+ tree objtype;
+ tree field_type;
+ int type_quals;
tree binfo;
if (processing_template_decl)
return build_min_nt (DOTSTAR_EXPR, datum, component);
+ datum = decay_conversion (datum);
+
+ if (datum == error_mark_node || component == error_mark_node)
+ return error_mark_node;
+
+ objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
+
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component)))
{
type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component)));
- rettype = type;
+ field_type = type;
}
- else
+ else if (TYPE_PTRMEM_P (TREE_TYPE (component)))
{
type = TREE_TYPE (TREE_TYPE (component));
- rettype = TREE_TYPE (type);
- }
-
- if (datum == error_mark_node || component == error_mark_node)
- return error_mark_node;
+ field_type = TREE_TYPE (type);
+
+ /* Compute the type of the field, as described in [expr.ref]. */
+ type_quals = TYPE_UNQUALIFIED;
+ if (TREE_CODE (field_type) == REFERENCE_TYPE)
+ /* The standard says that the type of the result should be the
+ type referred to by the reference. But for now, at least,
+ we do the conversion from reference type later. */
+ ;
+ else
+ {
+ type_quals = (cp_type_quals (field_type)
+ | cp_type_quals (TREE_TYPE (datum)));
- if (TREE_CODE (type) != OFFSET_TYPE && TREE_CODE (type) != METHOD_TYPE)
+ /* There's no such thing as a mutable pointer-to-member, so
+ we don't need to deal with that here like we do in
+ build_component_ref. */
+ field_type = cp_build_qualified_type (field_type, type_quals);
+ }
+ }
+ else
{
- cp_error ("`%E' cannot be used as a member pointer, since it is of type `%T'", component, type);
+ error ("`%E' cannot be used as a member pointer, since it is of type `%T'",
+ component, TREE_TYPE (component));
return error_mark_node;
}
- if (TREE_CODE (objtype) == REFERENCE_TYPE)
- objtype = TREE_TYPE (objtype);
- objtype = TYPE_MAIN_VARIANT (objtype);
-
if (! IS_AGGR_TYPE (objtype))
{
- cp_error ("cannot apply member pointer `%E' to `%E'", component, datum);
- cp_error ("which is of non-aggregate type `%T'", objtype);
+ error ("cannot apply member pointer `%E' to `%E', which is of non-aggregate type `%T'",
+ component, datum, objtype);
return error_mark_node;
}
- binfo = get_binfo (TYPE_METHOD_BASETYPE (type), objtype, 1);
- if (binfo == NULL_TREE)
+ binfo = lookup_base (objtype, TYPE_METHOD_BASETYPE (type),
+ ba_check, NULL);
+ if (!binfo)
{
- cp_error ("member type `%T::' incompatible with object type `%T'",
+ error ("member type `%T::' incompatible with object type `%T'",
TYPE_METHOD_BASETYPE (type), objtype);
return error_mark_node;
}
else if (binfo == error_mark_node)
return error_mark_node;
- component = build (OFFSET_REF, rettype, datum, component);
+ component = build (OFFSET_REF, field_type, datum, component);
if (TREE_CODE (type) == OFFSET_TYPE)
component = resolve_offset_ref (component);
return component;
@@ -1439,7 +1184,7 @@ build_functional_cast (exp, parms)
type = lookup_name (exp, 1);
if (!type || TREE_CODE (type) != TYPE_DECL)
{
- cp_error ("`%T' fails to be a typedef or built-in type", exp);
+ error ("`%T' fails to be a typedef or built-in type", exp);
return error_mark_node;
}
type = TREE_TYPE (type);
@@ -1453,12 +1198,6 @@ build_functional_cast (exp, parms)
if (processing_template_decl)
return build_min (CAST_EXPR, type, parms);
- if (IS_SIGNATURE (type))
- {
- error ("signature type not allowed in cast or constructor expression");
- return error_mark_node;
- }
-
if (! IS_AGGR_TYPE (type))
{
/* this must build a C cast */
@@ -1481,16 +1220,10 @@ build_functional_cast (exp, parms)
then the slot being initialized will be filled in. */
- if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
- {
- 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 (!complete_type_or_else (type, NULL_TREE))
+ return error_mark_node;
+ if (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));
@@ -1504,7 +1237,7 @@ build_functional_cast (exp, parms)
return get_target_expr (exp);
}
- exp = build_method_call (NULL_TREE, ctor_identifier, parms,
+ exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms,
TYPE_BINFO (type), LOOKUP_NORMAL);
if (exp == error_mark_node)
@@ -1513,148 +1246,107 @@ build_functional_cast (exp, parms)
return build_cplus_new (type, exp);
}
-/* Return the character string for the name that encodes the
- enumeral value VALUE in the domain TYPE. */
-char *
-enum_name_string (value, type)
- tree value;
- tree type;
-{
- register tree values = TYPE_VALUES (type);
- register HOST_WIDE_INT intval = TREE_INT_CST_LOW (value);
-
- my_friendly_assert (TREE_CODE (type) == ENUMERAL_TYPE, 324);
- while (values
- && TREE_INT_CST_LOW (TREE_VALUE (values)) != intval)
- values = TREE_CHAIN (values);
- if (values == NULL_TREE)
- {
- char *buf = (char *)oballoc (16 + TYPE_NAME_LENGTH (type));
+/* Complain about defining new types in inappropriate places. We give an
+ exception for C-style casts, to accommodate GNU C stylings. */
- /* Value must have been cast. */
- sprintf (buf, "(enum %s)%ld",
- TYPE_NAME_STRING (type), (long) intval);
- return buf;
- }
- return IDENTIFIER_POINTER (TREE_PURPOSE (values));
+void
+check_for_new_type (string, inptree)
+ const char *string;
+ flagged_type_tree inptree;
+{
+ if (inptree.new_type_flag
+ && (pedantic || strcmp (string, "cast") != 0))
+ pedwarn ("ISO C++ forbids defining types within %s", string);
}
-#if 0
-/* Print out a language-specific error message for
- (Pascal) case or (C) switch statements.
- CODE tells what sort of message to print.
- TYPE is the type of the switch index expression.
- NEW is the new value that we were trying to add.
- OLD is the old value that stopped us from adding it. */
+/* Add new exception specifier SPEC, to the LIST we currently have.
+ If it's already in LIST then do nothing.
+ Moan if it's bad and we're allowed to. COMPLAIN < 0 means we
+ know what we're doing. */
-void
-report_case_error (code, type, new_value, old_value)
- int code;
- tree type;
- tree new_value, old_value;
+tree
+add_exception_specifier (list, spec, complain)
+ tree list, spec;
+ int complain;
{
- if (code == 1)
- {
- if (new_value)
- error ("case label not within a switch statement");
- else
- error ("default label not within a switch statement");
- }
- else if (code == 2)
- {
- if (new_value == 0)
- {
- error ("multiple default labels in one switch");
- return;
- }
- if (TREE_CODE (new_value) == RANGE_EXPR)
- if (TREE_CODE (old_value) == RANGE_EXPR)
- {
- char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type)));
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- sprintf (buf, "overlapping ranges [%s..%s], [%s..%s] in case expression",
- enum_name_string (TREE_OPERAND (new_value, 0), type),
- enum_name_string (TREE_OPERAND (new_value, 1), type),
- enum_name_string (TREE_OPERAND (old_value, 0), type),
- enum_name_string (TREE_OPERAND (old_value, 1), type));
- else
- sprintf (buf, "overlapping ranges [%d..%d], [%d..%d] in case expression",
- TREE_INT_CST_LOW (TREE_OPERAND (new_value, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (new_value, 1)),
- TREE_INT_CST_LOW (TREE_OPERAND (old_value, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (old_value, 1)));
- error (buf);
- }
- else
- {
- char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type)));
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- sprintf (buf, "range [%s..%s] includes element `%s' in case expression",
- enum_name_string (TREE_OPERAND (new_value, 0), type),
- enum_name_string (TREE_OPERAND (new_value, 1), type),
- enum_name_string (old_value, type));
- else
- sprintf (buf, "range [%d..%d] includes (%d) in case expression",
- TREE_INT_CST_LOW (TREE_OPERAND (new_value, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (new_value, 1)),
- TREE_INT_CST_LOW (old_value));
- error (buf);
- }
- else if (TREE_CODE (old_value) == RANGE_EXPR)
- {
- char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type)));
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- sprintf (buf, "range [%s..%s] includes element `%s' in case expression",
- enum_name_string (TREE_OPERAND (old_value, 0), type),
- enum_name_string (TREE_OPERAND (old_value, 1), type),
- enum_name_string (new_value, type));
- else
- sprintf (buf, "range [%d..%d] includes (%d) in case expression",
- TREE_INT_CST_LOW (TREE_OPERAND (old_value, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (old_value, 1)),
- TREE_INT_CST_LOW (new_value));
- error (buf);
- }
- else
- {
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- error ("duplicate label `%s' in switch statement",
- enum_name_string (new_value, type));
- else
- error ("duplicate label (%d) in switch statement",
- TREE_INT_CST_LOW (new_value));
- }
- }
- else if (code == 3)
- {
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- warning ("case value out of range for enum %s",
- TYPE_NAME_STRING (type));
- else
- warning ("case value out of range");
- }
- else if (code == 4)
+ int ok;
+ tree core = spec;
+ int is_ptr;
+
+ if (spec == error_mark_node)
+ return list;
+
+ my_friendly_assert (spec && (!list || TREE_VALUE (list)), 19990317);
+
+ /* [except.spec] 1, type in an exception specifier shall not be
+ incomplete, or pointer or ref to incomplete other than pointer
+ to cv void. */
+ is_ptr = TREE_CODE (core) == POINTER_TYPE;
+ if (is_ptr || TREE_CODE (core) == REFERENCE_TYPE)
+ core = TREE_TYPE (core);
+ if (complain < 0)
+ ok = 1;
+ else if (VOID_TYPE_P (core))
+ ok = is_ptr;
+ else if (TREE_CODE (core) == TEMPLATE_TYPE_PARM)
+ ok = 1;
+ else if (processing_template_decl)
+ ok = 1;
+ else
+ ok = COMPLETE_TYPE_P (complete_type (core));
+
+ if (ok)
{
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- error ("range values `%s' and `%s' reversed",
- enum_name_string (new_value, type),
- enum_name_string (old_value, type));
- else
- error ("range values reversed");
+ tree probe;
+
+ for (probe = list; probe; probe = TREE_CHAIN (probe))
+ if (same_type_p (TREE_VALUE (probe), spec))
+ break;
+ if (!probe)
+ {
+ spec = build_tree_list (NULL_TREE, spec);
+ TREE_CHAIN (spec) = list;
+ list = spec;
+ }
}
+ else if (complain)
+ incomplete_type_error (NULL_TREE, core);
+ return list;
}
-#endif
-/* Complain about defining new types in inappropriate places. We give an
- exception for C-style casts, to accommodate GNU C stylings. */
+/* Combine the two exceptions specifier lists LIST and ADD, and return
+ their union. */
-void
-check_for_new_type (string, inptree)
- const char *string;
- flagged_type_tree inptree;
+tree
+merge_exception_specifiers (list, add)
+ tree list, add;
{
- if (inptree.new_type_flag
- && (pedantic || strcmp (string, "cast") != 0))
- pedwarn ("ANSI C++ forbids defining types within %s",string);
+ if (!list || !add)
+ return NULL_TREE;
+ else if (!TREE_VALUE (list))
+ return add;
+ else if (!TREE_VALUE (add))
+ return list;
+ else
+ {
+ tree orig_list = list;
+
+ for (; add; add = TREE_CHAIN (add))
+ {
+ tree spec = TREE_VALUE (add);
+ tree probe;
+
+ for (probe = orig_list; probe; probe = TREE_CHAIN (probe))
+ if (same_type_p (TREE_VALUE (probe), spec))
+ break;
+ if (!probe)
+ {
+ spec = build_tree_list (NULL_TREE, spec);
+ TREE_CHAIN (spec) = list;
+ list = spec;
+ }
+ }
+ }
+ return list;
}
OpenPOWER on IntegriCloud