]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/doc/ux.texi
* doc/ux.texi: Move @section directly after @node.
[thirdparty/gcc.git] / gcc / doc / ux.texi
1 @c Copyright (C) 2018 Free Software Foundation, Inc.
2 @c Free Software Foundation, Inc.
3 @c This is part of the GCC manual.
4 @c For copying conditions, see the file gcc.texi.
5
6 @node User Experience Guidelines
7 @chapter User Experience Guidelines
8 @cindex user experience guidelines
9 @cindex guidelines, user experience
10
11 To borrow a slogan from
12 @uref{https://elm-lang.org/blog/compilers-as-assistants, Elm},
13
14 @quotation
15 @strong{Compilers should be assistants, not adversaries.} A compiler should
16 not just detect bugs, it should then help you understand why there is a bug.
17 It should not berate you in a robot voice, it should give you specific hints
18 that help you write better code. Ultimately, a compiler should make
19 programming faster and more fun!
20 @author Evan Czaplicki
21 @end quotation
22
23 This chapter provides guidelines on how to implement diagnostics and
24 command-line options in ways that we hope achieve the above ideal.
25
26 @menu
27 * Guidelines for Diagnostics:: How to implement diagnostics.
28 * Guidelines for Options:: Guidelines for command-line options.
29 @end menu
30
31
32 @node Guidelines for Diagnostics
33 @section Guidelines for Diagnostics
34 @cindex guidelines for diagnostics
35 @cindex diagnostics, guidelines for
36
37 @subsection Talk in terms of the user's code
38
39 Diagnostics should be worded in terms of the user's source code, and the
40 source language, rather than GCC's own implementation details.
41
42 @subsection Diagnostics are actionable
43 @cindex diagnostics, actionable
44
45 A good diagnostic is @dfn{actionable}: it should assist the user in
46 taking action.
47
48 Consider what an end user will want to do when encountering a diagnostic.
49
50 Given an error, an end user will think: ``How do I fix this?''
51
52 Given a warning, an end user will think:
53
54 @itemize @bullet
55 @item
56 ``Is this a real problem?''
57 @item
58 ``Do I care?''
59 @item
60 if they decide it's genuine: ``How do I fix this?''
61 @end itemize
62
63 A good diagnostic provides pertinent information to allow the user to
64 easily answer the above questions.
65
66 @subsection The user's attention is important
67
68 A perfect compiler would issue a warning on every aspect of the user's
69 source code that ought to be fixed, and issue no other warnings.
70 Naturally, this ideal is impossible to achieve.
71
72 @cindex signal-to-noise ratio (metaphorical usage for diagnostics)
73 @cindex diagnostics, false positive
74 @cindex diagnostics, true positive
75 @cindex false positive
76 @cindex true positive
77
78 Warnings should have a good @dfn{signal-to-noise ratio}: we should have few
79 @dfn{false positives} (falsely issuing a warning when no warning is
80 warranted) and few @dfn{false negatives} (failing to issue a warning when
81 one @emph{is} justified).
82
83 Note that a false positive can mean, in practice, a warning that the
84 user doesn't agree with. Ideally a diagnostic should contain enough
85 information to allow the user to make an informed choice about whether
86 they should care (and how to fix it), but a balance must be drawn against
87 overloading the user with irrelevant data.
88
89 @subsection Precision of Wording
90
91 Provide the user with details that allow them to identify what the
92 problem is. For example, the vaguely-worded message:
93
94 @smallexample
95 demo.c:1:1: warning: 'noinline' attribute ignored [-Wattributes]
96 1 | int foo __attribute__((noinline));
97 | ^~~
98 @end smallexample
99
100 @noindent
101 doesn't tell the user why the attribute was ignored, or what kind of
102 entity the compiler thought the attribute was being applied to (the
103 source location for the diagnostic is also poor;
104 @pxref{input_location_example,,discussion of @code{input_location}}).
105 A better message would be:
106
107 @smallexample
108 demo.c:1:24: warning: attribute 'noinline' on variable 'foo' was
109 ignored [-Wattributes]
110 1 | int foo __attribute__((noinline));
111 | ~~~ ~~~~~~~~~~~~~~~^~~~~~~~~
112 demo.c:1:24: note: attribute 'noinline' is only applicable to functions
113 @end smallexample
114
115 @noindent
116 which spells out the missing information (and fixes the location
117 information, as discussed below).
118
119 The above example uses a note to avoid a combinatorial explosion of possible
120 messages.
121
122 @subsection Try the diagnostic on real-world code
123
124 It's worth testing a new warning on many instances of real-world code,
125 written by different people, and seeing what it complains about, and
126 what it doesn't complain about.
127
128 This may suggest heuristics that silence common false positives.
129
130 It may also suggest ways to improve the precision of the message.
131
132 @subsection Make mismatches clear
133
134 Many diagnostics relate to a mismatch between two different places in the
135 user's source code. Examples include:
136 @itemize @bullet
137 @item
138 a type mismatch, where the type at a usage site does not match the type
139 at a declaration
140
141 @item
142 the argument count at a call site does not match the parameter count
143 at the declaration
144
145 @item
146 something is erroneously duplicated (e.g. an error, due to breaking a
147 uniqueness requirement, or a warning, if it's suggestive of a bug)
148
149 @item
150 an ``opened'' syntactic construct (such as an open-parenthesis) is not
151 closed
152
153 @c TODO: more examples?
154 @end itemize
155
156 In each case, the diagnostic should indicate @strong{both} pertinent
157 locations (so that the user can easily see the problem and how to fix it).
158
159 The standard way to do this is with a note (via @code{inform}). For
160 example:
161
162 @smallexample
163 auto_diagnostic_group d;
164 if (warning_at (loc, OPT_Wduplicated_cond,
165 "duplicated %<if%> condition"))
166 inform (EXPR_LOCATION (t), "previously used here");
167 @end smallexample
168
169 @noindent
170 which leads to:
171
172 @smallexample
173 demo.c: In function 'test':
174 demo.c:5:17: warning: duplicated 'if' condition [-Wduplicated-cond]
175 5 | else if (flag > 3)
176 | ~~~~~^~~
177 demo.c:3:12: note: previously used here
178 3 | if (flag > 3)
179 | ~~~~~^~~
180 @end smallexample
181
182 @noindent
183 The @code{inform} call should be guarded by the return value from the
184 @code{warning_at} call so that the note isn't emitted when the warning
185 is suppressed.
186
187 For cases involving punctuation where the locations might be near
188 each other, they can be conditionally consolidated via
189 @code{gcc_rich_location::add_location_if_nearby}:
190
191 @smallexample
192 auto_diagnostic_group d;
193 gcc_rich_location richloc (primary_loc);
194 bool added secondary = richloc.add_location_if_nearby (secondary_loc);
195 error_at (&richloc, "main message");
196 if (!added secondary)
197 inform (secondary_loc, "message for secondary");
198 @end smallexample
199
200 @noindent
201 This will emit either one diagnostic with two locations:
202 @smallexample
203 demo.c:42:10: error: main message
204 (foo)
205 ~ ^
206 @end smallexample
207
208 @noindent
209 or two diagnostics:
210
211 @smallexample
212 demo.c:42:4: error: main message
213 foo)
214 ^
215 demo.c:40:2: note: message for secondary
216 (
217 ^
218 @end smallexample
219
220 @subsection Location Information
221 @cindex diagnostics, locations
222 @cindex location information
223 @cindex source code, location information
224 @cindex caret
225
226 GCC's @code{location_t} type can support both ordinary locations,
227 and locations relating to a macro expansion.
228
229 As of GCC 6, ordinary locations changed from supporting just a
230 point in the user's source code to supporting three points: the
231 @dfn{caret} location, plus a start and a finish:
232
233 @smallexample
234 a = foo && bar;
235 ~~~~^~~~~~
236 | | |
237 | | finish
238 | caret
239 start
240 @end smallexample
241
242 Tokens coming out of libcpp have locations of the form @code{caret == start},
243 such as for @code{foo} here:
244
245 @smallexample
246 a = foo && bar;
247 ^~~
248 | |
249 | finish
250 caret == start
251 @end smallexample
252
253 Compound expressions should be reported using the location of the
254 expression as a whole, rather than just of one token within it.
255
256 For example, in @code{-Wformat}, rather than underlining just the first
257 token of a bad argument:
258
259 @smallexample
260 printf("hello %i %s", (long)0, "world");
261 ~^ ~
262 %li
263 @end smallexample
264
265 @noindent
266 the whole of the expression should be underlined, so that the user can
267 easily identify what is being referred to:
268
269 @smallexample
270 printf("hello %i %s", (long)0, "world");
271 ~^ ~~~~~~~
272 %li
273 @end smallexample
274
275 @c this was r251239
276
277 Avoid using the @code{input_location} global, and the diagnostic functions
278 that implicitly use it---use @code{error_at} and @code{warning_at} rather
279 than @code{error} and @code{warning}, and provide the most appropriate
280 @code{location_t} value available at that phase of the compilation. It's
281 possible to supply secondary @code{location_t} values via
282 @code{rich_location}.
283
284 @noindent
285 @anchor{input_location_example}
286 For example, in the example of imprecise wording above, generating the
287 diagnostic using @code{warning}:
288
289 @smallexample
290 // BAD: implicitly uses @code{input_location}
291 warning (OPT_Wattributes, "%qE attribute ignored", name);
292 @end smallexample
293
294 @noindent
295 leads to:
296
297 @smallexample
298 // BAD: uses @code{input_location}
299 demo.c:1:1: warning: 'noinline' attribute ignored [-Wattributes]
300 1 | int foo __attribute__((noinline));
301 | ^~~
302 @end smallexample
303
304 @noindent
305 which thus happened to use the location of the @code{int} token, rather
306 than that of the attribute. Using @code{warning_at} with the location of
307 the attribute, providing the location of the declaration in question
308 as a secondary location, and adding a note:
309
310 @smallexample
311 auto_diagnostic_group d;
312 gcc_rich_location richloc (attrib_loc);
313 richloc.add_range (decl_loc);
314 if (warning_at (OPT_Wattributes, &richloc,
315 "attribute %qE on variable %qE was ignored", name))
316 inform (attrib_loc, "attribute %qE is only applicable to functions");
317 @end smallexample
318
319 @noindent
320 would lead to:
321
322 @smallexample
323 // OK: use location of attribute, with a secondary location
324 demo.c:1:24: warning: attribute 'noinline' on variable 'foo' was
325 ignored [-Wattributes]
326 1 | int foo __attribute__((noinline));
327 | ~~~ ~~~~~~~~~~~~~~~^~~~~~~~~
328 demo.c:1:24: note: attribute 'noinline' is only applicable to functions
329 @end smallexample
330
331 @c TODO labelling of ranges
332
333 @subsection Coding Conventions
334
335 See the @uref{https://gcc.gnu.org/codingconventions.html#Diagnostics,
336 diagnostics section} of the GCC coding conventions.
337
338 In the C++ front end, when comparing two types in a message, use @samp{%H}
339 and @samp{%I} rather than @samp{%T}, as this allows the diagnostics
340 subsystem to highlight differences between template-based types.
341 For example, rather than using @samp{%qT}:
342
343 @smallexample
344 // BAD: a pair of %qT used in C++ front end for type comparison
345 error_at (loc, "could not convert %qE from %qT to %qT", expr,
346 TREE_TYPE (expr), type);
347 @end smallexample
348
349 @noindent
350 which could lead to:
351
352 @smallexample
353 error: could not convert 'map<int, double>()' from 'map<int,double>'
354 to 'map<int,int>'
355 @end smallexample
356
357 @noindent
358 using @samp{%H} and @samp{%I} (via @samp{%qH} and @samp{%qI}):
359
360 @smallexample
361 // OK: compare types in C++ front end via %qH and %qI
362 error_at (loc, "could not convert %qE from %qH to %qI", expr,
363 TREE_TYPE (expr), type);
364 @end smallexample
365
366 @noindent
367 allows the above output to be simplified to:
368
369 @smallexample
370 error: could not convert 'map<int, double>()' from 'map<[...],double>'
371 to 'map<[...],int>'
372 @end smallexample
373
374 @noindent
375 where the @code{double} and @code{int} are colorized to highlight them.
376
377 @c %H and %I were added in r248698.
378
379 Use @code{auto_diagnostic_group} when issuing multiple related
380 diagnostics (seen in various examples on this page). This informs the
381 diagnostic subsystem that all diagnostics issued within the lifetime
382 of the @code{auto_diagnostic_group} are related. (Currently it doesn't
383 do anything with this information, but we may implement that in the
384 future).
385
386 @subsection Spelling and Terminology
387
388 See the @uref{https://gcc.gnu.org/codingconventions.html#Spelling
389 Spelling, terminology and markup} section of the GCC coding conventions.
390
391 @subsection Fix-it hints
392 @cindex fix-it hints
393 @cindex diagnostics guidelines, fix-it hints
394
395 GCC's diagnostic subsystem can emit @dfn{fix-it hints}: small suggested
396 edits to the user's source code.
397
398 They are printed by default underneath the code in question. They
399 can also be viewed via @option{-fdiagnostics-generate-patch} and
400 @option{-fdiagnostics-parseable-fixits}. With the latter, an IDE
401 ought to be able to offer to automatically apply the suggested fix.
402
403 Fix-it hints can be added to a diagnostic by using a @code{rich_location}
404 rather than a @code{location_t} - the fix-it hints are added to the
405 @code{rich_location} using one of the various @code{add_fixit} member
406 functions of @code{rich_location}. They are documented with
407 @code{rich_location} in @file{libcpp/line-map.h}.
408 It's easiest to use the @code{gcc_rich_location} subclass of
409 @code{rich_location} found in @file{gcc-rich-location.h}, as this
410 implicitly supplies the @code{line_table} variable.
411
412 For example:
413
414 @smallexample
415 if (const char *suggestion = hint.suggestion ())
416 @{
417 gcc_rich_location richloc (location);
418 richloc.add_fixit_replace (suggestion);
419 error_at (&richloc,
420 "%qE does not name a type; did you mean %qs?",
421 id, suggestion);
422 @}
423 @end smallexample
424
425 @noindent
426 which can lead to:
427
428 @smallexample
429 spellcheck-typenames.C:73:1: error: 'singed' does not name a type; did
430 you mean 'signed'?
431 73 | singed char ch;
432 | ^~~~~~
433 | signed
434 @end smallexample
435
436 Non-trivial edits can be built up by adding multiple fix-it hints to one
437 @code{rich_location}. It's best to express the edits in terms of the
438 locations of individual tokens. Various handy functions for adding
439 fix-it hints for idiomatic C and C++ can be seen in
440 @file{gcc-rich-location.h}.
441
442 @subsubsection Fix-it hints should work
443
444 When implementing a fix-it hint, please verify that the suggested edit
445 leads to fixed, compilable code. (Unfortunately, this currently must be
446 done by hand using @option{-fdiagnostics-generate-patch}. It would be
447 good to have an automated way of verifying that fix-it hints actually fix
448 the code).
449
450 For example, a ``gotcha'' here is to forget to add a space when adding a
451 missing reserved word. Consider a C++ fix-it hint that adds
452 @code{typename} in front of a template declaration. A naive way to
453 implement this might be:
454
455 @smallexample
456 gcc_rich_location richloc (loc);
457 // BAD: insertion is missing a trailing space
458 richloc.add_fixit_insert_before ("typename");
459 error_at (&richloc, "need %<typename%> before %<%T::%E%> because "
460 "%qT is a dependent scope",
461 parser->scope, id, parser->scope);
462 @end smallexample
463
464 @noindent
465 When applied to the code, this might lead to:
466
467 @smallexample
468 T::type x;
469 @end smallexample
470
471 @noindent
472 being ``corrected'' to:
473
474 @smallexample
475 typenameT::type x;
476 @end smallexample
477
478 @noindent
479 In this case, the correct thing to do is to add a trailing space after
480 @code{typename}:
481
482 @smallexample
483 gcc_rich_location richloc (loc);
484 // OK: note that here we have a trailing space
485 richloc.add_fixit_insert_before ("typename ");
486 error_at (&richloc, "need %<typename%> before %<%T::%E%> because "
487 "%qT is a dependent scope",
488 parser->scope, id, parser->scope);
489 @end smallexample
490
491 @noindent
492 leading to this corrected code:
493
494 @smallexample
495 typename T::type x;
496 @end smallexample
497
498 @subsubsection Express deletion in terms of deletion, not replacement
499
500 It's best to express deletion suggestions in terms of deletion fix-it
501 hints, rather than replacement fix-it hints. For example, consider this:
502
503 @smallexample
504 auto_diagnostic_group d;
505 gcc_rich_location richloc (location_of (retval));
506 tree name = DECL_NAME (arg);
507 richloc.add_fixit_replace (IDENTIFIER_POINTER (name));
508 warning_at (&richloc, OPT_Wredundant_move,
509 "redundant move in return statement");
510 @end smallexample
511
512 @noindent
513 which is intended to e.g. replace a @code{std::move} with the underlying
514 value:
515
516 @smallexample
517 return std::move (retval);
518 ~~~~~~~~~~^~~~~~~~
519 retval
520 @end smallexample
521
522 @noindent
523 where the change has been expressed as replacement, replacing
524 with the name of the declaration.
525 This works for simple cases, but consider this case:
526
527 @smallexample
528 #ifdef SOME_CONFIG_FLAG
529 # define CONFIGURY_GLOBAL global_a
530 #else
531 # define CONFIGURY_GLOBAL global_b
532 #endif
533
534 int fn ()
535 @{
536 return std::move (CONFIGURY_GLOBAL /* some comment */);
537 @}
538 @end smallexample
539
540 @noindent
541 The above implementation erroneously strips out the macro and the
542 comment in the fix-it hint:
543
544 @smallexample
545 return std::move (CONFIGURY_GLOBAL /* some comment */);
546 ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
547 global_a
548 @end smallexample
549
550 @noindent
551 and thus this resulting code:
552
553 @smallexample
554 return global_a;
555 @end smallexample
556
557 @noindent
558 It's better to do deletions in terms of deletions; deleting the
559 @code{std::move (} and the trailing close-paren, leading to
560 this:
561
562 @smallexample
563 return std::move (CONFIGURY_GLOBAL /* some comment */);
564 ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
565 CONFIGURY_GLOBAL /* some comment */
566 @end smallexample
567
568 @noindent
569 and thus this result:
570
571 @smallexample
572 return CONFIGURY_GLOBAL /* some comment */;
573 @end smallexample
574
575 @noindent
576 Unfortunately, the pertinent @code{location_t} values are not always
577 available.
578
579 @c the above was https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01474.html
580
581 @subsubsection Multiple suggestions
582
583 In the rare cases where you need to suggest more than one mutually
584 exclusive solution to a problem, this can be done by emitting
585 multiple notes and calling
586 @code{rich_location::fixits_cannot_be_auto_applied} on each note's
587 @code{rich_location}. If this is called, then the fix-it hints in
588 the @code{rich_location} will be printed, but will not be added to
589 generated patches.
590
591
592 @node Guidelines for Options
593 @section Guidelines for Options
594 @cindex command-line options, guidelines for
595 @cindex options, guidelines for
596 @cindex guidelines for options
597
598 @c TODO