+2018-12-19 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-12-19 David Malcolm <dmalcolm@redhat.com>
PR c++/43064
+2018-12-19 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-12-19 David Malcolm <dmalcolm@redhat.com>
PR c++/43064
extern void overflow_warning (location_t, tree, tree = NULL_TREE);
extern void warn_logical_operator (location_t, enum tree_code, tree,
enum tree_code, tree, enum tree_code, tree);
-extern void warn_tautological_cmp (location_t, enum tree_code, tree, tree);
+extern void warn_tautological_cmp (const op_location_t &, enum tree_code,
+ tree, tree);
extern void warn_logical_not_parentheses (location_t, enum tree_code, tree,
tree);
extern bool warn_if_unused_value (const_tree, location_t);
if ((TREE_CODE (expr) == ARRAY_REF
|| TREE_CODE (expr) == ARRAY_RANGE_REF)
- && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST)
+ && (TREE_CODE (fold_for_warn (TREE_OPERAND (expr, 1)))
+ == INTEGER_CST))
return integer_type_node;
return NULL_TREE;
of this comparison. */
static void
-warn_tautological_bitwise_comparison (location_t loc, tree_code code,
+warn_tautological_bitwise_comparison (const op_location_t &loc, tree_code code,
tree lhs, tree rhs)
{
if (code != EQ_EXPR && code != NE_EXPR)
if (res == cstw)
return;
+ binary_op_rich_location richloc (loc, lhs, rhs, false);
if (code == EQ_EXPR)
- warning_at (loc, OPT_Wtautological_compare,
+ warning_at (&richloc, OPT_Wtautological_compare,
"bitwise comparison always evaluates to false");
else
- warning_at (loc, OPT_Wtautological_compare,
+ warning_at (&richloc, OPT_Wtautological_compare,
"bitwise comparison always evaluates to true");
}
+/* Given LOC_A and LOC_B from macro expansions, return true if
+ they are "spelled the same" i.e. if they are both directly from
+ expansion of the same non-function-like macro. */
+
+static bool
+spelled_the_same_p (location_t loc_a, location_t loc_b)
+{
+ gcc_assert (from_macro_expansion_at (loc_a));
+ gcc_assert (from_macro_expansion_at (loc_b));
+
+ const line_map_macro *map_a
+ = linemap_check_macro (linemap_lookup (line_table, loc_a));
+
+ const line_map_macro *map_b
+ = linemap_check_macro (linemap_lookup (line_table, loc_b));
+
+ if (map_a->macro == map_b->macro)
+ if (!cpp_fun_like_macro_p (map_a->macro))
+ return true;
+
+ return false;
+}
+
/* Warn if a self-comparison always evaluates to true or false. LOC
is the location of the comparison with code CODE, LHS and RHS are
operands of the comparison. */
void
-warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs)
+warn_tautological_cmp (const op_location_t &loc, enum tree_code code,
+ tree lhs, tree rhs)
{
if (TREE_CODE_CLASS (code) != tcc_comparison)
return;
/* Don't warn for various macro expansions. */
- if (from_macro_expansion_at (loc)
- || from_macro_expansion_at (EXPR_LOCATION (lhs))
- || from_macro_expansion_at (EXPR_LOCATION (rhs)))
+ if (from_macro_expansion_at (loc))
return;
+ bool lhs_in_macro = from_macro_expansion_at (EXPR_LOCATION (lhs));
+ bool rhs_in_macro = from_macro_expansion_at (EXPR_LOCATION (rhs));
+ if (lhs_in_macro || rhs_in_macro)
+ {
+ /* Don't warn if exactly one is from a macro. */
+ if (!(lhs_in_macro && rhs_in_macro))
+ return;
+
+ /* If both are in a macro, only warn if they're spelled the same. */
+ if (!spelled_the_same_p (EXPR_LOCATION (lhs), EXPR_LOCATION (rhs)))
+ return;
+ }
warn_tautological_bitwise_comparison (loc, code, lhs, rhs);
const bool always_true = (code == EQ_EXPR || code == LE_EXPR
|| code == GE_EXPR || code == UNLE_EXPR
|| code == UNGE_EXPR || code == UNEQ_EXPR);
+ binary_op_rich_location richloc (loc, lhs, rhs, false);
if (always_true)
- warning_at (loc, OPT_Wtautological_compare,
+ warning_at (&richloc, OPT_Wtautological_compare,
"self-comparison always evaluates to true");
else
- warning_at (loc, OPT_Wtautological_compare,
+ warning_at (&richloc, OPT_Wtautological_compare,
"self-comparison always evaluates to false");
}
}
+2018-12-19 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-12-11 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/88426
return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
}
-/* Subclass of range_label for labelling the type of EXPR when reporting
- a type mismatch between EXPR and OTHER_EXPR.
- Either or both of EXPR and OTHER_EXPR could be NULL. */
-
-class maybe_range_label_for_tree_type_mismatch : public range_label
-{
- public:
- maybe_range_label_for_tree_type_mismatch (tree expr, tree other_expr)
- : m_expr (expr), m_other_expr (other_expr)
- {
- }
-
- label_text get_text (unsigned range_idx) const FINAL OVERRIDE
- {
- if (m_expr == NULL_TREE
- || !EXPR_P (m_expr))
- return label_text (NULL, false);
- tree expr_type = TREE_TYPE (m_expr);
-
- tree other_type = NULL_TREE;
- if (m_other_expr && EXPR_P (m_other_expr))
- other_type = TREE_TYPE (m_other_expr);
-
- range_label_for_type_mismatch inner (expr_type, other_type);
- return inner.get_text (range_idx);
- }
-
- private:
- tree m_expr;
- tree m_other_expr;
-};
-
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the operator's location.
if (!result_type)
{
- gcc_rich_location richloc (location);
- maybe_range_label_for_tree_type_mismatch
- label_for_op0 (orig_op0, orig_op1),
- label_for_op1 (orig_op1, orig_op0);
- richloc.maybe_add_expr (orig_op0, &label_for_op0);
- richloc.maybe_add_expr (orig_op1, &label_for_op1);
+ /* Favor showing any expression locations that are available. */
+ op_location_t oploc (location, UNKNOWN_LOCATION);
+ binary_op_rich_location richloc (oploc, orig_op0, orig_op1, true);
binary_op_error (&richloc, code, TREE_TYPE (op0), TREE_TYPE (op1));
return error_mark_node;
}
+2018-12-19 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-12-19 David Malcolm <dmalcolm@redhat.com>
PR c++/43064
/*c_cast_p=*/false, (COMPLAIN))
static tree convert_like_real (conversion *, tree, tree, int, bool,
bool, tsubst_flags_t);
-static void op_error (location_t, enum tree_code, enum tree_code, tree,
- tree, tree, bool);
+static void op_error (const op_location_t &, enum tree_code, enum tree_code,
+ tree, tree, tree, bool);
static struct z_candidate *build_user_type_conversion_1 (tree, tree, int,
tsubst_flags_t);
static void print_z_candidate (location_t, const char *, struct z_candidate *);
}
static void
-op_error (location_t loc, enum tree_code code, enum tree_code code2,
+op_error (const op_location_t &loc,
+ enum tree_code code, enum tree_code code2,
tree arg1, tree arg2, tree arg3, bool match)
{
bool assop = code == MODIFY_EXPR;
default:
if (arg2)
if (flag_diagnostics_show_caret)
- error_at (loc, op_error_string (G_("%<operator%s%>"), 2, match),
- opname, TREE_TYPE (arg1), TREE_TYPE (arg2));
+ {
+ binary_op_rich_location richloc (loc, arg1, arg2, true);
+ error_at (&richloc,
+ op_error_string (G_("%<operator%s%>"), 2, match),
+ opname, TREE_TYPE (arg1), TREE_TYPE (arg2));
+ }
else
error_at (loc, op_error_string (G_("%<operator%s%> in %<%E %s %E%>"),
2, match),
arguments to the conditional expression. */
static tree
-build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
+build_conditional_expr_1 (const op_location_t &loc,
+ tree arg1, tree arg2, tree arg3,
tsubst_flags_t complain)
{
tree arg2_type;
/* Wrapper for above. */
tree
-build_conditional_expr (location_t loc, tree arg1, tree arg2, tree arg3,
+build_conditional_expr (const op_location_t &loc,
+ tree arg1, tree arg2, tree arg3,
tsubst_flags_t complain)
{
tree ret;
}
static tree
-build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
- tree arg2, tree arg3, tree *overload, tsubst_flags_t complain)
+build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
+ tree arg1, tree arg2, tree arg3, tree *overload,
+ tsubst_flags_t complain)
{
struct z_candidate *candidates = 0, *cand;
vec<tree, va_gc> *arglist;
/* Wrapper for above. */
tree
-build_new_op (location_t loc, enum tree_code code, int flags,
+build_new_op (const op_location_t &loc, enum tree_code code, int flags,
tree arg1, tree arg2, tree arg3,
tree *overload, tsubst_flags_t complain)
{
extern bool check_dtor_name (tree, tree);
int magic_varargs_p (tree);
-extern tree build_conditional_expr (location_t, tree, tree, tree,
+extern tree build_conditional_expr (const op_location_t &,
+ tree, tree, tree,
tsubst_flags_t);
extern tree build_addr_func (tree, tsubst_flags_t);
extern void set_flags_from_callee (tree);
extern tree build_special_member_call (tree, tree,
vec<tree, va_gc> **,
tree, int, tsubst_flags_t);
-extern tree build_new_op (location_t, enum tree_code,
+extern tree build_new_op (const op_location_t &,
+ enum tree_code,
int, tree, tree, tree, tree *,
tsubst_flags_t);
extern tree build_op_call (tree, vec<tree, va_gc> **,
ATTRIBUTE_SENTINEL;
extern tree cp_build_function_call_vec (tree, vec<tree, va_gc> **,
tsubst_flags_t);
-extern tree build_x_binary_op (location_t,
+extern tree build_x_binary_op (const op_location_t &,
enum tree_code, tree,
enum tree_code, tree,
enum tree_code, tree *,
extern tree merge_types (tree, tree);
extern tree strip_array_domain (tree);
extern tree check_return_expr (tree, bool *);
-extern tree cp_build_binary_op (location_t,
+extern tree cp_build_binary_op (const op_location_t &,
enum tree_code, tree, tree,
tsubst_flags_t);
extern tree build_x_vec_perm_expr (location_t,
id_expression.get_location ()));
if (error_msg)
cp_parser_error (parser, error_msg);
- decl.set_location (id_expression.get_location ());
- decl.set_range (id_expr_token->location, id_expression.get_finish ());
+ /* Build a location for an id-expression of the form:
+ ::ns::id
+ ~~~~~~^~
+ or:
+ id
+ ^~
+ i.e. from the start of the first token to the end of the final
+ token, with the caret at the start of the unqualified-id. */
+ location_t caret_loc = get_pure_location (id_expression.get_location ());
+ location_t start_loc = get_start (id_expr_token->location);
+ location_t finish_loc = get_finish (id_expression.get_location ());
+ location_t combined_loc
+ = make_location (caret_loc, start_loc, finish_loc);
+
+ decl.set_location (combined_loc);
return decl;
}
}
else
{
- current.lhs = build_x_binary_op (combined_loc, current.tree_type,
+ op_location_t op_loc (current.loc, combined_loc);
+ current.lhs = build_x_binary_op (op_loc, current.tree_type,
current.lhs, current.lhs_type,
rhs, rhs_type, &overload,
complain_flags (decltype_p));
const char *name = IDENTIFIER_POINTER (id);
id = cp_literal_operator_id (name);
}
- start_loc = make_location (start_loc, start_loc, get_finish (end_loc));
- return cp_expr (id, start_loc);
+ /* Generate a location of the form:
+ "" _suffix_identifier
+ ^~~~~~~~~~~~~~~~~~~~~
+ with caret == start at the start token, finish at the end of the
+ suffix identifier. */
+ location_t finish_loc
+ = get_finish (cp_lexer_previous_token (parser->lexer)->location);
+ location_t combined_loc
+ = make_location (start_loc, start_loc, finish_loc);
+ return cp_expr (id, combined_loc);
}
default:
ARG2_CODE as ERROR_MARK. */
tree
-build_x_binary_op (location_t loc, enum tree_code code, tree arg1,
+build_x_binary_op (const op_location_t &loc, enum tree_code code, tree arg1,
enum tree_code arg1_code, tree arg2,
enum tree_code arg2_code, tree *overload_p,
tsubst_flags_t complain)
multiple inheritance, and deal with pointer to member functions. */
tree
-cp_build_binary_op (location_t location,
+cp_build_binary_op (const op_location_t &location,
enum tree_code code, tree orig_op0, tree orig_op1,
tsubst_flags_t complain)
{
if (!result_type)
{
if (complain & tf_error)
- error_at (location,
- "invalid operands of types %qT and %qT to binary %qO",
- TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
+ {
+ binary_op_rich_location richloc (location,
+ orig_op0, orig_op1, true);
+ error_at (&richloc,
+ "invalid operands of types %qT and %qT to binary %qO",
+ TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
+ }
return error_mark_node;
}
else
add_fixit_insert_before (insertion_point, content);
}
+
+/* Implementation of range_label::get_text for
+ maybe_range_label_for_tree_type_mismatch.
+
+ If both expressions are non-NULL, then generate text describing
+ the first expression's type (using the other expression's type
+ for comparison, analogous to %H and %I in the C++ frontend, but
+ on expressions rather than types). */
+
+label_text
+maybe_range_label_for_tree_type_mismatch::get_text (unsigned range_idx) const
+{
+ if (m_expr == NULL_TREE
+ || !EXPR_P (m_expr))
+ return label_text (NULL, false);
+ tree expr_type = TREE_TYPE (m_expr);
+
+ tree other_type = NULL_TREE;
+ if (m_other_expr && EXPR_P (m_other_expr))
+ other_type = TREE_TYPE (m_other_expr);
+
+ range_label_for_type_mismatch inner (expr_type, other_type);
+ return inner.get_text (range_idx);
+}
+
+/* binary_op_rich_location's ctor.
+
+ If use_operator_loc_p (LOC, ARG0, ARG1), then attempt to make a 3-location
+ rich_location of the form:
+
+ arg_0 op arg_1
+ ~~~~~ ^~ ~~~~~
+ | |
+ | arg1 type
+ arg0 type
+
+ labelling the types of the arguments if SHOW_TYPES is true.
+
+ Otherwise, make a 1-location rich_location using the compound
+ location within LOC:
+
+ arg_0 op arg_1
+ ~~~~~~^~~~~~~~
+
+ for which we can't label the types. */
+
+binary_op_rich_location::binary_op_rich_location (const op_location_t &loc,
+ tree arg0, tree arg1,
+ bool show_types)
+: gcc_rich_location (loc.m_combined_loc),
+ m_label_for_arg0 (arg0, arg1),
+ m_label_for_arg1 (arg1, arg0)
+{
+ /* Default (above) to using the combined loc.
+ Potentially override it here: if we have location information for the
+ operator and for both arguments, then split them all out.
+ Alternatively, override it if we don't have the combined location. */
+ if (use_operator_loc_p (loc, arg0, arg1))
+ {
+ set_range (0, loc.m_operator_loc, SHOW_RANGE_WITH_CARET);
+ maybe_add_expr (arg0, show_types ? &m_label_for_arg0 : NULL);
+ maybe_add_expr (arg1, show_types ? &m_label_for_arg1 : NULL);
+ }
+}
+
+/* Determine if binary_op_rich_location's ctor should attempt to make
+ a 3-location rich_location (the location of the operator and of
+ the 2 arguments), or fall back to a 1-location rich_location showing
+ just the combined location of the operation as a whole. */
+
+bool
+binary_op_rich_location::use_operator_loc_p (const op_location_t &loc,
+ tree arg0, tree arg1)
+{
+ /* If we don't have a combined location, then use the operator location,
+ and try to add ranges for the operators. */
+ if (loc.m_combined_loc == UNKNOWN_LOCATION)
+ return true;
+
+ /* If we don't have the operator location, then use the
+ combined location. */
+ if (loc.m_operator_loc == UNKNOWN_LOCATION)
+ return false;
+
+ /* We have both operator location and combined location: only use the
+ operator location if we have locations for both arguments. */
+ return (EXPR_HAS_LOCATION (arg0)
+ && EXPR_HAS_LOCATION (arg1));
+}
tree m_other_type;
};
+/* Subclass of range_label for labelling the type of EXPR when reporting
+ a type mismatch between EXPR and OTHER_EXPR.
+ Either or both of EXPR and OTHER_EXPR could be NULL. */
+
+class maybe_range_label_for_tree_type_mismatch : public range_label
+{
+ public:
+ maybe_range_label_for_tree_type_mismatch (tree expr, tree other_expr)
+ : m_expr (expr), m_other_expr (other_expr)
+ {
+ }
+
+ label_text get_text (unsigned range_idx) const FINAL OVERRIDE;
+
+ private:
+ tree m_expr;
+ tree m_other_expr;
+};
+
+struct op_location_t;
+
+/* A subclass of rich_location for showing problems with binary operations.
+
+ If enough location information is available, the ctor will make a
+ 3-location rich_location of the form:
+
+ arg_0 op arg_1
+ ~~~~~ ^~ ~~~~~
+ | |
+ | arg1 type
+ arg0 type
+
+ labelling the types of the arguments if SHOW_TYPES is true.
+
+ Otherwise, it will fall back to a 1-location rich_location using the
+ compound location within LOC:
+
+ arg_0 op arg_1
+ ~~~~~~^~~~~~~~
+
+ for which we can't label the types. */
+
+class binary_op_rich_location : public gcc_rich_location
+{
+ public:
+ binary_op_rich_location (const op_location_t &loc,
+ tree arg0, tree arg1,
+ bool show_types);
+
+ private:
+ static bool use_operator_loc_p (const op_location_t &loc,
+ tree arg0, tree arg1);
+
+ maybe_range_label_for_tree_type_mismatch m_label_for_arg0;
+ maybe_range_label_for_tree_type_mismatch m_label_for_arg1;
+};
+
#endif /* GCC_RICH_LOCATION_H */
+2018-12-19 David Malcolm <dmalcolm@redhat.com>
+
+ * 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.
+
2018-12-19 David Malcolm <dmalcolm@redhat.com>
PR c++/43064
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-Wtautological-compare -fdiagnostics-show-caret" } */
+
+#define FOO foo
+
+void
+fn1 (int foo)
+{
+ if (foo == foo); /* { dg-warning "self-comparison always evaluates to true" } */
+ /* { dg-begin-multiline-output "" }
+ if (foo == foo);
+ ^~
+ { dg-end-multiline-output "" { target c } } */
+ /* { dg-begin-multiline-output "" }
+ if (foo == foo);
+ ~~~ ^~ ~~~
+ { dg-end-multiline-output "" { target c++ } } */
+}
+
+void
+fn2 (int foo)
+{
+ if (FOO == FOO); /* { dg-warning "self-comparison always evaluates to true" } */
+ /* { dg-begin-multiline-output "" }
+ if (FOO == FOO);
+ ^~
+ { dg-end-multiline-output "" } */
+}
+
+void
+fn3 (int foo)
+{
+ if ((foo & 16) == 10); /* { dg-warning "bitwise comparison always evaluates to false" } */
+ /* { dg-begin-multiline-output "" }
+ if ((foo & 16) == 10);
+ ^~
+ { dg-end-multiline-output "" { target c } } */
+ /* { dg-begin-multiline-output "" }
+ if ((foo & 16) == 10);
+ ~~~~~~~~~~ ^~ ~~
+ { dg-end-multiline-output "" { target c++ } } */
+}
// { dg-do compile { target c++11 } }
+// { dg-options "-fdiagnostics-show-caret" }
void
foo()
{
float x = operator"" _F(); // { dg-error "13:'operator\"\"_F' was not declared in this scope" }
+ /* { dg-begin-multiline-output "" }
+ float x = operator"" _F();
+ ^~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
float y = 0_F; // { dg-error "unable to find numeric literal operator" }
+ /* { dg-begin-multiline-output "" }
+ float y = 0_F;
+ ^~~
+ { dg-end-multiline-output "" } */
}
/* { dg-begin-multiline-output "" }
myvec[1] / ptr;
- ~~~~~~~~~^~~~~
+ ~~~~~~~~ ^ ~~~
+ | |
+ | const int*
+ __m128 {aka float}
{ dg-end-multiline-output "" } */
}
/* { dg-begin-multiline-output "" }
return (some_function ()
~~~~~~~~~~~~~~~~
+ |
+ s
+ some_other_function ());
- ^~~~~~~~~~~~~~~~~~~~~~~~
+ ^ ~~~~~~~~~~~~~~~~~~~~~~
+ |
+ t
{ dg-end-multiline-output "" } */
}
{
return param_s && param_t; // { dg-error "no match for .operator" }
+/* { dg-begin-multiline-output "" }
+ return param_s && param_t;
+ ~~~~~~~ ^~ ~~~~~~~
+ | |
+ s t
+ { dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
return param_s && param_t;
~~~~~~~~^~~~~~~~~~
{ dg-end-multiline-output "" } */
}
+
+namespace ns_4
+{
+ struct s foo;
+ namespace inner {
+ struct t bar;
+ };
+};
+
+int test_4a (void)
+{
+ return ns_4::foo && ns_4::inner::bar; // { dg-error "no match for .operator" }
+ /* { dg-begin-multiline-output "" }
+ return ns_4::foo && ns_4::inner::bar;
+ ~~~~~~~~~ ^~ ~~~~~~~~~~~~~~~~
+ | |
+ s t
+ { dg-end-multiline-output "" } */
+
+ /* { dg-begin-multiline-output "" }
+ return ns_4::foo && ns_4::inner::bar;
+ ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+int test_4b (void)
+{
+ return ::ns_4::foo && ns_4::inner::bar; // { dg-error "no match for .operator" }
+ /* { dg-begin-multiline-output "" }
+ return ::ns_4::foo && ns_4::inner::bar;
+ ~~~~~~~~~~~ ^~ ~~~~~~~~~~~~~~~~
+ | |
+ s t
+ { dg-end-multiline-output "" } */
+
+ /* { dg-begin-multiline-output "" }
+ return ::ns_4::foo && ns_4::inner::bar;
+ ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+}
return v10_a - v10_b; // { dg-error "no match for" }
/* { dg-begin-multiline-output "" }
return v10_a - v10_b;
- ~~~~~~^~~~~~~
+ ~~~~~ ^ ~~~~~
+ | |
+ s10 s10
{ dg-end-multiline-output "" } */
// { dg-message "candidate" "" { target *-*-* } s10_operator }
/* { dg-begin-multiline-output "" }
&& DECL_FUNCTION_CODE (node) == name);
}
+/* A struct for encapsulating location information about an operator
+ and the operation built from it.
+
+ m_operator_loc is the location of the operator
+ m_combined_loc is the location of the compound expression.
+
+ For example, given "a && b" the, operator location is:
+ a && b
+ ^~
+ and the combined location is:
+ a && b
+ ~~^~~~
+ Capturing this information allows for class binary_op_rich_location
+ to provide detailed information about e.g. type mismatches in binary
+ operations where enough location information is available:
+
+ arg_0 op arg_1
+ ~~~~~ ^~ ~~~~~
+ | |
+ | arg1 type
+ arg0 type
+
+ falling back to just showing the combined location:
+
+ arg_0 op arg_1
+ ~~~~~~^~~~~~~~
+
+ where it is not. */
+
+struct op_location_t
+{
+ location_t m_operator_loc;
+ location_t m_combined_loc;
+
+ /* 1-argument ctor, for constructing from a combined location. */
+ op_location_t (location_t combined_loc)
+ : m_operator_loc (UNKNOWN_LOCATION), m_combined_loc (combined_loc)
+ {}
+
+ /* 2-argument ctor, for distinguishing between the operator's location
+ and the combined location. */
+ op_location_t (location_t operator_loc, location_t combined_loc)
+ : m_operator_loc (operator_loc), m_combined_loc (combined_loc)
+ {}
+
+ /* Implicitly convert back to a location_t, using the combined location. */
+ operator location_t () const { return m_combined_loc; }
+};
+
#endif /* GCC_TREE_H */