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