<div>On Thu Jan 23 2014 at 8:08:46 PM, Nico Weber <<a href="mailto:thakis@chromium.org">thakis@chromium.org</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">They have at least a flag to turn it on: <a href="http://llvm.org/viewvc/llvm-project?view=revision&revision=179728" target="_blank">http://llvm.org/viewvc/llvm-project?view=revision&revision=179728</a><div>
<br></div>
<div>Maybe it's not on by default though?</div></div></blockquote><div><br></div><div>They have a flag, but it appears to be off by default. (At least, I built and ran GCC trunk, and it produced caret diagnostics but no colors for me.)</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>On Thu, Jan 23, 2014 at 8:04 PM, Sean Silva <span dir="ltr"><<a href="mailto:silvas@purdue.edu" target="_blank">silvas@purdue.edu</a>></span> wrote:<br>

<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Does GCC's output still not have color?<span><font color="#888888"><div><br></div><div>
-- Sean Silva</div></font></span></div><div><div><div><br><br><div>On Thu, Jan 23, 2014 at 10:13 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br>


<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Thu Jan 23 21:13:34 2014<br>
New Revision: 199970<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=199970&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=199970&view=rev</a><br>
Log:<br>
Update page on clang diagnostics to contrast to GCC 4.9 instead of 4.2. A lot<br>
of the differences we identified here have been fixed by improvements in GCC.<br>
<br>
Modified:<br>
    cfe/trunk/www/diagnostics.html<br>
<br>
Modified: cfe/trunk/www/diagnostics.html<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/www/diagnostics.html?rev=199970&r1=199969&r2=199970&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/www/diagnostics.html?rev=199970&r1=199969&r2=199970&view=diff</a><br>



==============================================================================<br>
--- cfe/trunk/www/diagnostics.html (original)<br>
+++ cfe/trunk/www/diagnostics.html Thu Jan 23 21:13:34 2014<br>
@@ -7,10 +7,14 @@<br>
   <link type="text/css" rel="stylesheet" href="menu.css"><br>
   <link type="text/css" rel="stylesheet" href="content.css"><br>
   <style type="text/css"><br>
-  .warn { color:magenta; }<br>
-  .err { color:red; }<br>
-  .snip { color:darkgreen; }<br>
-  .point { color:blue; }<br>
+  .loc { font-weight: bold; }<br>
+  .err { color:red; font-weight: bold; }<br>
+  .warn { color:magenta; font-weight: bold; }<br>
+  .note { color:gray; font-weight: bold; }<br>
+  .msg { font-weight: bold; }<br>
+  .cmd { font-style: italic; }<br>
+  .snip { }<br>
+  .point { color:green; font-weight: bold; }<br>
   </style><br>
 </head><br>
 <body><br>
@@ -29,10 +33,7 @@ friendly.  As far as a command-line comp<br>
 making the diagnostics (error and warning messages) generated by the compiler<br>
 be as useful as possible.  There are several ways that we do this.  This section<br>
 talks about the experience provided by the command line compiler, contrasting<br>
-Clang output to GCC 4.2's output in several examples.<br>
-<!--<br>
-Other clients<br>
-that embed Clang and extract equivalent information through internal APIs.--><br>
+Clang output to GCC 4.9's output in some cases.<br>
 </p><br>
<br>
 <h2>Column Numbers and Caret Diagnostics</h2><br>
@@ -41,25 +42,35 @@ that embed Clang and extract equivalent<br>
 information. The clang command-line compiler driver uses this information<br>
 to print "point diagnostics".<br>
 (IDEs can use the information to display in-line error markup.)<br>
-Precise error location in the source is a feature provided by many commercial<br>
-compilers, but is generally missing from open source<br>
-compilers.  This is nice because it makes it very easy to understand exactly<br>
-what is wrong in a particular piece of code</p><br>
+This is nice because it makes it very easy to understand exactly<br>
+what is wrong in a particular piece of code.</p><br>
<br>
-<p>The point (the blue "^" character) exactly shows where the problem is, even<br>
+<p>The point (the green "^" character) exactly shows where the problem is, even<br>
 inside of a string.  This makes it really easy to jump to the problem and<br>
