xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/doc/ux.texi (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1*4c3eb207Smrg@c Copyright (C) 2018-2020 Free Software Foundation, Inc.
2627f7eb2Smrg@c Free Software Foundation, Inc.
3627f7eb2Smrg@c This is part of the GCC manual.
4627f7eb2Smrg@c For copying conditions, see the file gcc.texi.
5627f7eb2Smrg
6627f7eb2Smrg@node User Experience Guidelines
7627f7eb2Smrg@chapter User Experience Guidelines
8627f7eb2Smrg@cindex user experience guidelines
9627f7eb2Smrg@cindex guidelines, user experience
10627f7eb2Smrg
11627f7eb2SmrgTo borrow a slogan from
12*4c3eb207Smrg@uref{https://elm-lang.org/news/compilers-as-assistants, Elm},
13627f7eb2Smrg
14627f7eb2Smrg@quotation
15627f7eb2Smrg@strong{Compilers should be assistants, not adversaries.}  A compiler should
16627f7eb2Smrgnot just detect bugs, it should then help you understand why there is a bug.
17627f7eb2SmrgIt should not berate you in a robot voice, it should give you specific hints
18627f7eb2Smrgthat help you write better code. Ultimately, a compiler should make
19627f7eb2Smrgprogramming faster and more fun!
20627f7eb2Smrg@author Evan Czaplicki
21627f7eb2Smrg@end quotation
22627f7eb2Smrg
23627f7eb2SmrgThis chapter provides guidelines on how to implement diagnostics and
24627f7eb2Smrgcommand-line options in ways that we hope achieve the above ideal.
25627f7eb2Smrg
26627f7eb2Smrg@menu
27627f7eb2Smrg* Guidelines for Diagnostics::       How to implement diagnostics.
28627f7eb2Smrg* Guidelines for Options::           Guidelines for command-line options.
29627f7eb2Smrg@end menu
30627f7eb2Smrg
31627f7eb2Smrg
32627f7eb2Smrg@node Guidelines for Diagnostics
33627f7eb2Smrg@section Guidelines for Diagnostics
34627f7eb2Smrg@cindex guidelines for diagnostics
35627f7eb2Smrg@cindex diagnostics, guidelines for
36627f7eb2Smrg
37627f7eb2Smrg@subsection Talk in terms of the user's code
38627f7eb2Smrg
39627f7eb2SmrgDiagnostics should be worded in terms of the user's source code, and the
40627f7eb2Smrgsource language, rather than GCC's own implementation details.
41627f7eb2Smrg
42627f7eb2Smrg@subsection Diagnostics are actionable
43627f7eb2Smrg@cindex diagnostics, actionable
44627f7eb2Smrg
45627f7eb2SmrgA good diagnostic is @dfn{actionable}: it should assist the user in
46627f7eb2Smrgtaking action.
47627f7eb2Smrg
48627f7eb2SmrgConsider what an end user will want to do when encountering a diagnostic.
49627f7eb2Smrg
50627f7eb2SmrgGiven an error, an end user will think: ``How do I fix this?''
51627f7eb2Smrg
52627f7eb2SmrgGiven a warning, an end user will think:
53627f7eb2Smrg
54627f7eb2Smrg@itemize @bullet
55627f7eb2Smrg@item
56627f7eb2Smrg``Is this a real problem?''
57627f7eb2Smrg@item
58627f7eb2Smrg``Do I care?''
59627f7eb2Smrg@item
60627f7eb2Smrgif they decide it's genuine: ``How do I fix this?''
61627f7eb2Smrg@end itemize
62627f7eb2Smrg
63627f7eb2SmrgA good diagnostic provides pertinent information to allow the user to
64627f7eb2Smrgeasily answer the above questions.
65627f7eb2Smrg
66627f7eb2Smrg@subsection The user's attention is important
67627f7eb2Smrg
68627f7eb2SmrgA perfect compiler would issue a warning on every aspect of the user's
69627f7eb2Smrgsource code that ought to be fixed, and issue no other warnings.
70627f7eb2SmrgNaturally, this ideal is impossible to achieve.
71627f7eb2Smrg
72627f7eb2Smrg@cindex signal-to-noise ratio (metaphorical usage for diagnostics)
73627f7eb2Smrg@cindex diagnostics, false positive
74627f7eb2Smrg@cindex diagnostics, true positive
75627f7eb2Smrg@cindex false positive
76627f7eb2Smrg@cindex true positive
77627f7eb2Smrg
78627f7eb2SmrgWarnings should have a good @dfn{signal-to-noise ratio}: we should have few
79627f7eb2Smrg@dfn{false positives} (falsely issuing a warning when no warning is
80627f7eb2Smrgwarranted) and few @dfn{false negatives} (failing to issue a warning when
81627f7eb2Smrgone @emph{is} justified).
82627f7eb2Smrg
83627f7eb2SmrgNote that a false positive can mean, in practice, a warning that the
84627f7eb2Smrguser doesn't agree with.  Ideally a diagnostic should contain enough
85627f7eb2Smrginformation to allow the user to make an informed choice about whether
86627f7eb2Smrgthey should care (and how to fix it), but a balance must be drawn against
87627f7eb2Smrgoverloading the user with irrelevant data.
88627f7eb2Smrg
89627f7eb2Smrg@subsection Precision of Wording
90627f7eb2Smrg
91627f7eb2SmrgProvide the user with details that allow them to identify what the
92627f7eb2Smrgproblem is.  For example, the vaguely-worded message:
93627f7eb2Smrg
94627f7eb2Smrg@smallexample
95627f7eb2Smrgdemo.c:1:1: warning: 'noinline' attribute ignored [-Wattributes]
96627f7eb2Smrg    1 | int foo __attribute__((noinline));
97627f7eb2Smrg      | ^~~
98627f7eb2Smrg@end smallexample
99627f7eb2Smrg
100627f7eb2Smrg@noindent
101627f7eb2Smrgdoesn't tell the user why the attribute was ignored, or what kind of
102627f7eb2Smrgentity the compiler thought the attribute was being applied to (the
103627f7eb2Smrgsource location for the diagnostic is also poor;
104627f7eb2Smrg@pxref{input_location_example,,discussion of @code{input_location}}).
105627f7eb2SmrgA better message would be:
106627f7eb2Smrg
107627f7eb2Smrg@smallexample
108627f7eb2Smrgdemo.c:1:24: warning: attribute 'noinline' on variable 'foo' was
109627f7eb2Smrg   ignored [-Wattributes]
110627f7eb2Smrg    1 | int foo __attribute__((noinline));
111627f7eb2Smrg      |     ~~~ ~~~~~~~~~~~~~~~^~~~~~~~~
112627f7eb2Smrgdemo.c:1:24: note: attribute 'noinline' is only applicable to functions
113627f7eb2Smrg@end smallexample
114627f7eb2Smrg
115627f7eb2Smrg@noindent
116627f7eb2Smrgwhich spells out the missing information (and fixes the location
117627f7eb2Smrginformation, as discussed below).
118627f7eb2Smrg
119627f7eb2SmrgThe above example uses a note to avoid a combinatorial explosion of possible
120627f7eb2Smrgmessages.
121627f7eb2Smrg
122627f7eb2Smrg@subsection Try the diagnostic on real-world code
123627f7eb2Smrg
124627f7eb2SmrgIt's worth testing a new warning on many instances of real-world code,
125627f7eb2Smrgwritten by different people, and seeing what it complains about, and
126627f7eb2Smrgwhat it doesn't complain about.
127627f7eb2Smrg
128627f7eb2SmrgThis may suggest heuristics that silence common false positives.
129627f7eb2Smrg
130627f7eb2SmrgIt may also suggest ways to improve the precision of the message.
131627f7eb2Smrg
132627f7eb2Smrg@subsection Make mismatches clear
133627f7eb2Smrg
134627f7eb2SmrgMany diagnostics relate to a mismatch between two different places in the
135627f7eb2Smrguser's source code.  Examples include:
136627f7eb2Smrg@itemize @bullet
137627f7eb2Smrg  @item
138627f7eb2Smrg  a type mismatch, where the type at a usage site does not match the type
139627f7eb2Smrg  at a declaration
140627f7eb2Smrg
141627f7eb2Smrg  @item
142627f7eb2Smrg  the argument count at a call site does not match the parameter count
143627f7eb2Smrg  at the declaration
144627f7eb2Smrg
145627f7eb2Smrg  @item
146627f7eb2Smrg  something is erroneously duplicated (e.g.@: an error, due to breaking a
147627f7eb2Smrg  uniqueness requirement, or a warning, if it's suggestive of a bug)
148627f7eb2Smrg
149627f7eb2Smrg  @item
150627f7eb2Smrg  an ``opened'' syntactic construct (such as an open-parenthesis) is not
151627f7eb2Smrg  closed
152627f7eb2Smrg
153627f7eb2Smrg  @c TODO: more examples?
154627f7eb2Smrg@end itemize
155627f7eb2Smrg
156627f7eb2SmrgIn each case, the diagnostic should indicate @strong{both} pertinent
157627f7eb2Smrglocations (so that the user can easily see the problem and how to fix it).
158627f7eb2Smrg
159627f7eb2SmrgThe standard way to do this is with a note (via @code{inform}).  For
160627f7eb2Smrgexample:
161627f7eb2Smrg
162627f7eb2Smrg@smallexample
163627f7eb2Smrg  auto_diagnostic_group d;
164627f7eb2Smrg  if (warning_at (loc, OPT_Wduplicated_cond,
165627f7eb2Smrg                  "duplicated %<if%> condition"))
166627f7eb2Smrg    inform (EXPR_LOCATION (t), "previously used here");
167627f7eb2Smrg@end smallexample
168627f7eb2Smrg
169627f7eb2Smrg@noindent
170627f7eb2Smrgwhich leads to:
171627f7eb2Smrg
172627f7eb2Smrg@smallexample
173627f7eb2Smrgdemo.c: In function 'test':
174627f7eb2Smrgdemo.c:5:17: warning: duplicated 'if' condition [-Wduplicated-cond]
175627f7eb2Smrg    5 |   else if (flag > 3)
176627f7eb2Smrg      |            ~~~~~^~~
177627f7eb2Smrgdemo.c:3:12: note: previously used here
178627f7eb2Smrg    3 |   if (flag > 3)
179627f7eb2Smrg      |       ~~~~~^~~
180627f7eb2Smrg@end smallexample
181627f7eb2Smrg
182627f7eb2Smrg@noindent
183627f7eb2SmrgThe @code{inform} call should be guarded by the return value from the
184627f7eb2Smrg@code{warning_at} call so that the note isn't emitted when the warning
185627f7eb2Smrgis suppressed.
186627f7eb2Smrg
187627f7eb2SmrgFor cases involving punctuation where the locations might be near
188627f7eb2Smrgeach other, they can be conditionally consolidated via
189627f7eb2Smrg@code{gcc_rich_location::add_location_if_nearby}:
190627f7eb2Smrg
191627f7eb2Smrg@smallexample
192627f7eb2Smrg    auto_diagnostic_group d;
193627f7eb2Smrg    gcc_rich_location richloc (primary_loc);
194627f7eb2Smrg    bool added secondary = richloc.add_location_if_nearby (secondary_loc);
195627f7eb2Smrg    error_at (&richloc, "main message");
196627f7eb2Smrg    if (!added secondary)
197627f7eb2Smrg      inform (secondary_loc, "message for secondary");
198627f7eb2Smrg@end smallexample
199627f7eb2Smrg
200627f7eb2Smrg@noindent
201627f7eb2SmrgThis will emit either one diagnostic with two locations:
202627f7eb2Smrg@smallexample
203627f7eb2Smrg  demo.c:42:10: error: main message
204627f7eb2Smrg    (foo)
205627f7eb2Smrg    ~   ^
206627f7eb2Smrg@end smallexample
207627f7eb2Smrg
208627f7eb2Smrg@noindent
209627f7eb2Smrgor two diagnostics:
210627f7eb2Smrg
211627f7eb2Smrg@smallexample
212627f7eb2Smrg  demo.c:42:4: error: main message
213627f7eb2Smrg    foo)
214627f7eb2Smrg       ^
215627f7eb2Smrg  demo.c:40:2: note: message for secondary
216627f7eb2Smrg    (
217627f7eb2Smrg    ^
218627f7eb2Smrg@end smallexample
219627f7eb2Smrg
220627f7eb2Smrg@subsection Location Information
221627f7eb2Smrg@cindex diagnostics, locations
222627f7eb2Smrg@cindex location information
223627f7eb2Smrg@cindex source code, location information
224627f7eb2Smrg@cindex caret
225627f7eb2Smrg
226627f7eb2SmrgGCC's @code{location_t} type can support both ordinary locations,
227627f7eb2Smrgand locations relating to a macro expansion.
228627f7eb2Smrg
229627f7eb2SmrgAs of GCC 6, ordinary locations changed from supporting just a
230627f7eb2Smrgpoint in the user's source code to supporting three points: the
231627f7eb2Smrg@dfn{caret} location, plus a start and a finish:
232627f7eb2Smrg
233627f7eb2Smrg@smallexample
234627f7eb2Smrg      a = foo && bar;
235627f7eb2Smrg          ~~~~^~~~~~
236627f7eb2Smrg          |   |    |
237627f7eb2Smrg          |   |    finish
238627f7eb2Smrg          |   caret
239627f7eb2Smrg          start
240627f7eb2Smrg@end smallexample
241627f7eb2Smrg
242627f7eb2SmrgTokens coming out of libcpp have locations of the form @code{caret == start},
243627f7eb2Smrgsuch as for @code{foo} here:
244627f7eb2Smrg
245627f7eb2Smrg@smallexample
246627f7eb2Smrg      a = foo && bar;
247627f7eb2Smrg          ^~~
248627f7eb2Smrg          | |
249627f7eb2Smrg          | finish
250627f7eb2Smrg          caret == start
251627f7eb2Smrg@end smallexample
252627f7eb2Smrg
253627f7eb2SmrgCompound expressions should be reported using the location of the
254627f7eb2Smrgexpression as a whole, rather than just of one token within it.
255627f7eb2Smrg
256627f7eb2SmrgFor example, in @code{-Wformat}, rather than underlining just the first
257627f7eb2Smrgtoken of a bad argument:
258627f7eb2Smrg
259627f7eb2Smrg@smallexample
260627f7eb2Smrg   printf("hello %i %s", (long)0, "world");
261627f7eb2Smrg                 ~^      ~
262627f7eb2Smrg                 %li
263627f7eb2Smrg@end smallexample
264627f7eb2Smrg
265627f7eb2Smrg@noindent
266627f7eb2Smrgthe whole of the expression should be underlined, so that the user can
267627f7eb2Smrgeasily identify what is being referred to:
268627f7eb2Smrg
269627f7eb2Smrg@smallexample
270627f7eb2Smrg   printf("hello %i %s", (long)0, "world");
271627f7eb2Smrg                 ~^      ~~~~~~~
272627f7eb2Smrg                 %li
273627f7eb2Smrg@end smallexample
274627f7eb2Smrg
275627f7eb2Smrg@c this was r251239
276627f7eb2Smrg
277627f7eb2SmrgAvoid using the @code{input_location} global, and the diagnostic functions
278627f7eb2Smrgthat implicitly use it---use @code{error_at} and @code{warning_at} rather
279627f7eb2Smrgthan @code{error} and @code{warning}, and provide the most appropriate
280627f7eb2Smrg@code{location_t} value available at that phase of the compilation.  It's
281627f7eb2Smrgpossible to supply secondary @code{location_t} values via
282627f7eb2Smrg@code{rich_location}.
283627f7eb2Smrg
284627f7eb2Smrg@noindent
285627f7eb2Smrg@anchor{input_location_example}
286627f7eb2SmrgFor example, in the example of imprecise wording above, generating the
287627f7eb2Smrgdiagnostic using @code{warning}:
288627f7eb2Smrg
289627f7eb2Smrg@smallexample
290627f7eb2Smrg  // BAD: implicitly uses @code{input_location}
291627f7eb2Smrg  warning (OPT_Wattributes, "%qE attribute ignored", name);
292627f7eb2Smrg@end smallexample
293627f7eb2Smrg
294627f7eb2Smrg@noindent
295627f7eb2Smrgleads to:
296627f7eb2Smrg
297627f7eb2Smrg@smallexample
298627f7eb2Smrg// BAD: uses @code{input_location}
299627f7eb2Smrgdemo.c:1:1: warning: 'noinline' attribute ignored [-Wattributes]
300627f7eb2Smrg    1 | int foo __attribute__((noinline));
301627f7eb2Smrg      | ^~~
302627f7eb2Smrg@end smallexample
303627f7eb2Smrg
304627f7eb2Smrg@noindent
305627f7eb2Smrgwhich thus happened to use the location of the @code{int} token, rather
306627f7eb2Smrgthan that of the attribute.  Using @code{warning_at} with the location of
307627f7eb2Smrgthe attribute, providing the location of the declaration in question
308627f7eb2Smrgas a secondary location, and adding a note:
309627f7eb2Smrg
310627f7eb2Smrg@smallexample
311627f7eb2Smrg  auto_diagnostic_group d;
312627f7eb2Smrg  gcc_rich_location richloc (attrib_loc);
313627f7eb2Smrg  richloc.add_range (decl_loc);
314627f7eb2Smrg  if (warning_at (OPT_Wattributes, &richloc,
315627f7eb2Smrg                  "attribute %qE on variable %qE was ignored", name))
316627f7eb2Smrg    inform (attrib_loc, "attribute %qE is only applicable to functions");
317627f7eb2Smrg@end smallexample
318627f7eb2Smrg
319627f7eb2Smrg@noindent
320627f7eb2Smrgwould lead to:
321627f7eb2Smrg
322627f7eb2Smrg@smallexample
323627f7eb2Smrg// OK: use location of attribute, with a secondary location
324627f7eb2Smrgdemo.c:1:24: warning: attribute 'noinline' on variable 'foo' was
325627f7eb2Smrg   ignored [-Wattributes]
326627f7eb2Smrg    1 | int foo __attribute__((noinline));
327627f7eb2Smrg      |     ~~~ ~~~~~~~~~~~~~~~^~~~~~~~~
328627f7eb2Smrgdemo.c:1:24: note: attribute 'noinline' is only applicable to functions
329627f7eb2Smrg@end smallexample
330627f7eb2Smrg
331627f7eb2Smrg@c TODO labelling of ranges
332627f7eb2Smrg
333627f7eb2Smrg@subsection Coding Conventions
334627f7eb2Smrg
335627f7eb2SmrgSee the @uref{https://gcc.gnu.org/codingconventions.html#Diagnostics,
336627f7eb2Smrgdiagnostics section} of the GCC coding conventions.
337627f7eb2Smrg
338627f7eb2SmrgIn the C++ front end, when comparing two types in a message, use @samp{%H}
339627f7eb2Smrgand @samp{%I} rather than @samp{%T}, as this allows the diagnostics
340627f7eb2Smrgsubsystem to highlight differences between template-based types.
341627f7eb2SmrgFor example, rather than using @samp{%qT}:
342627f7eb2Smrg
343627f7eb2Smrg@smallexample
344627f7eb2Smrg  // BAD: a pair of %qT used in C++ front end for type comparison
345627f7eb2Smrg  error_at (loc, "could not convert %qE from %qT to %qT", expr,
346627f7eb2Smrg            TREE_TYPE (expr), type);
347627f7eb2Smrg@end smallexample
348627f7eb2Smrg
349627f7eb2Smrg@noindent
350627f7eb2Smrgwhich could lead to:
351627f7eb2Smrg
352627f7eb2Smrg@smallexample
353627f7eb2Smrgerror: could not convert 'map<int, double>()' from 'map<int,double>'
354627f7eb2Smrg   to 'map<int,int>'
355627f7eb2Smrg@end smallexample
356627f7eb2Smrg
357627f7eb2Smrg@noindent
358627f7eb2Smrgusing @samp{%H} and @samp{%I} (via @samp{%qH} and @samp{%qI}):
359627f7eb2Smrg
360627f7eb2Smrg@smallexample
361627f7eb2Smrg  // OK: compare types in C++ front end via %qH and %qI
362627f7eb2Smrg  error_at (loc, "could not convert %qE from %qH to %qI", expr,
363627f7eb2Smrg            TREE_TYPE (expr), type);
364627f7eb2Smrg@end smallexample
365627f7eb2Smrg
366627f7eb2Smrg@noindent
367627f7eb2Smrgallows the above output to be simplified to:
368627f7eb2Smrg
369627f7eb2Smrg@smallexample
370627f7eb2Smrgerror: could not convert 'map<int, double>()' from 'map<[...],double>'
371627f7eb2Smrg   to 'map<[...],int>'
372627f7eb2Smrg@end smallexample
373627f7eb2Smrg
374627f7eb2Smrg@noindent
375627f7eb2Smrgwhere the @code{double} and @code{int} are colorized to highlight them.
376627f7eb2Smrg
377627f7eb2Smrg@c %H and %I were added in r248698.
378627f7eb2Smrg
379627f7eb2Smrg@subsection Group logically-related diagnostics
380627f7eb2Smrg
381627f7eb2SmrgUse @code{auto_diagnostic_group} when issuing multiple related
382627f7eb2Smrgdiagnostics (seen in various examples on this page).  This informs the
383627f7eb2Smrgdiagnostic subsystem that all diagnostics issued within the lifetime
384627f7eb2Smrgof the @code{auto_diagnostic_group} are related.  For example,
385627f7eb2Smrg@option{-fdiagnostics-format=json} will treat the first diagnostic
386627f7eb2Smrgemitted within the group as a top-level diagnostic, and all subsequent
387627f7eb2Smrgdiagnostics within the group as its children.
388627f7eb2Smrg
389627f7eb2Smrg@subsection Quoting
390627f7eb2SmrgText should be quoted by either using the @samp{q} modifier in a directive
391627f7eb2Smrgsuch as @samp{%qE}, or by enclosing the quoted text in a pair of @samp{%<}
392627f7eb2Smrgand @samp{%>} directives, and never by using explicit quote characters.
393627f7eb2SmrgThe directives handle the appropriate quote characters for each language
394627f7eb2Smrgand apply the correct color or highlighting.
395627f7eb2Smrg
396627f7eb2SmrgThe following elements should be quoted in GCC diagnostics:
397627f7eb2Smrg
398627f7eb2Smrg@itemize @bullet
399627f7eb2Smrg@item
400627f7eb2SmrgLanguage keywords.
401627f7eb2Smrg@item
402627f7eb2SmrgTokens.
403627f7eb2Smrg@item
404627f7eb2SmrgBoolean, numerical, character, and string constants that appear in the
405627f7eb2Smrgsource code.
406627f7eb2Smrg@item
407627f7eb2SmrgIdentifiers, including function, macro, type, and variable names.
408627f7eb2Smrg@end itemize
409627f7eb2Smrg
410627f7eb2SmrgOther elements such as numbers that do not refer to numeric constants that
411627f7eb2Smrgappear in the source code should not be quoted. For example, in the message:
412627f7eb2Smrg
413627f7eb2Smrg@smallexample
414627f7eb2Smrgargument %d of %qE must be a pointer type
415627f7eb2Smrg@end smallexample
416627f7eb2Smrg
417627f7eb2Smrg@noindent
418627f7eb2Smrgsince the argument number does not refer to a numerical constant in the
419627f7eb2Smrgsource code it should not be quoted.
420627f7eb2Smrg
421627f7eb2Smrg@subsection Spelling and Terminology
422627f7eb2Smrg
423627f7eb2SmrgSee the @uref{https://gcc.gnu.org/codingconventions.html#Spelling
424627f7eb2SmrgSpelling, terminology and markup} section of the GCC coding conventions.
425627f7eb2Smrg
426627f7eb2Smrg@subsection Fix-it hints
427627f7eb2Smrg@cindex fix-it hints
428627f7eb2Smrg@cindex diagnostics guidelines, fix-it hints
429627f7eb2Smrg
430627f7eb2SmrgGCC's diagnostic subsystem can emit @dfn{fix-it hints}: small suggested
431627f7eb2Smrgedits to the user's source code.
432627f7eb2Smrg
433627f7eb2SmrgThey are printed by default underneath the code in question.  They
434627f7eb2Smrgcan also be viewed via @option{-fdiagnostics-generate-patch} and
435627f7eb2Smrg@option{-fdiagnostics-parseable-fixits}.  With the latter, an IDE
436627f7eb2Smrgought to be able to offer to automatically apply the suggested fix.
437627f7eb2Smrg
438627f7eb2SmrgFix-it hints contain code fragments, and thus they should not be marked
439627f7eb2Smrgfor translation.
440627f7eb2Smrg
441627f7eb2SmrgFix-it hints can be added to a diagnostic by using a @code{rich_location}
442627f7eb2Smrgrather than a @code{location_t} - the fix-it hints are added to the
443627f7eb2Smrg@code{rich_location} using one of the various @code{add_fixit} member
444627f7eb2Smrgfunctions of @code{rich_location}.  They are documented with
445627f7eb2Smrg@code{rich_location} in @file{libcpp/line-map.h}.
446627f7eb2SmrgIt's easiest to use the @code{gcc_rich_location} subclass of
447627f7eb2Smrg@code{rich_location} found in @file{gcc-rich-location.h}, as this
448627f7eb2Smrgimplicitly supplies the @code{line_table} variable.
449627f7eb2Smrg
450627f7eb2SmrgFor example:
451627f7eb2Smrg
452627f7eb2Smrg@smallexample
453627f7eb2Smrg   if (const char *suggestion = hint.suggestion ())
454627f7eb2Smrg     @{
455627f7eb2Smrg       gcc_rich_location richloc (location);
456627f7eb2Smrg       richloc.add_fixit_replace (suggestion);
457627f7eb2Smrg       error_at (&richloc,
458627f7eb2Smrg                 "%qE does not name a type; did you mean %qs?",
459627f7eb2Smrg                 id, suggestion);
460627f7eb2Smrg     @}
461627f7eb2Smrg@end smallexample
462627f7eb2Smrg
463627f7eb2Smrg@noindent
464627f7eb2Smrgwhich can lead to:
465627f7eb2Smrg
466627f7eb2Smrg@smallexample
467627f7eb2Smrgspellcheck-typenames.C:73:1: error: 'singed' does not name a type; did
468627f7eb2Smrg   you mean 'signed'?
469627f7eb2Smrg   73 | singed char ch;
470627f7eb2Smrg      | ^~~~~~
471627f7eb2Smrg      | signed
472627f7eb2Smrg@end smallexample
473627f7eb2Smrg
474627f7eb2SmrgNon-trivial edits can be built up by adding multiple fix-it hints to one
475627f7eb2Smrg@code{rich_location}.  It's best to express the edits in terms of the
476627f7eb2Smrglocations of individual tokens.  Various handy functions for adding
477627f7eb2Smrgfix-it hints for idiomatic C and C++ can be seen in
478627f7eb2Smrg@file{gcc-rich-location.h}.
479627f7eb2Smrg
480627f7eb2Smrg@subsubsection Fix-it hints should work
481627f7eb2Smrg
482627f7eb2SmrgWhen implementing a fix-it hint, please verify that the suggested edit
483627f7eb2Smrgleads to fixed, compilable code.  (Unfortunately, this currently must be
484627f7eb2Smrgdone by hand using @option{-fdiagnostics-generate-patch}.  It would be
485627f7eb2Smrggood to have an automated way of verifying that fix-it hints actually fix
486627f7eb2Smrgthe code).
487627f7eb2Smrg
488627f7eb2SmrgFor example, a ``gotcha'' here is to forget to add a space when adding a
489627f7eb2Smrgmissing reserved word.  Consider a C++ fix-it hint that adds
490627f7eb2Smrg@code{typename} in front of a template declaration.  A naive way to
491627f7eb2Smrgimplement this might be:
492627f7eb2Smrg
493627f7eb2Smrg@smallexample
494627f7eb2Smrggcc_rich_location richloc (loc);
495627f7eb2Smrg// BAD: insertion is missing a trailing space
496627f7eb2Smrgrichloc.add_fixit_insert_before ("typename");
497627f7eb2Smrgerror_at (&richloc, "need %<typename%> before %<%T::%E%> because "
498627f7eb2Smrg                     "%qT is a dependent scope",
499627f7eb2Smrg                     parser->scope, id, parser->scope);
500627f7eb2Smrg@end smallexample
501627f7eb2Smrg
502627f7eb2Smrg@noindent
503627f7eb2SmrgWhen applied to the code, this might lead to:
504627f7eb2Smrg
505627f7eb2Smrg@smallexample
506627f7eb2SmrgT::type x;
507627f7eb2Smrg@end smallexample
508627f7eb2Smrg
509627f7eb2Smrg@noindent
510627f7eb2Smrgbeing ``corrected'' to:
511627f7eb2Smrg
512627f7eb2Smrg@smallexample
513627f7eb2SmrgtypenameT::type x;
514627f7eb2Smrg@end smallexample
515627f7eb2Smrg
516627f7eb2Smrg@noindent
517627f7eb2SmrgIn this case, the correct thing to do is to add a trailing space after
518627f7eb2Smrg@code{typename}:
519627f7eb2Smrg
520627f7eb2Smrg@smallexample
521627f7eb2Smrggcc_rich_location richloc (loc);
522627f7eb2Smrg// OK: note that here we have a trailing space
523627f7eb2Smrgrichloc.add_fixit_insert_before ("typename ");
524627f7eb2Smrgerror_at (&richloc, "need %<typename%> before %<%T::%E%> because "
525627f7eb2Smrg                     "%qT is a dependent scope",
526627f7eb2Smrg                     parser->scope, id, parser->scope);
527627f7eb2Smrg@end smallexample
528627f7eb2Smrg
529627f7eb2Smrg@noindent
530627f7eb2Smrgleading to this corrected code:
531627f7eb2Smrg
532627f7eb2Smrg@smallexample
533627f7eb2Smrgtypename T::type x;
534627f7eb2Smrg@end smallexample
535627f7eb2Smrg
536627f7eb2Smrg@subsubsection Express deletion in terms of deletion, not replacement
537627f7eb2Smrg
538627f7eb2SmrgIt's best to express deletion suggestions in terms of deletion fix-it
539627f7eb2Smrghints, rather than replacement fix-it hints.  For example, consider this:
540627f7eb2Smrg
541627f7eb2Smrg@smallexample
542627f7eb2Smrg    auto_diagnostic_group d;
543627f7eb2Smrg    gcc_rich_location richloc (location_of (retval));
544627f7eb2Smrg    tree name = DECL_NAME (arg);
545627f7eb2Smrg    richloc.add_fixit_replace (IDENTIFIER_POINTER (name));
546627f7eb2Smrg    warning_at (&richloc, OPT_Wredundant_move,
547627f7eb2Smrg                "redundant move in return statement");
548627f7eb2Smrg@end smallexample
549627f7eb2Smrg
550627f7eb2Smrg@noindent
551627f7eb2Smrgwhich is intended to e.g.@: replace a @code{std::move} with the underlying
552627f7eb2Smrgvalue:
553627f7eb2Smrg
554627f7eb2Smrg@smallexample
555627f7eb2Smrg   return std::move (retval);
556627f7eb2Smrg          ~~~~~~~~~~^~~~~~~~
557627f7eb2Smrg          retval
558627f7eb2Smrg@end smallexample
559627f7eb2Smrg
560627f7eb2Smrg@noindent
561627f7eb2Smrgwhere the change has been expressed as replacement, replacing
562627f7eb2Smrgwith the name of the declaration.
563627f7eb2SmrgThis works for simple cases, but consider this case:
564627f7eb2Smrg
565627f7eb2Smrg@smallexample
566627f7eb2Smrg#ifdef SOME_CONFIG_FLAG
567627f7eb2Smrg# define CONFIGURY_GLOBAL global_a
568627f7eb2Smrg#else
569627f7eb2Smrg# define CONFIGURY_GLOBAL global_b
570627f7eb2Smrg#endif
571627f7eb2Smrg
572627f7eb2Smrgint fn ()
573627f7eb2Smrg@{
574627f7eb2Smrg  return std::move (CONFIGURY_GLOBAL /* some comment */);
575627f7eb2Smrg@}
576627f7eb2Smrg@end smallexample
577627f7eb2Smrg
578627f7eb2Smrg@noindent
579627f7eb2SmrgThe above implementation erroneously strips out the macro and the
580627f7eb2Smrgcomment in the fix-it hint:
581627f7eb2Smrg
582627f7eb2Smrg@smallexample
583627f7eb2Smrg   return std::move (CONFIGURY_GLOBAL /* some comment */);
584627f7eb2Smrg          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
585627f7eb2Smrg          global_a
586627f7eb2Smrg@end smallexample
587627f7eb2Smrg
588627f7eb2Smrg@noindent
589627f7eb2Smrgand thus this resulting code:
590627f7eb2Smrg
591627f7eb2Smrg@smallexample
592627f7eb2Smrg   return global_a;
593627f7eb2Smrg@end smallexample
594627f7eb2Smrg
595627f7eb2Smrg@noindent
596627f7eb2SmrgIt's better to do deletions in terms of deletions; deleting the
597627f7eb2Smrg@code{std::move (} and the trailing close-paren, leading to
598627f7eb2Smrgthis:
599627f7eb2Smrg
600627f7eb2Smrg@smallexample
601627f7eb2Smrg   return std::move (CONFIGURY_GLOBAL /* some comment */);
602627f7eb2Smrg          ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
603627f7eb2Smrg          CONFIGURY_GLOBAL /* some comment */
604627f7eb2Smrg@end smallexample
605627f7eb2Smrg
606627f7eb2Smrg@noindent
607627f7eb2Smrgand thus this result:
608627f7eb2Smrg
609627f7eb2Smrg@smallexample
610627f7eb2Smrg   return CONFIGURY_GLOBAL /* some comment */;
611627f7eb2Smrg@end smallexample
612627f7eb2Smrg
613627f7eb2Smrg@noindent
614627f7eb2SmrgUnfortunately, the pertinent @code{location_t} values are not always
615627f7eb2Smrgavailable.
616627f7eb2Smrg
617627f7eb2Smrg@c the above was https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01474.html
618627f7eb2Smrg
619627f7eb2Smrg@subsubsection Multiple suggestions
620627f7eb2Smrg
621627f7eb2SmrgIn the rare cases where you need to suggest more than one mutually
622627f7eb2Smrgexclusive solution to a problem, this can be done by emitting
623627f7eb2Smrgmultiple notes and calling
624627f7eb2Smrg@code{rich_location::fixits_cannot_be_auto_applied} on each note's
625627f7eb2Smrg@code{rich_location}.  If this is called, then the fix-it hints in
626627f7eb2Smrgthe @code{rich_location} will be printed, but will not be added to
627627f7eb2Smrggenerated patches.
628627f7eb2Smrg
629627f7eb2Smrg
630627f7eb2Smrg@node Guidelines for Options
631627f7eb2Smrg@section Guidelines for Options
632627f7eb2Smrg@cindex command-line options, guidelines for
633627f7eb2Smrg@cindex options, guidelines for
634627f7eb2Smrg@cindex guidelines for options
635627f7eb2Smrg
636627f7eb2Smrg@c TODO
637