145
|
1 @c Copyright (C) 2018-2020 Free Software Foundation, Inc.
|
131
|
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
|
145
|
12 @uref{https://elm-lang.org/news/compilers-as-assistants, Elm},
|
131
|
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
|
145
|
146 something is erroneously duplicated (e.g.@: an error, due to breaking a
|
131
|
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
|
145
|
379 @subsection Group logically-related diagnostics
|
|
380
|
131
|
381 Use @code{auto_diagnostic_group} when issuing multiple related
|
|
382 diagnostics (seen in various examples on this page). This informs the
|
|
383 diagnostic subsystem that all diagnostics issued within the lifetime
|
145
|
384 of the @code{auto_diagnostic_group} are related. For example,
|
|
385 @option{-fdiagnostics-format=json} will treat the first diagnostic
|
|
386 emitted within the group as a top-level diagnostic, and all subsequent
|
|
387 diagnostics within the group as its children.
|
|
388
|
|
389 @subsection Quoting
|
|
390 Text should be quoted by either using the @samp{q} modifier in a directive
|
|
391 such as @samp{%qE}, or by enclosing the quoted text in a pair of @samp{%<}
|
|
392 and @samp{%>} directives, and never by using explicit quote characters.
|
|
393 The directives handle the appropriate quote characters for each language
|
|
394 and apply the correct color or highlighting.
|
|
395
|
|
396 The following elements should be quoted in GCC diagnostics:
|
|
397
|
|
398 @itemize @bullet
|
|
399 @item
|
|
400 Language keywords.
|
|
401 @item
|
|
402 Tokens.
|
|
403 @item
|
|
404 Boolean, numerical, character, and string constants that appear in the
|
|
405 source code.
|
|
406 @item
|
|
407 Identifiers, including function, macro, type, and variable names.
|
|
408 @end itemize
|
|
409
|
|
410 Other elements such as numbers that do not refer to numeric constants that
|
|
411 appear in the source code should not be quoted. For example, in the message:
|
|
412
|
|
413 @smallexample
|
|
414 argument %d of %qE must be a pointer type
|
|
415 @end smallexample
|
|
416
|
|
417 @noindent
|
|
418 since the argument number does not refer to a numerical constant in the
|
|
419 source code it should not be quoted.
|
131
|
420
|
|
421 @subsection Spelling and Terminology
|
|
422
|
|
423 See the @uref{https://gcc.gnu.org/codingconventions.html#Spelling
|
|
424 Spelling, 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
|
|
430 GCC's diagnostic subsystem can emit @dfn{fix-it hints}: small suggested
|
|
431 edits to the user's source code.
|
|
432
|
|
433 They are printed by default underneath the code in question. They
|
|
434 can also be viewed via @option{-fdiagnostics-generate-patch} and
|
|
435 @option{-fdiagnostics-parseable-fixits}. With the latter, an IDE
|
|
436 ought to be able to offer to automatically apply the suggested fix.
|
|
437
|
145
|
438 Fix-it hints contain code fragments, and thus they should not be marked
|
|
439 for translation.
|
|
440
|
131
|
441 Fix-it hints can be added to a diagnostic by using a @code{rich_location}
|
|
442 rather 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
|
|
444 functions of @code{rich_location}. They are documented with
|
|
445 @code{rich_location} in @file{libcpp/line-map.h}.
|
|
446 It's easiest to use the @code{gcc_rich_location} subclass of
|
|
447 @code{rich_location} found in @file{gcc-rich-location.h}, as this
|
|
448 implicitly supplies the @code{line_table} variable.
|
|
449
|
|
450 For 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
|
|
464 which can lead to:
|
|
465
|
|
466 @smallexample
|
|
467 spellcheck-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
|
|
474 Non-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
|
|
476 locations of individual tokens. Various handy functions for adding
|
|
477 fix-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
|
|
482 When implementing a fix-it hint, please verify that the suggested edit
|
|
483 leads to fixed, compilable code. (Unfortunately, this currently must be
|
|
484 done by hand using @option{-fdiagnostics-generate-patch}. It would be
|
|
485 good to have an automated way of verifying that fix-it hints actually fix
|
|
486 the code).
|
|
487
|
|
488 For example, a ``gotcha'' here is to forget to add a space when adding a
|
|
489 missing reserved word. Consider a C++ fix-it hint that adds
|
|
490 @code{typename} in front of a template declaration. A naive way to
|
|
491 implement this might be:
|
|
492
|
|
493 @smallexample
|
|
494 gcc_rich_location richloc (loc);
|
|
495 // BAD: insertion is missing a trailing space
|
|
496 richloc.add_fixit_insert_before ("typename");
|
|
497 error_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
|
|
503 When applied to the code, this might lead to:
|
|
504
|
|
505 @smallexample
|
|
506 T::type x;
|
|
507 @end smallexample
|
|
508
|
|
509 @noindent
|
|
510 being ``corrected'' to:
|
|
511
|
|
512 @smallexample
|
|
513 typenameT::type x;
|
|
514 @end smallexample
|
|
515
|
|
516 @noindent
|
|
517 In this case, the correct thing to do is to add a trailing space after
|
|
518 @code{typename}:
|
|
519
|
|
520 @smallexample
|
|
521 gcc_rich_location richloc (loc);
|
|
522 // OK: note that here we have a trailing space
|
|
523 richloc.add_fixit_insert_before ("typename ");
|
|
524 error_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
|
|
530 leading to this corrected code:
|
|
531
|
|
532 @smallexample
|
|
533 typename T::type x;
|
|
534 @end smallexample
|
|
535
|
|
536 @subsubsection Express deletion in terms of deletion, not replacement
|
|
537
|
|
538 It's best to express deletion suggestions in terms of deletion fix-it
|
|
539 hints, 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
|
145
|
551 which is intended to e.g.@: replace a @code{std::move} with the underlying
|
131
|
552 value:
|
|
553
|
|
554 @smallexample
|
|
555 return std::move (retval);
|
|
556 ~~~~~~~~~~^~~~~~~~
|
|
557 retval
|
|
558 @end smallexample
|
|
559
|
|
560 @noindent
|
|
561 where the change has been expressed as replacement, replacing
|
|
562 with the name of the declaration.
|
|
563 This 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
|
|
572 int fn ()
|
|
573 @{
|
|
574 return std::move (CONFIGURY_GLOBAL /* some comment */);
|
|
575 @}
|
|
576 @end smallexample
|
|
577
|
|
578 @noindent
|
|
579 The above implementation erroneously strips out the macro and the
|
|
580 comment 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
|
|
589 and thus this resulting code:
|
|
590
|
|
591 @smallexample
|
|
592 return global_a;
|
|
593 @end smallexample
|
|
594
|
|
595 @noindent
|
|
596 It's better to do deletions in terms of deletions; deleting the
|
|
597 @code{std::move (} and the trailing close-paren, leading to
|
|
598 this:
|
|
599
|
|
600 @smallexample
|
|
601 return std::move (CONFIGURY_GLOBAL /* some comment */);
|
|
602 ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
603 CONFIGURY_GLOBAL /* some comment */
|
|
604 @end smallexample
|
|
605
|
|
606 @noindent
|
|
607 and thus this result:
|
|
608
|
|
609 @smallexample
|
|
610 return CONFIGURY_GLOBAL /* some comment */;
|
|
611 @end smallexample
|
|
612
|
|
613 @noindent
|
|
614 Unfortunately, the pertinent @code{location_t} values are not always
|
|
615 available.
|
|
616
|
|
617 @c the above was https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01474.html
|
|
618
|
|
619 @subsubsection Multiple suggestions
|
|
620
|
|
621 In the rare cases where you need to suggest more than one mutually
|
|
622 exclusive solution to a problem, this can be done by emitting
|
|
623 multiple 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
|
|
626 the @code{rich_location} will be printed, but will not be added to
|
|
627 generated 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
|