aboutsummaryrefslogtreecommitdiff
path: root/gcc/gcc-rich-location.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gcc-rich-location.c')
-rw-r--r--gcc/gcc-rich-location.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/gcc/gcc-rich-location.c b/gcc/gcc-rich-location.c
index 81beb61..25a604f 100644
--- a/gcc/gcc-rich-location.c
+++ b/gcc/gcc-rich-location.c
@@ -182,3 +182,92 @@ gcc_rich_location::add_fixit_insert_formatted (const char *content,
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));
+}