]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/doc/ux.texi
Update copyright years.
[thirdparty/gcc.git] / gcc / doc / ux.texi
1 @c Copyright (C) 2018-2024 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/news/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 Sometimes the user didn't write the code
90
91 GCC is typically used in two different ways:
92
93 @itemize @bullet
94 @item
95 Semi-interactive usage: GCC is used as a development tool when the user
96 is writing code, as the ``compile'' part of the ``edit-compile-debug''
97 cycle. The user is actively hacking on the code themself (perhaps a
98 project they wrote, or someone else's), where they just made a change
99 to the code and want to see what happens, and to be warned about
100 mistakes.
101
102 @item
103 Batch rebuilds: where the user is recompiling one or more existing
104 packages, and GCC is a detail that's being invoked by various build
105 scripts. Examples include a user trying to bring up an operating system
106 consisting of hundreds of packages on a new CPU architecture, where the
107 packages were written by many different people, or simply rebuilding
108 packages after a dependency changed, where the user is hoping
109 ``nothing breaks'', since they are unfamiliar with the code.
110 @end itemize
111
112 Keep both of these styles of usage in mind when implementing diagnostics.
113
114 @subsection Precision of Wording
115
116 Provide the user with details that allow them to identify what the
117 problem is. For example, the vaguely-worded message:
118
119 @smallexample
120 demo.c:1:1: warning: 'noinline' attribute ignored [-Wattributes]
121 1 | int foo __attribute__((noinline));
122 | ^~~
123 @end smallexample
124
125 @noindent
126 doesn't tell the user why the attribute was ignored, or what kind of
127 entity the compiler thought the attribute was being applied to (the
128 source location for the diagnostic is also poor;
129 @pxref{input_location_example,,discussion of @code{input_location}}).
130 A better message would be:
131
132 @smallexample
133 demo.c:1:24: warning: attribute 'noinline' on variable 'foo' was
134 ignored [-Wattributes]
135 1 | int foo __attribute__((noinline));
136 | ~~~ ~~~~~~~~~~~~~~~^~~~~~~~~
137 demo.c:1:24: note: attribute 'noinline' is only applicable to functions
138 @end smallexample
139
140 @noindent
141 which spells out the missing information (and fixes the location
142 information, as discussed below).
143
144 The above example uses a note to avoid a combinatorial explosion of possible
145 messages.
146
147 @subsection Try the diagnostic on real-world code
148
149 It's worth testing a new warning on many instances of real-world code,
150 written by different people, and seeing what it complains about, and
151 what it doesn't complain about.
152
153 This may suggest heuristics that silence common false positives.
154
155 It may also suggest ways to improve the precision of the message.
156
157 @subsection Make mismatches clear
158
159 Many diagnostics relate to a mismatch between two different places in the
160 user's source code. Examples include:
161 @itemize @bullet
162 @item
163 a type mismatch, where the type at a usage site does not match the type
164 at a declaration
165
166 @item
167 the argument count at a call site does not match the parameter count
168 at the declaration
169
170 @item
171 something is erroneously duplicated (e.g.@: an error, due to breaking a
172 uniqueness requirement, or a warning, if it's suggestive of a bug)
173
174 @item
175 an ``opened'' syntactic construct (such as an open-parenthesis) is not
176 closed
177
178 @c TODO: more examples?
179 @end itemize
180
181 In each case, the diagnostic should indicate @strong{both} pertinent
182 locations (so that the user can easily see the problem and how to fix it).
183
184 The standard way to do this is with a note (via @code{inform}). For
185 example:
186
187 @smallexample
188 auto_diagnostic_group d;
189 if (warning_at (loc, OPT_Wduplicated_cond,
190 "duplicated %<if%> condition"))
191 inform (EXPR_LOCATION (t), "previously used here");
192 @end smallexample
193
194 @noindent
195 which leads to:
196
197 @smallexample
198 demo.c: In function 'test':
199 demo.c:5:17: warning: duplicated 'if' condition [-Wduplicated-cond]
200 5 | else if (flag > 3)
201 | ~~~~~^~~
202 demo.c:3:12: note: previously used here
203 3 | if (flag > 3)
204 | ~~~~~^~~
205 @end smallexample
206
207 @noindent
208 The @code{inform} call should be guarded by the return value from the
209 @code{warning_at} call so that the note isn't emitted when the warning
210 is suppressed.
211
212 For cases involving punctuation where the locations might be near
213 each other, they can be conditionally consolidated via
214 @code{gcc_rich_location::add_location_if_nearby}:
215
216 @smallexample
217 auto_diagnostic_group d;
218 gcc_rich_location richloc (primary_loc);
219 bool added secondary = richloc.add_location_if_nearby (secondary_loc);
220 error_at (&richloc, "main message");
221 if (!added secondary)
222 inform (secondary_loc, "message for secondary");
223 @end smallexample
224
225 @noindent
226 This will emit either one diagnostic with two locations:
227 @smallexample
228 demo.c:42:10: error: main message
229 (foo)
230 ~ ^
231 @end smallexample
232
233 @noindent
234 or two diagnostics:
235
236 @smallexample
237 demo.c:42:4: error: main message
238 foo)
239 ^
240 demo.c:40:2: note: message for secondary
241 (
242 ^
243 @end smallexample
244
245 @subsection Location Information
246 @cindex diagnostics, locations
247 @cindex location information
248 @cindex source code, location information
249 @cindex caret
250
251 GCC's @code{location_t} type can support both ordinary locations,
252 and locations relating to a macro expansion.
253
254 As of GCC 6, ordinary locations changed from supporting just a
255 point in the user's source code to supporting three points: the
256 @dfn{caret} location, plus a start and a finish:
257
258 @smallexample
259 a = foo && bar;
260 ~~~~^~~~~~
261 | | |
262 | | finish
263 | caret
264 start
265 @end smallexample
266
267 Tokens coming out of libcpp have locations of the form @code{caret == start},
268 such as for @code{foo} here:
269
270 @smallexample
271 a = foo && bar;
272 ^~~
273 | |
274 | finish
275 caret == start
276 @end smallexample
277
278 Compound expressions should be reported using the location of the
279 expression as a whole, rather than just of one token within it.
280
281 For example, in @code{-Wformat}, rather than underlining just the first
282 token of a bad argument:
283
284 @smallexample
285 printf("hello %i %s", (long)0, "world");
286 ~^ ~
287 %li
288 @end smallexample
289
290 @noindent
291 the whole of the expression should be underlined, so that the user can
292 easily identify what is being referred to:
293
294 @smallexample
295 printf("hello %i %s", (long)0, "world");
296 ~^ ~~~~~~~
297 %li
298 @end smallexample
299
300 @c this was r251239
301
302 Avoid using the @code{input_location} global, and the diagnostic functions
303 that implicitly use it---use @code{error_at} and @code{warning_at} rather
304 than @code{error} and @code{warning}, and provide the most appropriate
305 @code{location_t} value available at that phase of the compilation. It's
306 possible to supply secondary @code{location_t} values via
307 @code{rich_location}.
308
309 @noindent
310 @anchor{input_location_example}
311 For example, in the example of imprecise wording above, generating the
312 diagnostic using @code{warning}:
313
314 @smallexample
315 // BAD: implicitly uses @code{input_location}
316 warning (OPT_Wattributes, "%qE attribute ignored", name);
317 @end smallexample
318
319 @noindent
320 leads to:
321
322 @smallexample
323 // BAD: uses @code{input_location}
324 demo.c:1:1: warning: 'noinline' attribute ignored [-Wattributes]
325 1 | int foo __attribute__((noinline));
326 | ^~~
327 @end smallexample
328
329 @noindent
330 which thus happened to use the location of the @code{int} token, rather
331 than that of the attribute. Using @code{warning_at} with the location of
332 the attribute, providing the location of the declaration in question
333 as a secondary location, and adding a note:
334
335 @smallexample
336 auto_diagnostic_group d;
337 gcc_rich_location richloc (attrib_loc);
338 richloc.add_range (decl_loc);
339 if (warning_at (OPT_Wattributes, &richloc,
340 "attribute %qE on variable %qE was ignored", name))
341 inform (attrib_loc, "attribute %qE is only applicable to functions");
342 @end smallexample
343
344 @noindent
345 would lead to:
346
347 @smallexample
348 // OK: use location of attribute, with a secondary location
349 demo.c:1:24: warning: attribute 'noinline' on variable 'foo' was
350 ignored [-Wattributes]
351 1 | int foo __attribute__((noinline));
352 | ~~~ ~~~~~~~~~~~~~~~^~~~~~~~~
353 demo.c:1:24: note: attribute 'noinline' is only applicable to functions
354 @end smallexample
355
356 @c TODO labelling of ranges
357
358 @subsection Coding Conventions
359
360 See the @uref{https://gcc.gnu.org/codingconventions.html#Diagnostics,
361 diagnostics section} of the GCC coding conventions.
362
363 In the C++ front end, when comparing two types in a message, use @samp{%H}
364 and @samp{%I} rather than @samp{%T}, as this allows the diagnostics
365 subsystem to highlight differences between template-based types.
366 For example, rather than using @samp{%qT}:
367
368 @smallexample
369 // BAD: a pair of %qT used in C++ front end for type comparison
370 error_at (loc, "could not convert %qE from %qT to %qT", expr,
371 TREE_TYPE (expr), type);
372 @end smallexample
373
374 @noindent
375 which could lead to:
376
377 @smallexample
378 error: could not convert 'map<int, double>()' from 'map<int,double>'
379 to 'map<int,int>'
380 @end smallexample
381
382 @noindent
383 using @samp{%H} and @samp{%I} (via @samp{%qH} and @samp{%qI}):
384
385 @smallexample
386 // OK: compare types in C++ front end via %qH and %qI
387 error_at (loc, "could not convert %qE from %qH to %qI", expr,
388 TREE_TYPE (expr), type);
389 @end smallexample
390
391 @noindent
392 allows the above output to be simplified to:
393
394 @smallexample
395 error: could not convert 'map<int, double>()' from 'map<[...],double>'
396 to 'map<[...],int>'
397 @end smallexample
398
399 @noindent
400 where the @code{double} and @code{int} are colorized to highlight them.
401
402 @c %H and %I were added in r248698.
403
404 @subsection Group logically-related diagnostics
405
406 Use @code{auto_diagnostic_group} when issuing multiple related
407 diagnostics (seen in various examples on this page). This informs the
408 diagnostic subsystem that all diagnostics issued within the lifetime
409 of the @code{auto_diagnostic_group} are related. For example,
410 @option{-fdiagnostics-format=json} will treat the first diagnostic
411 emitted within the group as a top-level diagnostic, and all subsequent
412 diagnostics within the group as its children.
413
414 @subsection Quoting
415 Text should be quoted by either using the @samp{q} modifier in a directive
416 such as @samp{%qE}, or by enclosing the quoted text in a pair of @samp{%<}
417 and @samp{%>} directives, and never by using explicit quote characters.
418 The directives handle the appropriate quote characters for each language
419 and apply the correct color or highlighting.
420
421 The following elements should be quoted in GCC diagnostics:
422
423 @itemize @bullet
424 @item
425 Language keywords.
426 @item
427 Tokens.
428 @item
429 Boolean, numerical, character, and string constants that appear in the
430 source code.
431 @item
432 Identifiers, including function, macro, type, and variable names.
433 @end itemize
434
435 Other elements such as numbers that do not refer to numeric constants that
436 appear in the source code should not be quoted. For example, in the message:
437
438 @smallexample
439 argument %d of %qE must be a pointer type
440 @end smallexample
441
442 @noindent
443 since the argument number does not refer to a numerical constant in the
444 source code it should not be quoted.
445
446 @subsection Spelling and Terminology
447
448 See the @uref{https://gcc.gnu.org/codingconventions.html#Spelling
449 Spelling, terminology and markup} section of the GCC coding conventions.
450
451 @subsection Fix-it hints
452 @cindex fix-it hints
453 @cindex diagnostics guidelines, fix-it hints
454
455 GCC's diagnostic subsystem can emit @dfn{fix-it hints}: small suggested
456 edits to the user's source code.
457
458 They are printed by default underneath the code in question. They
459 can also be viewed via @option{-fdiagnostics-generate-patch} and
460 @option{-fdiagnostics-parseable-fixits}. With the latter, an IDE
461 ought to be able to offer to automatically apply the suggested fix.
462
463 Fix-it hints contain code fragments, and thus they should not be marked
464 for translation.
465
466 Fix-it hints can be added to a diagnostic by using a @code{rich_location}
467 rather than a @code{location_t} - the fix-it hints are added to the
468 @code{rich_location} using one of the various @code{add_fixit} member
469 functions of @code{rich_location}. They are documented with
470 @code{rich_location} in @file{libcpp/line-map.h}.
471 It's easiest to use the @code{gcc_rich_location} subclass of
472 @code{rich_location} found in @file{gcc-rich-location.h}, as this
473 implicitly supplies the @code{line_table} variable.
474
475 For example:
476
477 @smallexample
478 if (const char *suggestion = hint.suggestion ())
479 @{
480 gcc_rich_location richloc (location);
481 richloc.add_fixit_replace (suggestion);
482 error_at (&richloc,
483 "%qE does not name a type; did you mean %qs?",
484 id, suggestion);
485 @}
486 @end smallexample
487
488 @noindent
489 which can lead to:
490
491 @smallexample
492 spellcheck-typenames.C:73:1: error: 'singed' does not name a type; did
493 you mean 'signed'?
494 73 | singed char ch;
495 | ^~~~~~
496 | signed
497 @end smallexample
498
499 Non-trivial edits can be built up by adding multiple fix-it hints to one
500 @code{rich_location}. It's best to express the edits in terms of the
501 locations of individual tokens. Various handy functions for adding
502 fix-it hints for idiomatic C and C++ can be seen in
503 @file{gcc-rich-location.h}.
504
505 @subsubsection Fix-it hints should work
506
507 When implementing a fix-it hint, please verify that the suggested edit
508 leads to fixed, compilable code. (Unfortunately, this currently must be
509 done by hand using @option{-fdiagnostics-generate-patch}. It would be
510 good to have an automated way of verifying that fix-it hints actually fix
511 the code).
512
513 For example, a ``gotcha'' here is to forget to add a space when adding a
514 missing reserved word. Consider a C++ fix-it hint that adds
515 @code{typename} in front of a template declaration. A naive way to
516 implement this might be:
517
518 @smallexample
519 gcc_rich_location richloc (loc);
520 // BAD: insertion is missing a trailing space
521 richloc.add_fixit_insert_before ("typename");
522 error_at (&richloc, "need %<typename%> before %<%T::%E%> because "
523 "%qT is a dependent scope",
524 parser->scope, id, parser->scope);
525 @end smallexample
526
527 @noindent
528 When applied to the code, this might lead to:
529
530 @smallexample
531 T::type x;
532 @end smallexample
533
534 @noindent
535 being ``corrected'' to:
536
537 @smallexample
538 typenameT::type x;
539 @end smallexample
540
541 @noindent
542 In this case, the correct thing to do is to add a trailing space after
543 @code{typename}:
544
545 @smallexample
546 gcc_rich_location richloc (loc);
547 // OK: note that here we have a trailing space
548 richloc.add_fixit_insert_before ("typename ");
549 error_at (&richloc, "need %<typename%> before %<%T::%E%> because "
550 "%qT is a dependent scope",
551 parser->scope, id, parser->scope);
552 @end smallexample
553
554 @noindent
555 leading to this corrected code:
556
557 @smallexample
558 typename T::type x;
559 @end smallexample
560
561 @subsubsection Express deletion in terms of deletion, not replacement
562
563 It's best to express deletion suggestions in terms of deletion fix-it
564 hints, rather than replacement fix-it hints. For example, consider this:
565
566 @smallexample
567 auto_diagnostic_group d;
568 gcc_rich_location richloc (location_of (retval));
569 tree name = DECL_NAME (arg);
570 richloc.add_fixit_replace (IDENTIFIER_POINTER (name));
571 warning_at (&richloc, OPT_Wredundant_move,
572 "redundant move in return statement");
573 @end smallexample
574
575 @noindent
576 which is intended to e.g.@: replace a @code{std::move} with the underlying
577 value:
578
579 @smallexample
580 return std::move (retval);
581 ~~~~~~~~~~^~~~~~~~
582 retval
583 @end smallexample
584
585 @noindent
586 where the change has been expressed as replacement, replacing
587 with the name of the declaration.
588 This works for simple cases, but consider this case:
589
590 @smallexample
591 #ifdef SOME_CONFIG_FLAG
592 # define CONFIGURY_GLOBAL global_a
593 #else
594 # define CONFIGURY_GLOBAL global_b
595 #endif
596
597 int fn ()
598 @{
599 return std::move (CONFIGURY_GLOBAL /* some comment */);
600 @}
601 @end smallexample
602
603 @noindent
604 The above implementation erroneously strips out the macro and the
605 comment in the fix-it hint:
606
607 @smallexample
608 return std::move (CONFIGURY_GLOBAL /* some comment */);
609 ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
610 global_a
611 @end smallexample
612
613 @noindent
614 and thus this resulting code:
615
616 @smallexample
617 return global_a;
618 @end smallexample
619
620 @noindent
621 It's better to do deletions in terms of deletions; deleting the
622 @code{std::move (} and the trailing close-paren, leading to
623 this:
624
625 @smallexample
626 return std::move (CONFIGURY_GLOBAL /* some comment */);
627 ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
628 CONFIGURY_GLOBAL /* some comment */
629 @end smallexample
630
631 @noindent
632 and thus this result:
633
634 @smallexample
635 return CONFIGURY_GLOBAL /* some comment */;
636 @end smallexample
637
638 @noindent
639 Unfortunately, the pertinent @code{location_t} values are not always
640 available.
641
642 @c the above was https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01474.html
643
644 @subsubsection Multiple suggestions
645
646 In the rare cases where you need to suggest more than one mutually
647 exclusive solution to a problem, this can be done by emitting
648 multiple notes and calling
649 @code{rich_location::fixits_cannot_be_auto_applied} on each note's
650 @code{rich_location}. If this is called, then the fix-it hints in
651 the @code{rich_location} will be printed, but will not be added to
652 generated patches.
653
654
655 @node Guidelines for Options
656 @section Guidelines for Options
657 @cindex command-line options, guidelines for
658 @cindex options, guidelines for
659 @cindex guidelines for options
660
661 @c TODO