2017-10-30 Nathan Sidwell <nathan@acm.org>
cp/
* call.c (build_op_call_1): Test for FUNCTION_DECL in same manner
as a few lines earlier.
* cp-tree.h (PACK_EXPANSION_PATTERN): Fix white space.
* decl.c (grokfndecl): Fix indentation.
(compute_array_index_type): Use processing_template_decl_sentinel.
(grok_op_properties): Move warnings to end. Reorder other checks
to group similar entities. Tweak diagnostics.
* lex.c (unqualified_name_lookup_error): No need to check name is
not ERROR_MARK operator.
* parser.c (cp_parser_operator): Select operator code before
looking it up.
* typeck.c (check_return_expr): Fix indentation and line wrapping.
testsuite/
* g++.dg/other/operator2.C: Adjust diagnostic.
* g++.old-deja/g++.jason/operator.C: Likewise.
===================================================================
@@ -4565,11 +4565,14 @@ build_op_call_1 (tree obj, vec<tree, va_
result = build_over_call (cand, LOOKUP_NORMAL, complain);
else
{
- if (DECL_P (cand->fn))
+ if (TREE_CODE (cand->fn) == FUNCTION_DECL)
obj = convert_like_with_context (cand->convs[0], obj, cand->fn,
-1, complain);
else
- obj = convert_like (cand->convs[0], obj, complain);
+ {
+ gcc_checking_assert (TYPE_P (cand->fn));
+ obj = convert_like (cand->convs[0], obj, complain);
+ }
obj = convert_from_reference (obj);
result = cp_build_function_call_vec (obj, args, complain);
}
===================================================================
@@ -3460,7 +3460,7 @@ extern void decl_shadowed_for_var_insert
/* Extracts the type or expression pattern from a TYPE_PACK_EXPANSION or
EXPR_PACK_EXPANSION. */
#define PACK_EXPANSION_PATTERN(NODE) \
- (TREE_CODE (NODE) == TYPE_PACK_EXPANSION? TREE_TYPE (NODE) \
+ (TREE_CODE (NODE) == TYPE_PACK_EXPANSION ? TREE_TYPE (NODE) \
: TREE_OPERAND (NODE, 0))
/* Sets the type or expression pattern for a TYPE_PACK_EXPANSION or
===================================================================
@@ -8698,7 +8698,7 @@ grokfndecl (tree ctype,
"deduction guide %qD must not have a function body", decl);
}
else if (IDENTIFIER_ANY_OP_P (DECL_NAME (decl))
- && !grok_op_properties (decl, /*complain=*/true))
+ && !grok_op_properties (decl, /*complain=*/true))
return NULL_TREE;
else if (UDLIT_OPER_P (DECL_NAME (decl)))
{
@@ -9472,22 +9472,20 @@ compute_array_index_type (tree name, tre
itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node);
else
{
- HOST_WIDE_INT saved_processing_template_decl;
-
/* Compute the index of the largest element in the array. It is
one less than the number of elements in the array. We save
and restore PROCESSING_TEMPLATE_DECL so that computations in
cp_build_binary_op will be appropriately folded. */
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- itype = cp_build_binary_op (input_location,
- MINUS_EXPR,
- cp_convert (ssizetype, size, complain),
- cp_convert (ssizetype, integer_one_node,
- complain),
- complain);
- itype = maybe_constant_value (itype);
- processing_template_decl = saved_processing_template_decl;
+ {
+ processing_template_decl_sentinel s;
+ itype = cp_build_binary_op (input_location,
+ MINUS_EXPR,
+ cp_convert (ssizetype, size, complain),
+ cp_convert (ssizetype, integer_one_node,
+ complain),
+ complain);
+ itype = maybe_constant_value (itype);
+ }
if (!TREE_CONSTANT (itype))
{
@@ -12909,25 +12907,14 @@ bool
grok_op_properties (tree decl, bool complain)
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
- tree argtype;
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl);
- enum tree_code operator_code;
- int arity;
- bool ellipsis_p;
- tree class_type;
-
- /* Count the number of arguments and check for ellipsis. */
- for (argtype = argtypes, arity = 0;
- argtype && argtype != void_list_node;
- argtype = TREE_CHAIN (argtype))
- ++arity;
- ellipsis_p = !argtype;
- class_type = DECL_CONTEXT (decl);
+ tree class_type = DECL_CONTEXT (decl);
if (class_type && !CLASS_TYPE_P (class_type))
class_type = NULL_TREE;
+ enum tree_code operator_code = ERROR_MARK;
if (IDENTIFIER_CONV_OP_P (name))
operator_code = TYPE_EXPR;
else
@@ -12953,39 +12940,40 @@ grok_op_properties (tree decl, bool comp
gcc_assert (operator_code != MAX_TREE_CODES);
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
- if (class_type)
- switch (operator_code)
- {
- case NEW_EXPR:
- TYPE_HAS_NEW_OPERATOR (class_type) = 1;
- break;
+ if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR
+ || operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
+ {
+ /* operator new and operator delete are quite special. */
+ if (class_type)
+ switch (operator_code)
+ {
+ case NEW_EXPR:
+ TYPE_HAS_NEW_OPERATOR (class_type) = 1;
+ break;
- case DELETE_EXPR:
- TYPE_GETS_DELETE (class_type) |= 1;
- break;
+ case DELETE_EXPR:
+ TYPE_GETS_DELETE (class_type) |= 1;
+ break;
- case VEC_NEW_EXPR:
- TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1;
- break;
+ case VEC_NEW_EXPR:
+ TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1;
+ break;
- case VEC_DELETE_EXPR:
- TYPE_GETS_DELETE (class_type) |= 2;
- break;
+ case VEC_DELETE_EXPR:
+ TYPE_GETS_DELETE (class_type) |= 2;
+ break;
- default:
- break;
- }
+ default:
+ gcc_unreachable ();
+ }
- /* [basic.std.dynamic.allocation]/1:
+ /* [basic.std.dynamic.allocation]/1:
- A program is ill-formed if an allocation function is declared
- in a namespace scope other than global scope or declared static
- in global scope.
+ A program is ill-formed if an allocation function is declared
+ in a namespace scope other than global scope or declared
+ static in global scope.
- The same also holds true for deallocation functions. */
- if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR
- || operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
- {
+ The same also holds true for deallocation functions. */
if (DECL_NAMESPACE_SCOPE_P (decl))
{
if (CP_DECL_CONTEXT (decl) != global_namespace)
@@ -12993,287 +12981,292 @@ grok_op_properties (tree decl, bool comp
error ("%qD may not be declared within a namespace", decl);
return false;
}
- else if (!TREE_PUBLIC (decl))
+
+ if (!TREE_PUBLIC (decl))
{
error ("%qD may not be declared as static", decl);
return false;
}
}
- }
-
- if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
- {
- TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
- DECL_IS_OPERATOR_NEW (decl) = 1;
- }
- else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
- TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
- else
- {
- /* An operator function must either be a non-static member function
- or have at least one parameter of a class, a reference to a class,
- an enumeration, or a reference to an enumeration. 13.4.0.6 */
- if (! methodp || DECL_STATIC_FUNCTION_P (decl))
- {
- if (operator_code == TYPE_EXPR
- || operator_code == CALL_EXPR
- || operator_code == COMPONENT_REF
- || operator_code == ARRAY_REF
- || operator_code == NOP_EXPR)
- {
- error ("%qD must be a nonstatic member function", decl);
- return false;
- }
- else
- {
- tree p;
- if (DECL_STATIC_FUNCTION_P (decl))
- {
- error ("%qD must be either a non-static member "
- "function or a non-member function", decl);
- return false;
- }
+ if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
+ TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
+ else
+ {
+ TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+ DECL_IS_OPERATOR_NEW (decl) = 1;
+ }
- for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
- {
- tree arg = non_reference (TREE_VALUE (p));
- if (arg == error_mark_node)
- return false;
-
- /* MAYBE_CLASS_TYPE_P, rather than CLASS_TYPE_P, is used
- because these checks are performed even on
- template functions. */
- if (MAYBE_CLASS_TYPE_P (arg)
- || TREE_CODE (arg) == ENUMERAL_TYPE)
- break;
- }
+ return true;
+ }
- if (!p || p == void_list_node)
- {
- if (complain)
- error ("%qD must have an argument of class or "
- "enumerated type", decl);
- return false;
- }
- }
+ /* An operator function must either be a non-static member function
+ or have at least one parameter of a class, a reference to a class,
+ an enumeration, or a reference to an enumeration. 13.4.0.6 */
+ if (! methodp || DECL_STATIC_FUNCTION_P (decl))
+ {
+ if (operator_code == TYPE_EXPR
+ || operator_code == CALL_EXPR
+ || operator_code == COMPONENT_REF
+ || operator_code == ARRAY_REF
+ || operator_code == NOP_EXPR)
+ {
+ error ("%qD must be a nonstatic member function", decl);
+ return false;
}
- /* There are no restrictions on the arguments to an overloaded
- "operator ()". */
- if (operator_code == CALL_EXPR)
- return true;
-
- /* Warn about conversion operators that will never be used. */
- if (IDENTIFIER_CONV_OP_P (name)
- && ! DECL_TEMPLATE_INFO (decl)
- && warn_conversion
- /* Warn only declaring the function; there is no need to
- warn again about out-of-class definitions. */
- && class_type == current_class_type)
+ if (DECL_STATIC_FUNCTION_P (decl))
{
- tree t = TREE_TYPE (name);
- int ref = (TREE_CODE (t) == REFERENCE_TYPE);
-
- if (ref)
- t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
+ error ("%qD must be either a non-static member "
+ "function or a non-member function", decl);
+ return false;
+ }
- if (VOID_TYPE_P (t))
- warning (OPT_Wconversion,
- ref
- ? G_("conversion to a reference to void "
- "will never use a type conversion operator")
- : G_("conversion to void "
- "will never use a type conversion operator"));
- else if (class_type)
+ for (tree arg = argtypes; ; arg = TREE_CHAIN (arg))
+ {
+ if (!arg || arg == void_list_node)
{
- if (t == class_type)
- warning (OPT_Wconversion,
- ref
- ? G_("conversion to a reference to the same type "
- "will never use a type conversion operator")
- : G_("conversion to the same type "
- "will never use a type conversion operator"));
- /* Don't force t to be complete here. */
- else if (MAYBE_CLASS_TYPE_P (t)
- && COMPLETE_TYPE_P (t)
- && DERIVED_FROM_P (t, class_type))
- warning (OPT_Wconversion,
- ref
- ? G_("conversion to a reference to a base class "
- "will never use a type conversion operator")
- : G_("conversion to a base class "
- "will never use a type conversion operator"));
+ if (complain)
+ error ("%qD must have an argument of class or "
+ "enumerated type", decl);
+ return false;
}
-
+
+ tree type = non_reference (TREE_VALUE (arg));
+ if (type == error_mark_node)
+ return false;
+
+ /* MAYBE_CLASS_TYPE_P, rather than CLASS_TYPE_P, is used
+ because these checks are performed even on template
+ functions. */
+ if (MAYBE_CLASS_TYPE_P (type)
+ || TREE_CODE (type) == ENUMERAL_TYPE)
+ break;
}
+ }
- if (operator_code == COND_EXPR)
- {
- /* 13.4.0.3 */
- error ("ISO C++ prohibits overloading operator ?:");
- return false;
- }
- else if (ellipsis_p)
+ /* There are no restrictions on the arguments to an overloaded
+ "operator ()". */
+ if (operator_code == CALL_EXPR)
+ return true;
+
+ if (operator_code == COND_EXPR)
+ {
+ /* 13.4.0.3 */
+ error ("ISO C++ prohibits overloading operator ?:");
+ return false;
+ }
+
+ /* Count the number of arguments and check for ellipsis. */
+ int arity = 0;
+ for (tree arg = argtypes; arg != void_list_node; arg = TREE_CHAIN (arg))
+ {
+ if (!arg)
{
+ /* Variadic. */
error ("%qD must not have variable number of arguments", decl);
return false;
}
- else if (ambi_op_p (operator_code))
+ ++arity;
+ }
+
+ /* Verify correct number of arguments. */
+ if (ambi_op_p (operator_code))
+ {
+ if (arity == 1)
+ /* We pick the one-argument operator codes by default, so
+ we don't have to change anything. */
+ ;
+ else if (arity == 2)
{
- if (arity == 1)
- /* We pick the one-argument operator codes by default, so
- we don't have to change anything. */
- ;
- else if (arity == 2)
+ /* If we thought this was a unary operator, we now know
+ it to be a binary operator. */
+ switch (operator_code)
{
- /* If we thought this was a unary operator, we now know
- it to be a binary operator. */
- switch (operator_code)
- {
- case INDIRECT_REF:
- operator_code = MULT_EXPR;
- break;
-
- case ADDR_EXPR:
- operator_code = BIT_AND_EXPR;
- break;
-
- case UNARY_PLUS_EXPR:
- operator_code = PLUS_EXPR;
- break;
-
- case NEGATE_EXPR:
- operator_code = MINUS_EXPR;
- break;
-
- case PREINCREMENT_EXPR:
- operator_code = POSTINCREMENT_EXPR;
- break;
-
- case PREDECREMENT_EXPR:
- operator_code = POSTDECREMENT_EXPR;
- break;
+ case INDIRECT_REF:
+ operator_code = MULT_EXPR;
+ break;
- default:
- gcc_unreachable ();
- }
+ case ADDR_EXPR:
+ operator_code = BIT_AND_EXPR;
+ break;
- SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
+ case UNARY_PLUS_EXPR:
+ operator_code = PLUS_EXPR;
+ break;
- if ((operator_code == POSTINCREMENT_EXPR
- || operator_code == POSTDECREMENT_EXPR)
- && ! processing_template_decl
- && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
- {
- if (methodp)
- error ("postfix %qD must take %<int%> as its argument",
- decl);
- else
- error ("postfix %qD must take %<int%> as its second "
- "argument", decl);
- return false;
- }
- }
- else
- {
- if (methodp)
- error ("%qD must take either zero or one argument", decl);
- else
- error ("%qD must take either one or two arguments", decl);
- return false;
+ case NEGATE_EXPR:
+ operator_code = MINUS_EXPR;
+ break;
+
+ case PREINCREMENT_EXPR:
+ operator_code = POSTINCREMENT_EXPR;
+ break;
+
+ case PREDECREMENT_EXPR:
+ operator_code = POSTDECREMENT_EXPR;
+ break;
+
+ default:
+ gcc_unreachable ();
}
- /* More Effective C++ rule 6. */
- if (warn_ecpp
- && (operator_code == POSTINCREMENT_EXPR
- || operator_code == POSTDECREMENT_EXPR
- || operator_code == PREINCREMENT_EXPR
- || operator_code == PREDECREMENT_EXPR))
+ SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
+
+ if ((operator_code == POSTINCREMENT_EXPR
+ || operator_code == POSTDECREMENT_EXPR)
+ && ! processing_template_decl
+ && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
- tree arg = TREE_VALUE (argtypes);
- tree ret = TREE_TYPE (TREE_TYPE (decl));
- if (methodp || TREE_CODE (arg) == REFERENCE_TYPE)
- arg = TREE_TYPE (arg);
- arg = TYPE_MAIN_VARIANT (arg);
- if (operator_code == PREINCREMENT_EXPR
- || operator_code == PREDECREMENT_EXPR)
- {
- if (TREE_CODE (ret) != REFERENCE_TYPE
- || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
- arg))
- warning (OPT_Weffc__, "prefix %qD should return %qT", decl,
- build_reference_type (arg));
- }
- else
- {
- if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
- warning (OPT_Weffc__, "postfix %qD should return %qT", decl, arg);
- }
+ error (methodp
+ ? G_("postfix %qD must have %<int%> as its argument")
+ : G_("postfix %qD must have %<int%> as its second argument"),
+ decl);
+ return false;
}
}
- else if (unary_op_p (operator_code))
+ else
{
- if (arity != 1)
- {
- if (methodp)
- error ("%qD must take %<void%>", decl);
- else
- error ("%qD must take exactly one argument", decl);
- return false;
- }
+ error (methodp
+ ? G_("%qD must have either zero or one argument")
+ : G_("%qD must have either one or two arguments"), decl);
+ return false;
}
- else /* if (binary_op_p (operator_code)) */
+ }
+ else if (unary_op_p (operator_code))
+ {
+ if (arity != 1)
{
- if (arity != 2)
- {
- if (methodp)
- error ("%qD must take exactly one argument", decl);
- else
- error ("%qD must take exactly two arguments", decl);
- return false;
- }
-
- /* More Effective C++ rule 7. */
- if (warn_ecpp
- && (operator_code == TRUTH_ANDIF_EXPR
- || operator_code == TRUTH_ORIF_EXPR
- || operator_code == COMPOUND_EXPR))
- warning (OPT_Weffc__, "user-defined %qD always evaluates both arguments",
- decl);
- }
-
- /* Effective C++ rule 23. */
- if (warn_ecpp
- && arity == 2
- && !DECL_ASSIGNMENT_OPERATOR_P (decl)
- && (operator_code == PLUS_EXPR
- || operator_code == MINUS_EXPR
- || operator_code == TRUNC_DIV_EXPR
- || operator_code == MULT_EXPR
- || operator_code == TRUNC_MOD_EXPR)
- && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
- warning (OPT_Weffc__, "%qD should return by value", decl);
-
- /* [over.oper]/8 */
- for (; argtypes && argtypes != void_list_node;
- argtypes = TREE_CHAIN (argtypes))
- if (TREE_PURPOSE (argtypes))
+ error (methodp
+ ? G_("%qD must have no arguments")
+ : G_("%qD must have exactly one argument"), decl);
+ return false;
+ }
+ }
+ else
+ {
+ if (arity != 2)
+ {
+ error (methodp
+ ? G_("%qD must have exactly one argument")
+ : G_("%qD must have exactly two arguments"), decl);
+ return false;
+ }
+ }
+
+ /* There can be no default arguments. */
+ for (tree arg = argtypes; arg != void_list_node; arg = TREE_CHAIN (arg))
+ if (TREE_PURPOSE (arg))
+ {
+ TREE_PURPOSE (arg) = NULL_TREE;
+ if (operator_code == POSTINCREMENT_EXPR
+ || operator_code == POSTDECREMENT_EXPR)
+ pedwarn (input_location, OPT_Wpedantic,
+ "%qD cannot have default arguments", decl);
+ else
{
- TREE_PURPOSE (argtypes) = NULL_TREE;
- if (operator_code == POSTINCREMENT_EXPR
- || operator_code == POSTDECREMENT_EXPR)
- {
- pedwarn (input_location, OPT_Wpedantic, "%qD cannot have default arguments",
- decl);
- }
- else
- {
- error ("%qD cannot have default arguments", decl);
- return false;
- }
+ error ("%qD cannot have default arguments", decl);
+ return false;
}
+ }
+
+ /* At this point the declaration is well-formed. It may not be
+ sensible though. */
+
+ /* Check member function warnings only on the in-class declaration.
+ There's no point warning on an out-of-class definition. */
+ if (class_type && class_type != current_class_type)
+ return true;
+
+ /* Warn about conversion operators that will never be used. */
+ if (IDENTIFIER_CONV_OP_P (name)
+ && ! DECL_TEMPLATE_INFO (decl)
+ && warn_conversion)
+ {
+ tree t = TREE_TYPE (name);
+ int ref = (TREE_CODE (t) == REFERENCE_TYPE);
+
+ if (ref)
+ t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
+
+ if (VOID_TYPE_P (t))
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to void "
+ "will never use a type conversion operator")
+ : G_("conversion to void "
+ "will never use a type conversion operator"));
+ else if (class_type)
+ {
+ if (t == class_type)
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to the same type "
+ "will never use a type conversion operator")
+ : G_("conversion to the same type "
+ "will never use a type conversion operator"));
+ /* Don't force t to be complete here. */
+ else if (MAYBE_CLASS_TYPE_P (t)
+ && COMPLETE_TYPE_P (t)
+ && DERIVED_FROM_P (t, class_type))
+ warning (OPT_Wconversion,
+ ref
+ ? G_("conversion to a reference to a base class "
+ "will never use a type conversion operator")
+ : G_("conversion to a base class "
+ "will never use a type conversion operator"));
+ }
}
+
+ if (!warn_ecpp)
+ return true;
+
+ /* Effective C++ rules below. */
+
+ /* More Effective C++ rule 7. */
+ if (operator_code == TRUTH_ANDIF_EXPR
+ || operator_code == TRUTH_ORIF_EXPR
+ || operator_code == COMPOUND_EXPR)
+ warning (OPT_Weffc__,
+ "user-defined %qD always evaluates both arguments", decl);
+
+ /* More Effective C++ rule 6. */
+ if (operator_code == POSTINCREMENT_EXPR
+ || operator_code == POSTDECREMENT_EXPR
+ || operator_code == PREINCREMENT_EXPR
+ || operator_code == PREDECREMENT_EXPR)
+ {
+ tree arg = TREE_VALUE (argtypes);
+ tree ret = TREE_TYPE (TREE_TYPE (decl));
+ if (methodp || TREE_CODE (arg) == REFERENCE_TYPE)
+ arg = TREE_TYPE (arg);
+ arg = TYPE_MAIN_VARIANT (arg);
+
+ if (operator_code == PREINCREMENT_EXPR
+ || operator_code == PREDECREMENT_EXPR)
+ {
+ if (TREE_CODE (ret) != REFERENCE_TYPE
+ || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)), arg))
+ warning (OPT_Weffc__, "prefix %qD should return %qT", decl,
+ build_reference_type (arg));
+ }
+ else
+ {
+ if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
+ warning (OPT_Weffc__, "postfix %qD should return %qT", decl, arg);
+ }
+ }
+
+ /* Effective C++ rule 23. */
+ if (!DECL_ASSIGNMENT_OPERATOR_P (decl)
+ && (operator_code == PLUS_EXPR
+ || operator_code == MINUS_EXPR
+ || operator_code == TRUNC_DIV_EXPR
+ || operator_code == MULT_EXPR
+ || operator_code == TRUNC_MOD_EXPR)
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
+ warning (OPT_Weffc__, "%qD should return by value", decl);
+
return true;
}
===================================================================
@@ -462,10 +462,7 @@ unqualified_name_lookup_error (tree name
loc = EXPR_LOC_OR_LOC (name, input_location);
if (IDENTIFIER_ANY_OP_P (name))
- {
- if (name != cp_operator_id (ERROR_MARK))
- error_at (loc, "%qD not defined", name);
- }
+ error_at (loc, "%qD not defined", name);
else
{
if (!objc_diagnose_private_ivar (name))
===================================================================
@@ -14715,12 +14715,13 @@ cp_parser_operator (cp_parser* parser)
location_t start_loc = token->location;
/* Figure out which operator we have. */
+ enum tree_code op = ERROR_MARK;
+ bool assop = false;
+ bool consumed = false;
switch (token->type)
{
case CPP_KEYWORD:
{
- enum tree_code op;
-
/* The keyword should be either `new' or `delete'. */
if (token->keyword == RID_NEW)
op = NEW_EXPR;
@@ -14744,160 +14745,166 @@ cp_parser_operator (cp_parser* parser)
if (cp_token *close_token
= cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
end_loc = close_token->location;
- id = cp_operator_id (op == NEW_EXPR
- ? VEC_NEW_EXPR : VEC_DELETE_EXPR);
+ op = op == NEW_EXPR ? VEC_NEW_EXPR : VEC_DELETE_EXPR;
}
- /* Otherwise, we have the non-array variant. */
- else
- id = cp_operator_id (op);
-
- location_t loc = make_location (start_loc, start_loc, end_loc);
-
- return cp_expr (id, loc);
+ start_loc = make_location (start_loc, start_loc, end_loc);
+ consumed = true;
+ break;
}
case CPP_PLUS:
- id = cp_operator_id (PLUS_EXPR);
+ op = PLUS_EXPR;
break;
case CPP_MINUS:
- id = cp_operator_id (MINUS_EXPR);
+ op = MINUS_EXPR;
break;
case CPP_MULT:
- id = cp_operator_id (MULT_EXPR);
+ op = MULT_EXPR;
break;
case CPP_DIV:
- id = cp_operator_id (TRUNC_DIV_EXPR);
+ op = TRUNC_DIV_EXPR;
break;
case CPP_MOD:
- id = cp_operator_id (TRUNC_MOD_EXPR);
+ op = TRUNC_MOD_EXPR;
break;
case CPP_XOR:
- id = cp_operator_id (BIT_XOR_EXPR);
+ op = BIT_XOR_EXPR;
break;
case CPP_AND:
- id = cp_operator_id (BIT_AND_EXPR);
+ op = BIT_AND_EXPR;
break;
case CPP_OR:
- id = cp_operator_id (BIT_IOR_EXPR);
+ op = BIT_IOR_EXPR;
break;
case CPP_COMPL:
- id = cp_operator_id (BIT_NOT_EXPR);
+ op = BIT_NOT_EXPR;
break;
case CPP_NOT:
- id = cp_operator_id (TRUTH_NOT_EXPR);
+ op = TRUTH_NOT_EXPR;
break;
case CPP_EQ:
- id = cp_assignment_operator_id (NOP_EXPR);
+ assop = true;
+ op = NOP_EXPR;
break;
case CPP_LESS:
- id = cp_operator_id (LT_EXPR);
+ op = LT_EXPR;
break;
case CPP_GREATER:
- id = cp_operator_id (GT_EXPR);
+ op = GT_EXPR;
break;
case CPP_PLUS_EQ:
- id = cp_assignment_operator_id (PLUS_EXPR);
+ assop = true;
+ op = PLUS_EXPR;
break;
case CPP_MINUS_EQ:
- id = cp_assignment_operator_id (MINUS_EXPR);
+ assop = true;
+ op = MINUS_EXPR;
break;
case CPP_MULT_EQ:
- id = cp_assignment_operator_id (MULT_EXPR);
+ assop = true;
+ op = MULT_EXPR;
break;
case CPP_DIV_EQ:
- id = cp_assignment_operator_id (TRUNC_DIV_EXPR);
+ assop = true;
+ op = TRUNC_DIV_EXPR;
break;
case CPP_MOD_EQ:
- id = cp_assignment_operator_id (TRUNC_MOD_EXPR);
+ assop = true;
+ op = TRUNC_MOD_EXPR;
break;
case CPP_XOR_EQ:
- id = cp_assignment_operator_id (BIT_XOR_EXPR);
+ assop = true;
+ op = BIT_XOR_EXPR;
break;
case CPP_AND_EQ:
- id = cp_assignment_operator_id (BIT_AND_EXPR);
+ assop = true;
+ op = BIT_AND_EXPR;
break;
case CPP_OR_EQ:
- id = cp_assignment_operator_id (BIT_IOR_EXPR);
+ assop = true;
+ op = BIT_IOR_EXPR;
break;
case CPP_LSHIFT:
- id = cp_operator_id (LSHIFT_EXPR);
+ op = LSHIFT_EXPR;
break;
case CPP_RSHIFT:
- id = cp_operator_id (RSHIFT_EXPR);
+ op = RSHIFT_EXPR;
break;
case CPP_LSHIFT_EQ:
- id = cp_assignment_operator_id (LSHIFT_EXPR);
+ assop = true;
+ op = LSHIFT_EXPR;
break;
case CPP_RSHIFT_EQ:
- id = cp_assignment_operator_id (RSHIFT_EXPR);
+ assop = true;
+ op = RSHIFT_EXPR;
break;
case CPP_EQ_EQ:
- id = cp_operator_id (EQ_EXPR);
+ op = EQ_EXPR;
break;
case CPP_NOT_EQ:
- id = cp_operator_id (NE_EXPR);
+ op = NE_EXPR;
break;
case CPP_LESS_EQ:
- id = cp_operator_id (LE_EXPR);
+ op = LE_EXPR;
break;
case CPP_GREATER_EQ:
- id = cp_operator_id (GE_EXPR);
+ op = GE_EXPR;
break;
case CPP_AND_AND:
- id = cp_operator_id (TRUTH_ANDIF_EXPR);
+ op = TRUTH_ANDIF_EXPR;
break;
case CPP_OR_OR:
- id = cp_operator_id (TRUTH_ORIF_EXPR);
+ op = TRUTH_ORIF_EXPR;
break;
case CPP_PLUS_PLUS:
- id = cp_operator_id (POSTINCREMENT_EXPR);
+ op = POSTINCREMENT_EXPR;
break;
case CPP_MINUS_MINUS:
- id = cp_operator_id (PREDECREMENT_EXPR);
+ op = PREDECREMENT_EXPR;
break;
case CPP_COMMA:
- id = cp_operator_id (COMPOUND_EXPR);
+ op = COMPOUND_EXPR;
break;
case CPP_DEREF_STAR:
- id = cp_operator_id (MEMBER_REF);
+ op = MEMBER_REF;
break;
case CPP_DEREF:
- id = cp_operator_id (COMPONENT_REF);
+ op = COMPONENT_REF;
break;
case CPP_OPEN_PAREN:
@@ -14907,7 +14914,9 @@ cp_parser_operator (cp_parser* parser)
parens.consume_open (parser);
/* Look for the matching `)'. */
parens.require_close (parser);
- return cp_operator_id (CALL_EXPR);
+ op = CALL_EXPR;
+ consumed = true;
+ break;
}
case CPP_OPEN_SQUARE:
@@ -14915,7 +14924,9 @@ cp_parser_operator (cp_parser* parser)
cp_lexer_consume_token (parser->lexer);
/* Look for the matching `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
- return cp_operator_id (ARRAY_REF);
+ op = ARRAY_REF;
+ consumed = true;
+ break;
case CPP_UTF8STRING:
case CPP_UTF8STRING_USERDEF:
@@ -14994,8 +15005,12 @@ cp_parser_operator (cp_parser* parser)
/* If we have selected an identifier, we need to consume the
operator token. */
- if (id)
- cp_lexer_consume_token (parser->lexer);
+ if (op != ERROR_MARK)
+ {
+ id = assop ? cp_assignment_operator_id (op) : cp_operator_id (op);
+ if (!consumed)
+ cp_lexer_consume_token (parser->lexer);
+ }
/* Otherwise, no valid operator name was present. */
else
{
===================================================================
@@ -9045,10 +9045,11 @@ check_return_expr (tree retval, bool *no
/* You can return a `void' value from a function of `void'
type. In that case, we have to evaluate the expression for
its side-effects. */
- finish_expr_stmt (retval);
+ finish_expr_stmt (retval);
else
- permerror (input_location, "return-statement with a value, in function "
- "returning 'void'");
+ permerror (input_location,
+ "return-statement with a value, in function "
+ "returning %qT", valtype);
current_function_returns_null = 1;
/* There's really no value to return, after all. */
===================================================================
@@ -3,7 +3,7 @@
struct A
{
- operator int&(int); // { dg-error "void" }
+ operator int&(int); // { dg-error "no arguments" }
};
A a;
===================================================================
@@ -9,7 +9,7 @@ struct A {
static int operator()(int a); // { dg-error "must be a nonstatic member" }
static int operator+(A,A); // { dg-error "either a non-static member" }
int operator+(int a, int b = 1); // { dg-error "either zero or one" }
- int operator++(char); // { dg-error "must take 'int'" }
+ int operator++(char); // { dg-error "must have 'int'" }
void operator delete (void *);
void operator delete (void *, unsigned long);
};