-helps when multiple instances of the same character occur on a line. (We'll<br>
+helps when multiple instances of the same character occur on a line. (We'll<br>
 revisit this more in following examples.)</p><br>
<br>
 <pre><br>
-  $ <b>gcc-4.2 -fsyntax-only -Wformat format-strings.c</b><br>
-  format-strings.c:91: warning: too few arguments for format<br>
-  $ <b>clang -fsyntax-only format-strings.c</b><br>
-  format-strings.c:91:13: <span class="warn">warning:</span> '.*' specified field precision is missing a matching 'int' argument<br>
-  <span class="snip">  printf("%.*d");</span><br>
+  $ <span class="cmd">gcc-4.9 -fsyntax-only -Wformat format-strings.c</span><br>
+  format-strings.c: In function 'void f()':<br>
+  format-strings.c:91:16: warning: field precision specifier '.*' expects a matching 'int' argument [-Wformat=]<br>
+     printf("%.*d");<br>
+                  ^<br>
+  format-strings.c:91:16: warning: format '%d' expects a matching 'int' argument [-Wformat=]<br>
+  $ <span class="cmd">clang -fsyntax-only format-strings.c</span><br>
+  <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><br>



+  <span class="snip" >  printf("%.*d");</span><br>
   <span class="point">            ^</span><br>
 </pre><br>
<br>
+<p>Note that modern versions of GCC have followed Clang's lead, and are<br>
+now able to give a column for a diagnostic, and include a snippet of source<br>
+text in the result. However, Clang's column number is much more accurate,<br>
+pointing at the problematic format specifier, rather than the <tt>)</tt><br>
+character the parser had reached when the problem was detected.<br>
+Also, Clang's diagnostic is colored by default, making it easier to<br>
+distinguish from nearby text.</p><br>
+<br>
 <h2>Range Highlighting for Related Text</h2><br>
<br>
 <p>Clang captures and accurately tracks range information for expressions,<br>
@@ -74,11 +85,14 @@ Range information is very useful for<br>
 cases involving precedence issues and many other cases.</p><br>
<br>
 <pre><br>
-  $ <b>gcc-4.2 -fsyntax-only t.c</b><br>
-  t.c:7: error: invalid operands to binary + (have 'int' and 'struct A')<br>
-  $ <b>clang -fsyntax-only t.c</b><br>
-  t.c:7:39: <span class="err">error:</span> invalid operands to binary expression ('int' and 'struct A')<br>
-  <span class="snip">  return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);</span><br>
+  $ <span class="cmd">gcc-4.9 -fsyntax-only t.c</span><br>
+  t.c: In function 'int f(int, int)':<br>
+  t.c:7:39: error: invalid operands to binary + (have 'int' and 'struct A')<br>
+     return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);<br>
+                                         ^<br>
+  $ <span class="cmd">clang -fsyntax-only t.c</span><br>
+  <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><br>



+  <span class="snip" >  return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);</span><br>
   <span class="point">                       ~~~~~~~~~~~~~~ ^ ~~~~~</span><br>
 </pre><br>
<br>
@@ -90,62 +104,24 @@ why.  In the example above, we tell you<br>
 the left and right hand sides, and we don't repeat what is obvious from the<br>
 point (e.g., that this is a "binary +").</p><br>
<br>
-<p>Many other examples abound. In the following example, not only do we tell you that there is a problem with the *<br>
+<p>Many other examples abound. In the following example, not only do we tell you<br>
+that there is a problem with the <tt>*</tt><br>
 and point to it, we say exactly why and tell you what the type is (in case it is<br>
 a complicated subexpression, such as a call to an overloaded function).  This<br>
 sort of attention to detail makes it much easier to understand and fix problems<br>
 quickly.</p><br>
<br>
 <pre><br>
-  $ <b>gcc-4.2 -fsyntax-only t.c</b><br>
-  t.c:5: error: invalid type argument of 'unary *'<br>
-  $ <b>clang -fsyntax-only t.c</b><br>
-  t.c:5:11: <span class="err">error:</span> indirection requires pointer operand ('int' invalid)<br>
-  <span class="snip">  int y = *SomeA.X;</span><br>
+  $ <span class="cmd">gcc-4.9 -fsyntax-only t.c</span><br>
+  t.c:5:11: error: invalid type argument of unary '*' (have 'int')<br>
+    return *SomeA.X;<br>
+           ^<br>
+  $ <span class="cmd">clang -fsyntax-only t.c</span><br>
+  <span class="loc">t.c:5:11:</span> <span class="err">error:</span> <span class="msg">indirection requires pointer operand ('int' invalid)</span><br>



