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