1@c Copyright (C) 2018-2020 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 11To 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 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 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 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 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 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 379@subsection Group logically-related diagnostics 380 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 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. 388 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 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 438Fix-it hints contain code fragments, and thus they should not be marked 439for translation. 440 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 551which is intended to e.g.@: replace a @code{std::move} with the underlying 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 631@section Guidelines for Options 632@cindex command-line options, guidelines for 633@cindex options, guidelines for 634@cindex guidelines for options 635 636@c TODO 637