+  <span class="snip" >  int y = *SomeA.X;</span><br>
   <span class="point">          ^~~~~~~~</span><br>
 </pre><br>
<br>
-<h2>No Pretty Printing of Expressions in Diagnostics</h2><br>
-<br>
-<p>Since Clang has range highlighting, it never needs to pretty print your code<br>
-back out to you.  GCC can produce inscrutible error messages in some cases when<br>
-it tries to do this.  In this example P and Q have type "int*":</p><br>
-<br>
-<pre><br>
-  $ <b>gcc-4.2 -fsyntax-only t.c</b><br>
-  #'exact_div_expr' not supported by pp_c_expression#'t.c:12: error: called object  is not a function<br>
-  $ <b>clang -fsyntax-only t.c</b><br>
-  t.c:12:8: <span class="err">error:</span> called object type 'int' is not a function or function pointer<br>
-  <span class="snip">  (P-Q)();</span><br>
-  <span class="point">  ~~~~~^</span><br>
-</pre><br>
-<br>
-<p>This can be particularly bad in G++, which often emits errors<br>
-   containing lowered vtable references.  For example:</p><br>
-<br>
-<pre><br>
-  $ <b>cat t.cc</b><br>
-  struct a {<br>
-    virtual int bar();<br>
-  };<br>
-<br>
-  struct foo : public virtual a {<br>
-  };<br>
-<br>
-  void test(foo *P) {<br>
-    return P->bar() + *P;<br>
-  }<br>
-  $ <b>gcc-4.2 t.cc</b><br>
-  t.cc: In function 'void test(foo*)':<br>
-  t.cc:9: error: no match for 'operator+' in '(((a*)P) + (*(long int*)(P-&gt;foo::&lt;anonymous&gt;.a::_vptr$a + -0x00000000000000020)))-&gt;a::bar() + * P'<br>
-  t.cc:9: error: return-statement with a value, in function returning 'void'<br>
-  $ <b>clang t.cc</b><br>
-  t.cc:9:18: <span class="err">error:</span> invalid operands to binary expression ('int' and 'foo')<br>
-  <span class="snip">  return P->bar() + *P;</span><br>
-  <span class="point">         ~~~~~~~~ ^ ~~</span><br>
-</pre><br>
-<br>
-<br>
 <h2>Typedef Preservation and Selective Unwrapping</h2><br>
<br>
 <p>Many programmers use high-level user defined types, typedefs, and other<br>
@@ -156,15 +132,11 @@ trivial types and it is important to str<br>
 is going on.  Clang aims to handle both cases well.<p><br>
<br>
 <p>The following example shows where it is important to preserve<br>
-a typedef in C. Here the type printed by GCC isn't even valid, but if the error<br>
-were about a very long and complicated type (as often happens in C++) the error<br>
-message would be ugly just because it was long and hard to read.</p><br>
+a typedef in C.</p><br>
<br>
 <pre><br>
-  $ <b>gcc-4.2 -fsyntax-only t.c</b><br>
-  t.c:15: error: invalid operands to binary / (have 'float __vector__' and 'const int *')<br>
-  $ <b>clang -fsyntax-only t.c</b><br>
-  t.c:15:11: <span class="err">error:</span> can't convert between vector values of different size ('__m128' and 'int const *')<br>
+  $ <span class="cmd">clang -fsyntax-only t.c</span><br>
+  <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><br>



   <span class="snip">  myvec[1]/P;</span><br>
   <span class="point">  ~~~~~~~~^~</span><br>
 </pre><br>
@@ -174,10 +146,8 @@ underlying details of a typedef. If the<br>
 system "pid_t" typedef is defined, Clang helpfully displays it with "aka".</p><br>
<br>
 <pre><br>
-  $ <b>gcc-4.2 -fsyntax-only t.c</b><br>
-  t.c:13: error: request for member 'x' in something not a structure or union<br>
-  $ <b>clang -fsyntax-only t.c</b><br>
-  t.c:13:9: <span class="err">error:</span> member reference base type 'pid_t' (aka 'int') is not a structure or union<br>
+  $ <span class="cmd">clang -fsyntax-only t.c</span><br>
+  <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><br>



   <span class="snip">  myvar = myvar.x;</span><br>
   <span class="point">          ~~~~~ ^</span><br>
 </pre><br>
