/* Report error messages, build initializers, and perform
some front-end optimizations for C++ compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "intl.h"
#include "cp-tree.h"
#include "flags.h"
#include "toplev.h"
#include "output.h"
#include "diagnostic.h"
+#include "real.h"
static tree
process_init_constructor (tree type, tree init);
value may not be changed thereafter. */
void
-readonly_error (tree arg, const char* string)
+readonly_error (tree arg, readonly_error_kind errstring)
{
- const char *fmt;
+
+/* This macro is used to emit diagnostics to ensure that all format
+ strings are complete sentences, visible to gettext and checked at
+ compile time. */
+
+#define ERROR_FOR_ASSIGNMENT(AS, ASM, IN, DE, ARG) \
+ do { \
+ switch (errstring) \
+ { \
+ case REK_ASSIGNMENT: \
+ error(AS, ARG); \
+ break; \
+ case REK_ASSIGNMENT_ASM: \
+ error(ASM, ARG); \
+ break; \
+ case REK_INCREMENT: \
+ error (IN, ARG); \
+ break; \
+ case REK_DECREMENT: \
+ error (DE, ARG); \
+ break; \
+ default: \
+ gcc_unreachable (); \
+ } \
+ } while (0)
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";
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "data-member %qD in read-only structure"),
+ G_("assignment (via 'asm' output) of "
+ "data-member %qD in read-only structure"),
+ G_("increment of "
+ "data-member %qD in read-only structure"),
+ G_("decrement of "
+ "data-member %qD in read-only structure"),
+ TREE_OPERAND (arg, 1));
else
- fmt = "%s of read-only data-member %qD";
- error (fmt, string, TREE_OPERAND (arg, 1));
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "read-only data-member %qD"),
+ G_("assignment (via 'asm' output) of "
+ "read-only data-member %qD"),
+ G_("increment of "
+ "read-only data-member %qD"),
+ G_("decrement of "
+ "read-only data-member %qD"),
+ 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";
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "constant field %qD"),
+ G_("assignment (via 'asm' output) of "
+ "constant field %qD"),
+ G_("increment of "
+ "constant field %qD"),
+ G_("decrement of "
+ "constant field %qD"),
+ arg);
else
- fmt = "%s of read-only variable %qD";
- error (fmt, string, arg);
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "read-only variable %qD"),
+ G_("assignment (via 'asm' output) of "
+ "read-only variable %qD"),
+ G_("increment of "
+ "read-only variable %qD"),
+ G_("decrement of "
+ "read-only variable %qD"),
+ arg);
+
}
else if (TREE_CODE (arg) == PARM_DECL)
- error ("%s of read-only parameter %qD", string, arg);
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "read-only parameter %qD"),
+ G_("assignment (via 'asm' output) of "
+ "read-only parameter %qD"),
+ G_("increment of "
+ "read-only parameter %qD"),
+ G_("decrement of "
+ "read-only parameter %qD"),
+ 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))
- error ("%s of read-only reference %qD", string, TREE_OPERAND (arg, 0));
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "read-only reference %qD"),
+ G_("assignment (via 'asm' output) of "
+ "read-only reference %qD"),
+ G_("increment of "
+ "read-only reference %qD"),
+ G_("decrement of "
+ "read-only reference %qD"),
+ TREE_OPERAND (arg, 0));
else if (TREE_CODE (arg) == RESULT_DECL)
- error ("%s of read-only named return value %qD", string, arg);
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "read-only named return value %qD"),
+ G_("assignment (via 'asm' output) of "
+ "read-only named return value %qD"),
+ G_("increment of "
+ "read-only named return value %qD"),
+ G_("decrement of "
+ "read-only named return value %qD"),
+ arg);
else if (TREE_CODE (arg) == FUNCTION_DECL)
- error ("%s of function %qD", string, arg);
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "function %qD"),
+ G_("assignment (via 'asm' output) of "
+ "function %qD"),
+ G_("increment of "
+ "function %qD"),
+ G_("decrement of "
+ "function %qD"),
+ arg);
else
- error ("%s of read-only location %qE", string, arg);
+ ERROR_FOR_ASSIGNMENT (G_("assignment of "
+ "read-only location %qE"),
+ G_("assignment (via 'asm' output) of "
+ "read-only location %qE"),
+ G_("increment of "
+ "read-only location %qE"),
+ G_("decrement of "
+ "read-only location %qE"),
+ arg);
}
\f
/* Structure that holds information about declarations whose type was
incomplete and we could not check whether it was abstract or not. */
-struct pending_abstract_type GTY((chain_next ("%h.next")))
-{
+struct GTY((chain_next ("%h.next"))) pending_abstract_type {
/* Declaration which we are checking for abstractness. It is either
a DECL node, or an IDENTIFIER_NODE if we do not have a full
declaration available. */
be abstract. */
if (!CLASS_TYPE_P (type))
return 0;
+ type = TYPE_MAIN_VARIANT (type);
/* If the type is incomplete, we register it within a hash table,
so that we can check again once it is completed. This makes sense
unsigned ix;
tree fn;
- inform ("%J because the following virtual functions are pure "
- "within %qT:", TYPE_MAIN_DECL (type), type);
+ inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+ " because the following virtual functions are pure within %qT:",
+ type);
for (ix = 0; VEC_iterate (tree, pure, ix, fn); ix++)
- inform ("\t%+#D", fn);
+ inform (input_location, "\t%+#D", fn);
/* Now truncate the vector. This leaves it non-null, so we know
there are pure virtuals, but empty so we don't list them out
again. */
VEC_truncate (tree, pure, 0);
}
else
- inform ("%J since type %qT has pure virtual functions",
- TYPE_MAIN_DECL (type), type);
+ inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+ " since type %qT has pure virtual functions",
+ type);
return 1;
}
/* Print an error message for invalid use of an incomplete type.
VALUE is the expression that was used (or 0 if that isn't known)
- and TYPE is the type that was invalid. DIAG_TYPE indicates the
- type of diagnostic: 0 for an error, 1 for a warning, 2 for a
- pedwarn. */
+ and TYPE is the type that was invalid. DIAG_KIND indicates the
+ type of diagnostic (see diagnostic.def). */
void
-cxx_incomplete_type_diagnostic (const_tree value, const_tree type, int diag_type)
+cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
+ diagnostic_t diag_kind)
{
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;
+ gcc_assert (diag_kind == DK_WARNING
+ || diag_kind == DK_PEDWARN
+ || diag_kind == DK_ERROR);
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
|| TREE_CODE (value) == PARM_DECL
|| TREE_CODE (value) == FIELD_DECL))
{
- p_msg ("%q+D has incomplete type", value);
+ emit_diagnostic (diag_kind, input_location, 0,
+ "%q+D has incomplete type", value);
decl = 1;
}
retry:
case UNION_TYPE:
case ENUMERAL_TYPE:
if (!decl)
- p_msg ("invalid use of incomplete type %q#T", type);
+ emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of incomplete type %q#T", type);
if (!TYPE_TEMPLATE_INFO (type))
- p_msg ("forward declaration of %q+#T", type);
+ emit_diagnostic (diag_kind, input_location, 0,
+ "forward declaration of %q+#T", type);
else
- p_msg ("declaration of %q+#T", type);
+ emit_diagnostic (diag_kind, input_location, 0,
+ "declaration of %q+#T", type);
break;
case VOID_TYPE:
- p_msg ("invalid use of %qT", type);
+ emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of %qT", type);
break;
case ARRAY_TYPE:
type = TREE_TYPE (type);
goto retry;
}
- p_msg ("invalid use of array with unspecified bounds");
+ emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of array with unspecified bounds");
break;
case OFFSET_TYPE:
bad_member:
- p_msg ("invalid use of member (did you forget the %<&%> ?)");
+ emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of member (did you forget the %<&%> ?)");
break;
case TEMPLATE_TYPE_PARM:
- p_msg ("invalid use of template type parameter %qT", type);
+ if (is_auto (type))
+ emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of %<auto%>");
+ else
+ emit_diagnostic (diag_kind, input_location, 0,
+ "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));
+ emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of template template parameter %qT",
+ TYPE_NAME (type));
break;
case TYPENAME_TYPE:
- p_msg ("invalid use of dependent type %qT", type);
+ emit_diagnostic (diag_kind, input_location, 0,
+ "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");
+ emit_diagnostic (diag_kind, input_location, 0,
+ "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");
+ emit_diagnostic (diag_kind, input_location, 0,
+ "overloaded function with no contextual type information");
else
- p_msg ("insufficient contextual information to determine type");
+ emit_diagnostic (diag_kind, input_location, 0,
+ "insufficient contextual information to determine type");
break;
default:
void
cxx_incomplete_type_error (const_tree value, const_tree type)
{
- cxx_incomplete_type_diagnostic (value, type, 0);
+ cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
}
\f
NULL_TREE);
code = build2 (INIT_EXPR, inner_type, sub, value);
- code = build_stmt (EXPR_STMT, code);
+ code = build_stmt (input_location, EXPR_STMT, code);
add_stmt (code);
continue;
}
tree cons = copy_node (init);
CONSTRUCTOR_ELTS (init) = NULL;
code = build2 (MODIFY_EXPR, type, dest, cons);
- code = build_stmt (EXPR_STMT, code);
+ code = build_stmt (input_location, EXPR_STMT, code);
add_stmt (code);
}
break;
for static variable. In that case, caller must emit the code. */
tree
-store_init_value (tree decl, tree init)
+store_init_value (tree decl, tree init, int flags)
{
tree value, type;
if (TREE_CODE (type) == ERROR_MARK)
return NULL_TREE;
- if (IS_AGGR_TYPE (type))
+ if (MAYBE_CLASS_TYPE_P (type))
{
gcc_assert (TYPE_HAS_TRIVIAL_INIT_REF (type)
|| TREE_CODE (init) == CONSTRUCTOR);
{
error ("constructor syntax used, but no constructor declared "
"for type %qT", type);
- init = build_constructor_from_list (NULL_TREE, nreverse (init));
+ init = build_constructor_from_list (init_list_type_node, nreverse (init));
}
}
else if (TREE_CODE (init) == TREE_LIST
/* End of special C++ code. */
/* Digest the specified initializer into an expression. */
- value = digest_init (type, init);
+ value = digest_init_flags (type, init, flags);
/* If the initializer is not a constant, fill in DECL_INITIAL with
the bits that are constant, and then return an expression that
will perform the dynamic initialization. */
}
\f
+/* Give errors about narrowing conversions within { }. */
+
+void
+check_narrowing (tree type, tree init)
+{
+ tree ftype = unlowered_expr_type (init);
+ bool ok = true;
+ REAL_VALUE_TYPE d;
+
+ if (DECL_P (init))
+ init = decl_constant_value (init);
+
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TREE_CODE (ftype) == REAL_TYPE)
+ ok = false;
+ else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype)
+ && CP_INTEGRAL_TYPE_P (type))
+ {
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype)
+ && (TREE_CODE (init) != INTEGER_CST
+ || !int_fits_type_p (init, type)))
+ ok = false;
+ }
+ else if (TREE_CODE (ftype) == REAL_TYPE
+ && TREE_CODE (type) == REAL_TYPE)
+ {
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype))
+ {
+ if (TREE_CODE (init) == REAL_CST)
+ {
+ /* Issue 703: Loss of precision is OK as long as the value is
+ within the representable range of the new type. */
+ REAL_VALUE_TYPE r;
+ d = TREE_REAL_CST (init);
+ real_convert (&r, TYPE_MODE (type), &d);
+ if (real_isinf (&r))
+ ok = false;
+ }
+ else
+ ok = false;
+ }
+ }
+ else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype)
+ && TREE_CODE (type) == REAL_TYPE)
+ {
+ ok = false;
+ if (TREE_CODE (init) == INTEGER_CST)
+ {
+ d = real_value_from_int_cst (0, init);
+ if (exact_real_truncate (TYPE_MODE (type), &d))
+ ok = true;
+ }
+ }
+
+ if (!ok)
+ permerror (input_location, "narrowing conversion of %qE from %qT to %qT inside { }",
+ init, ftype, type);
+}
+
/* Process the initializer INIT for a variable of type TYPE, emitting
diagnostics for invalid initializers and converting the initializer as
appropriate.
For aggregate types, it assumes that reshape_init has already run, thus the
- initializer will have the right shape (brace elision has been undone). */
+ initializer will have the right shape (brace elision has been undone).
-tree
-digest_init (tree type, tree init)
+ NESTED is true iff we are being called for an element of a CONSTRUCTOR. */
+
+static tree
+digest_init_r (tree type, tree init, bool nested, int flags)
{
enum tree_code code = TREE_CODE (type);
- if (init == error_mark_node)
+ if (error_operand_p (init))
return error_mark_node;
gcc_assert (init);
{
tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init)));
- if (char_type != char_type_node
- && TYPE_PRECISION (typ1) == BITS_PER_UNIT)
+ if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
{
- error ("char-array initialized from wide string");
- return error_mark_node;
+ if (char_type != char_type_node)
+ {
+ error ("char-array initialized from wide string");
+ return error_mark_node;
+ }
}
- if (char_type == char_type_node
- && TYPE_PRECISION (typ1) != BITS_PER_UNIT)
+ else
{
- error ("int-array initialized from non-wide string");
- return error_mark_node;
+ if (char_type == char_type_node)
+ {
+ error ("int-array initialized from non-wide string");
+ return error_mark_node;
+ }
+ else if (char_type != typ1)
+ {
+ error ("int-array initialized from incompatible wide string");
+ return error_mark_node;
+ }
}
TREE_TYPE (init) = type;
counted in the length of the constant, but in C++ this would
be invalid. */
if (size < TREE_STRING_LENGTH (init))
- pedwarn ("initializer-string for array of chars is too long");
+ permerror (input_location, "initializer-string for array of chars is too long");
}
return init;
}
}
/* Handle scalar types (including conversions) and references. */
- if (TREE_CODE (type) != COMPLEX_TYPE
+ if ((TREE_CODE (type) != COMPLEX_TYPE
+ || BRACE_ENCLOSED_INITIALIZER_P (init))
&& (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
- return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
- "initialization", NULL_TREE, 0);
+ {
+ tree *exp;
+
+ if (cxx_dialect != cxx98 && nested)
+ check_narrowing (type, init);
+ init = convert_for_initialization (0, type, init, flags,
+ "initialization", NULL_TREE, 0,
+ tf_warning_or_error);
+ exp = &init;
+
+ /* Skip any conversions since we'll be outputting the underlying
+ constant. */
+ while (CONVERT_EXPR_P (*exp)
+ || TREE_CODE (*exp) == NON_LVALUE_EXPR)
+ exp = &TREE_OPERAND (*exp, 0);
+
+ *exp = cplus_expand_constant (*exp);
+
+ return init;
+ }
/* Come here only for aggregates: records, arrays, unions, complex numbers
and vectors. */
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == COMPLEX_TYPE);
- if (BRACE_ENCLOSED_INITIALIZER_P (init))
- return process_init_constructor (type, init);
+ if (BRACE_ENCLOSED_INITIALIZER_P (init)
+ && !TYPE_NON_AGGREGATE_CLASS (type))
+ return process_init_constructor (type, init);
else
{
if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE)
if (TREE_CODE (type) == ARRAY_TYPE
&& TREE_CODE (init) != CONSTRUCTOR)
{
+ /* Allow the result of build_array_copy. */
+ if (TREE_CODE (init) == TARGET_EXPR
+ && (same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (init))))
+ return init;
+
error ("array must be initialized with a brace-enclosed"
" initializer");
return error_mark_node;
}
return convert_for_initialization (NULL_TREE, type, init,
- LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING,
- "initialization", NULL_TREE, 0);
+ flags,
+ "initialization", NULL_TREE, 0,
+ tf_warning_or_error);
}
}
+tree
+digest_init (tree type, tree init)
+{
+ return digest_init_r (type, init, false, LOOKUP_IMPLICIT);
+}
+
+tree
+digest_init_flags (tree type, tree init, int flags)
+{
+ return digest_init_r (type, init, false, flags);
+}
\f
/* Set of flags used within process_init_constructor to describe the
initializers. */
/* Vectors are like simple fixed-size arrays. */
len = TYPE_VECTOR_SUBPARTS (type);
- /* There cannot be more initializers than needed as otherwise
- reshape_init would have already rejected the initializer. */
- if (!unbounded)
- gcc_assert (VEC_length (constructor_elt, v) <= len);
+ /* There must not be more initializers than needed. */
+ if (!unbounded && VEC_length (constructor_elt, v) > len)
+ error ("too many initializers for %qT", type);
for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
{
else
ce->index = size_int (i);
gcc_assert (ce->value);
- ce->value = digest_init (TREE_TYPE (type), ce->value);
+ ce->value = digest_init_r (TREE_TYPE (type), ce->value, true, LOOKUP_IMPLICIT);
if (ce->value != error_mark_node)
gcc_assert (same_type_ignoring_top_level_qualifiers_p
we can't rely on the back end to do it for us, so build up
TARGET_EXPRs. If the type in question is a class, just build
one up; if it's an array, recurse. */
- if (IS_AGGR_TYPE (TREE_TYPE (type)))
- next = build_functional_cast (TREE_TYPE (type), NULL_TREE);
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (type)))
+ next = build_functional_cast (TREE_TYPE (type), NULL_TREE,
+ tf_warning_or_error);
else
- next = build_constructor (NULL_TREE, NULL);
+ next = build_constructor (init_list_type_node, NULL);
next = digest_init (TREE_TYPE (type), next);
}
else if (!zero_init_p (TREE_TYPE (type)))
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
tree next;
+ tree type;
if (!DECL_NAME (field) && DECL_C_BIT_FIELD (field))
{
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
+ /* If this is a bitfield, first convert to the declared type. */
+ type = TREE_TYPE (field);
+ if (DECL_BIT_FIELD_TYPE (field))
+ type = DECL_BIT_FIELD_TYPE (field);
+
if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)))
{
constructor_elt *ce = VEC_index (constructor_elt,
}
gcc_assert (ce->value);
- next = digest_init (TREE_TYPE (field), ce->value);
+ next = digest_init_r (type, ce->value, true, LOOKUP_IMPLICIT);
++idx;
}
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
default-initialization, we can't rely on the back end to do it
for us, so build up TARGET_EXPRs. If the type in question is
a class, just build one up; if it's an array, recurse. */
- if (IS_AGGR_TYPE (TREE_TYPE (field)))
- next = build_functional_cast (TREE_TYPE (field), NULL_TREE);
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (field)))
+ next = build_functional_cast (TREE_TYPE (field), NULL_TREE,
+ tf_warning_or_error);
else
- next = build_constructor (NULL_TREE, NULL);
+ next = build_constructor (init_list_type_node, NULL);
- next = digest_init (TREE_TYPE (field), next);
+ next = digest_init_r (TREE_TYPE (field), next, true, LOOKUP_IMPLICIT);
/* Warn when some struct elements are implicitly initialized. */
warning (OPT_Wmissing_field_initializers,
continue;
}
+ /* If this is a bitfield, now convert to the lowered type. */
+ if (type != TREE_TYPE (field))
+ next = cp_convert_and_check (TREE_TYPE (field), next);
flags |= picflag_from_initializer (next);
CONSTRUCTOR_APPEND_ELT (v, field, next);
}
+ if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)))
+ error ("too many initializers for %qT", type);
+
CONSTRUCTOR_ELTS (init) = v;
return flags;
}
process_init_constructor_union (tree type, tree init)
{
constructor_elt *ce;
+ int len;
/* If the initializer was empty, use default zero initialization. */
if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init)))
return 0;
- gcc_assert (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) == 1);
+ len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
+ if (len > 1)
+ {
+ error ("too many initializers for %qT", type);
+ VEC_block_remove (constructor_elt, CONSTRUCTOR_ELTS (init), 1, len-1);
+ }
+
ce = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (init), 0);
/* If this element specifies a field, initialize via that field. */
tree field = TYPE_FIELDS (type);
while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
- gcc_assert (field);
+ if (field == NULL_TREE)
+ {
+ error ("too many initializers for %qT", type);
+ ce->value = error_mark_node;
+ }
ce->index = field;
}
if (ce->value && ce->value != error_mark_node)
- ce->value = digest_init (TREE_TYPE (ce->index), ce->value);
+ ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true, LOOKUP_IMPLICIT);
return picflag_from_initializer (ce->value);
}
if (!(flags & PICFLAG_NOT_ALL_CONSTANT))
{
TREE_CONSTANT (init) = 1;
- TREE_INVARIANT (init) = 1;
if (!(flags & PICFLAG_NOT_ALL_SIMPLE))
TREE_STATIC (init) = 1;
}
expr = build_non_dependent_expr (expr);
}
- if (IS_AGGR_TYPE (type))
+ if (MAYBE_CLASS_TYPE_P (type))
{
while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr,
NULL_TREE, NULL_TREE,
- /*overloaded_p=*/NULL)))
+ /*overloaded_p=*/NULL,
+ tf_warning_or_error)))
{
if (expr == error_mark_node)
return error_mark_node;
return expr;
}
- return build_indirect_ref (last_rval, NULL);
+ return cp_build_indirect_ref (last_rval, RO_NULL, tf_warning_or_error);
}
if (types_memoized)
}
objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
- if (! IS_AGGR_TYPE (objtype))
+ if (! MAYBE_CLASS_TYPE_P (objtype))
{
error ("cannot apply member pointer %qE to %qE, which is of "
"non-class type %qT",
datum = build2 (POINTER_PLUS_EXPR, ptype,
fold_convert (ptype, datum),
build_nop (sizetype, component));
- return build_indirect_ref (datum, 0);
+ return cp_build_indirect_ref (datum, RO_NULL, tf_warning_or_error);
}
else
return build2 (OFFSET_REF, type, datum, component);
/* Return a tree node for the expression TYPENAME '(' PARMS ')'. */
tree
-build_functional_cast (tree exp, tree parms)
+build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
{
/* This is either a call to a constructor,
or a C cast in C++'s `functional' notation. */
+
+ /* The type to which we are casting. */
tree type;
+ VEC(tree,gc) *parmvec;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
else
type = exp;
+ if (TREE_CODE (type) == REFERENCE_TYPE && !parms)
+ {
+ error ("invalid value-initialization of reference types");
+ return error_mark_node;
+ }
+
if (processing_template_decl)
{
tree t = build_min (CAST_EXPR, type, parms);
return t;
}
- if (! IS_AGGR_TYPE (type))
+ if (! MAYBE_CLASS_TYPE_P (type))
{
if (parms == NULL_TREE)
return cp_convert (type, integer_zero_node);
/* This must build a C cast. */
parms = build_x_compound_expr_from_list (parms, "functional cast");
- return build_c_cast (type, parms);
+ return cp_build_c_cast (type, parms, complain);
}
/* Prepare to evaluate as a call to a constructor. If this expression
if (abstract_virtuals_error (NULL_TREE, type))
return error_mark_node;
+ /* [expr.type.conv]
+
+ If the expression list is a single-expression, the type
+ conversion is equivalent (in definedness, and if defined in
+ meaning) to the corresponding cast expression. */
if (parms && TREE_CHAIN (parms) == NULL_TREE)
- return build_c_cast (type, TREE_VALUE (parms));
+ return cp_build_c_cast (type, TREE_VALUE (parms), complain);
+
+ /* [expr.type.conv]
+
+ The expression T(), where T is a simple-type-specifier for a
+ non-array complete object type or the (possibly cv-qualified)
+ void type, creates an rvalue of the specified type, which is
+ value-initialized. */
- /* We need to zero-initialize POD types. */
- if (parms == NULL_TREE
- && !CLASSTYPE_NON_POD_P (type)
- && TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+ if (parms == NULL_TREE
+ /* If there's a user-defined constructor, value-initialization is
+ just calling the constructor, so fall through. */
+ && !TYPE_HAS_USER_CONSTRUCTOR (type))
{
- exp = build_zero_init (type,
- /*nelts=*/NULL_TREE,
- /*static_storage_p=*/false);
+ exp = build_value_init (type);
return get_target_expr (exp);
}
- exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
- type, LOOKUP_NORMAL);
+ /* Call the constructor. */
+ parmvec = make_tree_vector ();
+ for (; parms != NULL_TREE; parms = TREE_CHAIN (parms))
+ VEC_safe_push (tree, gc, parmvec, TREE_VALUE (parms));
+ exp = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ &parmvec, type, LOOKUP_NORMAL, complain);
+ release_tree_vector (parmvec);
if (exp == error_mark_node)
return error_mark_node;
bool ok;
tree core = spec;
bool is_ptr;
- int diag_type = -1; /* none */
+ diagnostic_t diag_type = DK_UNSPECIFIED; /* none */
if (spec == error_mark_node)
return list;
and calls. So just give a pedwarn at this point; we will give an
error later if we hit one of those two cases. */
if (!COMPLETE_TYPE_P (complete_type (core)))
- diag_type = 2; /* pedwarn */
+ diag_type = DK_PEDWARN; /* pedwarn */
}
if (ok)
list = tree_cons (NULL_TREE, spec, list);
}
else
- diag_type = 0; /* error */
+ diag_type = DK_ERROR; /* error */
- if (diag_type >= 0 && complain)
+ if (diag_type != DK_UNSPECIFIED && complain)
cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
return list;