static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (tree);
static tree lookup_destructor (tree, tree, tree);
+static void warn_args_num (location_t, tree, bool);
static int convert_arguments (tree, VEC(tree,gc) **, tree, int,
tsubst_flags_t);
return cp_build_type_attribute_variant (t1, attributes);
}
+/* Return the ARRAY_TYPE type without its domain. */
+
+tree
+strip_array_domain (tree type)
+{
+ tree t2;
+ gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+ if (TYPE_DOMAIN (type) == NULL_TREE)
+ return type;
+ t2 = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
+ return cp_build_type_attribute_variant (t2, TYPE_ATTRIBUTES (type));
+}
+
/* Wrapper around cp_common_type that is used by c-common.c and other
front end optimizations that remove promotions.
else if (typedef_variant_p (t)
&& !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
- /* If T is a TYPENAME_TYPE which context is a template type
- parameter, get the template parameters from that context. */
- else if (TYPE_CONTEXT (t)
- && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
+ else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ && DECL_CONTEXT (TYPE_NAME (t)) == NULL_TREE)
+ /* We have not yet created the DECL_TEMPLATE this
+ template type parm belongs to. It probably means
+ that we are in the middle of parsing the template parameters
+ of a template, and T is one of the parameters we have parsed.
+ Let's return the list of template parms we have parsed so far. */
+ return get_template_parms_at_level (current_template_parms,
+ TEMPLATE_TYPE_LEVEL (t));
else if (TYPE_CONTEXT (t)
&& !NAMESPACE_SCOPE_P (t))
tinfo = get_template_info (TYPE_CONTEXT (t));
incompatible_dependent_types_p (tree t1, tree t2)
{
tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
+ bool t1_typedef_variant_p, t2_typedef_variant_p;
if (!uses_template_parms (t1) || !uses_template_parms (t2))
return false;
return true;
}
+ t1_typedef_variant_p = typedef_variant_p (t1);
+ t2_typedef_variant_p = typedef_variant_p (t2);
+
/* Either T1 or T2 must be a typedef. */
- if (!typedef_variant_p (t1) && !typedef_variant_p (t2))
+ if (!t1_typedef_variant_p && !t2_typedef_variant_p)
return false;
+ if (!t1_typedef_variant_p || !t2_typedef_variant_p)
+ /* Either T1 or T2 is not a typedef so we cannot compare the
+ the template parms of the typedefs of T1 and T2.
+ At this point, if the main variant type of T1 and T2 are equal
+ it means the two types can't be incompatible, from the perspective
+ of this function. */
+ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ return false;
+
/* So if we reach this point, it means either T1 or T2 is a typedef variant.
Let's compare their template parameters. */
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return false;
+ /* If T1 and T2 are dependent typedefs then check upfront that
+ the template parameters of their typedef DECLs match before
+ going down checking their subtypes. */
+ if (incompatible_dependent_types_p (t1, t2))
+ return false;
+
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
qualifiers (just above). */
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return true;
- /* If T1 and T2 are dependent typedefs then check upfront that
- the template parameters of their typedef DECLs match before
- going down checking their subtypes. */
- if (incompatible_dependent_types_p (t1, t2))
- return false;
/* Compare the types. Break out if they could be the same. */
switch (TREE_CODE (t1))
return e;
}
+ /* To get the size of a static data member declared as an array of
+ unknown bound, we need to instantiate it. */
+ if (TREE_CODE (e) == VAR_DECL
+ && VAR_HAD_UNKNOWN_BOUND (e)
+ && DECL_TEMPLATE_INSTANTIATION (e))
+ instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false);
+
+ e = mark_type_use (e);
+
if (TREE_CODE (e) == COMPONENT_REF
&& TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
&& DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
return e;
}
+ e = mark_type_use (e);
+
if (TREE_CODE (e) == VAR_DECL)
t = size_int (DECL_ALIGN_UNIT (e));
else if (TREE_CODE (e) == COMPONENT_REF
in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
function-to-pointer conversions. In addition, manifest constants
are replaced by their values, and bitfield references are converted
- to their declared types.
+ to their declared types. Note that this function does not perform the
+ lvalue-to-rvalue conversion for class types. If you need that conversion
+ to for class types, then you probably need to use force_rvalue.
Although the returned value is being used as an rvalue, this
function does not wrap the returned expression in a
if (type == error_mark_node)
return error_mark_node;
+ exp = mark_rvalue_use (exp);
+
exp = resolve_nondeduced_context (exp);
if (type_unknown_p (exp))
{
tree type;
tree promoted_type;
+ expr = mark_rvalue_use (expr);
+
/* [conv.prom]
If the bitfield has an enumerated type, it is treated as any
LOC is the location to use in building the array reference. */
tree
-build_array_ref (location_t loc, tree array, tree idx)
+cp_build_array_ref (location_t loc, tree array, tree idx,
+ tsubst_flags_t complain)
{
tree ret;
if (idx == 0)
{
- error_at (loc, "subscript missing in array reference");
+ if (complain & tf_error)
+ error_at (loc, "subscript missing in array reference");
return error_mark_node;
}
{
case COMPOUND_EXPR:
{
- tree value = build_array_ref (loc, TREE_OPERAND (array, 1), idx);
+ tree value = cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx,
+ complain);
ret = build2 (COMPOUND_EXPR, TREE_TYPE (value),
TREE_OPERAND (array, 0), value);
SET_EXPR_LOCATION (ret, loc);
case COND_EXPR:
ret = build_conditional_expr
(TREE_OPERAND (array, 0),
- build_array_ref (loc, TREE_OPERAND (array, 1), idx),
- build_array_ref (loc, TREE_OPERAND (array, 2), idx),
+ cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx,
+ complain),
+ cp_build_array_ref (loc, TREE_OPERAND (array, 2), idx,
+ complain),
tf_warning_or_error);
protected_set_expr_location (ret, loc);
return ret;
if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (idx)))
{
- error_at (loc, "array subscript is not an integer");
+ if (complain & tf_error)
+ error_at (loc, "array subscript is not an integer");
return error_mark_node;
}
return error_mark_node;
}
- if (!lvalue_p (array))
+ if (!lvalue_p (array) && (complain & tf_error))
pedwarn (loc, OPT_pedantic,
"ISO C++ forbids subscripting non-lvalue array");
tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0);
- if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
+ if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)
+ && (complain & tf_warning))
warning_at (loc, OPT_Wextra,
"subscripting array declared %<register%>");
}
if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE)
{
- error_at (loc, "subscripted value is neither array nor pointer");
+ if (complain & tf_error)
+ error_at (loc, "subscripted value is neither array nor pointer");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)
{
- error_at (loc, "array subscript is not an integer");
+ if (complain & tf_error)
+ error_at (loc, "array subscript is not an integer");
return error_mark_node;
}
ret = cp_build_indirect_ref (cp_build_binary_op (input_location,
PLUS_EXPR, ar, ind,
- tf_warning_or_error),
+ complain),
RO_ARRAY_INDEXING,
- tf_warning_or_error);
+ complain);
protected_set_expr_location (ret, loc);
return ret;
}
}
+
+/* Entry point for Obj-C++. */
+
+tree
+build_array_ref (location_t loc, tree array, tree idx)
+{
+ return cp_build_array_ref (loc, array, idx, tf_warning_or_error);
+}
\f
/* Resolve a pointer to member function. INSTANCE is the object
instance to use, if the member points to a virtual member.
return ret;
}
\f
+/* Subroutine of convert_arguments.
+ Warn about wrong number of args are genereted. */
+
+static void
+warn_args_num (location_t loc, tree fndecl, bool too_many_p)
+{
+ if (fndecl)
+ {
+ if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
+ {
+ if (DECL_NAME (fndecl) == NULL_TREE
+ || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
+ error_at (loc,
+ too_many_p
+ ? G_("too many arguments to constructor %q#D")
+ : G_("too few arguments to constructor %q#D"),
+ fndecl);
+ else
+ error_at (loc,
+ too_many_p
+ ? G_("too many arguments to member function %q#D")
+ : G_("too few arguments to member function %q#D"),
+ fndecl);
+ }
+ else
+ error_at (loc,
+ too_many_p
+ ? G_("too many arguments to function %q#D")
+ : G_("too few arguments to function %q#D"),
+ fndecl);
+ inform (DECL_SOURCE_LOCATION (fndecl),
+ "declared here");
+ }
+ else
+ error_at (loc, too_many_p ? G_("too many arguments to function")
+ : G_("too few arguments to function"));
+}
+
/* Convert the actual parameter expressions in the list VALUES to the
types in the list TYPELIST. The converted expressions are stored
back in the VALUES vector.
int flags, tsubst_flags_t complain)
{
tree typetail;
- const char *called_thing = 0;
unsigned int i;
/* Argument passing is always copy-initialization. */
flags |= LOOKUP_ONLYCONVERTING;
- if (fndecl)
- {
- if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
- {
- if (DECL_NAME (fndecl) == NULL_TREE
- || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
- called_thing = "constructor";
- else
- called_thing = "member function";
- }
- else
- called_thing = "function";
- }
-
for (i = 0, typetail = typelist;
i < VEC_length (tree, *values);
i++)
{
if (complain & tf_error)
{
- if (fndecl)
- {
- error_at (input_location, "too many arguments to %s %q#D",
- called_thing, fndecl);
- inform (DECL_SOURCE_LOCATION (fndecl),
- "declared here");
- }
- else
- error ("too many arguments to function");
+ warn_args_num (input_location, fndecl, /*too_many_p=*/true);
return i;
}
else
else
{
if (complain & tf_error)
- {
- if (fndecl)
- {
- error_at (input_location, "too few arguments to %s %q#D",
- called_thing, fndecl);
- inform (DECL_SOURCE_LOCATION (fndecl),
- "declared here");
- }
- else
- error ("too few arguments to function");
- }
+ warn_args_num (input_location, fndecl, /*too_many_p=*/false);
return -1;
}
}
}
result_type = type1;
}
+ else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1))
+ /* One of the operands must be of nullptr_t type. */
+ result_type = TREE_TYPE (nullptr_node);
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
}
build_type = boolean_type_node;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == ENUMERAL_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == ENUMERAL_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
result_type = composite_pointer_type (type0, type1, op0, op1,
CPO_COMPARISON, complain);
- else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
- && integer_zerop (op1))
+ else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
result_type = type0;
- else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
- && integer_zerop (op0))
+ else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0))
result_type = type1;
+ else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1))
+ /* One of the operands must be of nullptr_t type. */
+ result_type = TREE_TYPE (nullptr_node);
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
if (val != 0)
return val;
+ arg = mark_lvalue_use (arg);
+
/* Increment or decrement the real part of the value,
and don't change the imaginary part. */
if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
argtype = lvalue_type (arg);
+ arg = mark_lvalue_use (arg);
+
if (TREE_CODE (arg) == OFFSET_REF)
goto offset_ref;
/* [expr.reinterpret.cast]
A pointer can be converted to any integral type large enough to
- hold it. */
- if (CP_INTEGRAL_TYPE_P (type) && TYPE_PTR_P (intype))
+ hold it. ... A value of type std::nullptr_t can be converted to
+ an integral type; the conversion has the same meaning and
+ validity as a conversion of (void*)0 to the integral type. */
+ if (CP_INTEGRAL_TYPE_P (type)
+ && (TYPE_PTR_P (intype) || NULLPTR_TYPE_P (intype)))
{
if (TYPE_PRECISION (type) < TYPE_PRECISION (intype))
{
else
return error_mark_node;
}
+ if (NULLPTR_TYPE_P (intype))
+ return build_int_cst (type, 0);
}
/* [expr.reinterpret.cast]
A value of integral or enumeration type can be explicitly
return error_mark_node;
}
+ if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
+ /* Casting to an integer of smaller size is an error detected elsewhere. */
+ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (value))
+ /* Don't warn about converting any constant. */
+ && !TREE_CONSTANT (value))
+ warning_at (input_location, OPT_Wint_to_pointer_cast,
+ "cast to pointer from integer of different size");
+
/* A C-style cast can be a const_cast. */
result = build_const_cast_1 (type, value, /*complain=*/false,
&valid_p);
if (BRACE_ENCLOSED_INITIALIZER_P (newrhs))
{
+ if (modifycode != INIT_EXPR)
+ {
+ if (complain & tf_error)
+ error ("assigning to an array from an initializer list");
+ return error_mark_node;
+ }
if (check_array_initializer (lhs, lhstype, newrhs))
return error_mark_node;
newrhs = digest_init (lhstype, newrhs);
return win;
}
+