#include "config.h"
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#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;
tree
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);
return error_mark_node;
}
tree
binfo_or_else (parent_or_type, type)
tree parent_or_type, 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;
}
void
readonly_error (arg, string, soft)
tree arg;
const char *string;
int soft;
{
const char *fmt;
void (*fn) PVPROTO ((const char *, ...));
if (soft)
fn = cp_pedwarn;
else
fn = cp_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";
else
fmt = "%s of read-only member `%D'";
(*fn) (fmt, string, TREE_OPERAND (arg, 1));
}
else if (TREE_CODE (arg) == VAR_DECL)
{
if (DECL_LANG_SPECIFIC (arg)
&& DECL_IN_AGGR_P (arg)
&& !TREE_STATIC (arg))
fmt = "%s of constant field `%D'";
else
fmt = "%s of read-only variable `%D'";
(*fn) (fmt, string, arg);
}
else if (TREE_CODE (arg) == PARM_DECL)
(*fn) ("%s of read-only parameter `%D'", string, arg);
else if (TREE_CODE (arg) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE
&& (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
|| TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
(*fn) ("%s of read-only reference `%D'", string, TREE_OPERAND (arg, 0));
else if (TREE_CODE (arg) == RESULT_DECL)
(*fn) ("%s of read-only named return value `%D'", string, arg);
else if (TREE_CODE (arg) == FUNCTION_DECL)
(*fn) ("%s of function `%D'", string, arg);
else
(*fn) ("%s of read-only location", string);
}
void
abstract_virtuals_error (decl, type)
tree decl;
tree type;
{
tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
tree tu;
if (decl)
{
if (TREE_CODE (decl) == RESULT_DECL)
return;
if (TREE_CODE (decl) == VAR_DECL)
cp_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'",
decl, type);
else if (TREE_CODE (decl) == FIELD_DECL)
cp_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);
else if (TREE_CODE (decl) == FUNCTION_DECL)
cp_error ("invalid return type for function `%#D'", decl);
}
else
cp_error ("cannot allocate an object of type `%T'", type);
if (TREE_PURPOSE (u) == NULL_TREE)
{
TREE_PURPOSE (u) = error_mark_node;
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
cp_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);
}
void
incomplete_type_error (value, type)
tree value;
tree type;
{
if (TREE_CODE (type) == ERROR_MARK)
return;
retry:
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 VOID_TYPE:
cp_error ("invalid use of void expression");
break;
case ARRAY_TYPE:
if (TYPE_DOMAIN (type))
{
type = TREE_TYPE (type);
goto retry;
}
cp_error ("invalid use of array with unspecified bounds");
break;
case OFFSET_TYPE:
bad_member:
cp_error ("invalid use of member (did you forget the `&' ?)");
break;
case TEMPLATE_TYPE_PARM:
cp_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");
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);
}
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");
}
static int abortcount = 0;
void
my_friendly_abort (i)
int i;
{
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);
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
ack ("Please submit a full bug report via the");
ack ("<URL:http://developer.apple.com/bugreporter> web page.");
#else
ack ("Please submit a full bug report.");
ack ("See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions.");
#endif
}
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);
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
error ("Please submit a full bug report via the");
fatal ("<URL:http://developer.apple.com/bugreporter> web page.");
#else
error ("Please submit a full bug report.");
fatal ("See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions.");
#endif
}
void
my_friendly_assert (cond, where)
int cond, where;
{
if (cond == 0)
my_friendly_abort (where);
}
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 VECTOR_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:
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);
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);
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);
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;
}
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);
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);
}
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 (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);
if (valid1 == null_pointer_node)
return valid0;
if (valid0 == valid1)
return null_pointer_node;
return 0;
}
default:
break;
}
return 0;
}
tree
store_init_value (decl, init)
tree decl, init;
{
register tree value, type;
type = TREE_TYPE (decl);
if (TREE_CODE (type) == ERROR_MARK)
return NULL_TREE;
#if 0
type = TYPE_MAIN_VARIANT (type);
#endif
if (IS_AGGR_TYPE (type))
{
if (! TYPE_HAS_TRIVIAL_INIT_REF (type)
&& TREE_CODE (init) != CONSTRUCTOR)
my_friendly_abort (109);
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)
{
cp_error ("constructor syntax used, but no constructor declared for type `%T'", type);
init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
}
#if 0
if (TREE_CODE (init) == CONSTRUCTOR)
{
tree field;
if (CLASSTYPE_N_BASECLASSES (type))
cp_error_at ("initializer list construction invalid for derived class object `%D'", decl);
if (CLASSTYPE_VTBL_PTR (type))
cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl);
if (TYPE_NEEDS_CONSTRUCTING (type))
{
cp_error_at ("initializer list construction invalid for `%D'", decl);
error ("due to the presence of a constructor");
}
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
{
cp_error_at ("initializer list construction invalid for `%D'", decl);
cp_error_at ("due to non-public access of member `%D'", field);
}
for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
{
cp_error_at ("initializer list construction invalid for `%D'", decl);
cp_error_at ("due to non-public access of member `%D'", field);
}
}
#endif
}
else if (TREE_CODE (init) == TREE_LIST
&& TREE_TYPE (init) != unknown_type_node)
{
if (TREE_CODE (decl) == RESULT_DECL)
{
if (TREE_CHAIN (init))
{
warning ("comma expression used to initialize return value");
init = build_compound_expr (init);
}
else
init = TREE_VALUE (init);
}
else if (TREE_CODE (init) == TREE_LIST
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
error ("cannot initialize arrays using this syntax");
return NULL_TREE;
}
else
{
if (TREE_CHAIN (init) != NULL_TREE)
{
pedwarn ("initializer list being treated as compound expression");
init = build_compound_expr (init);
}
else
init = TREE_VALUE (init);
}
}
value = digest_init (type, init, (tree *) 0);
if (TREE_CODE (value) == ERROR_MARK)
;
else if (TYPE_NEEDS_CONSTRUCTING (type))
return value;
else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value)
|| ! initializer_constant_valid_p (value, TREE_TYPE (value))
#if 0
|| (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))
#endif
))
return value;
#if 0
else
{
if (pedantic && TREE_CODE (value) == CONSTRUCTOR
&& ! (TYPE_LANG_SPECIFIC (type)
&& (IS_SIGNATURE (type)
|| IS_SIGNATURE_POINTER (type)
|| IS_SIGNATURE_REFERENCE (type))))
{
if (! TREE_CONSTANT (value) || ! TREE_STATIC (value))
pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions");
}
}
#endif
DECL_INITIAL (decl) = value;
return NULL_TREE;
}
tree
digest_init (type, init, tail)
tree type, init, *tail;
{
enum tree_code code = TREE_CODE (type);
tree element = NULL_TREE;
tree old_tail_contents = NULL_TREE;
int raw_constructor;
if (tail)
{
old_tail_contents = *tail;
*tail = TREE_CHAIN (*tail);
}
if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST
&& TREE_VALUE (init) == error_mark_node))
return error_mark_node;
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
&& CONSTRUCTOR_ELTS (init) != 0
&& TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0)
{
element = TREE_VALUE (CONSTRUCTOR_ELTS (init));
if (element && TREE_CODE (element) == NON_LVALUE_EXPR)
element = TREE_OPERAND (element, 0);
if (element == error_mark_node)
return element;
}
if (code == ARRAY_TYPE)
{
tree typ1;
if (TREE_CODE (init) == TREE_LIST)
{
error ("initializing array with parameter list");
return error_mark_node;
}
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)
&& ((init && TREE_CODE (init) == STRING_CST)
|| (element && TREE_CODE (element) == STRING_CST)))
{
tree string = element ? element : init;
tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)));
if ((typ2 != char_type_node)
#ifdef PASCAL_STRINGS
&& (typ2 != unsigned_char_type_node)
#endif
&& TYPE_PRECISION (typ1) == BITS_PER_UNIT)
{
error ("char-array initialized from wide string");
return error_mark_node;
}
if (typ2 == char_type_node && TYPE_PRECISION (typ1) != BITS_PER_UNIT)
{
error ("int-array initialized from non-wide string");
return error_mark_node;
}
TREE_TYPE (string) = type;
if (TYPE_DOMAIN (type) != 0
&& TREE_CONSTANT (TYPE_SIZE (type)))
{
register int size
= TREE_INT_CST_LOW (TYPE_SIZE (type));
size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
if (size < TREE_STRING_LENGTH (string))
{
#ifdef PASCAL_STRINGS
if ((typ2 != unsigned_char_type_node)
|| (size+1 < TREE_STRING_LENGTH (string)))
#endif
pedwarn ("initializer-string for array of chars is too long");
}
}
return string;
}
}
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == REFERENCE_TYPE
|| code == BOOLEAN_TYPE || code == COMPLEX_TYPE || code == VECTOR_TYPE
|| TYPE_PTRMEMFUNC_P (type)
|| (code == RECORD_TYPE && ! raw_constructor
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))))
{
if (raw_constructor)
{
if (element == 0)
{
error ("initializer for scalar variable requires one element");
return error_mark_node;
}
init = element;
}
while (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
{
cp_pedwarn ("braces around scalar initializer for `%T'", type);
init = CONSTRUCTOR_ELTS (init);
if (TREE_CHAIN (init))
cp_pedwarn ("ignoring extra initializers for `%T'", type);
init = TREE_VALUE (init);
}
return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0);
}
if (TYPE_SIZE (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
{
cp_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 (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type))
{
cp_error ("subobject of type `%T' must be initialized by constructor, not by `%E'",
type, init);
return error_mark_node;
}
else if (raw_constructor)
return process_init_constructor (type, init, (tree *)0);
else if (can_convert_arg (type, TREE_TYPE (init), init)
|| TYPE_NON_AGGREGATE_CLASS (type))
;
else if (tail != 0)
{
*tail = old_tail_contents;
return process_init_constructor (type, 0, tail);
}
if (code != ARRAY_TYPE)
{
int flags = LOOKUP_NORMAL;
if (tail)
flags |= LOOKUP_ONLYCONVERTING;
return convert_for_initialization (NULL_TREE, type, init, flags,
"initialization", NULL_TREE, 0);
}
}
error ("invalid initializer");
return error_mark_node;
}
static tree
process_init_constructor (type, init, elts)
tree type, init, *elts;
{
register tree tail;
register tree members = NULL;
register tree next1;
tree result;
int allconstant = 1;
int allsimple = 1;
int erroneous = 0;
if (elts)
{
if (warn_missing_braces)
warning ("aggregate has a partly bracketed initializer");
tail = *elts;
}
else
tail = CONSTRUCTOR_ELTS (init);
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree domain = TYPE_DOMAIN (type);
register long len;
register int i;
if (domain)
len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain))
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain))
+ 1);
else
len = -1;
for (i = 0; len < 0 || i < len; i++)
{
if (tail)
{
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)
{
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");
tail1 = NULL_TREE;
}
tail = tail1;
}
else
{
next1 = error_mark_node;
tail = TREE_CHAIN (tail);
}
}
else if (len < 0)
break;
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
{
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
break;
if (next1 == error_mark_node)
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 (NULL_TREE, next1, members);
}
}
else if (TREE_CODE (type) == RECORD_TYPE)
{
register tree field;
if (tail)
{
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
sorry ("initializer list for object of class with virtual baseclasses");
return error_mark_node;
}
if (TYPE_BINFO_BASETYPES (type))
{
sorry ("initializer list for object of class with baseclasses");
return error_mark_node;
}
if (TYPE_VIRTUAL_P (type))
{
sorry ("initializer list for object using virtual functions");
return error_mark_node;
}
}
for (field = TYPE_FIELDS (type); field;
field = TREE_CHAIN (field))
{
if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field))
{
members = expr_tree_cons (field, integer_zero_node, members);
continue;
}
if (TREE_CODE (field) != FIELD_DECL)
continue;
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;
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)))
{
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);
if (extra_warnings)
cp_warning ("missing initializer for member `%D'", field);
}
else
{
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);
if (extra_warnings)
cp_warning ("missing initializer for member `%D'", field);
continue;
}
if (next1 == error_mark_node)
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_CODE (type) == UNION_TYPE)
{
register tree field = TYPE_FIELDS (type);
while (field && (DECL_NAME (field) == 0
|| TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
if (TREE_PURPOSE (tail) != NULL_TREE)
{
int win = 0;
if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL)
field = TREE_PURPOSE (tail), win = 1;
else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE)
error ("index value instead of field name in union initializer");
else
{
tree temp;
for (temp = TYPE_FIELDS (type);
temp;
temp = TREE_CHAIN (temp))
if (DECL_NAME (temp) == TREE_PURPOSE (tail))
break;
if (temp)
field = temp, win = 1;
else
cp_error ("no field `%D' in union being initialized",
TREE_PURPOSE (tail));
}
if (!win)
TREE_VALUE (tail) = error_mark_node;
}
else if (field == 0)
{
cp_error ("union `%T' with no named members cannot be initialized",
type);
TREE_VALUE (tail) = error_mark_node;
}
if (TREE_VALUE (tail) != 0)
{
tree tail1 = tail;
next1 = digest_init (TREE_TYPE (field),
TREE_VALUE (tail), &tail1);
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
my_friendly_abort (357);
tail = tail1;
}
else
{
next1 = error_mark_node;
tail = TREE_CHAIN (tail);
}
if (next1 == error_mark_node)
erroneous = 1;
else if (!TREE_CONSTANT (next1))
allconstant = 0;
else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
allsimple = 0;
members = expr_tree_cons (field, next1, members);
}
if (elts)
*elts = tail;
else if (tail)
pedwarn ("excess elements in aggregate initializer");
if (erroneous)
return error_mark_node;
result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members));
if (init)
TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init);
if (allconstant) TREE_CONSTANT (result) = 1;
if (allconstant && allsimple) TREE_STATIC (result) = 1;
return result;
}
tree
build_scoped_ref (datum, basetype)
tree datum;
tree basetype;
{
tree ref;
tree type = TREE_TYPE (datum);
if (datum == error_mark_node)
return error_mark_node;
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = TYPE_MAIN_VARIANT (type);
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);
}
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;
}
tree
build_x_arrow (datum)
tree datum;
{
tree types_memoized = NULL_TREE;
register tree rval = datum;
tree type = TREE_TYPE (rval);
tree last_rval = NULL_TREE;
if (type == error_mark_node)
return error_mark_node;
if (processing_template_decl)
return build_min_nt (ARROW_EXPR, rval);
if (TREE_CODE (rval) == OFFSET_REF)
{
rval = resolve_offset_ref (datum);
type = TREE_TYPE (rval);
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
rval = convert_from_reference (rval);
type = TREE_TYPE (rval);
}
if (IS_AGGR_TYPE (type))
{
while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval,
NULL_TREE, NULL_TREE)))
{
if (rval == error_mark_node)
return error_mark_node;
if (value_member (TREE_TYPE (rval), types_memoized))
{
error ("circular pointer delegation detected");
return error_mark_node;
}
else
{
types_memoized = tree_cons (NULL_TREE, TREE_TYPE (rval),
types_memoized);
}
last_rval = rval;
}
if (last_rval == NULL_TREE)
{
cp_error ("base operand of `->' has non-pointer type `%T'", type);
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE)
last_rval = convert_from_reference (last_rval);
}
else
last_rval = default_conversion (rval);
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);
if (types_memoized)
error ("result of `operator->()' yields non-pointer result");
else
error ("base operand of `->' is not a pointer");
return error_mark_node;
}
tree
build_m_component_ref (datum, component)
tree datum, component;
{
tree type;
tree objtype = TREE_TYPE (datum);
tree rettype;
tree binfo;
if (processing_template_decl)
return build_min_nt (DOTSTAR_EXPR, datum, component);
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component)))
{
type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component)));
rettype = type;
}
else
{
type = TREE_TYPE (TREE_TYPE (component));
rettype = TREE_TYPE (type);
}
if (datum == error_mark_node || component == error_mark_node)
return error_mark_node;
if (TREE_CODE (type) != OFFSET_TYPE && TREE_CODE (type) != METHOD_TYPE)
{
cp_error ("`%E' cannot be used as a member pointer, since it is of type `%T'", component, type);
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);
return error_mark_node;
}
binfo = get_binfo (TYPE_METHOD_BASETYPE (type), objtype, 1);
if (binfo == NULL_TREE)
{
cp_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);
if (TREE_CODE (type) == OFFSET_TYPE)
component = resolve_offset_ref (component);
return component;
}
tree
build_functional_cast (exp, parms)
tree exp;
tree parms;
{
tree type;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
if (TREE_CODE (exp) == IDENTIFIER_NODE)
{
if (IDENTIFIER_HAS_TYPE_VALUE (exp))
type = IDENTIFIER_TYPE_VALUE (exp);
else
{
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);
return error_mark_node;
}
type = TREE_TYPE (type);
}
}
else if (TREE_CODE (exp) == TYPE_DECL)
type = TREE_TYPE (exp);
else
type = exp;
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))
{
if (parms == NULL_TREE)
parms = integer_zero_node;
else
{
if (TREE_CHAIN (parms) != NULL_TREE)
pedwarn ("initializer list being treated as compound expression");
parms = build_compound_expr (parms);
}
return build_c_cast (type, parms);
}
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 (parms && TREE_CHAIN (parms) == NULL_TREE)
return build_c_cast (type, TREE_VALUE (parms));
if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type)
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
{
exp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
return get_target_expr (exp);
}
exp = build_method_call (NULL_TREE, ctor_identifier, parms,
TYPE_BINFO (type), LOOKUP_NORMAL);
if (exp == error_mark_node)
return error_mark_node;
return build_cplus_new (type, exp);
}
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));
sprintf (buf, "(enum %s)%ld",
TYPE_NAME_STRING (type), (long) intval);
return buf;
}
return IDENTIFIER_POINTER (TREE_PURPOSE (values));
}
#if 0
void
report_case_error (code, type, new_value, old_value)
int code;
tree type;
tree new_value, old_value;
{
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)
{
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");
}
}
#endif
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 ("ANSI C++ forbids defining types within %s",string);
#ifdef OBJCPLUS
if(strcmp (string, "new") == 0 && inptree.t != NULL_TREE
&& TREE_PURPOSE(inptree.t) != NULL_TREE)
objc_check_type (TREE_VALUE(TREE_PURPOSE(inptree.t)));
#endif
}