1 /* Declarations relating to class gcc_rich_location
2    Copyright (C) 2014-2020 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #ifndef GCC_RICH_LOCATION_H
21 #define GCC_RICH_LOCATION_H
22 
23 /* A gcc_rich_location is libcpp's rich_location with additional
24    helper methods for working with gcc's types.  */
25 class gcc_rich_location : public rich_location
26 {
27  public:
28   /* Constructors.  */
29 
30   /* Constructing from a location.  */
31   gcc_rich_location (location_t loc, const range_label *label = NULL)
rich_location(line_table,loc,label)32   : rich_location (line_table, loc, label)
33   {
34   }
35 
36   /* Methods for adding ranges via gcc entities.  */
37   void
38   add_expr (tree expr, range_label *label);
39 
40   void
41   maybe_add_expr (tree t, range_label *label);
42 
43   void add_fixit_misspelled_id (location_t misspelled_token_loc,
44 				tree hint_id);
45 
46   /* If LOC is within the spans of lines that will already be printed for
47      this gcc_rich_location, then add it as a secondary location
48      and return true.
49 
50      Otherwise return false.
51 
52      This allows for a diagnostic to compactly print secondary locations
53      in one diagnostic when these are near enough the primary locations for
54      diagnostics-show-locus.c to cope with them, and to fall back to
55      printing them via a note otherwise e.g.:
56 
57 	gcc_rich_location richloc (primary_loc);
58 	bool added secondary = richloc.add_location_if_nearby (secondary_loc);
59 	error_at (&richloc, "main message");
60 	if (!added secondary)
61 	  inform (secondary_loc, "message for secondary");
62 
63      Implemented in diagnostic-show-locus.c.  */
64 
65   bool add_location_if_nearby (location_t loc,
66 			       bool restrict_to_current_line_spans = true,
67 			       const range_label *label = NULL);
68 
69   /* Add a fix-it hint suggesting the insertion of CONTENT before
70      INSERTION_POINT.
71 
72      Attempt to handle formatting: if INSERTION_POINT is the first thing on
73      its line, and INDENT is sufficiently sane, then add CONTENT on its own
74      line, using the indentation of INDENT.
75      Otherwise, add CONTENT directly before INSERTION_POINT.
76 
77      For example, adding "CONTENT;" with the closing brace as the insertion
78      point and using "INDENT;" for indentation:
79 
80        if ()
81          {
82            INDENT;
83          }
84 
85      would lead to:
86 
87        if ()
88          {
89            INDENT;
90            CONTENT;
91          }
92 
93      but adding it to:
94 
95        if () {INDENT;}
96 
97      would lead to:
98 
99        if () {INDENT;CONTENT;}
100   */
101   void add_fixit_insert_formatted (const char *content,
102 				   location_t insertion_point,
103 				   location_t indent);
104 };
105 
106 /* Concrete subclass of libcpp's range_label.
107    Simple implementation using a string literal.  */
108 
109 class text_range_label : public range_label
110 {
111  public:
text_range_label(const char * text)112   text_range_label (const char *text) : m_text (text) {}
113 
get_text(unsigned)114   label_text get_text (unsigned /*range_idx*/) const FINAL OVERRIDE
115   {
116     return label_text::borrow (m_text);
117   }
118 
119  private:
120   const char *m_text;
121 };
122 
123 /* Concrete subclass of libcpp's range_label for use in
124    diagnostics involving mismatched types.
125 
126    Each frontend that uses this should supply its own implementation.
127 
128    Generate a label describing LABELLED_TYPE.  The frontend may use
129    OTHER_TYPE where appropriate for highlighting the differences between
130    the two types (analogous to C++'s use of %H and %I with
131    template types).
132 
133    Either or both of LABELLED_TYPE and OTHER_TYPE may be NULL_TREE.
134    If LABELLED_TYPE is NULL_TREE, then there is no label.
135 
136    For example, this rich_location could use two instances of
137    range_label_for_type_mismatch:
138 
139       printf ("arg0: %i  arg1: %s arg2: %i",
140                                ^~
141                                |
142                                const char *
143               100, 101, 102);
144                    ~~~
145                    |
146                    int
147 
148    (a) the label for "%s" with LABELLED_TYPE for "const char*" and
149    (b) the label for "101" with LABELLED TYPE for "int"
150    where each one uses the other's type as OTHER_TYPE.  */
151 
152 class range_label_for_type_mismatch : public range_label
153 {
154  public:
range_label_for_type_mismatch(tree labelled_type,tree other_type)155   range_label_for_type_mismatch (tree labelled_type, tree other_type)
156   : m_labelled_type (labelled_type), m_other_type (other_type)
157   {
158   }
159 
160   label_text get_text (unsigned range_idx) const OVERRIDE;
161 
162  protected:
163   tree m_labelled_type;
164   tree m_other_type;
165 };
166 
167 /* Subclass of range_label for labelling the type of EXPR when reporting
168    a type mismatch between EXPR and OTHER_EXPR.
169    Either or both of EXPR and OTHER_EXPR could be NULL.  */
170 
171 class maybe_range_label_for_tree_type_mismatch : public range_label
172 {
173  public:
maybe_range_label_for_tree_type_mismatch(tree expr,tree other_expr)174   maybe_range_label_for_tree_type_mismatch (tree expr, tree other_expr)
175   : m_expr (expr), m_other_expr (other_expr)
176   {
177   }
178 
179   label_text get_text (unsigned range_idx) const FINAL OVERRIDE;
180 
181  private:
182   tree m_expr;
183   tree m_other_expr;
184 };
185 
186 class op_location_t;
187 
188 /* A subclass of rich_location for showing problems with binary operations.
189 
190    If enough location information is available, the ctor will make a
191    3-location rich_location of the form:
192 
193      arg_0 op arg_1
194      ~~~~~ ^~ ~~~~~
195        |        |
196        |        arg1 type
197        arg0 type
198 
199    labelling the types of the arguments if SHOW_TYPES is true.
200 
201    Otherwise, it will fall back to a 1-location rich_location using the
202    compound location within LOC:
203 
204      arg_0 op arg_1
205      ~~~~~~^~~~~~~~
206 
207    for which we can't label the types.  */
208 
209 class binary_op_rich_location : public gcc_rich_location
210 {
211  public:
212   binary_op_rich_location (const op_location_t &loc,
213 			   tree arg0, tree arg1,
214 			   bool show_types);
215 
216  private:
217   static bool use_operator_loc_p (const op_location_t &loc,
218 				  tree arg0, tree arg1);
219 
220   maybe_range_label_for_tree_type_mismatch m_label_for_arg0;
221   maybe_range_label_for_tree_type_mismatch m_label_for_arg1;
222 };
223 
224 #endif /* GCC_RICH_LOCATION_H */
225