@@ -202,13 +172,11 @@ void addHTTPService(servers::Server cons<br>
 </pre><br>
 </blockquote><br>
<br>
-<p>and then compile it, we see that Clang is both providing more accurate information and is retaining the types as written by the user (e.g., "servers::Server", "::services::WebService"):<br>
+<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"):<br>
<br>
 <pre><br>
-  $ <b>g++-4.2 -fsyntax-only t.cpp</b><br>
-  t.cpp:9: error: no match for 'operator+=' in 'server += http'<br>
-  $ <b>clang -fsyntax-only t.cpp</b><br>
-  t.cpp:9:10: <span class="err">error:</span> invalid operands to binary expression ('servers::Server const' and '::services::WebService const *')<br>
+  $ <span class="cmd">clang -fsyntax-only t.cpp</span><br>
+  <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><br>



     <span class="snip">server += http;</span><br>
     <span class="point">~~~~~~ ^  ~~~~</span><br>
 </pre><br>
@@ -216,10 +184,8 @@ void addHTTPService(servers::Server cons<br>
 <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><br>



<br>
 <pre><br>
-  $ <b>g++-4.2 -fsyntax-only t.cpp</b><br>
-  t.cpp:12: error: no match for 'operator=' in 'str = vec'<br>
-  $ <b>clang -fsyntax-only t.cpp</b><br>
-  t.cpp:12:7: <span class="err">error:</span> incompatible type assigning 'vector&lt;Real&gt;', expected 'std::string' (aka 'class std::basic_string&lt;char&gt;')<br>



+  $ <span class="cmd">clang -fsyntax-only t.cpp</span><br>
+  <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><br>



     <span class="snip">str = vec</span>;<br>
         <span class="point">^ ~~~</span><br>
 </pre><br>
@@ -237,14 +203,14 @@ code should be removed, then replaced wi<br>
 point line (".x =" or ".y =", respectively).</p><br>
<br>
 <pre><br>
-  $ <b>clang t.c</b><br>
-  t.c:5:28: <span class="warn">warning:</span> use of GNU old-style field designator extension<br>
+  $ <span class="cmd">clang t.c</span><br>
+  <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><br>
   <span class="snip">struct point origin = { x: 0.0, y: 0.0 };</span><br>
-                          <span class="err">~~</span> <span class="point">^</span><br>
+                          <span class="err">~~</span> <span class="msg"><span class="point">^</span></span><br>
                           <span class="snip">.x = </span><br>
-  t.c:5:36: <span class="warn">warning:</span> use of GNU old-style field designator extension<br>
+  <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><br>
   <span class="snip">struct point origin = { x: 0.0, y: 0.0 };</span><br>
-                                  <span class="err">~~</span> <span class="point">^</span><br>
+                                  <span class="err">~~</span> <span class="msg"><span class="point">^</span></span><br>
                                   <span class="snip">.y = </span><br>
 </pre><br>
<br>
@@ -256,8 +222,8 @@ Clang provides the fix--add <code>templa<br>
 diagnostic.<p><br>
<br>
 <pre><br>
-  $ <b>clang t.cpp</b><br>
-  t.cpp:9:3: <span class="err">error:</span> template specialization requires 'template&lt;&gt;'<br>
+  $ <span class="cmd">clang t.cpp</span><br>
+  <span class="loc">t.cpp:9:3:</span> <span class="err">error:</span> <span class="msg">template specialization requires 'template&lt;&gt;'</span><br>



     struct iterator_traits&lt;file_iterator&gt; {<br>
     <span class="point">^</span><br>
     <span class="snip">template&lt;&gt; </span><br>
@@ -273,15 +239,15 @@ printed as an indented text tree.</p><br>
<br>
 Default: template diff with type elision<br>
 <pre><br>
-t.cc:4:5: <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;<br>



+<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;<br>



 </pre><br>
 -fno-elide-type: template diff without elision<br>
 <pre><br>
-t.cc:4:5: <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;<br>



+<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;<br>



 </pre><br>
 -fdiagnostics-show-template-tree: template tree printing with elision<br>
 <pre><br>
-t.cc:4:5: <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument;<br>
+<span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument;<br>
   vector&lt;<br>
     map&lt;<br>
       [...],<br>
@@ -289,7 +255,7 @@ t.cc:4:5: <span class="note">note:</span<br>
 </pre><br>
 -fdiagnostics-show-template-tree -fno-elide-type: template tree printing with no elision<br>
 <pre><br>
-t.cc:4:5: <span class="note">note:M</span> candidate function not viable: no known conversion for 1st argument;<br>
+<span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument;<br>
   vector&lt;<br>
     map&lt;<br>
       int,<br>
@@ -306,14 +272,11 @@ nested range information for diagnostics<br>
 and also shows how some of the other pieces work in a bigger example.</p><br>
<br>
 <pre><br>
-  $ <b>gcc-4.2 -fsyntax-only t.c</b><br>
-  t.c: In function 'test':<br>
-  t.c:80: error: invalid operands to binary &lt; (have 'struct mystruct' and 'float')<br>
-  $ <b>clang -fsyntax-only t.c</b><br>
-  t.c:80:3: <span class="err">error:</span> invalid operands to binary expression ('typeof(P)' (aka 'struct mystruct') and 'typeof(F)' (aka 'float'))<br>
+  $ <span class="cmd">clang -fsyntax-only t.c</span><br>
+  <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><br>



   <span class="snip">  X = MYMAX(P, F);</span><br>
   <span class="point">      ^~~~~~~~~~~</span><br>
-  t.c:76:94: note: expanded from:<br>
+  <span class="loc">t.c:76:94:</span> <span class="note">note:</span> expanded from:<br>
   <span class="snip">#define MYMAX(A,B)    __extension__ ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a &lt; __b ? __b : __a; })</span><br>
   <span class="point">                                                                                         ~~~ ^ ~~~</span><br>
 </pre><br>
@@ -322,14 +285,14 @@ and also shows how some of the other pie<br>
 implements the "wwopen" class of APIs):</p><br>
<br>
 <pre><br>
-  $ <b>clang -fsyntax-only t.c</b><br>
-  t.c:22:2: <span class="warn">warning:</span> type specifier missing, defaults to 'int'<br>
+  $ <span class="cmd">clang -fsyntax-only t.c</span><br>
+  <span class="loc">t.c:22:2:</span> <span class="warn">warning:</span> <span class="msg">type specifier missing, defaults to 'int'</span><br>
   <span class="snip">        ILPAD();</span><br>
   <span class="point">        ^</span><br>
-  t.c:17:17: note: expanded from:<br>
+  <span class="loc">t.c:17:17:</span> <span class="note">note:</span> expanded from:<br>
   <span class="snip">#define ILPAD() PAD((NROW - tt.tt_row) * 10)    /* 1 ms per char */</span><br>
   <span class="point">                ^</span><br>
-  t.c:14:2: note: expanded from:<br>
+  <span class="loc">t.c:14:2:</span> <span class="note">note:</span> expanded from:<br>
   <span class="snip">        register i; \</span><br>
   <span class="point">        ^</span><br>
 </pre><br>
@@ -342,63 +305,65 @@ macros that in simple ones.</p><br>
 <p>Finally, we have put a lot of work polishing the little things, because<br>
 little things add up over time and contribute to a great user experience.</p><br>
<br>
-<p>The following example shows a trivial little tweak, where we tell you to put the semicolon at<br>
-the end of the line that is missing it (line 4) instead of at the beginning of<br>
-the following line (line 5).  This is particularly important with fixit hints<br>
-and point diagnostics, because otherwise you don't get the important context.<br>
-</p><br>
-<br>
-<pre><br>
-  $ <b>gcc-4.2 t.c</b><br>
-  t.c: In function 'foo':<br>
-  t.c:5: error: expected ';' before '}' token<br>
-  $ <b>clang t.c</b><br>
-  t.c:4:8: <span class="err">error:</span> expected ';' after expression<br>
-  <span class="snip">  bar()</span><br>
-  <span class="point">       ^</span><br>
-  <span class="point">       ;</span><br>
-</pre><br>
-<br>
-<p>The following example shows much better error recovery than GCC. The message coming out<br>
-of GCC is completely useless for diagnosing the problem. Clang tries much harder<br>
-and produces a much more useful diagnosis of the problem.</p><br>
-<br>
-<pre><br>
-  $ <b>gcc-4.2 t.c</b><br>
-  t.c:3: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token<br>
-  $ <b>clang t.c</b><br>
-  t.c:3:1: <span class="err">error:</span> unknown type name 'foo_t'<br>
-  <span class="snip">foo_t *P = 0;</span><br>
-  <span class="point">^</span><br>
-</pre><br>
-<br>
 <p>The following example shows that we recover from the simple case of<br>
 forgetting a ; after a struct definition much better than GCC.</p><br>
<br>
 <pre><br>
-  $ <b>cat t.cc</b><br>
+  $ <span class="cmd">cat t.cc</span><br>
   template&lt;class T&gt;<br>
-  class a {}<br>
-  class temp {};<br>
-  a&lt;temp&gt; b;<br>
-  struct b {<br>
+  class a {};<br>
+  struct b {}<br>
+  a&lt;int&gt; c;<br>
+  $ <span class="cmd">gcc-4.9 t.cc</span><br>
+  t.cc:4:8: error: invalid declarator before 'c'<br>
+   a<int> c;<br>
+           ^<br>
+  $ <span class="cmd">clang t.cc</span><br>
+  <span class="loc">t.cc:3:12:</span> <span class="err">error:</span> <span class="msg">expected ';' after struct</span><br>
+  <span class="snip" >struct b {}</span><br>
+  <span class="point">           ^</span><br>
+  <span class="point">           ;</span><br>
+</pre><br>
+<br>
+<p>The following example shows that we diagnose and recover from a missing<br>
+<tt>typename</tt> keyword well, even in complex circumstances where GCC<br>
+cannot cope.</p><br>
+<br>
+<pre><br>
+  $ <span class="cmd">cat t.cc</span><br>
+  template&lt;class T&gt; void f(T::type) { }<br>
+  struct A { };<br>
+  void g()<br>
+  {<br>
+      A a;<br>
+      f&lt;A&gt;(a);<br>
   }<br>
-  $ <b>gcc-4.2 t.cc</b><br>
-  t.cc:3: error: multiple types in one declaration<br>
-  t.cc:4: error: non-template type 'a' used as a template<br>
-  t.cc:4: error: invalid type in declaration before ';' token<br>
-  t.cc:6: error: expected unqualified-id at end of input<br>
-  $ <b>clang t.cc</b><br>
-  t.cc:2:11: <span class="err">error:</span> expected ';' after class<br>
-  <span class="snip">class a {}</span><br>
-  <span class="point">          ^</span><br>
-  <span class="point">          ;</span><br>
-  t.cc:6:2: <span class="err">error:</span> expected ';' after struct<br>
-  <span class="snip">}</span><br>
-  <span class="point"> ^</span><br>
-  <span class="point"> ;</span><br>
+  $ <span class="cmd">gcc-4.9 t.cc</span><br>
+  t.cc:1:33: error: variable or field 'f' declared void<br>
+   template&lt;class T&gt; void f(T::type) { }<br>
+                                   ^<br>
+  t.cc: In function 'void g()':<br>
+  t.cc:6:5: error: 'f' was not declared in this scope<br>
+       f&lt;A&gt;(a);<br>
+       ^<br>
+  t.cc:6:8: error: expected primary-expression before '>' token<br>
+       f&lt;A&gt;(a);<br>
+          ^<br>
+  $ <span class="cmd">clang t.cc</span><br>
+  <span class="loc">t.cc:1:26:</span> <span class="error">error:</span> <span class="msg">missing 'typename' prior to dependent type name 'T::type'</span><br>



+  <span class="snip" >template&lt;class T&gt; void f(T::type) { }</span><br>
+  <span class="point">                         ^~~~~~~</span><br>
+  <span class="point">                         typename </span><br>
+  <span class="loc">t.cc:6:5:</span> <span class="error">error:</span> <span class="msg">no matching function for call to 'f'</span><br>
+  <span class="snip" >    f&lt;A&gt;(a);</span><br>
+  <span class="point">    ^~~~</span><br>
+  <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><br>



+  <span class="snip" >template&lt;class T&gt; void f(T::type) { }</span><br>
+  <span class="point">                       ^    ~~~~</span><br>
 </pre><br>
<br>
+<br>
+<br>
 <p>While each of these details is minor, we feel that they all add up to provide<br>
 a much more polished experience.</p><br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
<br></blockquote></div><br></div>
</blockquote>