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> |
367 | |