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 &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<Real></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<Real>', expected 'std::string' (aka 'class std::basic_string<char>')</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<></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<>'</span> 221*e5dd7070Spatrick struct iterator_traits<file_iterator> { 222*e5dd7070Spatrick <span class="point">^</span> 223*e5dd7070Spatrick <span class="snip">template<> </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<map<[...], <span class="template-highlight">float</span>>>' to 'vector<map<[...], <span class="template-highlight">double</span>>>' 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<map<int, <span class="template-highlight">float</span>>>' to 'vector<map<int, <span class="template-highlight">double</span>>>' 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< 246*e5dd7070Spatrick map< 247*e5dd7070Spatrick [...], 248*e5dd7070Spatrick [<span class="template-highlight">float</span> != <span class="template-highlight">double</span>]>> 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< 254*e5dd7070Spatrick map< 255*e5dd7070Spatrick int, 256*e5dd7070Spatrick [<span class="template-highlight">float</span> != <span class="template-highlight">double</span>]>> 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 < __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<class T> 308*e5dd7070Spatrick class a {}; 309*e5dd7070Spatrick struct b {} 310*e5dd7070Spatrick a<int> 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<int> 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<class T> void f(T::type) { } 329*e5dd7070Spatrick struct A { }; 330*e5dd7070Spatrick void g() 331*e5dd7070Spatrick { 332*e5dd7070Spatrick A a; 333*e5dd7070Spatrick f<A>(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<class T> 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<A>(a); 342*e5dd7070Spatrick ^ 343*e5dd7070Spatrick t.cc:6:8: error: expected primary-expression before '>' token 344*e5dd7070Spatrick f<A>(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<class T> 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<A>(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<class T> 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