]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/doc/ux.texi
Update copyright years.
[thirdparty/gcc.git] / gcc / doc / ux.texi
CommitLineData
99dee823 1@c Copyright (C) 2018-2021 Free Software Foundation, Inc.
92646d25
DM
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
11To borrow a slogan from
d782af8f 12@uref{https://elm-lang.org/news/compilers-as-assistants, Elm},
92646d25
DM
13
14@quotation
15@strong{Compilers should be assistants, not adversaries.} A compiler should
16not just detect bugs, it should then help you understand why there is a bug.
17It should not berate you in a robot voice, it should give you specific hints
18that help you write better code. Ultimately, a compiler should make
19programming faster and more fun!
20@author Evan Czaplicki
21@end quotation
22
23This chapter provides guidelines on how to implement diagnostics and
24command-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
79e61dc2 33@section Guidelines for Diagnostics
92646d25
DM
34@cindex guidelines for diagnostics
35@cindex diagnostics, guidelines for
36
92646d25
DM
37@subsection Talk in terms of the user's code
38
39Diagnostics should be worded in terms of the user's source code, and the
40source language, rather than GCC's own implementation details.
41
42@subsection Diagnostics are actionable
43@cindex diagnostics, actionable
44
45A good diagnostic is @dfn{actionable}: it should assist the user in
46taking action.
47
48Consider what an end user will want to do when encountering a diagnostic.
49
50Given an error, an end user will think: ``How do I fix this?''
51
52Given 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
60if they decide it's genuine: ``How do I fix this?''
61@end itemize
62
63A good diagnostic provides pertinent information to allow the user to
64easily answer the above questions.
65
66@subsection The user's attention is important
67
68A perfect compiler would issue a warning on every aspect of the user's
69source code that ought to be fixed, and issue no other warnings.
70Naturally, 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
78Warnings 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
80warranted) and few @dfn{false negatives} (failing to issue a warning when
81one @emph{is} justified).
82
83Note that a false positive can mean, in practice, a warning that the
84user doesn't agree with. Ideally a diagnostic should contain enough
85information to allow the user to make an informed choice about whether
86they should care (and how to fix it), but a balance must be drawn against
87overloading the user with irrelevant data.
88
89@subsection Precision of Wording
90
91Provide the user with details that allow them to identify what the
92problem is. For example, the vaguely-worded message:
93
94@smallexample
95demo.c:1:1: warning: 'noinline' attribute ignored [-Wattributes]
96 1 | int foo __attribute__((noinline));
97 | ^~~
98@end smallexample
99
100@noindent
101doesn't tell the user why the attribute was ignored, or what kind of
102entity the compiler thought the attribute was being applied to (the
103source location for the diagnostic is also poor;
104@pxref{input_location_example,,discussion of @code{input_location}}).
105A better message would be:
106
107@smallexample
108demo.c:1:24: warning: attribute 'noinline' on variable 'foo' was
109 ignored [-Wattributes]
110 1 | int foo __attribute__((noinline));
111 | ~~~ ~~~~~~~~~~~~~~~^~~~~~~~~
112demo.c:1:24: note: attribute 'noinline' is only applicable to functions
113@end smallexample
114
115@noindent
116which spells out the missing information (and fixes the location
117information, as discussed below).
118
119The above example uses a note to avoid a combinatorial explosion of possible
120messages.
121
122@subsection Try the diagnostic on real-world code
123
124It's worth testing a new warning on many instances of real-world code,
125written by different people, and seeing what it complains about, and
126what it doesn't complain about.
127
128This may suggest heuristics that silence common false positives.
129
130It may also suggest ways to improve the precision of the message.
131
132@subsection Make mismatches clear
133
134Many diagnostics relate to a mismatch between two different places in the
135user'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
630ba2fd 146 something is erroneously duplicated (e.g.@: an error, due to breaking a
92646d25
DM
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
156In each case, the diagnostic should indicate @strong{both} pertinent
157locations (so that the user can easily see the problem and how to fix it).
158
159The standard way to do this is with a note (via @code{inform}). For
160example:
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
170which leads to:
171
172@smallexample
173demo.c: In function 'test':
174demo.c:5:17: warning: duplicated 'if' condition [-Wduplicated-cond]
175 5 | else if (flag > 3)
176 | ~~~~~^~~
177demo.c:3:12: note: previously used here
178 3 | if (flag > 3)
179 | ~~~~~^~~
180@end smallexample
181
182@noindent
183The @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
185is suppressed.
186
187For cases involving punctuation where the locations might be near
188each 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
201This 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
209or 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
226GCC's @code{location_t} type can support both ordinary locations,
227and locations relating to a macro expansion.
228
229As of GCC 6, ordinary locations changed from supporting just a
230point 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
242Tokens coming out of libcpp have locations of the form @code{caret == start},
243such as for @code{foo} here:
244
245@smallexample
246 a = foo && bar;
247 ^~~
248 | |
249 | finish
250 caret == start
251@end smallexample
252
253Compound expressions should be reported using the location of the
254expression as a whole, rather than just of one token within it.
255
256For example, in @code{-Wformat}, rather than underlining just the first
257token of a bad argument:
258
259@smallexample
260 printf("hello %i %s", (long)0, "world");
261 ~^ ~
262 %li
263@end smallexample
264
265@noindent
266the whole of the expression should be underlined, so that the user can
267easily 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
277Avoid using the @code{input_location} global, and the diagnostic functions
278that implicitly use it---use @code{error_at} and @code{warning_at} rather
279than @code{error} and @code{warning}, and provide the most appropriate
280@code{location_t} value available at that phase of the compilation. It's
281possible to supply secondary @code{location_t} values via
282@code{rich_location}.
283
284@noindent
285@anchor{input_location_example}
286For example, in the example of imprecise wording above, generating the
287diagnostic 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
295leads to:
296
297@smallexample
298// BAD: uses @code{input_location}
299demo.c:1:1: warning: 'noinline' attribute ignored [-Wattributes]
300 1 | int foo __attribute__((noinline));
301 | ^~~
302@end smallexample
303
304@noindent
305which thus happened to use the location of the @code{int} token, rather
306than that of the attribute. Using @code{warning_at} with the location of
307the attribute, providing the location of the declaration in question
308as 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
320would lead to:
321
322@smallexample
323// OK: use location of attribute, with a secondary location
324demo.c:1:24: warning: attribute 'noinline' on variable 'foo' was
325 ignored [-Wattributes]
326 1 | int foo __attribute__((noinline));
327 | ~~~ ~~~~~~~~~~~~~~~^~~~~~~~~
328demo.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
335See the @uref{https://gcc.gnu.org/codingconventions.html#Diagnostics,
336diagnostics section} of the GCC coding conventions.
337
338In the C++ front end, when comparing two types in a message, use @samp{%H}
339and @samp{%I} rather than @samp{%T}, as this allows the diagnostics
340subsystem to highlight differences between template-based types.
341For 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
350which could lead to:
351
352@smallexample
353error: could not convert 'map<int, double>()' from 'map<int,double>'
354 to 'map<int,int>'
355@end smallexample
356
357@noindent
358using @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
367allows the above output to be simplified to:
368
369@smallexample
370error: could not convert 'map<int, double>()' from 'map<[...],double>'
371 to 'map<[...],int>'
372@end smallexample
373
374@noindent
375where the @code{double} and @code{int} are colorized to highlight them.
376
377@c %H and %I were added in r248698.
378
1a50c428
DM
379@subsection Group logically-related diagnostics
380
92646d25
DM
381Use @code{auto_diagnostic_group} when issuing multiple related
382diagnostics (seen in various examples on this page). This informs the
383diagnostic subsystem that all diagnostics issued within the lifetime
1a50c428
DM
384of the @code{auto_diagnostic_group} are related. For example,
385@option{-fdiagnostics-format=json} will treat the first diagnostic
386emitted within the group as a top-level diagnostic, and all subsequent
387diagnostics within the group as its children.
92646d25 388
90938ef8
DM
389@subsection Quoting
390Text should be quoted by either using the @samp{q} modifier in a directive
391such as @samp{%qE}, or by enclosing the quoted text in a pair of @samp{%<}
392and @samp{%>} directives, and never by using explicit quote characters.
393The directives handle the appropriate quote characters for each language
394and apply the correct color or highlighting.
395
396The following elements should be quoted in GCC diagnostics:
397
398@itemize @bullet
399@item
400Language keywords.
401@item
402Tokens.
403@item
404Boolean, numerical, character, and string constants that appear in the
405source code.
406@item
407Identifiers, including function, macro, type, and variable names.
408@end itemize
409
410Other elements such as numbers that do not refer to numeric constants that
411appear in the source code should not be quoted. For example, in the message:
412
413@smallexample
414argument %d of %qE must be a pointer type
415@end smallexample
416
417@noindent
418since the argument number does not refer to a numerical constant in the
419source code it should not be quoted.
420
92646d25
DM
421@subsection Spelling and Terminology
422
423See the @uref{https://gcc.gnu.org/codingconventions.html#Spelling
424Spelling, terminology and markup} section of the GCC coding conventions.
425
426@subsection Fix-it hints
427@cindex fix-it hints
428@cindex diagnostics guidelines, fix-it hints
429
430GCC's diagnostic subsystem can emit @dfn{fix-it hints}: small suggested
431edits to the user's source code.
432
433They are printed by default underneath the code in question. They
434can also be viewed via @option{-fdiagnostics-generate-patch} and
435@option{-fdiagnostics-parseable-fixits}. With the latter, an IDE
436ought to be able to offer to automatically apply the suggested fix.
437
90938ef8
DM
438Fix-it hints contain code fragments, and thus they should not be marked
439for translation.
440
92646d25
DM
441Fix-it hints can be added to a diagnostic by using a @code{rich_location}
442rather than a @code{location_t} - the fix-it hints are added to the
443@code{rich_location} using one of the various @code{add_fixit} member
444functions of @code{rich_location}. They are documented with
445@code{rich_location} in @file{libcpp/line-map.h}.
446It's easiest to use the @code{gcc_rich_location} subclass of
447@code{rich_location} found in @file{gcc-rich-location.h}, as this
448implicitly supplies the @code{line_table} variable.
449
450For example:
451
452@smallexample
453 if (const char *suggestion = hint.suggestion ())
454 @{
455 gcc_rich_location richloc (location);
456 richloc.add_fixit_replace (suggestion);
457 error_at (&richloc,
458 "%qE does not name a type; did you mean %qs?",
459 id, suggestion);
460 @}
461@end smallexample
462
463@noindent
464which can lead to:
465
466@smallexample
467spellcheck-typenames.C:73:1: error: 'singed' does not name a type; did
468 you mean 'signed'?
469 73 | singed char ch;
470 | ^~~~~~
471 | signed
472@end smallexample
473
474Non-trivial edits can be built up by adding multiple fix-it hints to one
475@code{rich_location}. It's best to express the edits in terms of the
476locations of individual tokens. Various handy functions for adding
477fix-it hints for idiomatic C and C++ can be seen in
478@file{gcc-rich-location.h}.
479
480@subsubsection Fix-it hints should work
481
482When implementing a fix-it hint, please verify that the suggested edit
483leads to fixed, compilable code. (Unfortunately, this currently must be
484done by hand using @option{-fdiagnostics-generate-patch}. It would be
485good to have an automated way of verifying that fix-it hints actually fix
486the code).
487
488For example, a ``gotcha'' here is to forget to add a space when adding a
489missing reserved word. Consider a C++ fix-it hint that adds
490@code{typename} in front of a template declaration. A naive way to
491implement this might be:
492
493@smallexample
494gcc_rich_location richloc (loc);
495// BAD: insertion is missing a trailing space
496richloc.add_fixit_insert_before ("typename");
497error_at (&richloc, "need %<typename%> before %<%T::%E%> because "
498 "%qT is a dependent scope",
499 parser->scope, id, parser->scope);
500@end smallexample
501
502@noindent
503When applied to the code, this might lead to:
504
505@smallexample
506T::type x;
507@end smallexample
508
509@noindent
510being ``corrected'' to:
511
512@smallexample
513typenameT::type x;
514@end smallexample
515
516@noindent
517In this case, the correct thing to do is to add a trailing space after
518@code{typename}:
519
520@smallexample
521gcc_rich_location richloc (loc);
522// OK: note that here we have a trailing space
523richloc.add_fixit_insert_before ("typename ");
524error_at (&richloc, "need %<typename%> before %<%T::%E%> because "
525 "%qT is a dependent scope",
526 parser->scope, id, parser->scope);
527@end smallexample
528
529@noindent
530leading to this corrected code:
531
532@smallexample
533typename T::type x;
534@end smallexample
535
536@subsubsection Express deletion in terms of deletion, not replacement
537
538It's best to express deletion suggestions in terms of deletion fix-it
539hints, rather than replacement fix-it hints. For example, consider this:
540
541@smallexample
542 auto_diagnostic_group d;
543 gcc_rich_location richloc (location_of (retval));
544 tree name = DECL_NAME (arg);
545 richloc.add_fixit_replace (IDENTIFIER_POINTER (name));
546 warning_at (&richloc, OPT_Wredundant_move,
547 "redundant move in return statement");
548@end smallexample
549
550@noindent
630ba2fd 551which is intended to e.g.@: replace a @code{std::move} with the underlying
92646d25
DM
552value:
553
554@smallexample
555 return std::move (retval);
556 ~~~~~~~~~~^~~~~~~~
557 retval
558@end smallexample
559
560@noindent
561where the change has been expressed as replacement, replacing
562with the name of the declaration.
563This works for simple cases, but consider this case:
564
565@smallexample
566#ifdef SOME_CONFIG_FLAG
567# define CONFIGURY_GLOBAL global_a
568#else
569# define CONFIGURY_GLOBAL global_b
570#endif
571
572int fn ()
573@{
574 return std::move (CONFIGURY_GLOBAL /* some comment */);
575@}
576@end smallexample
577
578@noindent
579The above implementation erroneously strips out the macro and the
580comment in the fix-it hint:
581
582@smallexample
583 return std::move (CONFIGURY_GLOBAL /* some comment */);
584 ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
585 global_a
586@end smallexample
587
588@noindent
589and thus this resulting code:
590
591@smallexample
592 return global_a;
593@end smallexample
594
595@noindent
596It's better to do deletions in terms of deletions; deleting the
597@code{std::move (} and the trailing close-paren, leading to
598this:
599
600@smallexample
601 return std::move (CONFIGURY_GLOBAL /* some comment */);
602 ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
603 CONFIGURY_GLOBAL /* some comment */
604@end smallexample
605
606@noindent
607and thus this result:
608
609@smallexample
610 return CONFIGURY_GLOBAL /* some comment */;
611@end smallexample
612
613@noindent
614Unfortunately, the pertinent @code{location_t} values are not always
615available.
616
617@c the above was https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01474.html
618
619@subsubsection Multiple suggestions
620
621In the rare cases where you need to suggest more than one mutually
622exclusive solution to a problem, this can be done by emitting
623multiple notes and calling
624@code{rich_location::fixits_cannot_be_auto_applied} on each note's
625@code{rich_location}. If this is called, then the fix-it hints in
626the @code{rich_location} will be printed, but will not be added to
627generated patches.
628
629
630@node Guidelines for Options
79e61dc2 631@section Guidelines for Options
92646d25
DM
632@cindex command-line options, guidelines for
633@cindex options, guidelines for
634@cindex guidelines for options
635
92646d25 636@c TODO