Mercurial > hg > CbC > CbC_llvm
comparison clang/www/diagnostics.html @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" | |
2 "http://www.w3.org/TR/html4/strict.dtd"> | |
3 <html> | |
4 <head> | |
5 <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> | |
6 <title>Clang - Expressive Diagnostics</title> | |
7 <link type="text/css" rel="stylesheet" href="menu.css"> | |
8 <link type="text/css" rel="stylesheet" href="content.css"> | |
9 <style type="text/css"> | |
10 .loc { font-weight: bold; } | |
11 .err { color:red; font-weight: bold; } | |
12 .warn { color:magenta; font-weight: bold; } | |
13 .note { color:gray; font-weight: bold; } | |
14 .msg { font-weight: bold; } | |
15 .cmd { font-style: italic; } | |
16 .snip { } | |
17 .point { color:green; font-weight: bold; } | |
18 </style> | |
19 </head> | |
20 <body> | |
21 | |
22 <!--#include virtual="menu.html.incl"--> | |
23 | |
24 <div id="content"> | |
25 | |
26 | |
27 <!--=======================================================================--> | |
28 <h1>Expressive Diagnostics</h1> | |
29 <!--=======================================================================--> | |
30 | |
31 <p>In addition to being fast and functional, we aim to make Clang extremely user | |
32 friendly. As far as a command-line compiler goes, this basically boils down to | |
33 making the diagnostics (error and warning messages) generated by the compiler | |
34 be as useful as possible. There are several ways that we do this. This section | |
35 talks about the experience provided by the command line compiler, contrasting | |
36 Clang output to GCC 4.9's output in some cases. | |
37 </p> | |
38 | |
39 <h2>Column Numbers and Caret Diagnostics</h2> | |
40 | |
41 <p>First, all diagnostics produced by clang include full column number | |
42 information. The clang command-line compiler driver uses this information | |
43 to print "point diagnostics". | |
44 (IDEs can use the information to display in-line error markup.) | |
45 This is nice because it makes it very easy to understand exactly | |
46 what is wrong in a particular piece of code.</p> | |
47 | |
48 <p>The point (the green "^" character) exactly shows where the problem is, even | |
49 inside of a string. This makes it really easy to jump to the problem and | |
50 helps when multiple instances of the same character occur on a line. (We'll | |
51 revisit this more in following examples.)</p> | |
52 | |
53 <pre> | |
54 $ <span class="cmd">clang -fsyntax-only format-strings.c</span> | |
55 <span class="loc">format-strings.c:91:13:</span> <span class="warn">warning:</span> <span class="msg">'.*' specified field precision is missing a matching 'int' argument</span> | |
56 <span class="snip" > printf("%.*d");</span> | |
57 <span class="point"> ^</span> | |
58 </pre> | |
59 | |
60 <p>Note that modern versions of GCC have followed Clang's lead, and are | |
61 now able to give a column for a diagnostic, and include a snippet of source | |
62 text in the result. However, Clang's column number is much more accurate, | |
63 pointing at the problematic format specifier, rather than the <tt>)</tt> | |
64 character the parser had reached when the problem was detected. | |
65 Also, Clang's diagnostic is colored by default, making it easier to | |
66 distinguish from nearby text.</p> | |
67 | |
68 <h2>Range Highlighting for Related Text</h2> | |
69 | |
70 <p>Clang captures and accurately tracks range information for expressions, | |
71 statements, and other constructs in your program and uses this to make | |
72 diagnostics highlight related information. In the following somewhat | |
73 nonsensical example you can see that you don't even need to see the original source code to | |
74 understand what is wrong based on the Clang error. Because clang prints a | |
75 point, you know exactly <em>which</em> plus it is complaining about. The range | |
76 information highlights the left and right side of the plus which makes it | |
77 immediately obvious what the compiler is talking about. | |
78 Range information is very useful for | |
79 cases involving precedence issues and many other cases.</p> | |
80 | |
81 <pre> | |
82 $ <span class="cmd">gcc-4.9 -fsyntax-only t.c</span> | |
83 t.c: In function 'int f(int, int)': | |
84 t.c:7:39: error: invalid operands to binary + (have 'int' and 'struct A') | |
85 return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X); | |
86 ^ | |
87 $ <span class="cmd">clang -fsyntax-only t.c</span> | |
88 <span class="loc">t.c:7:39:</span> <span class="err">error:</span> <span class="msg">invalid operands to binary expression ('int' and 'struct A')</span> | |
89 <span class="snip" > return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);</span> | |
90 <span class="point"> ~~~~~~~~~~~~~~ ^ ~~~~~</span> | |
91 </pre> | |
92 | |
93 <h2>Precision in Wording</h2> | |
94 | |
95 <p>A detail is that we have tried really hard to make the diagnostics that come | |
96 out of clang contain exactly the pertinent information about what is wrong and | |
97 why. In the example above, we tell you what the inferred types are for | |
98 the left and right hand sides, and we don't repeat what is obvious from the | |
99 point (e.g., that this is a "binary +").</p> | |
100 | |
101 <p>Many other examples abound. In the following example, not only do we tell you | |
102 that there is a problem with the <tt>*</tt> | |
103 and point to it, we say exactly why and tell you what the type is (in case it is | |
104 a complicated subexpression, such as a call to an overloaded function). This | |
105 sort of attention to detail makes it much easier to understand and fix problems | |
106 quickly.</p> | |
107 | |
108 <pre> | |
109 $ <span class="cmd">gcc-4.9 -fsyntax-only t.c</span> | |
110 t.c:5:11: error: invalid type argument of unary '*' (have 'int') | |
111 return *SomeA.X; | |
112 ^ | |
113 $ <span class="cmd">clang -fsyntax-only t.c</span> | |
114 <span class="loc">t.c:5:11:</span> <span class="err">error:</span> <span class="msg">indirection requires pointer operand ('int' invalid)</span> | |
115 <span class="snip" > int y = *SomeA.X;</span> | |
116 <span class="point"> ^~~~~~~~</span> | |
117 </pre> | |
118 | |
119 <h2>Typedef Preservation and Selective Unwrapping</h2> | |
120 | |
121 <p>Many programmers use high-level user defined types, typedefs, and other | |
122 syntactic sugar to refer to types in their program. This is useful because they | |
123 can abbreviate otherwise very long types and it is useful to preserve the | |
124 typename in diagnostics. However, sometimes very simple typedefs can wrap | |
125 trivial types and it is important to strip off the typedef to understand what | |
126 is going on. Clang aims to handle both cases well.<p> | |
127 | |
128 <p>The following example shows where it is important to preserve | |
129 a typedef in C.</p> | |
130 | |
131 <pre> | |
132 $ <span class="cmd">clang -fsyntax-only t.c</span> | |
133 <span class="loc">t.c:15:11:</span> <span class="err">error:</span> <span class="msg">can't convert between vector values of different size ('__m128' and 'int const *')</span> | |
134 <span class="snip"> myvec[1]/P;</span> | |
135 <span class="point"> ~~~~~~~~^~</span> | |
136 </pre> | |
137 | |
138 <p>The following example shows where it is useful for the compiler to expose | |
139 underlying details of a typedef. If the user was somehow confused about how the | |
140 system "pid_t" typedef is defined, Clang helpfully displays it with "aka".</p> | |
141 | |
142 <pre> | |
143 $ <span class="cmd">clang -fsyntax-only t.c</span> | |
144 <span class="loc">t.c:13:9:</span> <span class="err">error:</span> <span class="msg">member reference base type 'pid_t' (aka 'int') is not a structure or union</span> | |
145 <span class="snip"> myvar = myvar.x;</span> | |
146 <span class="point"> ~~~~~ ^</span> | |
147 </pre> | |
148 | |
149 <p>In C++, type preservation includes retaining any qualification written into type names. For example, if we take a small snippet of code such as: | |
150 | |
151 <blockquote> | |
152 <pre> | |
153 namespace services { | |
154 struct WebService { }; | |
155 } | |
156 namespace myapp { | |
157 namespace servers { | |
158 struct Server { }; | |
159 } | |
160 } | |
161 | |
162 using namespace myapp; | |
163 void addHTTPService(servers::Server const &server, ::services::WebService const *http) { | |
164 server += http; | |
165 } | |
166 </pre> | |
167 </blockquote> | |
168 | |
169 <p>and then compile it, we see that Clang is both providing accurate information and is retaining the types as written by the user (e.g., "servers::Server", "::services::WebService"): | |
170 | |
171 <pre> | |
172 $ <span class="cmd">clang -fsyntax-only t.cpp</span> | |
173 <span class="loc">t.cpp:9:10:</span> <span class="err">error:</span> <span class="msg">invalid operands to binary expression ('servers::Server const' and '::services::WebService const *')</span> | |
174 <span class="snip">server += http;</span> | |
175 <span class="point">~~~~~~ ^ ~~~~</span> | |
176 </pre> | |
177 | |
178 <p>Naturally, type preservation extends to uses of templates, and Clang retains information about how a particular template specialization (like <code>std::vector<Real></code>) was spelled within the source code. For example:</p> | |
179 | |
180 <pre> | |
181 $ <span class="cmd">clang -fsyntax-only t.cpp</span> | |
182 <span class="loc">t.cpp:12:7:</span> <span class="err">error:</span> <span class="msg">incompatible type assigning 'vector<Real>', expected 'std::string' (aka 'class std::basic_string<char>')</span> | |
183 <span class="snip">str = vec</span>; | |
184 <span class="point">^ ~~~</span> | |
185 </pre> | |
186 | |
187 <h2>Fix-it Hints</h2> | |
188 | |
189 <p>"Fix-it" hints provide advice for fixing small, localized problems | |
190 in source code. When Clang produces a diagnostic about a particular | |
191 problem that it can work around (e.g., non-standard or redundant | |
192 syntax, missing keywords, common mistakes, etc.), it may also provide | |
193 specific guidance in the form of a code transformation to correct the | |
194 problem. In the following example, Clang warns about the use of a GCC | |
195 extension that has been considered obsolete since 1993. The underlined | |
196 code should be removed, then replaced with the code below the | |
197 point line (".x =" or ".y =", respectively).</p> | |
198 | |
199 <pre> | |
200 $ <span class="cmd">clang t.c</span> | |
201 <span class="loc">t.c:5:28:</span> <span class="warn">warning:</span> <span class="msg">use of GNU old-style field designator extension</span> | |
202 <span class="snip">struct point origin = { x: 0.0, y: 0.0 };</span> | |
203 <span class="err">~~</span> <span class="msg"><span class="point">^</span></span> | |
204 <span class="snip">.x = </span> | |
205 <span class="loc">t.c:5:36:</span> <span class="warn">warning:</span> <span class="msg">use of GNU old-style field designator extension</span> | |
206 <span class="snip">struct point origin = { x: 0.0, y: 0.0 };</span> | |
207 <span class="err">~~</span> <span class="msg"><span class="point">^</span></span> | |
208 <span class="snip">.y = </span> | |
209 </pre> | |
210 | |
211 <p>"Fix-it" hints are most useful for | |
212 working around common user errors and misconceptions. For example, C++ users | |
213 commonly forget the syntax for explicit specialization of class templates, | |
214 as in the error in the following example. Again, after describing the problem, | |
215 Clang provides the fix--add <code>template<></code>--as part of the | |
216 diagnostic.<p> | |
217 | |
218 <pre> | |
219 $ <span class="cmd">clang t.cpp</span> | |
220 <span class="loc">t.cpp:9:3:</span> <span class="err">error:</span> <span class="msg">template specialization requires 'template<>'</span> | |
221 struct iterator_traits<file_iterator> { | |
222 <span class="point">^</span> | |
223 <span class="snip">template<> </span> | |
224 </pre> | |
225 | |
226 <h2>Template Type Diffing</h2> | |
227 | |
228 <p>Templates types can be long and difficult to read. More so when part of an | |
229 error message. Instead of just printing out the type name, Clang has enough | |
230 information to remove the common elements and highlight the differences. To | |
231 show the template structure more clearly, the templated type can also be | |
232 printed as an indented text tree.</p> | |
233 | |
234 Default: template diff with type elision | |
235 <pre> | |
236 <span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion from 'vector<map<[...], <span class="template-highlight">float</span>>>' to 'vector<map<[...], <span class="template-highlight">double</span>>>' for 1st argument; | |
237 </pre> | |
238 -fno-elide-type: template diff without elision | |
239 <pre> | |
240 <span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion from 'vector<map<int, <span class="template-highlight">float</span>>>' to 'vector<map<int, <span class="template-highlight">double</span>>>' for 1st argument; | |
241 </pre> | |
242 -fdiagnostics-show-template-tree: template tree printing with elision | |
243 <pre> | |
244 <span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument; | |
245 vector< | |
246 map< | |
247 [...], | |
248 [<span class="template-highlight">float</span> != <span class="template-highlight">double</span>]>> | |
249 </pre> | |
250 -fdiagnostics-show-template-tree -fno-elide-type: template tree printing with no elision | |
251 <pre> | |
252 <span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument; | |
253 vector< | |
254 map< | |
255 int, | |
256 [<span class="template-highlight">float</span> != <span class="template-highlight">double</span>]>> | |
257 </pre> | |
258 | |
259 <h2>Automatic Macro Expansion</h2> | |
260 | |
261 <p>Many errors happen in macros that are sometimes deeply nested. With | |
262 traditional compilers, you need to dig deep into the definition of the macro to | |
263 understand how you got into trouble. The following simple example shows how | |
264 Clang helps you out by automatically printing instantiation information and | |
265 nested range information for diagnostics as they are instantiated through macros | |
266 and also shows how some of the other pieces work in a bigger example.</p> | |
267 | |
268 <pre> | |
269 $ <span class="cmd">clang -fsyntax-only t.c</span> | |
270 <span class="loc">t.c:80:3:</span> <span class="err">error:</span> <span class="msg">invalid operands to binary expression ('typeof(P)' (aka 'struct mystruct') and 'typeof(F)' (aka 'float'))</span> | |
271 <span class="snip"> X = MYMAX(P, F);</span> | |
272 <span class="point"> ^~~~~~~~~~~</span> | |
273 <span class="loc">t.c:76:94:</span> <span class="note">note:</span> expanded from: | |
274 <span class="snip">#define MYMAX(A,B) __extension__ ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })</span> | |
275 <span class="point"> ~~~ ^ ~~~</span> | |
276 </pre> | |
277 | |
278 <p>Here's another real world warning that occurs in the "window" Unix package (which | |
279 implements the "wwopen" class of APIs):</p> | |
280 | |
281 <pre> | |
282 $ <span class="cmd">clang -fsyntax-only t.c</span> | |
283 <span class="loc">t.c:22:2:</span> <span class="warn">warning:</span> <span class="msg">type specifier missing, defaults to 'int'</span> | |
284 <span class="snip"> ILPAD();</span> | |
285 <span class="point"> ^</span> | |
286 <span class="loc">t.c:17:17:</span> <span class="note">note:</span> expanded from: | |
287 <span class="snip">#define ILPAD() PAD((NROW - tt.tt_row) * 10) /* 1 ms per char */</span> | |
288 <span class="point"> ^</span> | |
289 <span class="loc">t.c:14:2:</span> <span class="note">note:</span> expanded from: | |
290 <span class="snip"> register i; \</span> | |
291 <span class="point"> ^</span> | |
292 </pre> | |
293 | |
294 <p>In practice, we've found that Clang's treatment of macros is actually more useful in multiply nested | |
295 macros than in simple ones.</p> | |
296 | |
297 <h2>Quality of Implementation and Attention to Detail</h2> | |
298 | |
299 <p>Finally, we have put a lot of work polishing the little things, because | |
300 little things add up over time and contribute to a great user experience.</p> | |
301 | |
302 <p>The following example shows that we recover from the simple case of | |
303 forgetting a ; after a struct definition much better than GCC.</p> | |
304 | |
305 <pre> | |
306 $ <span class="cmd">cat t.cc</span> | |
307 template<class T> | |
308 class a {}; | |
309 struct b {} | |
310 a<int> c; | |
311 $ <span class="cmd">gcc-4.9 t.cc</span> | |
312 t.cc:4:8: error: invalid declarator before 'c' | |
313 a<int> c; | |
314 ^ | |
315 $ <span class="cmd">clang t.cc</span> | |
316 <span class="loc">t.cc:3:12:</span> <span class="err">error:</span> <span class="msg">expected ';' after struct</span> | |
317 <span class="snip" >struct b {}</span> | |
318 <span class="point"> ^</span> | |
319 <span class="point"> ;</span> | |
320 </pre> | |
321 | |
322 <p>The following example shows that we diagnose and recover from a missing | |
323 <tt>typename</tt> keyword well, even in complex circumstances where GCC | |
324 cannot cope.</p> | |
325 | |
326 <pre> | |
327 $ <span class="cmd">cat t.cc</span> | |
328 template<class T> void f(T::type) { } | |
329 struct A { }; | |
330 void g() | |
331 { | |
332 A a; | |
333 f<A>(a); | |
334 } | |
335 $ <span class="cmd">gcc-4.9 t.cc</span> | |
336 t.cc:1:33: error: variable or field 'f' declared void | |
337 template<class T> void f(T::type) { } | |
338 ^ | |
339 t.cc: In function 'void g()': | |
340 t.cc:6:5: error: 'f' was not declared in this scope | |
341 f<A>(a); | |
342 ^ | |
343 t.cc:6:8: error: expected primary-expression before '>' token | |
344 f<A>(a); | |
345 ^ | |
346 $ <span class="cmd">clang t.cc</span> | |
347 <span class="loc">t.cc:1:26:</span> <span class="err">error:</span> <span class="msg">missing 'typename' prior to dependent type name 'T::type'</span> | |
348 <span class="snip" >template<class T> void f(T::type) { }</span> | |
349 <span class="point"> ^~~~~~~</span> | |
350 <span class="point"> typename </span> | |
351 <span class="loc">t.cc:6:5:</span> <span class="err">error:</span> <span class="msg">no matching function for call to 'f'</span> | |
352 <span class="snip" > f<A>(a);</span> | |
353 <span class="point"> ^~~~</span> | |
354 <span class="loc">t.cc:1:24:</span> <span class="note">note:</span> <span class="msg">candidate template ignored: substitution failure [with T = A]: no type named 'type' in 'A'</span> | |
355 <span class="snip" >template<class T> void f(T::type) { }</span> | |
356 <span class="point"> ^ ~~~~</span> | |
357 </pre> | |
358 | |
359 | |
360 | |
361 <p>While each of these details is minor, we feel that they all add up to provide | |
362 a much more polished experience.</p> | |
363 | |
364 </div> | |
365 </body> | |
366 </html> |