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