tree do_friend (tree ctype, tree declarator, tree decl, tree attrlist, enum overload_flags flags, bool funcdef_flag) { gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); gcc_assert (!ctype || MAYBE_CLASS_TYPE_P (ctype)); /* Every decl that gets here is a friend of something. */ DECL_FRIEND_P (decl) = 1; /* Unfortunately, we have to handle attributes here. Normally we would handle them in start_decl_1, but since this is a friend decl start_decl_1 never gets to see it. */ /* Set attributes here so if duplicate decl, will have proper attributes. */ cplus_decl_attributes (&decl, attrlist, 0); if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) { declarator = TREE_OPERAND (declarator, 0); if (is_overloaded_fn (declarator)) declarator = DECL_NAME (get_first_fn (declarator)); } if (ctype) { /* CLASS_TEMPLATE_DEPTH counts the number of template headers for the enclosing class. FRIEND_DEPTH counts the number of template headers used for this friend declaration. TEMPLATE_MEMBER_P is true if a template header in FRIEND_DEPTH is intended for DECLARATOR. For example, the code template <class T> struct A { template <class U> struct B { template <class V> template <class W> friend void C<V>::f(W); }; }; will eventually give the following results 1. CLASS_TEMPLATE_DEPTH equals 2 (for `T' and `U'). 2. FRIEND_DEPTH equals 2 (for `V' and `W'). 3. TEMPLATE_MEMBER_P is true (for `W'). */ int class_template_depth = template_class_depth (current_class_type); int friend_depth = processing_template_decl - class_template_depth; /* We will figure this out later. */ bool template_member_p = false; tree cname = TYPE_NAME (ctype); if (TREE_CODE (cname) == TYPE_DECL) cname = DECL_NAME (cname); /* A method friend. */ if (flags == NO_SPECIAL && declarator == cname) DECL_CONSTRUCTOR_P (decl) = 1; grokclassfn (ctype, decl, flags); if (friend_depth) { if (!uses_template_parms_level (ctype, class_template_depth + friend_depth)) template_member_p = true; } /* A nested class may declare a member of an enclosing class to be a friend, so we do lookup here even if CTYPE is in the process of being defined. */ if (class_template_depth || COMPLETE_TYPE_P (ctype) || (CLASS_TYPE_P (ctype) && TYPE_BEING_DEFINED (ctype))) { if (DECL_TEMPLATE_INFO (decl)) /* DECL is a template specialization. No need to build a new TEMPLATE_DECL. */ ; else if (class_template_depth) /* We rely on tsubst_friend_function to check the validity of the declaration later. */ decl = push_template_decl_real (decl, /*is_friend=*/true); else decl = check_classfn (ctype, decl, template_member_p ? current_template_parms : NULL_TREE); if (template_member_p && decl && TREE_CODE (decl) == FUNCTION_DECL) decl = DECL_TI_TEMPLATE (decl); if (decl) add_friend (current_class_type, decl, /*complain=*/true); } else error ("member %qD declared as friend before type %qT defined", decl, ctype); } /* A global friend. @@ or possibly a friend from a base class ?!? */ else if (TREE_CODE (decl) == FUNCTION_DECL) { int is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P (); /* Friends must all go through the overload machinery, even though they may not technically be overloaded. Note that because classes all wind up being top-level in their scope, their friend wind up in top-level scope as well. */ if (funcdef_flag) SET_DECL_FRIEND_CONTEXT (decl, current_class_type); if (! DECL_USE_TEMPLATE (decl)) { /* We must check whether the decl refers to template arguments before push_template_decl_real adds a reference to the containing template class. */ int warn = (warn_nontemplate_friend && ! funcdef_flag && ! is_friend_template && current_template_parms && uses_template_parms (decl)); if (is_friend_template || template_class_depth (current_class_type) != 0) /* We can't call pushdecl for a template class, since in general, such a declaration depends on template parameters. Instead, we call pushdecl when the class is instantiated. */ decl = push_template_decl_real (decl, /*is_friend=*/true); else if (current_function_decl) { /* This must be a local class. 11.5p11: If a friend declaration appears in a local class (9.8) and the name specified is an unqualified name, a prior declaration is looked up without considering scopes that are outside the innermost enclosing non-class scope. For a friend function declaration, if there is no prior declaration, the program is ill-formed. */ tree t = lookup_name_innermost_nonclass_level (DECL_NAME (decl)); if (t) decl = pushdecl_maybe_friend (decl, /*is_friend=*/true); else { error ("friend declaration %qD in local class without " "prior declaration", decl); return error_mark_node; } } else { /* We can't use pushdecl, as we might be in a template class specialization, and pushdecl will insert an unqualified friend decl into the template parameter scope, rather than the namespace containing it. */ tree ns = decl_namespace_context (decl); push_nested_namespace (ns); decl = pushdecl_namespace_level (decl, /*is_friend=*/true); pop_nested_namespace (ns); } if (warn) { static int explained; bool warned; warned = warning (OPT_Wnon_template_friend, "friend declaration " "%q#D declares a non-template function", decl); if (! explained && warned) { inform (input_location, "(if this is not what you intended, make sure " "the function template has already been declared " "and add <> after the function name here) "); explained = 1; } } } if (decl == error_mark_node) return error_mark_node; add_friend (current_class_type, is_friend_template ? DECL_TI_TEMPLATE (decl) : decl, /*complain=*/true); DECL_FRIEND_P (decl) = 1; } return decl; }
tree convert_to_void (tree expr, const char *implicit) { if (expr == error_mark_node || TREE_TYPE (expr) == error_mark_node) return error_mark_node; if (!TREE_TYPE (expr)) return expr; if (invalid_nonstatic_memfn_p (expr)) return error_mark_node; if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR) { error ("pseudo-destructor is not called"); return error_mark_node; } if (VOID_TYPE_P (TREE_TYPE (expr))) return expr; switch (TREE_CODE (expr)) { case COND_EXPR: { /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr,1); tree op2 = TREE_OPERAND (expr,2); tree new_op1 = convert_to_void (op1, (implicit && !TREE_SIDE_EFFECTS (op2) ? "second operand of conditional" : NULL)); tree new_op2 = convert_to_void (op2, (implicit && !TREE_SIDE_EFFECTS (op1) ? "third operand of conditional" : NULL)); expr = build (COND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1, new_op2); break; } case COMPOUND_EXPR: { /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr,1); tree new_op1 = convert_to_void (op1, (implicit && !TREE_NO_UNUSED_WARNING (expr) ? "right-hand operand of comma" : NULL)); if (new_op1 != op1) { tree t = build (COMPOUND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1); expr = t; } break; } case NON_LVALUE_EXPR: case NOP_EXPR: /* These have already decayed to rvalue. */ break; case CALL_EXPR: /* We have a special meaning for volatile void fn(). */ break; case INDIRECT_REF: { tree type = TREE_TYPE (expr); int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE; int is_volatile = TYPE_VOLATILE (type); int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (is_volatile && !is_complete) warning ("object of incomplete type `%T' will not be accessed in %s", type, implicit ? implicit : "void context"); else if (is_reference && is_volatile) warning ("object of type `%T' will not be accessed in %s", TREE_TYPE (TREE_OPERAND (expr, 0)), implicit ? implicit : "void context"); if (is_reference || !is_volatile || !is_complete) expr = TREE_OPERAND (expr, 0); break; } case VAR_DECL: { /* External variables might be incomplete. */ tree type = TREE_TYPE (expr); int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (TYPE_VOLATILE (type) && !is_complete) warning ("object `%E' of incomplete type `%T' will not be accessed in %s", expr, type, implicit ? implicit : "void context"); break; } default:; } { tree probe = expr; if (TREE_CODE (probe) == ADDR_EXPR) probe = TREE_OPERAND (expr, 0); if (type_unknown_p (probe)) { /* [over.over] enumerates the places where we can take the address of an overloaded function, and this is not one of them. */ pedwarn ("%s cannot resolve address of overloaded function", implicit ? implicit : "void cast"); expr = void_zero_node; } else if (implicit && probe == expr && is_overloaded_fn (probe)) /* Only warn when there is no &. */ warning ("%s is a reference, not call, to function `%E'", implicit, expr); } if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) { if (implicit && !TREE_SIDE_EFFECTS (expr) && warn_unused_value) warning ("%s has no effect", implicit); expr = build1 (CONVERT_EXPR, void_type_node, expr); } return expr; }
tree convert_to_void (tree expr, const char *implicit, tsubst_flags_t complain) { if (expr == error_mark_node || TREE_TYPE (expr) == error_mark_node) return error_mark_node; if (!TREE_TYPE (expr)) return expr; if (invalid_nonstatic_memfn_p (expr, complain)) return error_mark_node; if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR) { if (complain & tf_error) error ("pseudo-destructor is not called"); return error_mark_node; } if (VOID_TYPE_P (TREE_TYPE (expr))) return expr; switch (TREE_CODE (expr)) { case COND_EXPR: { /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr,1); tree op2 = TREE_OPERAND (expr,2); tree new_op1 = convert_to_void (op1, (implicit && !TREE_SIDE_EFFECTS (op2) ? "second operand of conditional" : NULL), complain); tree new_op2 = convert_to_void (op2, (implicit && !TREE_SIDE_EFFECTS (op1) ? "third operand of conditional" : NULL), complain); expr = build3 (COND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1, new_op2); break; } case COMPOUND_EXPR: { /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr,1); tree new_op1 = convert_to_void (op1, (implicit && !TREE_NO_WARNING (expr) ? "right-hand operand of comma" : NULL), complain); if (new_op1 != op1) { tree t = build2 (COMPOUND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1); expr = t; } break; } case NON_LVALUE_EXPR: case NOP_EXPR: /* These have already decayed to rvalue. */ break; case CALL_EXPR: /* We have a special meaning for volatile void fn(). */ break; case INDIRECT_REF: { tree type = TREE_TYPE (expr); int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE; int is_volatile = TYPE_VOLATILE (type); int is_complete = COMPLETE_TYPE_P (complete_type (type)); /* Can't load the value if we don't know the type. */ if (is_volatile && !is_complete) { if (complain & tf_warning) warning (0, "object of incomplete type %qT will not be accessed in %s", type, implicit ? implicit : "void context"); } /* Don't load the value if this is an implicit dereference, or if the type needs to be handled by ctors/dtors. */ else if (is_volatile && (is_reference || TREE_ADDRESSABLE (type))) { if (complain & tf_warning) warning (0, "object of type %qT will not be accessed in %s", TREE_TYPE (TREE_OPERAND (expr, 0)), implicit ? implicit : "void context"); } if (is_reference || !is_volatile || !is_complete || TREE_ADDRESSABLE (type)) expr = TREE_OPERAND (expr, 0); break; } case VAR_DECL: { /* External variables might be incomplete. */ tree type = TREE_TYPE (expr); int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning)) warning (0, "object %qE of incomplete type %qT will not be accessed in %s", expr, type, implicit ? implicit : "void context"); break; } case TARGET_EXPR: /* Don't bother with the temporary object returned from a function if we don't use it and don't need to destroy it. We'll still allocate space for it in expand_call or declare_return_variable, but we don't need to track it through all the tree phases. */ if (TARGET_EXPR_IMPLICIT_P (expr) && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (expr))) { tree init = TARGET_EXPR_INITIAL (expr); if (TREE_CODE (init) == AGGR_INIT_EXPR && !AGGR_INIT_VIA_CTOR_P (init)) { tree fn = AGGR_INIT_EXPR_FN (init); expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn, aggr_init_expr_nargs (init), AGGR_INIT_EXPR_ARGP (init)); } } break; default:; } { tree probe = expr; if (TREE_CODE (probe) == ADDR_EXPR) probe = TREE_OPERAND (expr, 0); if (type_unknown_p (probe)) { /* [over.over] enumerates the places where we can take the address of an overloaded function, and this is not one of them. */ if (complain & tf_error) error ("%s cannot resolve address of overloaded function", implicit ? implicit : "void cast"); else return error_mark_node; expr = void_zero_node; } else if (implicit && probe == expr && is_overloaded_fn (probe)) { /* Only warn when there is no &. */ if (complain & tf_warning) warning (OPT_Waddress, "%s is a reference, not call, to function %qE", implicit, expr); if (TREE_CODE (expr) == COMPONENT_REF) expr = TREE_OPERAND (expr, 0); } } if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) { if (implicit && warn_unused_value && !TREE_NO_WARNING (expr) && !processing_template_decl) { /* The middle end does not warn about expressions that have been explicitly cast to void, so we must do so here. */ if (!TREE_SIDE_EFFECTS (expr)) { if (complain & tf_warning) warning (OPT_Wunused_value, "%s has no effect", implicit); } else { tree e; enum tree_code code; enum tree_code_class tclass; e = expr; /* We might like to warn about (say) "(int) f()", as the cast has no effect, but the compiler itself will generate implicit conversions under some circumstances. (For example a block copy will be turned into a call to "__builtin_memcpy", with a conversion of the return value to an appropriate type.) So, to avoid false positives, we strip conversions. Do not use STRIP_NOPs because it will not strip conversions to "void", as that is not a mode-preserving conversion. */ while (TREE_CODE (e) == NOP_EXPR) e = TREE_OPERAND (e, 0); code = TREE_CODE (e); tclass = TREE_CODE_CLASS (code); if ((tclass == tcc_comparison || tclass == tcc_unary || (tclass == tcc_binary && !(code == MODIFY_EXPR || code == INIT_EXPR || code == PREDECREMENT_EXPR || code == PREINCREMENT_EXPR || code == POSTDECREMENT_EXPR || code == POSTINCREMENT_EXPR))) && (complain & tf_warning)) warning (OPT_Wunused_value, "value computed is not used"); } } expr = build1 (CONVERT_EXPR, void_type_node, expr); } if (! TREE_SIDE_EFFECTS (expr)) expr = void_zero_node; return expr; }
tree convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) { if (expr == error_mark_node || TREE_TYPE (expr) == error_mark_node) return error_mark_node; if (implicit == ICV_CAST) mark_exp_read (expr); else { tree exprv = expr; while (TREE_CODE (exprv) == COMPOUND_EXPR) exprv = TREE_OPERAND (exprv, 1); if (DECL_P (exprv) || handled_component_p (exprv) || TREE_CODE (exprv) == INDIRECT_REF) /* Expr is not being 'used' here, otherwise we whould have called mark_{rl}value_use use here, which would have in turn called mark_exp_read. Rather, we call mark_exp_read directly to avoid some warnings when -Wunused-but-set-{variable,parameter} is in effect. */ mark_exp_read (exprv); } if (!TREE_TYPE (expr)) return expr; if (invalid_nonstatic_memfn_p (expr, complain)) return error_mark_node; if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR) { if (complain & tf_error) error ("pseudo-destructor is not called"); return error_mark_node; } if (VOID_TYPE_P (TREE_TYPE (expr))) return expr; switch (TREE_CODE (expr)) { case COND_EXPR: { /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr,1); tree op2 = TREE_OPERAND (expr,2); bool side_effects = TREE_SIDE_EFFECTS (op1) || TREE_SIDE_EFFECTS (op2); tree new_op1, new_op2; if (implicit != ICV_CAST && !side_effects) { new_op1 = convert_to_void (op1, ICV_SECOND_OF_COND, complain); new_op2 = convert_to_void (op2, ICV_THIRD_OF_COND, complain); } else { new_op1 = convert_to_void (op1, ICV_CAST, complain); new_op2 = convert_to_void (op2, ICV_CAST, complain); } expr = build3 (COND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1, new_op2); break; } case COMPOUND_EXPR: { /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr,1); tree new_op1; if (implicit != ICV_CAST && !TREE_NO_WARNING (expr)) new_op1 = convert_to_void (op1, ICV_RIGHT_OF_COMMA, complain); else new_op1 = convert_to_void (op1, ICV_CAST, complain); if (new_op1 != op1) { tree t = build2 (COMPOUND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1); expr = t; } break; } case NON_LVALUE_EXPR: case NOP_EXPR: /* These have already decayed to rvalue. */ break; case CALL_EXPR: /* We have a special meaning for volatile void fn(). */ break; case INDIRECT_REF: { tree type = TREE_TYPE (expr); int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE; int is_volatile = TYPE_VOLATILE (type); int is_complete = COMPLETE_TYPE_P (complete_type (type)); /* Can't load the value if we don't know the type. */ if (is_volatile && !is_complete) { if (complain & tf_warning) switch (implicit) { case ICV_CAST: warning (0, "conversion to void will not access " "object of incomplete type %qT", type); break; case ICV_SECOND_OF_COND: warning (0, "indirection will not access object of " "incomplete type %qT in second operand " "of conditional expression", type); break; case ICV_THIRD_OF_COND: warning (0, "indirection will not access object of " "incomplete type %qT in third operand " "of conditional expression", type); break; case ICV_RIGHT_OF_COMMA: warning (0, "indirection will not access object of " "incomplete type %qT in right operand of " "comma operator", type); break; case ICV_LEFT_OF_COMMA: warning (0, "indirection will not access object of " "incomplete type %qT in left operand of " "comma operator", type); break; case ICV_STATEMENT: warning (0, "indirection will not access object of " "incomplete type %qT in statement", type); break; case ICV_THIRD_IN_FOR: warning (0, "indirection will not access object of " "incomplete type %qT in for increment " "expression", type); break; default: gcc_unreachable (); } } /* Don't load the value if this is an implicit dereference, or if the type needs to be handled by ctors/dtors. */ else if (is_volatile && is_reference) { if (complain & tf_warning) switch (implicit) { case ICV_CAST: warning (0, "conversion to void will not access " "object of type %qT", type); break; case ICV_SECOND_OF_COND: warning (0, "implicit dereference will not access object " "of type %qT in second operand of " "conditional expression", type); break; case ICV_THIRD_OF_COND: warning (0, "implicit dereference will not access object " "of type %qT in third operand of " "conditional expression", type); break; case ICV_RIGHT_OF_COMMA: warning (0, "implicit dereference will not access object " "of type %qT in right operand of " "comma operator", type); break; case ICV_LEFT_OF_COMMA: warning (0, "implicit dereference will not access object " "of type %qT in left operand of comma operator", type); break; case ICV_STATEMENT: warning (0, "implicit dereference will not access object " "of type %qT in statement", type); break; case ICV_THIRD_IN_FOR: warning (0, "implicit dereference will not access object " "of type %qT in for increment expression", type); break; default: gcc_unreachable (); } } else if (is_volatile && TREE_ADDRESSABLE (type)) { if (complain & tf_warning) switch (implicit) { case ICV_CAST: warning (0, "conversion to void will not access " "object of non-trivially-copyable type %qT", type); break; case ICV_SECOND_OF_COND: warning (0, "indirection will not access object of " "non-trivially-copyable type %qT in second " "operand of conditional expression", type); break; case ICV_THIRD_OF_COND: warning (0, "indirection will not access object of " "non-trivially-copyable type %qT in third " "operand of conditional expression", type); break; case ICV_RIGHT_OF_COMMA: warning (0, "indirection will not access object of " "non-trivially-copyable type %qT in right " "operand of comma operator", type); break; case ICV_LEFT_OF_COMMA: warning (0, "indirection will not access object of " "non-trivially-copyable type %qT in left " "operand of comma operator", type); break; case ICV_STATEMENT: warning (0, "indirection will not access object of " "non-trivially-copyable type %qT in statement", type); break; case ICV_THIRD_IN_FOR: warning (0, "indirection will not access object of " "non-trivially-copyable type %qT in for " "increment expression", type); break; default: gcc_unreachable (); } } if (is_reference || !is_volatile || !is_complete || TREE_ADDRESSABLE (type)) { /* Emit a warning (if enabled) when the "effect-less" INDIRECT_REF operation is stripped off. Note that we don't warn about - an expression with TREE_NO_WARNING set. (For an example of such expressions, see build_over_call in call.c.) - automatic dereferencing of references, since the user cannot control it. (See also warn_if_unused_value() in stmt.c.) */ if (warn_unused_value && implicit != ICV_CAST && (complain & tf_warning) && !TREE_NO_WARNING (expr) && !is_reference) warning (OPT_Wunused_value, "value computed is not used"); expr = TREE_OPERAND (expr, 0); } break; } case VAR_DECL: { /* External variables might be incomplete. */ tree type = TREE_TYPE (expr); int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning)) switch (implicit) { case ICV_CAST: warning (0, "conversion to void will not access " "object %qE of incomplete type %qT", expr, type); break; case ICV_SECOND_OF_COND: warning (0, "variable %qE of incomplete type %qT will not " "be accessed in second operand of " "conditional expression", expr, type); break; case ICV_THIRD_OF_COND: warning (0, "variable %qE of incomplete type %qT will not " "be accessed in third operand of " "conditional expression", expr, type); break; case ICV_RIGHT_OF_COMMA: warning (0, "variable %qE of incomplete type %qT will not " "be accessed in right operand of comma operator", expr, type); break; case ICV_LEFT_OF_COMMA: warning (0, "variable %qE of incomplete type %qT will not " "be accessed in left operand of comma operator", expr, type); break; case ICV_STATEMENT: warning (0, "variable %qE of incomplete type %qT will not " "be accessed in statement", expr, type); break; case ICV_THIRD_IN_FOR: warning (0, "variable %qE of incomplete type %qT will not " "be accessed in for increment expression", expr, type); break; default: gcc_unreachable (); } break; } case TARGET_EXPR: /* Don't bother with the temporary object returned from a function if we don't use it and don't need to destroy it. We'll still allocate space for it in expand_call or declare_return_variable, but we don't need to track it through all the tree phases. */ if (TARGET_EXPR_IMPLICIT_P (expr) && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (expr))) { tree init = TARGET_EXPR_INITIAL (expr); if (TREE_CODE (init) == AGGR_INIT_EXPR && !AGGR_INIT_VIA_CTOR_P (init)) { tree fn = AGGR_INIT_EXPR_FN (init); expr = build_call_array_loc (input_location, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn, aggr_init_expr_nargs (init), AGGR_INIT_EXPR_ARGP (init)); } } break; default:; } expr = resolve_nondeduced_context (expr); { tree probe = expr; if (TREE_CODE (probe) == ADDR_EXPR) probe = TREE_OPERAND (expr, 0); if (type_unknown_p (probe)) { /* [over.over] enumerates the places where we can take the address of an overloaded function, and this is not one of them. */ if (complain & tf_error) switch (implicit) { case ICV_CAST: error ("conversion to void " "cannot resolve address of overloaded function"); break; case ICV_SECOND_OF_COND: error ("second operand of conditional expression " "cannot resolve address of overloaded function"); break; case ICV_THIRD_OF_COND: error ("third operand of conditional expression " "cannot resolve address of overloaded function"); break; case ICV_RIGHT_OF_COMMA: error ("right operand of comma operator " "cannot resolve address of overloaded function"); break; case ICV_LEFT_OF_COMMA: error ("left operand of comma operator " "cannot resolve address of overloaded function"); break; case ICV_STATEMENT: error ("statement " "cannot resolve address of overloaded function"); break; case ICV_THIRD_IN_FOR: error ("for increment expression " "cannot resolve address of overloaded function"); break; } else return error_mark_node; expr = void_zero_node; } else if (implicit != ICV_CAST && probe == expr && is_overloaded_fn (probe)) { /* Only warn when there is no &. */ if (complain & tf_warning) switch (implicit) { case ICV_SECOND_OF_COND: warning (OPT_Waddress, "second operand of conditional expression " "is a reference, not call, to function %qE", expr); break; case ICV_THIRD_OF_COND: warning (OPT_Waddress, "third operand of conditional expression " "is a reference, not call, to function %qE", expr); break; case ICV_RIGHT_OF_COMMA: warning (OPT_Waddress, "right operand of comma operator " "is a reference, not call, to function %qE", expr); break; case ICV_LEFT_OF_COMMA: warning (OPT_Waddress, "left operand of comma operator " "is a reference, not call, to function %qE", expr); break; case ICV_STATEMENT: warning (OPT_Waddress, "statement is a reference, not call, to function %qE", expr); break; case ICV_THIRD_IN_FOR: warning (OPT_Waddress, "for increment expression " "is a reference, not call, to function %qE", expr); break; default: gcc_unreachable (); } if (TREE_CODE (expr) == COMPONENT_REF) expr = TREE_OPERAND (expr, 0); } } if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) { if (implicit != ICV_CAST && warn_unused_value && !TREE_NO_WARNING (expr) && !processing_template_decl) { /* The middle end does not warn about expressions that have been explicitly cast to void, so we must do so here. */ if (!TREE_SIDE_EFFECTS (expr)) { if (complain & tf_warning) switch (implicit) { case ICV_SECOND_OF_COND: warning (OPT_Wunused_value, "second operand of conditional expression has no effect"); break; case ICV_THIRD_OF_COND: warning (OPT_Wunused_value, "third operand of conditional expression has no effect"); break; case ICV_RIGHT_OF_COMMA: warning (OPT_Wunused_value, "right operand of comma operator has no effect"); break; case ICV_LEFT_OF_COMMA: warning (OPT_Wunused_value, "left operand of comma operator has no effect"); break; case ICV_STATEMENT: warning (OPT_Wunused_value, "statement has no effect"); break; case ICV_THIRD_IN_FOR: warning (OPT_Wunused_value, "for increment expression has no effect"); break; default: gcc_unreachable (); } } else { tree e; enum tree_code code; enum tree_code_class tclass; e = expr; /* We might like to warn about (say) "(int) f()", as the cast has no effect, but the compiler itself will generate implicit conversions under some circumstances. (For example a block copy will be turned into a call to "__builtin_memcpy", with a conversion of the return value to an appropriate type.) So, to avoid false positives, we strip conversions. Do not use STRIP_NOPs because it will not strip conversions to "void", as that is not a mode-preserving conversion. */ while (TREE_CODE (e) == NOP_EXPR) e = TREE_OPERAND (e, 0); code = TREE_CODE (e); tclass = TREE_CODE_CLASS (code); if ((tclass == tcc_comparison || tclass == tcc_unary || (tclass == tcc_binary && !(code == MODIFY_EXPR || code == INIT_EXPR || code == PREDECREMENT_EXPR || code == PREINCREMENT_EXPR || code == POSTDECREMENT_EXPR || code == POSTINCREMENT_EXPR))) && (complain & tf_warning)) warning (OPT_Wunused_value, "value computed is not used"); } } expr = build1 (CONVERT_EXPR, void_type_node, expr); } if (! TREE_SIDE_EFFECTS (expr)) expr = void_zero_node; return expr; }