https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87504

--- Comment #2 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
Author: dmalcolm
Date: Wed Dec 19 15:15:42 2018
New Revision: 267273

URL: https://gcc.gnu.org/viewcvs?rev=267273&root=gcc&view=rev
Log:
C++: improvements to binary operator diagnostics (PR c++/87504)

The C frontend is able (where expression locations are available) to print
problems with binary operators in 3-location form, labelling the types of
the expressions:

  arg_0 op arg_1
  ~~~~~ ^~ ~~~~~
    |        |
    |        arg1 type
    arg0 type

The C++ frontend currently just shows the combined location:

  arg_0 op arg_1
  ~~~~~~^~~~~~~~

and fails to highlight where the subexpressions are, or their types.

This patch introduces a op_location_t struct for handling the above
operator-location vs combined-location split, and a new
class binary_op_rich_location for displaying the above, so that the
C++ frontend is able to use the more detailed 3-location form for
type mismatches in binary operators, and for -Wtautological-compare
(where types are not displayed).  Both forms can be seen in this
example:

bad-binary-ops.C:69:20: error: no match for 'operator&&' (operand types are
  's' and 't')
   69 |   return ns_4::foo && ns_4::inner::bar;
      |          ~~~~~~~~~ ^~ ~~~~~~~~~~~~~~~~
      |                |                   |
      |                s                   t
bad-binary-ops.C:69:20: note: candidate: 'operator&&(bool, bool)' <built-in>
   69 |   return ns_4::foo && ns_4::inner::bar;
      |          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~

The patch also allows for some uses of macros in
-Wtautological-compare, where both sides of the comparison have
been spelled the same way, e.g.:

Wtautological-compare-ranges.c:23:11: warning: self-comparison always
   evaluates to true [-Wtautological-compare]
   23 |   if (FOO == FOO);
      |           ^~

gcc/c-family/ChangeLog:
        PR c++/87504
        * c-common.h (warn_tautological_cmp): Convert 1st param from
        location_t to const op_location_t &.
        * c-warn.c (find_array_ref_with_const_idx_r): Call fold_for_warn
        when testing for INTEGER_CST.
        (warn_tautological_bitwise_comparison): Convert 1st param from
        location_t to const op_location_t &; use it to build a
        binary_op_rich_location, and use this.
        (spelled_the_same_p): New function.
        (warn_tautological_cmp): Convert 1st param from location_t to
        const op_location_t &.  Warn for macro expansions if
        spelled_the_same_p.  Use binary_op_rich_location.

gcc/c/ChangeLog:
        PR c++/87504
        * c-typeck.c (class maybe_range_label_for_tree_type_mismatch):
        Move from here to gcc-rich-location.h and gcc-rich-location.c.
        (build_binary_op): Use struct op_location_t and
        class binary_op_rich_location.

gcc/cp/ChangeLog:
        PR c++/87504
        * call.c (op_error): Convert 1st param from location_t to
        const op_location_t &.  Use binary_op_rich_location for binary
        ops.
        (build_conditional_expr_1): Convert 1st param from location_t to
        const op_location_t &.
        (build_conditional_expr): Likewise.
        (build_new_op_1): Likewise.
        (build_new_op): Likewise.
        * cp-tree.h (build_conditional_expr): Likewise.
        (build_new_op): Likewise.
        (build_x_binary_op): Likewise.
        (cp_build_binary_op): Likewise.
        * parser.c (cp_parser_primary_expression): Build a location
        for id-expression nodes.
        (cp_parser_binary_expression): Use an op_location_t when
        calling build_x_binary_op.
        (cp_parser_operator): Build a location for user-defined literals.
        * typeck.c (build_x_binary_op): Convert 1st param from location_t
        to const op_location_t &.
        (cp_build_binary_op): Likewise.  Use binary_op_rich_location.

gcc/ChangeLog:
        PR c++/87504
        * gcc-rich-location.c
        (maybe_range_label_for_tree_type_mismatch::get_text): Move here from
        c/c-typeck.c.
        (binary_op_rich_location::binary_op_rich_location): New ctor.
        (binary_op_rich_location::use_operator_loc_p): New function.
        * gcc-rich-location.h
        (class maybe_range_label_for_tree_type_mismatch)): Move here from
        c/c-typeck.c.
        (struct op_location_t): New forward decl.
        (class binary_op_rich_location): New class.
        * tree.h (struct op_location_t): New struct.

gcc/testsuite/ChangeLog:
        * c-c++-common/Wtautological-compare-ranges.c: New test.
        * g++.dg/cpp0x/pr51420.C: Add -fdiagnostics-show-caret and update
        expected output.
        * g++.dg/diagnostic/bad-binary-ops.C: Update expected output from
        1-location form to 3-location form, with labelling of ranges with
        types.  Add examples of id-expression nodes with namespaces.
        * g++.dg/diagnostic/param-type-mismatch-2.C: Likewise.


Added:
    trunk/gcc/testsuite/c-c++-common/Wtautological-compare-ranges.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/c-family/ChangeLog
    trunk/gcc/c-family/c-common.h
    trunk/gcc/c-family/c-warn.c
    trunk/gcc/c/ChangeLog
    trunk/gcc/c/c-typeck.c
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/parser.c
    trunk/gcc/cp/typeck.c
    trunk/gcc/gcc-rich-location.c
    trunk/gcc/gcc-rich-location.h
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/cpp0x/pr51420.C
    trunk/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C
    trunk/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
    trunk/gcc/tree.h

Reply via email to