#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
"invalid use of dependent type %qT", type);
break;
- case UNKNOWN_TYPE:
+ case LANG_TYPE:
+ gcc_assert (type == unknown_type_node);
if (value && TREE_CODE (value) == COMPONENT_REF)
goto bad_member;
else if (value && TREE_CODE (value) == ADDR_EXPR)
expression to which INIT should be assigned. INIT is a CONSTRUCTOR. */
static void
-split_nonconstant_init_1 (tree dest, tree init)
+split_nonconstant_init_1 (tree dest, tree *initp)
{
unsigned HOST_WIDE_INT idx;
+ tree init = *initp;
tree field_index, value;
tree type = TREE_TYPE (dest);
tree inner_type = NULL;
bool array_type_p = false;
+ HOST_WIDE_INT num_type_elements, num_initialized_elements;
switch (TREE_CODE (type))
{
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
+ num_initialized_elements = 0;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx,
field_index, value)
{
sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
- split_nonconstant_init_1 (sub, value);
+ split_nonconstant_init_1 (sub, &value);
}
else if (!initializer_constant_valid_p (value, inner_type))
{
tree code;
tree sub;
+ HOST_WIDE_INT inner_elements;
/* FIXME: Ordered removal is O(1) so the whole function is
worst-case quadratic. This could be fixed using an aside
code = build2 (INIT_EXPR, inner_type, sub, value);
code = build_stmt (input_location, EXPR_STMT, code);
add_stmt (code);
+
+ inner_elements = count_type_elements (inner_type, true);
+ if (inner_elements < 0)
+ num_initialized_elements = -1;
+ else if (num_initialized_elements >= 0)
+ num_initialized_elements += inner_elements;
continue;
}
}
+
+ num_type_elements = count_type_elements (type, true);
+ /* If all elements of the initializer are non-constant and
+ have been split out, we don't need the empty CONSTRUCTOR. */
+ if (num_type_elements > 0
+ && num_type_elements == num_initialized_elements)
+ *initp = NULL;
break;
case VECTOR_TYPE:
if (TREE_CODE (init) == CONSTRUCTOR)
{
code = push_stmt_list ();
- split_nonconstant_init_1 (dest, init);
+ split_nonconstant_init_1 (dest, &init);
code = pop_stmt_list (code);
DECL_INITIAL (dest) = init;
TREE_READONLY (dest) = 0;
tree ftype = unlowered_expr_type (init);
bool ok = true;
REAL_VALUE_TYPE d;
- bool was_decl = false;
if (DECL_P (init))
- {
- was_decl = true;
- init = decl_constant_value (init);
- }
+ init = decl_constant_value (init);
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (ftype) == REAL_TYPE)
}
if (TREE_CODE (type) == ARRAY_TYPE
- && TREE_CODE (init) != CONSTRUCTOR)
+ && !BRACE_ENCLOSED_INITIALIZER_P (init))
{
- /* Allow the result of build_array_copy. */
- if (TREE_CODE (init) == TARGET_EXPR
+ /* Allow the result of build_array_copy and of
+ build_value_init_noctor. */
+ if ((TREE_CODE (init) == TARGET_EXPR
+ || TREE_CODE (init) == CONSTRUCTOR)
&& (same_type_ignoring_top_level_qualifiers_p
(type, TREE_TYPE (init))))
return init;
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 (MAYBE_CLASS_TYPE_P (TREE_TYPE (field)))
- next = build_functional_cast (TREE_TYPE (field), NULL_TREE,
- tf_warning_or_error);
+ {
+ next = build_functional_cast (TREE_TYPE (field), NULL_TREE,
+ tf_warning_or_error);
+ /* direct-initialize the target. No temporary is going
+ to be involved. */
+ if (TREE_CODE (next) == TARGET_EXPR)
+ TARGET_EXPR_DIRECT_INIT_P (next) = true;
+ }
else
next = build_constructor (init_list_type_node, NULL);
return expr;
}
- return cp_build_indirect_ref (last_rval, NULL, tf_warning_or_error);
+ return cp_build_indirect_ref (last_rval, RO_NULL, tf_warning_or_error);
}
if (types_memoized)
datum = build2 (POINTER_PLUS_EXPR, ptype,
fold_convert (ptype, datum),
build_nop (sizetype, component));
- return cp_build_indirect_ref (datum, 0, tf_warning_or_error);
+ return cp_build_indirect_ref (datum, RO_NULL, tf_warning_or_error);
}
else
return build2 (OFFSET_REF, type, datum, component);
if (TREE_CODE (type) == REFERENCE_TYPE && !parms)
{
- error ("invalid value-initialization of reference types");
+ error ("invalid value-initialization of reference type");
return error_mark_node;
}