#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#include "toplev.h"
#include "output.h"
#include "diagnostic.h"
static tree process_init_constructor (tree, tree, tree *);
tree
error_not_base_type (tree basetype, tree type)
{
if (TREE_CODE (basetype) == FUNCTION_DECL)
basetype = DECL_CONTEXT (basetype);
error ("type %qT is not a base type for type %qT", basetype, type);
return error_mark_node;
}
tree
binfo_or_else (tree base, tree type)
{
tree binfo = lookup_base (type, base, ba_unique, NULL);
if (binfo == error_mark_node)
return NULL_TREE;
else if (!binfo)
error_not_base_type (base, type);
return binfo;
}
void
readonly_error (tree arg, const char* string, int soft)
{
const char *fmt;
void (*fn) (const char *, ...);
if (soft)
fn = pedwarn;
else
fn = error;
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
fmt = "%s of data-member %qD in read-only structure";
else
fmt = "%s of read-only data-member %qD";
(*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 %qD";
else
fmt = "%s of read-only variable %qD";
(*fn) (fmt, string, arg);
}
else if (TREE_CODE (arg) == PARM_DECL)
(*fn) ("%s of read-only parameter %qD", 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 %qD", string, TREE_OPERAND (arg, 0));
else if (TREE_CODE (arg) == RESULT_DECL)
(*fn) ("%s of read-only named return value %qD", string, arg);
else if (TREE_CODE (arg) == FUNCTION_DECL)
(*fn) ("%s of function %qD", string, arg);
else
(*fn) ("%s of read-only location", string);
}
struct pending_abstract_type GTY((chain_next ("%h.next")))
{
tree decl;
tree type;
location_t locus;
struct pending_abstract_type* next;
};
static hashval_t
pat_calc_hash (const void* val)
{
const struct pending_abstract_type* pat = val;
return (hashval_t) TYPE_UID (pat->type);
}
static int
pat_compare (const void* val1, const void* val2)
{
const struct pending_abstract_type* pat1 = val1;
tree type2 = (tree)val2;
return (pat1->type == type2);
}
static GTY ((param_is (struct pending_abstract_type)))
htab_t abstract_pending_vars = NULL;
void
complete_type_check_abstract (tree type)
{
void **slot;
struct pending_abstract_type *pat;
location_t cur_loc = input_location;
gcc_assert (COMPLETE_TYPE_P (type));
if (!abstract_pending_vars)
return;
slot = htab_find_slot_with_hash (abstract_pending_vars, type,
(hashval_t)TYPE_UID (type), NO_INSERT);
if (!slot)
return;
pat = (struct pending_abstract_type*)*slot;
gcc_assert (pat);
if (CLASSTYPE_PURE_VIRTUALS (type))
{
struct pending_abstract_type *prev = 0, *next;
for (; pat; pat = next)
{
next = pat->next;
pat->next = prev;
prev = pat;
}
pat = prev;
while (pat)
{
gcc_assert (type == pat->type);
input_location = pat->locus;
abstract_virtuals_error (pat->decl, pat->type);
pat = pat->next;
}
}
htab_clear_slot (abstract_pending_vars, slot);
input_location = cur_loc;
}
int
abstract_virtuals_error (tree decl, tree type)
{
VEC (tree) *pure;
if (!CLASS_TYPE_P (type))
return 0;
if (!COMPLETE_TYPE_P (type))
{
void **slot;
struct pending_abstract_type *pat;
gcc_assert (!decl || DECL_P (decl)
|| TREE_CODE (decl) == IDENTIFIER_NODE);
if (!abstract_pending_vars)
abstract_pending_vars = htab_create_ggc (31, &pat_calc_hash,
&pat_compare, NULL);
slot = htab_find_slot_with_hash (abstract_pending_vars, type,
(hashval_t)TYPE_UID (type), INSERT);
pat = GGC_NEW (struct pending_abstract_type);
pat->type = type;
pat->decl = decl;
pat->locus = ((decl && DECL_P (decl))
? DECL_SOURCE_LOCATION (decl)
: input_location);
pat->next = *slot;
*slot = pat;
return 0;
}
if (!TYPE_SIZE (type))
return 0;
pure = CLASSTYPE_PURE_VIRTUALS (type);
if (!pure)
return 0;
if (decl)
{
if (TREE_CODE (decl) == RESULT_DECL)
return 0;
if (TREE_CODE (decl) == VAR_DECL)
cp_error_at ("cannot declare variable %q+D to be of abstract "
"type %qT", decl, type);
else if (TREE_CODE (decl) == PARM_DECL)
cp_error_at ("cannot declare parameter %q+D to be of abstract "
"type %qT", decl, type);
else if (TREE_CODE (decl) == FIELD_DECL)
cp_error_at ("cannot declare field %q+D to be of abstract "
"type %qT", decl, type);
else if (TREE_CODE (decl) == FUNCTION_DECL
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
cp_error_at ("invalid abstract return type for member function %q+#D",
decl);
else if (TREE_CODE (decl) == FUNCTION_DECL)
cp_error_at ("invalid abstract return type for function %q+#D",
decl);
else if (TREE_CODE (decl) == IDENTIFIER_NODE)
error ("invalid abstract type %qT for %qE", type, decl);
else
cp_error_at ("invalid abstract type for %q+D", decl);
}
else
error ("cannot allocate an object of abstract type %qT", type);
if (VEC_length (tree, pure))
{
unsigned ix;
tree fn;
inform ("%J because the following virtual functions are pure "
"within %qT:", TYPE_MAIN_DECL (type), type);
for (ix = 0; VEC_iterate (tree, pure, ix, fn); ix++)
inform ("%J\t%#D", fn, fn);
VEC_truncate (tree, pure, 0);
}
else
inform ("%J since type %qT has pure virtual functions",
TYPE_MAIN_DECL (type), type);
return 1;
}
void
cxx_incomplete_type_diagnostic (tree value, tree type, int diag_type)
{
int decl = 0;
void (*p_msg) (const char *, ...);
void (*p_msg_at) (const char *, ...);
if (diag_type == 1)
{
p_msg = warning;
p_msg_at = cp_warning_at;
}
else if (diag_type == 2)
{
p_msg = pedwarn;
p_msg_at = cp_pedwarn_at;
}
else
{
p_msg = error;
p_msg_at = cp_error_at;
}
if (TREE_CODE (type) == ERROR_MARK)
return;
if (value != 0 && (TREE_CODE (value) == VAR_DECL
|| TREE_CODE (value) == PARM_DECL
|| TREE_CODE (value) == FIELD_DECL))
{
(*p_msg_at) ("%qD has incomplete type", value);
decl = 1;
}
retry:
switch (TREE_CODE (type))
{
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
if (!decl)
(*p_msg) ("invalid use of undefined type %q#T", type);
if (!TYPE_TEMPLATE_INFO (type))
(*p_msg_at) ("forward declaration of %q#T", type);
else
(*p_msg_at) ("declaration of %q#T", type);
break;
case VOID_TYPE:
(*p_msg) ("invalid use of %qT", type);
break;
case ARRAY_TYPE:
if (TYPE_DOMAIN (type))
{
type = TREE_TYPE (type);
goto retry;
}
(*p_msg) ("invalid use of array with unspecified bounds");
break;
case OFFSET_TYPE:
bad_member:
(*p_msg) ("invalid use of member (did you forget the %<&%> ?)");
break;
case TEMPLATE_TYPE_PARM:
(*p_msg) ("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)
(*p_msg) ("address of overloaded function with no contextual "
"type information");
else if (value && TREE_CODE (value) == OVERLOAD)
(*p_msg) ("overloaded function with no contextual type information");
else
(*p_msg) ("insufficient contextual information to determine type");
break;
default:
gcc_unreachable ();
}
}
#undef cxx_incomplete_type_error
void
cxx_incomplete_type_error (tree value, tree type)
{
cxx_incomplete_type_diagnostic (value, type, 0);
}
static void
split_nonconstant_init_1 (tree dest, tree init)
{
tree *pelt, elt, type = TREE_TYPE (dest);
tree sub, code, inner_type = NULL;
bool array_type_p = false;
pelt = &CONSTRUCTOR_ELTS (init);
switch (TREE_CODE (type))
{
case ARRAY_TYPE:
inner_type = TREE_TYPE (type);
array_type_p = true;
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
while ((elt = *pelt))
{
tree field_index = TREE_PURPOSE (elt);
tree value = TREE_VALUE (elt);
if (!array_type_p)
inner_type = TREE_TYPE (field_index);
if (TREE_CODE (value) == CONSTRUCTOR)
{
if (array_type_p)
sub = build4 (ARRAY_REF, inner_type, dest, field_index,
NULL_TREE, NULL_TREE);
else
sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
split_nonconstant_init_1 (sub, value);
}
else if (!initializer_constant_valid_p (value, inner_type))
{
*pelt = TREE_CHAIN (elt);
if (array_type_p)
sub = build4 (ARRAY_REF, inner_type, dest, field_index,
NULL_TREE, NULL_TREE);
else
sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
code = build2 (MODIFY_EXPR, inner_type, sub, value);
code = build_stmt (EXPR_STMT, code);
add_stmt (code);
continue;
}
pelt = &TREE_CHAIN (elt);
}
break;
case VECTOR_TYPE:
if (!initializer_constant_valid_p (init, type))
{
tree cons = copy_node (init);
CONSTRUCTOR_ELTS (init) = NULL;
code = build2 (MODIFY_EXPR, type, dest, cons);
code = build_stmt (EXPR_STMT, code);
add_stmt (code);
}
break;
default:
gcc_unreachable ();
}
}
static tree
split_nonconstant_init (tree dest, tree init)
{
tree code;
if (TREE_CODE (init) == CONSTRUCTOR)
{
code = push_stmt_list ();
split_nonconstant_init_1 (dest, init);
code = pop_stmt_list (code);
DECL_INITIAL (dest) = init;
TREE_READONLY (dest) = 0;
}
else
code = build2 (INIT_EXPR, TREE_TYPE (dest), dest, init);
return code;
}
tree
store_init_value (tree decl, tree init)
{
tree value, type;
type = TREE_TYPE (decl);
if (TREE_CODE (type) == ERROR_MARK)
return NULL_TREE;
if (IS_AGGR_TYPE (type))
{
gcc_assert (TYPE_HAS_TRIVIAL_INIT_REF (type)
|| TREE_CODE (init) == CONSTRUCTOR);
if (TREE_CODE (init) == TREE_LIST)
{
error ("constructor syntax used, but no constructor declared "
"for type %qT", type);
init = build_constructor (NULL_TREE, nreverse (init));
}
}
else if (TREE_CODE (init) == TREE_LIST
&& TREE_TYPE (init) != unknown_type_node)
{
if (TREE_CODE (decl) == RESULT_DECL)
init = build_x_compound_expr_from_list (init,
"return value initializer");
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
init = build_x_compound_expr_from_list (init, "initializer");
}
value = digest_init (type, init, (tree *) 0);
if (value != error_mark_node
&& (TREE_SIDE_EFFECTS (value)
|| ! initializer_constant_valid_p (value, TREE_TYPE (value))))
return split_nonconstant_init (decl, value);
DECL_INITIAL (decl) = value;
return NULL_TREE;
}
tree
digest_init (tree type, tree init, tree* tail)
{
enum tree_code code = TREE_CODE (type);
tree element = NULL_TREE;
tree old_tail_contents = NULL_TREE;
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) == ERROR_MARK)
return init;
if (!complete_type_or_else (TREE_CODE (type) == ARRAY_TYPE
? TREE_TYPE (type) : type, NULL_TREE))
return error_mark_node;
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
if (BRACE_ENCLOSED_INITIALIZER_P (init)
&& 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 (char_type_p (typ1)
&& ((init && TREE_CODE (init) == STRING_CST)
|| (element && TREE_CODE (element) == STRING_CST)))
{
tree string = element ? element : init;
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
!= char_type_node)
&& TYPE_PRECISION (typ1) == BITS_PER_UNIT)
{
error ("char-array initialized from wide string");
return error_mark_node;
}
if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
== 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)))
{
int size = TREE_INT_CST_LOW (TYPE_SIZE (type));
size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
if (size < TREE_STRING_LENGTH (string))
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
|| TYPE_PTR_TO_MEMBER_P (type))
{
if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
if (element == 0)
{
error ("initializer for scalar variable requires one element");
return error_mark_node;
}
init = element;
}
while (BRACE_ENCLOSED_INITIALIZER_P (init))
{
pedwarn ("braces around scalar initializer for %qT", type);
init = CONSTRUCTOR_ELTS (init);
if (TREE_CHAIN (init))
pedwarn ("ignoring extra initializers for %qT", type);
init = TREE_VALUE (init);
}
return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0);
}
if (COMPLETE_TYPE_P (type) && ! TREE_CONSTANT (TYPE_SIZE (type)))
{
error ("variable-sized object of type %qT may not be initialized",
type);
return error_mark_node;
}
if (code == ARRAY_TYPE || code == VECTOR_TYPE || IS_AGGR_TYPE_CODE (code))
{
if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
error ("subobject of type %qT must be initialized by "
"constructor, not by %qE",
type, init);
return error_mark_node;
}
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 (tree type, tree init, tree* elts)
{
tree tail;
tree members = NULL;
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_CODE (type) == VECTOR_TYPE)
{
long len;
int i;
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree domain = TYPE_DOMAIN (type);
if (domain)
len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain))
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain))
+ 1);
else
len = -1;
}
else
{
len = TYPE_VECTOR_SUBPARTS (type);
}
for (i = 0; len < 0 || i < len; i++)
{
if (tail)
{
if (TREE_PURPOSE (tail)
&& (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST
|| compare_tree_int (TREE_PURPOSE (tail), i) != 0))
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;
gcc_assert (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (type), TREE_TYPE (next1)));
gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST);
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);
next1 = digest_init (TREE_TYPE (type), next1, 0);
}
else if (! zero_init_p (TREE_TYPE (type)))
next1 = build_zero_init (TREE_TYPE (type),
NULL_TREE,
false);
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 = tree_cons (size_int (i), next1, members);
}
}
else if (TREE_CODE (type) == RECORD_TYPE)
{
tree field;
if (tail)
{
gcc_assert (!CLASSTYPE_VBASECLASSES (type));
gcc_assert (!TYPE_BINFO (type)
|| !BINFO_N_BASE_BINFOS (TYPE_BINFO (type)));
gcc_assert (!TYPE_POLYMORPHIC_P (type));
}
for (field = TYPE_FIELDS (type); field;
field = TREE_CHAIN (field))
{
if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field))
{
members = tree_cons (field, integer_zero_node, members);
continue;
}
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
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);
gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST);
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);
if (init)
TREE_HAS_CONSTRUCTOR (next1)
= TREE_HAS_CONSTRUCTOR (init);
}
next1 = digest_init (TREE_TYPE (field), next1, 0);
if (warn_missing_field_initializers
&& (!init || BRACE_ENCLOSED_INITIALIZER_P (init)))
warning ("missing initializer for member %qD", field);
}
else
{
if (TREE_READONLY (field))
error ("uninitialized const member %qD", field);
else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field)))
error ("member %qD with uninitialized const fields", field);
else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
error ("member %qD is uninitialized reference", field);
if (warn_missing_field_initializers
&& (!init || BRACE_ENCLOSED_INITIALIZER_P (init)))
warning ("missing initializer for member %qD", field);
if (! zero_init_p (TREE_TYPE (field)))
next1 = build_zero_init (TREE_TYPE (field),
NULL_TREE,
false);
else
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 = tree_cons (field, next1, members);
}
}
else if (TREE_CODE (type) == UNION_TYPE
&& tail)
{
tree field = TYPE_FIELDS (type);
while (field && (!DECL_NAME (field) || 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
error ("no field %qD in union being initialized",
TREE_PURPOSE (tail));
}
if (!win)
TREE_VALUE (tail) = error_mark_node;
}
else if (field == 0)
{
error ("union %qT 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);
gcc_assert (!tail1 || TREE_CODE (tail1) == TREE_LIST);
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 = 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, nreverse (members));
if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE)
cp_complete_array_type (&TREE_TYPE (result), result, 0);
if (init)
TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init);
if (allconstant)
{
TREE_CONSTANT (result) = 1;
TREE_INVARIANT (result) = 1;
if (allsimple)
TREE_STATIC (result) = 1;
}
return result;
}
tree
build_scoped_ref (tree datum, tree basetype, tree* binfo_p)
{
tree binfo;
if (datum == error_mark_node)
return error_mark_node;
if (*binfo_p)
binfo = *binfo_p;
else
binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
if (!binfo || binfo == error_mark_node)
{
*binfo_p = NULL_TREE;
if (!binfo)
error_not_base_type (basetype, TREE_TYPE (datum));
return error_mark_node;
}
*binfo_p = binfo;
return build_base_path (PLUS_EXPR, datum, binfo, 1);
}
tree
build_x_arrow (tree expr)
{
tree orig_expr = expr;
tree types_memoized = NULL_TREE;
tree type = TREE_TYPE (expr);
tree last_rval = NULL_TREE;
if (type == error_mark_node)
return error_mark_node;
if (processing_template_decl)
{
if (type_dependent_expression_p (expr))
return build_min_nt (ARROW_EXPR, expr);
expr = build_non_dependent_expr (expr);
}
if (IS_AGGR_TYPE (type))
{
while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr,
NULL_TREE, NULL_TREE,
NULL)))
{
if (expr == error_mark_node)
return error_mark_node;
if (value_member (TREE_TYPE (expr), types_memoized))
{
error ("circular pointer delegation detected");
return error_mark_node;
}
else
{
types_memoized = tree_cons (NULL_TREE, TREE_TYPE (expr),
types_memoized);
}
last_rval = expr;
}
if (last_rval == NULL_TREE)
{
error ("base operand of %<->%> has non-pointer type %qT", type);
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE)
last_rval = convert_from_reference (last_rval);
}
else
last_rval = decay_conversion (expr);
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
{
if (processing_template_decl)
{
expr = build_min_non_dep (ARROW_EXPR, last_rval, orig_expr);
TREE_TYPE (expr) = TREE_TYPE (TREE_TYPE (last_rval));
return expr;
}
return build_indirect_ref (last_rval, NULL);
}
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 (tree datum, tree component)
{
tree ptrmem_type;
tree objtype;
tree type;
tree binfo;
tree ctype;
datum = decay_conversion (datum);
if (datum == error_mark_node || component == error_mark_node)
return error_mark_node;
ptrmem_type = TREE_TYPE (component);
if (!TYPE_PTR_TO_MEMBER_P (ptrmem_type))
{
error ("%qE cannot be used as a member pointer, since it is of "
"type %qT",
component, ptrmem_type);
return error_mark_node;
}
objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
if (! IS_AGGR_TYPE (objtype))
{
error ("cannot apply member pointer %qE to %qE, which is of "
"non-aggregate type %qT",
component, datum, objtype);
return error_mark_node;
}
type = TYPE_PTRMEM_POINTED_TO_TYPE (ptrmem_type);
ctype = complete_type (TYPE_PTRMEM_CLASS_TYPE (ptrmem_type));
if (!COMPLETE_TYPE_P (ctype))
{
if (!same_type_p (ctype, objtype))
goto mismatch;
binfo = NULL;
}
else
{
binfo = lookup_base (objtype, ctype, ba_check, NULL);
if (!binfo)
{
mismatch:
error ("pointer to member type %qT incompatible with object "
"type %qT",
type, objtype);
return error_mark_node;
}
else if (binfo == error_mark_node)
return error_mark_node;
}
if (TYPE_PTRMEM_P (ptrmem_type))
{
type = cp_build_qualified_type (type,
(cp_type_quals (type)
| cp_type_quals (TREE_TYPE (datum))));
datum = build_address (datum);
if (binfo)
datum = build_base_path (PLUS_EXPR, datum, binfo, 1);
datum = build2 (PLUS_EXPR, build_pointer_type (type),
datum, build_nop (ptrdiff_type_node, component));
return build_indirect_ref (datum, 0);
}
else
return build2 (OFFSET_REF, type, datum, component);
}
tree
build_functional_cast (tree exp, tree parms)
{
tree type;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
if (TREE_CODE (exp) == TYPE_DECL)
type = TREE_TYPE (exp);
else
type = exp;
if (processing_template_decl)
{
tree t = build_min (CAST_EXPR, type, parms);
TREE_SIDE_EFFECTS (t) = 1;
return t;
}
if (! IS_AGGR_TYPE (type))
{
if (parms == NULL_TREE)
parms = integer_zero_node;
else
parms = build_x_compound_expr_from_list (parms, "functional cast");
return build_c_cast (type, parms);
}
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));
if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type)
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
{
exp = build_constructor (type, NULL_TREE);
return get_target_expr (exp);
}
exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
type, LOOKUP_NORMAL);
if (exp == error_mark_node)
return error_mark_node;
return build_cplus_new (type, exp);
}
tree
add_exception_specifier (tree list, tree spec, int complain)
{
bool ok;
tree core = spec;
bool is_ptr;
int diag_type = -1;
if (spec == error_mark_node)
return list;
gcc_assert (spec && (!list || TREE_VALUE (list)));
is_ptr = TREE_CODE (core) == POINTER_TYPE;
if (is_ptr || TREE_CODE (core) == REFERENCE_TYPE)
core = TREE_TYPE (core);
if (complain < 0)
ok = true;
else if (VOID_TYPE_P (core))
ok = is_ptr;
else if (TREE_CODE (core) == TEMPLATE_TYPE_PARM)
ok = true;
else if (processing_template_decl)
ok = true;
else
{
ok = true;
if (!COMPLETE_TYPE_P (complete_type (core)))
diag_type = 2;
}
if (ok)
{
tree probe;
for (probe = list; probe; probe = TREE_CHAIN (probe))
if (same_type_p (TREE_VALUE (probe), spec))
break;
if (!probe)
list = tree_cons (NULL_TREE, spec, list);
}
else
diag_type = 0;
if (diag_type >= 0 && complain)
cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
return list;
}
tree
merge_exception_specifiers (tree list, tree add)
{
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;
}
void
require_complete_eh_spec_types (tree fntype, tree decl)
{
tree raises;
if (decl && DECL_ARTIFICIAL (decl))
return;
for (raises = TYPE_RAISES_EXCEPTIONS (fntype); raises;
raises = TREE_CHAIN (raises))
{
tree type = TREE_VALUE (raises);
if (type && !COMPLETE_TYPE_P (type))
{
if (decl)
error
("call to function %qD which throws incomplete type %q#T",
decl, type);
else
error ("call to function which throws incomplete type %q#T",
decl);
}
}
}
#include "gt-cp-typeck2.h"