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

Reply via email to