#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 type, tree init);
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 *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
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 =
(const struct pending_abstract_type *) val;
return (hashval_t) TYPE_UID (pat->type);
}
static int
pat_compare (const void* val1, const void* val2)
{
const struct pending_abstract_type *pat1 =
(const struct pending_abstract_type *) 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,gc) *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 = (struct pending_abstract_type *) *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)
error ("cannot declare variable %q+D to be of abstract "
"type %qT", decl, type);
else if (TREE_CODE (decl) == PARM_DECL)
error ("cannot declare parameter %q+D to be of abstract type %qT",
decl, type);
else if (TREE_CODE (decl) == FIELD_DECL)
error ("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)
error ("invalid abstract return type for member function %q+#D", decl);
else if (TREE_CODE (decl) == FUNCTION_DECL)
error ("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
error ("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 ("\t%+#D", 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 *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
if (diag_type == 1)
p_msg = warning0;
else if (diag_type == 2)
p_msg = pedwarn;
else
p_msg = error;
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 ("%q+D 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 incomplete type %q#T", type);
if (!TYPE_TEMPLATE_INFO (type))
p_msg ("forward declaration of %q+#T", type);
else
p_msg ("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 %qT", type);
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
p_msg ("invalid use of template template parameter %qT",
TYPE_NAME (type));
break;
case TYPENAME_TYPE:
p_msg ("invalid use of dependent type %qT", type);
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)
{
unsigned HOST_WIDE_INT idx;
tree field_index, value;
tree type = TREE_TYPE (dest);
tree inner_type = NULL;
bool array_type_p = false;
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:
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx,
field_index, value)
{
gcc_assert (field_index);
if (!array_type_p)
inner_type = TREE_TYPE (field_index);
if (TREE_CODE (value) == CONSTRUCTOR)
{
tree sub;
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))
{
tree code;
tree sub;
VEC_ordered_remove (constructor_elt, CONSTRUCTOR_ELTS (init),
idx);
--idx;
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 (INIT_EXPR, inner_type, sub, value);
code = build_stmt (EXPR_STMT, code);
add_stmt (code);
continue;
}
}
break;
case VECTOR_TYPE:
if (!initializer_constant_valid_p (init, type))
{
tree code;
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 ();
}
TREE_CONSTANT (init) = 1;
}
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_from_list (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);
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)
{
enum tree_code code = TREE_CODE (type);
if (init == error_mark_node)
return error_mark_node;
gcc_assert (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 (code == ARRAY_TYPE)
{
tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type));
if (char_type_p (typ1)
&& TREE_CODE (init) == STRING_CST)
{
tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init)));
bool pascal_p = (char_type == unsigned_char_type_node);
if (char_type != char_type_node
&& !pascal_p
&& TYPE_PRECISION (typ1) == BITS_PER_UNIT)
{
error ("char-array initialized from wide string");
return error_mark_node;
}
if ((char_type == char_type_node
|| pascal_p)
&& TYPE_PRECISION (typ1) != BITS_PER_UNIT)
{
error ("int-array initialized from non-wide string");
return error_mark_node;
}
TREE_TYPE (init) = 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 < (pascal_p
? TREE_STRING_LENGTH (init) - 1
: TREE_STRING_LENGTH (init)))
pedwarn ("initializer-string for array of chars is too long");
}
return init;
}
}
if (TREE_CODE (type) != COMPLEX_TYPE
&& (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0);
gcc_assert (TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == VECTOR_TYPE
|| TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == COMPLEX_TYPE);
if (BRACE_ENCLOSED_INITIALIZER_P (init))
return process_init_constructor (type, init);
else
{
if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE)
{
error ("cannot initialize aggregate of type %qT with "
"a compound literal", type);
return error_mark_node;
}
if (TREE_CODE (type) == ARRAY_TYPE
&& TREE_CODE (init) != CONSTRUCTOR)
{
error ("array must be initialized with a brace-enclosed"
" initializer");
return error_mark_node;
}
if (code == VECTOR_TYPE
&& TREE_CODE (init) == VAR_DECL
&& TREE_CODE (TREE_TYPE (init)) == VECTOR_TYPE
&& vector_types_convertible_p (TREE_TYPE (init), type, true)
&& TYPE_READONLY (type)
&& !TYPE_VOLATILE (type))
{
tree v = DECL_INITIAL (init);
if (v
&& v != error_mark_node
&& TREE_CONSTANT (v))
init = v;
}
if (code == VECTOR_TYPE
&& TREE_CODE (init) == CONSTRUCTOR
&& TREE_CODE (TREE_TYPE (init)) == VECTOR_TYPE
&& vector_types_convertible_p (TREE_TYPE (init), type, true)
&& TREE_CONSTANT (init))
return build_vector_from_ctor (type, CONSTRUCTOR_ELTS (init));
return convert_for_initialization (NULL_TREE, type, init,
LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING,
"initialization", NULL_TREE, 0);
}
}
#define PICFLAG_ERRONEOUS 1
#define PICFLAG_NOT_ALL_CONSTANT 2
#define PICFLAG_NOT_ALL_SIMPLE 4
static int
picflag_from_initializer (tree init)
{
if (init == error_mark_node)
return PICFLAG_ERRONEOUS;
else if (!TREE_CONSTANT (init))
return PICFLAG_NOT_ALL_CONSTANT;
else if (!initializer_constant_valid_p (init, TREE_TYPE (init)))
return PICFLAG_NOT_ALL_SIMPLE;
return 0;
}
static int
process_init_constructor_array (tree type, tree init)
{
unsigned HOST_WIDE_INT i, len = 0;
int flags = 0;
bool unbounded = false;
constructor_elt *ce;
VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (init);
gcc_assert (TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == VECTOR_TYPE);
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
unbounded = true;
}
else
len = TYPE_VECTOR_SUBPARTS (type);
if (!unbounded)
gcc_assert (VEC_length (constructor_elt, v) <= len);
for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
{
if (ce->index)
{
gcc_assert (TREE_CODE (ce->index) == INTEGER_CST);
if (compare_tree_int (ce->index, i) != 0)
{
ce->value = error_mark_node;
sorry ("non-trivial designated initializers not supported");
}
}
else
ce->index = size_int (i);
gcc_assert (ce->value);
ce->value = digest_init (TREE_TYPE (type), ce->value);
if (ce->value != error_mark_node)
gcc_assert (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (type), TREE_TYPE (ce->value)));
flags |= picflag_from_initializer (ce->value);
}
if (!unbounded)
for (; i < len; ++i)
{
tree next;
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
{
if (IS_AGGR_TYPE (TREE_TYPE (type)))
next = build_functional_cast (TREE_TYPE (type), NULL_TREE);
else
next = build_constructor (NULL_TREE, NULL);
next = digest_init (TREE_TYPE (type), next);
}
else if (!zero_init_p (TREE_TYPE (type)))
next = build_zero_init (TREE_TYPE (type),
NULL_TREE,
false);
else
break;
flags |= picflag_from_initializer (next);
CONSTRUCTOR_APPEND_ELT (v, size_int (i), next);
}
CONSTRUCTOR_ELTS (init) = v;
return flags;
}
static int
process_init_constructor_record (tree type, tree init)
{
VEC(constructor_elt,gc) *v = NULL;
int flags = 0;
tree field;
unsigned HOST_WIDE_INT idx = 0;
gcc_assert (TREE_CODE (type) == RECORD_TYPE);
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))
{
tree next;
if (!DECL_NAME (field) && DECL_C_BIT_FIELD (field))
{
flags |= picflag_from_initializer (integer_zero_node);
CONSTRUCTOR_APPEND_ELT (v, field, integer_zero_node);
continue;
}
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)))
{
constructor_elt *ce = VEC_index (constructor_elt,
CONSTRUCTOR_ELTS (init), idx);
if (ce->index)
{
gcc_assert (TREE_CODE (ce->index) == FIELD_DECL
|| TREE_CODE (ce->index) == IDENTIFIER_NODE);
if (ce->index != field
&& ce->index != DECL_NAME (field))
{
ce->value = error_mark_node;
sorry ("non-trivial designated initializers not supported");
}
}
gcc_assert (ce->value);
next = digest_init (TREE_TYPE (field), ce->value);
++idx;
}
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
{
if (IS_AGGR_TYPE (TREE_TYPE (field)))
next = build_functional_cast (TREE_TYPE (field), NULL_TREE);
else
next = build_constructor (NULL_TREE, NULL);
next = digest_init (TREE_TYPE (field), next);
warning (OPT_Wmissing_field_initializers,
"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);
warning (OPT_Wmissing_field_initializers,
"missing initializer for member %qD", field);
if (!zero_init_p (TREE_TYPE (field)))
next = build_zero_init (TREE_TYPE (field), NULL_TREE,
false);
else
continue;
}
flags |= picflag_from_initializer (next);
CONSTRUCTOR_APPEND_ELT (v, field, next);
}
CONSTRUCTOR_ELTS (init) = v;
return flags;
}
static int
process_init_constructor_union (tree type, tree init)
{
constructor_elt *ce;
if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init)))
return 0;
gcc_assert (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) == 1);
ce = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (init), 0);
if (ce->index)
{
if (TREE_CODE (ce->index) == FIELD_DECL)
;
else if (TREE_CODE (ce->index) == IDENTIFIER_NODE)
{
tree name = ce->index;
tree field;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (DECL_NAME (field) == name)
break;
if (!field)
{
error ("no field %qD found in union being initialized", field);
ce->value = error_mark_node;
}
ce->index = field;
}
else
{
gcc_assert (TREE_CODE (ce->index) == INTEGER_CST
|| TREE_CODE (ce->index) == RANGE_EXPR);
error ("index value instead of field name in union initializer");
ce->value = error_mark_node;
}
}
else
{
tree field = TYPE_FIELDS (type);
while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
gcc_assert (field);
ce->index = field;
}
if (ce->value && ce->value != error_mark_node)
ce->value = digest_init (TREE_TYPE (ce->index), ce->value);
return picflag_from_initializer (ce->value);
}
static tree
process_init_constructor (tree type, tree init)
{
int flags;
gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init));
if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
flags = process_init_constructor_array (type, init);
else if (TREE_CODE (type) == RECORD_TYPE)
flags = process_init_constructor_record (type, init);
else if (TREE_CODE (type) == UNION_TYPE)
flags = process_init_constructor_union (type, init);
else
gcc_unreachable ();
if (flags & PICFLAG_ERRONEOUS)
return error_mark_node;
TREE_TYPE (init) = type;
if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE)
cp_complete_array_type (&TREE_TYPE (init), init, 0);
if (!(flags & PICFLAG_NOT_ALL_CONSTANT))
{
TREE_CONSTANT (init) = 1;
TREE_INVARIANT (init) = 1;
if (!(flags & PICFLAG_NOT_ALL_SIMPLE))
TREE_STATIC (init) = 1;
}
return init;
}
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;
if (error_operand_p (datum) || error_operand_p (component))
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-class 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)
return cp_convert (type, integer_zero_node);
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
&& !CLASSTYPE_NON_POD_P (type)
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
{
exp = build_zero_init (type,
NULL_TREE,
false);
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"