Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- We crash while we call warning_at ("inline function used but never defined") since it invokes dump_template_bindings -> tsubst -> ... -> convert_like -> ... -> c_common_truthvalue_conversion -> warning_at ("enum constant in boolean context")
cp_truthvalue_conversion correctly gets complain=0 but it calls c_common_truthvalue_conversion from c-family which doesn't have a similar parameter. PR c++/119303 gcc/c-family/ChangeLog: * c-common.cc (c_common_truthvalue_conversion): New complain parameter. Use it. * c-common.h (c_common_truthvalue_conversion): New parameter with a default argument. gcc/cp/ChangeLog: * typeck.cc (cp_truthvalue_conversion): Pass complain to c_common_truthvalue_conversion. gcc/testsuite/ChangeLog: * g++.dg/warn/undefined2.C: New test. --- gcc/c-family/c-common.cc | 76 +++++++++++++++++--------- gcc/c-family/c-common.h | 2 +- gcc/cp/typeck.cc | 2 +- gcc/testsuite/g++.dg/warn/undefined2.C | 14 +++++ 4 files changed, 65 insertions(+), 29 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/undefined2.C diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 587d76461e9..cefba2f5f44 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -3551,7 +3551,8 @@ decl_with_nonnull_addr_p (const_tree expr) have been validated to be of suitable type; otherwise, a bad diagnostic may result. - The EXPR is located at LOCATION. + The EXPR is located at LOCATION. COMPLAIN controls whether we should + diagnose possibly ill-formed constructs or not. This preparation consists of taking the ordinary representation of an expression expr and producing a valid tree @@ -3562,7 +3563,8 @@ decl_with_nonnull_addr_p (const_tree expr) The resulting type should always be `truthvalue_type_node'. */ tree -c_common_truthvalue_conversion (location_t location, tree expr) +c_common_truthvalue_conversion (location_t location, tree expr, + bool complain/*=true*/) { STRIP_ANY_LOCATION_WRAPPER (expr); switch (TREE_CODE (expr)) @@ -3586,9 +3588,11 @@ c_common_truthvalue_conversion (location_t location, tree expr) return expr; expr = build2 (TREE_CODE (expr), truthvalue_type_node, c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 0)), + TREE_OPERAND (expr, 0), + complain), c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 1))); + TREE_OPERAND (expr, 1), + complain)); goto ret; case TRUTH_NOT_EXPR: @@ -3596,7 +3600,8 @@ c_common_truthvalue_conversion (location_t location, tree expr) return expr; expr = build1 (TREE_CODE (expr), truthvalue_type_node, c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 0))); + TREE_OPERAND (expr, 0), + complain)); goto ret; case ERROR_MARK: @@ -3605,7 +3610,8 @@ c_common_truthvalue_conversion (location_t location, tree expr) case INTEGER_CST: if (TREE_CODE (TREE_TYPE (expr)) == ENUMERAL_TYPE && !integer_zerop (expr) - && !integer_onep (expr)) + && !integer_onep (expr) + && complain) warning_at (location, OPT_Wint_in_bool_context, "enum constant in boolean context"); return integer_zerop (expr) ? truthvalue_false_node @@ -3630,6 +3636,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) { tree inner = TREE_OPERAND (expr, 0); if (decl_with_nonnull_addr_p (inner) + && complain /* Check both EXPR and INNER for suppression. */ && !warning_suppressed_p (expr, OPT_Waddress) && !warning_suppressed_p (inner, OPT_Waddress)) @@ -3650,9 +3657,11 @@ c_common_truthvalue_conversion (location_t location, tree expr) (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)) ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 0)), + TREE_OPERAND (expr, 0), + complain), c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 1)), + TREE_OPERAND (expr, 1), + complain), false); goto ret; @@ -3662,7 +3671,8 @@ c_common_truthvalue_conversion (location_t location, tree expr) case FLOAT_EXPR: case EXCESS_PRECISION_EXPR: /* These don't change whether an object is nonzero or zero. */ - return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0)); + return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0), + complain); case LROTATE_EXPR: case RROTATE_EXPR: @@ -3673,16 +3683,18 @@ c_common_truthvalue_conversion (location_t location, tree expr) expr = build2 (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1), c_common_truthvalue_conversion - (location, TREE_OPERAND (expr, 0))); + (location, TREE_OPERAND (expr, 0), complain)); goto ret; } else return c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 0)); + TREE_OPERAND (expr, 0), + complain); case MULT_EXPR: - warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context, - "%<*%> in boolean context, suggest %<&&%> instead"); + if (complain) + warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context, + "%<*%> in boolean context, suggest %<&&%> instead"); break; case LSHIFT_EXPR: @@ -3693,7 +3705,8 @@ c_common_truthvalue_conversion (location_t location, tree expr) result of the shift is not subject to integer promotion rules. */ if ((TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE || TREE_CODE (TREE_TYPE (expr)) == BITINT_TYPE) - && !TYPE_UNSIGNED (TREE_TYPE (expr))) + && !TYPE_UNSIGNED (TREE_TYPE (expr)) + && complain) warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context, "%<<<%> in boolean context, did you mean %<<%>?"); break; @@ -3709,16 +3722,18 @@ c_common_truthvalue_conversion (location_t location, tree expr) && !integer_zerop (val1) && !integer_zerop (val2) && (!integer_onep (val1) - || !integer_onep (val2))) + || !integer_onep (val2)) + && complain) warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context, "%<?:%> using integer constants in boolean context, " "the expression will always evaluate to %<true%>"); - else if ((TREE_CODE (val1) == INTEGER_CST - && !integer_zerop (val1) - && !integer_onep (val1)) - || (TREE_CODE (val2) == INTEGER_CST - && !integer_zerop (val2) - && !integer_onep (val2))) + else if (((TREE_CODE (val1) == INTEGER_CST + && !integer_zerop (val1) + && !integer_onep (val1)) + || (TREE_CODE (val2) == INTEGER_CST + && !integer_zerop (val2) + && !integer_onep (val2))) + && complain) warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context, "%<?:%> using integer constants in boolean context"); } @@ -3734,9 +3749,11 @@ c_common_truthvalue_conversion (location_t location, tree expr) expr = build3 (COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0), c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 1)), + TREE_OPERAND (expr, 1), + complain), c_common_truthvalue_conversion (location, - TREE_OPERAND (expr, 2))); + TREE_OPERAND (expr, 2), + complain)); warn_int_in_bool_context = w; goto ret; } @@ -3748,6 +3765,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) if (POINTER_TYPE_P (totype) && !c_inhibit_evaluation_warnings + && complain && TREE_CODE (fromtype) == REFERENCE_TYPE) { tree inner = expr; @@ -3783,7 +3801,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) any suppression from the enclosing expression to its operand. */ suppress_warning (op0, OPT_Waddress); - return c_common_truthvalue_conversion (location, op0); + return c_common_truthvalue_conversion (location, op0, complain); } } break; @@ -3791,6 +3809,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) case MODIFY_EXPR: if (!warning_suppressed_p (expr, OPT_Wparentheses) && warn_parentheses + && complain && warning_at (location, OPT_Wparentheses, "suggest parentheses around assignment used as " "truth value")) @@ -3801,7 +3820,8 @@ c_common_truthvalue_conversion (location_t location, tree expr) { tree folded_expr = fold_for_warn (expr); if (folded_expr != expr) - return c_common_truthvalue_conversion (location, folded_expr); + return c_common_truthvalue_conversion (location, folded_expr, + complain); } break; @@ -3818,10 +3838,12 @@ c_common_truthvalue_conversion (location_t location, tree expr) ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), c_common_truthvalue_conversion (location, - build_unary_op (location, REALPART_EXPR, t, false)), + build_unary_op (location, REALPART_EXPR, t, false), + complain), c_common_truthvalue_conversion (location, - build_unary_op (location, IMAGPART_EXPR, t, false)), + build_unary_op (location, IMAGPART_EXPR, t, false), + complain), false)); goto ret; } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index ea6c2975056..b8eb3f49958 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -886,7 +886,7 @@ extern enum conversion_safety unsafe_conversion_p (tree, tree, tree, bool); extern bool decl_with_nonnull_addr_p (const_tree); extern tree c_fully_fold (tree, bool, bool *, bool = false); extern tree c_wrap_maybe_const (tree, bool); -extern tree c_common_truthvalue_conversion (location_t, tree); +extern tree c_common_truthvalue_conversion (location_t, tree, bool = true); extern void c_apply_type_quals_to_decl (int, tree); extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int); extern tree c_alignof_expr (location_t, tree); diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 4b382b95de1..cc6f95c14ca 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -7114,7 +7114,7 @@ cp_truthvalue_conversion (tree expr, tsubst_flags_t complain) || TREE_CODE (expr) == FUNCTION_DECL) return cp_build_binary_op (loc, NE_EXPR, expr, nullptr_node, complain); else - return c_common_truthvalue_conversion (loc, expr); + return c_common_truthvalue_conversion (loc, expr, bool (complain)); } /* Returns EXPR contextually converted to bool. */ diff --git a/gcc/testsuite/g++.dg/warn/undefined2.C b/gcc/testsuite/g++.dg/warn/undefined2.C new file mode 100644 index 00000000000..1b2ec353adb --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/undefined2.C @@ -0,0 +1,14 @@ +// PR c++/119303 + +template <class> struct c { + enum { d = 4 }; +}; +template <bool> struct e { + typedef void g; +}; +template <class _Tp> +inline typename e<!c<_Tp>::d>::g bar(_Tp); // { dg-warning "used but never defined" } + +int x; + +void foo() { bar(x); } base-commit: 8e0e17677afc1a93aa31b8b83849848b7bb52b9b -- 2.48.1