annotate clang/www/diagnostics.html @ 180:680fa57a2f20

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