/* 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
+ 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This file is part of the C++ front end.
}
/* According to ARM $7.1.6, "A `const' object may be initialized, but its
- value may not be changed thereafter. Thus, we emit hard errors for these,
- rather than just pedwarns. If `SOFT' is 1, then we just pedwarn. (For
- example, conversions to references.) */
+ value may not be changed thereafter. */
void
-readonly_error (tree arg, const char* string, int soft)
+readonly_error (tree arg, const char* string)
{
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)
{
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));
+ error (fmt, string, TREE_OPERAND (arg, 1));
}
else if (TREE_CODE (arg) == VAR_DECL)
{
fmt = "%s of constant field %qD";
else
fmt = "%s of read-only variable %qD";
- (*fn) (fmt, string, arg);
+ error (fmt, string, arg);
}
else if (TREE_CODE (arg) == PARM_DECL)
- (*fn) ("%s of read-only parameter %qD", string, arg);
+ error ("%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));
+ error ("%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);
+ error ("%s of read-only named return value %qD", string, arg);
else if (TREE_CODE (arg) == FUNCTION_DECL)
- (*fn) ("%s of function %qD", string, arg);
+ error ("%s of function %qD", string, arg);
else
- (*fn) ("%s of read-only location", string);
+ error ("%s of read-only location %qE", string, arg);
}
\f
static int
pat_compare (const void* val1, const void* val2)
{
- const struct pending_abstract_type *pat1 =
+ const struct pending_abstract_type *const pat1 =
(const struct pending_abstract_type *) val1;
- tree type2 = (tree)val2;
+ const_tree const type2 = (const_tree)val2;
return (pat1->type == type2);
}
pedwarn. */
void
-cxx_incomplete_type_diagnostic (tree value, tree type, int diag_type)
+cxx_incomplete_type_diagnostic (const_tree value, const_tree type, int diag_type)
{
int decl = 0;
void (*p_msg) (const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
required by ../tree.c. */
#undef cxx_incomplete_type_error
void
-cxx_incomplete_type_error (tree value, tree type)
+cxx_incomplete_type_error (const_tree value, const_tree type)
{
cxx_incomplete_type_diagnostic (value, type, 0);
}
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);
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 ("initializer-string for array of chars is too long");
}
return init;
}
}
/* Handle scalar types (including conversions) and references. */
- if (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE)
- return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
- "initialization", NULL_TREE, 0);
+ if (TREE_CODE (type) != COMPLEX_TYPE
+ && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
+ {
+ tree *exp;
+
+ init = convert_for_initialization (0, type, init, LOOKUP_NORMAL,
+ "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. */
return convert_for_initialization (NULL_TREE, type, init,
LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING,
- "initialization", NULL_TREE, 0);
+ "initialization", NULL_TREE, 0,
+ tf_warning_or_error);
}
}
}
/* Subroutine of process_init_constructor, which will process an initializer
- INIT for a array or vector of type TYPE. Returns the flags (PICFLAG_*) which
- describe the initializers. */
+ INIT for an array or vector of type TYPE. Returns the flags (PICFLAG_*)
+ which describe the initializers. */
static int
process_init_constructor_array (tree type, tree init)
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
{
/* If this type needs constructors run for default-initialization,
- we can't rely on the backend to do it for us, so build up
+ 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 = digest_init (TREE_TYPE (type), next);
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
{
/* If this type needs constructors run for
- default-initialization, we can't rely on the backend to do it
+ 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);
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, 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",
if (TYPE_PTRMEM_P (ptrmem_type))
{
+ tree ptype;
+
/* Compute the type of the field, as described in [expr.ref].
There's no such thing as a mutable pointer-to-member, so
things are not as complex as they are for references to
/* Build an expression for "object + offset" where offset is the
value stored in the pointer-to-data-member. */
- datum = build2 (PLUS_EXPR, build_pointer_type (type),
- datum, build_nop (ptrdiff_type_node, component));
- return build_indirect_ref (datum, 0);
+ ptype = build_pointer_type (type);
+ 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);
}
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;
if (exp == error_mark_node || parms == error_mark_node)
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_constructor (type, NULL);
+ exp = build_value_init (type);
return get_target_expr (exp);
}
+ /* Call the constructor. */
exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
- type, LOOKUP_NORMAL);
+ type, LOOKUP_NORMAL, complain);
if (exp == error_mark_node)
return error_mark_node;