&& TREE_CODE (pointee2) == POINTER_TYPE)
|| (TYPE_PTR_TO_MEMBER_P (pointee1)
&& TYPE_PTR_TO_MEMBER_P (pointee2)))
- result_type = composite_pointer_type_r (pointee1, pointee2, operation,
- complain);
+ {
+ result_type = composite_pointer_type_r (pointee1, pointee2, operation,
+ complain);
+ if (result_type == error_mark_node)
+ return error_mark_node;
+ }
else
{
if (complain & tf_error)
if (!cp_tree_equal (TYPENAME_TYPE_FULLNAME (t1),
TYPENAME_TYPE_FULLNAME (t2)))
return false;
- if (!same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2)))
+ /* Qualifiers don't matter on scopes. */
+ if (!same_type_ignoring_top_level_qualifiers_p (TYPE_CONTEXT (t1),
+ TYPE_CONTEXT (t2)))
return false;
break;
break;
case TYPE_PACK_EXPANSION:
- return same_type_p (PACK_EXPANSION_PATTERN (t1),
- PACK_EXPANSION_PATTERN (t2));
+ return (same_type_p (PACK_EXPANSION_PATTERN (t1),
+ PACK_EXPANSION_PATTERN (t2))
+ && comp_template_args (PACK_EXPANSION_EXTRA_ARGS (t1),
+ PACK_EXPANSION_EXTRA_ARGS (t2)));
case DECLTYPE_TYPE:
if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1)
!= DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t2)
|| (DECLTYPE_FOR_LAMBDA_CAPTURE (t1)
!= DECLTYPE_FOR_LAMBDA_CAPTURE (t2))
- || (DECLTYPE_FOR_LAMBDA_RETURN (t1)
- != DECLTYPE_FOR_LAMBDA_RETURN (t2))
+ || (DECLTYPE_FOR_LAMBDA_PROXY (t1)
+ != DECLTYPE_FOR_LAMBDA_PROXY (t2))
|| !cp_tree_equal (DECLTYPE_TYPE_EXPR (t1),
DECLTYPE_TYPE_EXPR (t2)))
return false;
/* FIXME remove? at least need to remember that this isn't really a
constant expression if EXP isn't decl_constant_var_p, like with
C_MAYBE_CONST_EXPR. */
- exp = decl_constant_value (exp);
+ exp = decl_constant_value_safe (exp);
if (error_operand_p (exp))
return error_mark_node;
tree object_type;
tree member_scope;
tree result = NULL_TREE;
+ tree using_decl = NULL_TREE;
if (error_operand_p (object) || error_operand_p (member))
return error_mark_node;
if (!CLASS_TYPE_P (object_type))
{
if (complain & tf_error)
- error ("request for member %qD in %qE, which is of non-class type %qT",
- member, object, object_type);
+ {
+ if (POINTER_TYPE_P (object_type)
+ && CLASS_TYPE_P (TREE_TYPE (object_type)))
+ error ("request for member %qD in %qE, which is of pointer "
+ "type %qT (maybe you meant to use %<->%> ?)",
+ member, object, object_type);
+ else
+ error ("request for member %qD in %qE, which is of non-class "
+ "type %qT", member, object, object_type);
+ }
return error_mark_node;
}
/* Convert to the base. */
object = build_base_path (PLUS_EXPR, object, binfo,
- /*nonnull=*/1);
+ /*nonnull=*/1, complain);
/* If we found the base successfully then we should be able
to convert to it successfully. */
gcc_assert (object != error_mark_node);
result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
object, result);
}
+ else if ((using_decl = strip_using_decl (member)) != member)
+ result = build_class_member_access_expr (object,
+ using_decl,
+ access_path, preserve_reference,
+ complain);
else
{
if (complain & tf_error)
return error_mark_node;
}
expr = lookup_member (dtor_type, complete_dtor_identifier,
- /*protect=*/1, /*want_type=*/false);
+ /*protect=*/1, /*want_type=*/false,
+ tf_warning_or_error);
expr = (adjust_result_of_qualified_name_lookup
(expr, dtor_type, object_type));
return expr;
if (!CLASS_TYPE_P (object_type))
{
if (complain & tf_error)
- error ("request for member %qD in %qE, which is of non-class type %qT",
- name, object, object_type);
+ {
+ if (POINTER_TYPE_P (object_type)
+ && CLASS_TYPE_P (TREE_TYPE (object_type)))
+ error ("request for member %qD in %qE, which is of pointer "
+ "type %qT (maybe you meant to use %<->%> ?)",
+ name, object, object_type);
+ else
+ error ("request for member %qD in %qE, which is of non-class "
+ "type %qT", name, object, object_type);
+ }
return error_mark_node;
}
{
/* Look up the member. */
member = lookup_member (access_path, name, /*protect=*/1,
- /*want_type=*/false);
+ /*want_type=*/false, complain);
if (member == NULL_TREE)
{
if (complain & tf_error)
- error ("%qD has no member named %qE", object_type, name);
+ error ("%qD has no member named %qE",
+ TREE_CODE (access_path) == TREE_BINFO
+ ? TREE_TYPE (access_path) : object_type, name);
return error_mark_node;
}
if (member == error_mark_node)
ptrmem_type = TREE_TYPE (ptrmem);
gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type));
member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
- /*want_type=*/false);
+ /*want_type=*/false, tf_warning_or_error);
member_type = cp_build_qualified_type (TREE_TYPE (member),
cp_type_quals (ptrmem_type));
return fold_build3_loc (input_location,
/* Helper function called from c-common. */
tree
-build_indirect_ref (location_t loc __attribute__ ((__unused__)),
+build_indirect_ref (location_t loc ATTRIBUTE_UNUSED,
tree ptr, ref_operator errorstring)
{
return cp_build_indirect_ref (ptr, errorstring, tf_warning_or_error);
basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
basetype, ba_check, NULL);
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
- 1);
+ 1, tf_warning_or_error);
if (instance_ptr == error_mark_node)
return error_mark_node;
}
else
{
op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
- op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
+ op1 = cp_convert (TREE_TYPE (op0), op1);
}
result_type = TREE_TYPE (op0);
}
result_type = composite_pointer_type (type0, type1, op0, op1,
CPO_COMPARISON, complain);
else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
- result_type = type0;
+ {
+ result_type = type0;
+ if (extra_warnings && (complain & tf_warning))
+ warning (OPT_Wextra,
+ "ordered comparison of pointer with integer zero");
+ }
else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0))
- result_type = type1;
+ {
+ result_type = type1;
+ if (extra_warnings && (complain & tf_warning))
+ warning (OPT_Wextra,
+ "ordered comparison of pointer with integer zero");
+ }
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);
tree type = TREE_TYPE (expr);
if (TYPE_PTRMEM_P (type))
return build_binary_op (EXPR_LOCATION (expr),
- NE_EXPR, expr, integer_zero_node, 1);
+ NE_EXPR, expr, nullptr_node, 1);
+ else if (TYPE_PTR_P (type) || TYPE_PTRMEMFUNC_P (type))
+ {
+ /* With -Wzero-as-null-pointer-constant do not warn for an
+ 'if (p)' or a 'while (!p)', where p is a pointer. */
+ tree ret;
+ ++c_inhibit_evaluation_warnings;
+ ret = c_common_truthvalue_conversion (input_location, expr);
+ --c_inhibit_evaluation_warnings;
+ return ret;
+ }
else
return c_common_truthvalue_conversion (input_location, expr);
}
&& TREE_CONSTANT (TREE_OPERAND (val, 0)))
{
tree type = build_pointer_type (argtype);
- tree op0 = fold_convert (type, TREE_OPERAND (val, 0));
- tree op1 = fold_offsetof (arg, val);
- return fold_build_pointer_plus (op0, op1);
+ return fold_convert (type, fold_offsetof_1 (arg));
}
/* Handle complex lvalues (when permitted)
if (TREE_CODE (arg) == OFFSET_REF)
PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
}
- else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
+ else if (BASELINK_P (TREE_OPERAND (arg, 1)))
{
tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
expr = build_conditional_expr (ifexp, op1, op2, complain);
if (processing_template_decl && expr != error_mark_node)
- return build_min_non_dep (COND_EXPR, expr,
- orig_ifexp, orig_op1, orig_op2);
+ {
+ tree min = build_min_non_dep (COND_EXPR, expr,
+ orig_ifexp, orig_op1, orig_op2);
+ /* Remember that the result is an lvalue or xvalue. */
+ if (lvalue_or_rvalue_with_address_p (expr)
+ && !lvalue_or_rvalue_with_address_p (min))
+ TREE_TYPE (min) = cp_build_reference_type (TREE_TYPE (min),
+ !real_lvalue_p (expr));
+ expr = convert_from_reference (min);
+ }
return expr;
}
\f
/* Convert from "B*" to "D*". This function will check that "B"
is not a virtual base of "D". */
expr = build_base_path (MINUS_EXPR, build_address (expr),
- base, /*nonnull=*/false);
+ base, /*nonnull=*/false, complain);
/* Convert the pointer to a reference -- but then remember that
there are no expressions with reference type in C++.
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
c_cast_p ? ba_unique : ba_check,
NULL);
- expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
+ expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
+ complain);
return cp_fold_convert(type, expr);
}
return error_mark_node;
}
- if ((TYPE_PTR_P (src_type) || TYPE_PTRMEM_P (src_type))
- && comp_ptr_ttypes_const (dst_type, src_type))
+ if (TYPE_PTR_P (src_type) || TYPE_PTRMEM_P (src_type))
{
- if (valid_p)
- {
- *valid_p = true;
- /* This cast is actually a C-style cast. Issue a warning if
- the user is making a potentially unsafe cast. */
- check_for_casting_away_constness (src_type, dst_type, CAST_EXPR,
- complain);
- }
- if (reference_type)
- {
- expr = cp_build_addr_expr (expr, complain);
- expr = build_nop (reference_type, expr);
- return convert_from_reference (expr);
- }
- else
+ if (comp_ptr_ttypes_const (dst_type, src_type))
{
- expr = decay_conversion (expr);
- /* build_c_cast puts on a NOP_EXPR to make the result not an
- lvalue. Strip such NOP_EXPRs if VALUE is being used in
- non-lvalue context. */
- if (TREE_CODE (expr) == NOP_EXPR
- && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
- expr = TREE_OPERAND (expr, 0);
- return build_nop (dst_type, expr);
+ if (valid_p)
+ {
+ *valid_p = true;
+ /* This cast is actually a C-style cast. Issue a warning if
+ the user is making a potentially unsafe cast. */
+ check_for_casting_away_constness (src_type, dst_type,
+ CAST_EXPR, complain);
+ }
+ if (reference_type)
+ {
+ expr = cp_build_addr_expr (expr, complain);
+ expr = build_nop (reference_type, expr);
+ return convert_from_reference (expr);
+ }
+ else
+ {
+ expr = decay_conversion (expr);
+ /* build_c_cast puts on a NOP_EXPR to make the result not an
+ lvalue. Strip such NOP_EXPRs if VALUE is being used in
+ non-lvalue context. */
+ if (TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
+ return build_nop (dst_type, expr);
+ }
}
+ else if (valid_p
+ && !at_least_as_qualified_p (TREE_TYPE (dst_type),
+ TREE_TYPE (src_type)))
+ check_for_casting_away_constness (src_type, dst_type, CAST_EXPR,
+ complain);
}
if (complain & tf_error)
/* Handle null pointer to member function conversions. */
if (null_ptr_cst_p (pfn))
{
- pfn = build_c_cast (input_location, type, integer_zero_node);
+ pfn = build_c_cast (input_location, type, nullptr_node);
return build_ptrmemfunc1 (to_type,
integer_zero_node,
pfn);
if (fndecl)
savew = warningcount, savee = errorcount;
- rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE,
- /*cleanup=*/NULL, complain);
+ rhs = initialize_reference (type, rhs, flags, complain);
if (fndecl)
{
if (warningcount > savew)
tree type = lambda_return_type (retval);
tree oldtype = LAMBDA_EXPR_RETURN_TYPE (lambda);
- if (VOID_TYPE_P (type))
- { /* Nothing. */ }
- else if (oldtype == NULL_TREE)
- {
- pedwarn (input_location, OPT_pedantic, "lambda return type "
- "can only be deduced when the return statement is "
- "the only statement in the function body");
- apply_lambda_return_type (lambda, type);
- }
+ if (oldtype == NULL_TREE)
+ apply_lambda_return_type (lambda, type);
+ /* If one of the answers is type-dependent, we can't do any
+ better until instantiation time. */
+ else if (oldtype == dependent_lambda_return_type_node)
+ /* Leave it. */;
+ else if (type == dependent_lambda_return_type_node)
+ apply_lambda_return_type (lambda, type);
else if (!same_type_p (type, oldtype))
error ("inconsistent types %qT and %qT deduced for "
"lambda return type", type, oldtype);
tree
non_reference (tree t)
{
- if (TREE_CODE (t) == REFERENCE_TYPE)
+ if (t && TREE_CODE (t) == REFERENCE_TYPE)
t = TREE_TYPE (t);
return t;
}
return 1;
}
+/* Return true if a user-defined literal operator is a raw operator. */
+
+bool
+check_raw_literal_operator (const_tree decl)
+{
+ tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ tree argtype;
+ int arity;
+ bool maybe_raw_p = false;
+
+ /* Count the number and type of arguments and check for ellipsis. */
+ for (argtype = argtypes, arity = 0;
+ argtype && argtype != void_list_node;
+ ++arity, argtype = TREE_CHAIN (argtype))
+ {
+ tree t = TREE_VALUE (argtype);
+
+ if (same_type_p (t, const_string_type_node))
+ maybe_raw_p = true;
+ }
+ if (!argtype)
+ return false; /* Found ellipsis. */
+
+ if (!maybe_raw_p || arity != 1)
+ return false;
+
+ return true;
+}
+
+
+/* Return true if a user-defined literal operator has one of the allowed
+ argument types. */
+
+bool
+check_literal_operator_args (const_tree decl,
+ bool *long_long_unsigned_p, bool *long_double_p)
+{
+ tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ if (processing_template_decl || processing_specialization)
+ return argtypes == void_list_node;
+ else
+ {
+ tree argtype;
+ int arity;
+ int max_arity = 2;
+
+ *long_long_unsigned_p = false;
+ *long_double_p = false;
+
+ /* Count the number and type of arguments and check for ellipsis. */
+ for (argtype = argtypes, arity = 0;
+ argtype && argtype != void_list_node;
+ argtype = TREE_CHAIN (argtype))
+ {
+ tree t = TREE_VALUE (argtype);
+ ++arity;
+
+ if (TREE_CODE (t) == POINTER_TYPE)
+ {
+ bool maybe_raw_p = false;
+ t = TREE_TYPE (t);
+ if (cp_type_quals (t) != TYPE_QUAL_CONST)
+ return false;
+ t = TYPE_MAIN_VARIANT (t);
+ if ((maybe_raw_p = same_type_p (t, char_type_node))
+ || same_type_p (t, wchar_type_node)
+ || same_type_p (t, char16_type_node)
+ || same_type_p (t, char32_type_node))
+ {
+ argtype = TREE_CHAIN (argtype);
+ if (!argtype)
+ return false;
+ t = TREE_VALUE (argtype);
+ if (maybe_raw_p && argtype == void_list_node)
+ return true;
+ else if (same_type_p (t, size_type_node))
+ {
+ ++arity;
+ continue;
+ }
+ else
+ return false;
+ }
+ }
+ else if (same_type_p (t, long_long_unsigned_type_node))
+ {
+ max_arity = 1;
+ *long_long_unsigned_p = true;
+ }
+ else if (same_type_p (t, long_double_type_node))
+ {
+ max_arity = 1;
+ *long_double_p = true;
+ }
+ else if (same_type_p (t, char_type_node))
+ max_arity = 1;
+ else if (same_type_p (t, wchar_type_node))
+ max_arity = 1;
+ else if (same_type_p (t, char16_type_node))
+ max_arity = 1;
+ else if (same_type_p (t, char32_type_node))
+ max_arity = 1;
+ else
+ return false;
+ }
+ if (!argtype)
+ return false; /* Found ellipsis. */
+
+ if (arity != max_arity)
+ return false;
+
+ return true;
+ }
+}
+