forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			367 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			367 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 | |
|           "http://www.w3.org/TR/html4/strict.dtd">
 | |
| <html>
 | |
| <head>
 | |
|   <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
 | |
|   <title>Clang - Expressive Diagnostics</title>
 | |
|   <link type="text/css" rel="stylesheet" href="menu.css">
 | |
|   <link type="text/css" rel="stylesheet" href="content.css">
 | |
|   <style type="text/css">
 | |
|   .loc { font-weight: bold; }
 | |
|   .err { color:red; font-weight: bold; }
 | |
|   .warn { color:magenta; font-weight: bold; }
 | |
|   .note { color:gray; font-weight: bold; }
 | |
|   .msg { font-weight: bold; }
 | |
|   .cmd { font-style: italic; }
 | |
|   .snip { }
 | |
|   .point { color:green; font-weight: bold; }
 | |
|   </style>
 | |
| </head>
 | |
| <body>
 | |
| 
 | |
| <!--#include virtual="menu.html.incl"-->
 | |
| 
 | |
| <div id="content">
 | |
| 
 | |
| 
 | |
| <!--=======================================================================-->
 | |
| <h1>Expressive Diagnostics</h1>
 | |
| <!--=======================================================================-->
 | |
| 
 | |
| <p>In addition to being fast and functional, we aim to make Clang extremely user
 | |
| friendly.  As far as a command-line compiler goes, this basically boils down to
 | |
| making the diagnostics (error and warning messages) generated by the compiler
 | |
| be as useful as possible.  There are several ways that we do this.  This section
 | |
| talks about the experience provided by the command line compiler, contrasting
 | |
| Clang output to GCC 4.9's output in some cases.
 | |
| </p>
 | |
| 
 | |
| <h2>Column Numbers and Caret Diagnostics</h2>
 | |
| 
 | |
| <p>First, all diagnostics produced by clang include full column number
 | |
| information. The clang command-line compiler driver uses this information
 | |
| to print "point diagnostics".
 | |
| (IDEs can use the information to display in-line error markup.)
 | |
| This is nice because it makes it very easy to understand exactly
 | |
| what is wrong in a particular piece of code.</p>
 | |
| 
 | |
| <p>The point (the green "^" character) exactly shows where the problem is, even
 | |
| inside of a string.  This makes it really easy to jump to the problem and
 | |
| helps when multiple instances of the same character occur on a line. (We'll
 | |
| revisit this more in following examples.)</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang -fsyntax-only format-strings.c</span>
 | |
|   <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>
 | |
|   <span class="snip" >  printf("%.*d");</span>
 | |
|   <span class="point">            ^</span>
 | |
| </pre>
 | |
| 
 | |
| <p>Note that modern versions of GCC have followed Clang's lead, and are
 | |
| now able to give a column for a diagnostic, and include a snippet of source
 | |
| text in the result. However, Clang's column number is much more accurate,
 | |
| pointing at the problematic format specifier, rather than the <tt>)</tt>
 | |
| character the parser had reached when the problem was detected.
 | |
| Also, Clang's diagnostic is colored by default, making it easier to
 | |
| distinguish from nearby text.</p>
 | |
| 
 | |
| <h2>Range Highlighting for Related Text</h2>
 | |
| 
 | |
| <p>Clang captures and accurately tracks range information for expressions,
 | |
| statements, and other constructs in your program and uses this to make
 | |
| diagnostics highlight related information.  In the following somewhat
 | |
| nonsensical example you can see that you don't even need to see the original source code to
 | |
| understand what is wrong based on the Clang error. Because clang prints a
 | |
| point, you know exactly <em>which</em> plus it is complaining about.  The range
 | |
| information highlights the left and right side of the plus which makes it
 | |
| immediately obvious what the compiler is talking about.
 | |
| Range information is very useful for
 | |
| cases involving precedence issues and many other cases.</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">gcc-4.9 -fsyntax-only t.c</span>
 | |
|   t.c: In function 'int f(int, int)':
 | |
|   t.c:7:39: error: invalid operands to binary + (have 'int' and 'struct A')
 | |
|      return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);
 | |
|                                          ^
 | |
|   $ <span class="cmd">clang -fsyntax-only t.c</span>
 | |
|   <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>
 | |
|   <span class="snip" >  return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);</span>
 | |
|   <span class="point">                       ~~~~~~~~~~~~~~ ^ ~~~~~</span>
 | |
| </pre>
 | |
| 
 | |
| <h2>Precision in Wording</h2>
 | |
| 
 | |
| <p>A detail is that we have tried really hard to make the diagnostics that come
 | |
| out of clang contain exactly the pertinent information about what is wrong and
 | |
| why.  In the example above, we tell you what the inferred types are for
 | |
| the left and right hand sides, and we don't repeat what is obvious from the
 | |
| point (e.g., that this is a "binary +").</p>
 | |
| 
 | |
| <p>Many other examples abound. In the following example, not only do we tell you
 | |
| that there is a problem with the <tt>*</tt>
 | |
| and point to it, we say exactly why and tell you what the type is (in case it is
 | |
| a complicated subexpression, such as a call to an overloaded function).  This
 | |
| sort of attention to detail makes it much easier to understand and fix problems
 | |
| quickly.</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">gcc-4.9 -fsyntax-only t.c</span>
 | |
|   t.c:5:11: error: invalid type argument of unary '*' (have 'int')
 | |
|     return *SomeA.X;
 | |
|            ^
 | |
|   $ <span class="cmd">clang -fsyntax-only t.c</span>
 | |
|   <span class="loc">t.c:5:11:</span> <span class="err">error:</span> <span class="msg">indirection requires pointer operand ('int' invalid)</span>
 | |
|   <span class="snip" >  int y = *SomeA.X;</span>
 | |
|   <span class="point">          ^~~~~~~~</span>
 | |
| </pre>
 | |
| 
 | |
| <h2>Typedef Preservation and Selective Unwrapping</h2>
 | |
| 
 | |
| <p>Many programmers use high-level user defined types, typedefs, and other
 | |
| syntactic sugar to refer to types in their program.  This is useful because they
 | |
| can abbreviate otherwise very long types and it is useful to preserve the
 | |
| typename in diagnostics.  However, sometimes very simple typedefs can wrap
 | |
| trivial types and it is important to strip off the typedef to understand what
 | |
| is going on.  Clang aims to handle both cases well.<p>
 | |
| 
 | |
| <p>The following example shows where it is important to preserve
 | |
| a typedef in C.</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang -fsyntax-only t.c</span>
 | |
|   <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>
 | |
|   <span class="snip">  myvec[1]/P;</span>
 | |
|   <span class="point">  ~~~~~~~~^~</span>
 | |
| </pre>
 | |
| 
 | |
| <p>The following example shows where it is useful for the compiler to expose
 | |
| underlying details of a typedef. If the user was somehow confused about how the
 | |
| system "pid_t" typedef is defined, Clang helpfully displays it with "aka".</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang -fsyntax-only t.c</span>
 | |
|   <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>
 | |
|   <span class="snip">  myvar = myvar.x;</span>
 | |
|   <span class="point">          ~~~~~ ^</span>
 | |
| </pre>
 | |
| 
 | |
| <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:
 | |
| 
 | |
| <blockquote>
 | |
| <pre>
 | |
| namespace services {
 | |
|   struct WebService {  };
 | |
| }
 | |
| namespace myapp {
 | |
|   namespace servers {
 | |
|     struct Server {  };
 | |
|   }
 | |
| }
 | |
| 
 | |
| using namespace myapp;
 | |
| void addHTTPService(servers::Server const &server, ::services::WebService const *http) {
 | |
|   server += http;
 | |
| }
 | |
| </pre>
 | |
| </blockquote>
 | |
| 
 | |
| <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"):
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang -fsyntax-only t.cpp</span>
 | |
|   <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>
 | |
|     <span class="snip">server += http;</span>
 | |
|     <span class="point">~~~~~~ ^  ~~~~</span>
 | |
| </pre>
 | |
| 
 | |
| <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>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang -fsyntax-only t.cpp</span>
 | |
|   <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>
 | |
|     <span class="snip">str = vec</span>;
 | |
|         <span class="point">^ ~~~</span>
 | |
| </pre>
 | |
| 
 | |
| <h2>Fix-it Hints</h2>
 | |
| 
 | |
| <p>"Fix-it" hints provide advice for fixing small, localized problems
 | |
| in source code. When Clang produces a diagnostic about a particular
 | |
| problem that it can work around (e.g., non-standard or redundant
 | |
| syntax, missing keywords, common mistakes, etc.), it may also provide
 | |
| specific guidance in the form of a code transformation to correct the
 | |
| problem. In the following example, Clang warns about the use of a GCC
 | |
| extension that has been considered obsolete since 1993. The underlined
 | |
| code should be removed, then replaced with the code below the
 | |
| point line (".x =" or ".y =", respectively).</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang t.c</span>
 | |
|   <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>
 | |
|   <span class="snip">struct point origin = { x: 0.0, y: 0.0 };</span>
 | |
|                           <span class="err">~~</span> <span class="msg"><span class="point">^</span></span>
 | |
|                           <span class="snip">.x = </span>
 | |
|   <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>
 | |
|   <span class="snip">struct point origin = { x: 0.0, y: 0.0 };</span>
 | |
|                                   <span class="err">~~</span> <span class="msg"><span class="point">^</span></span>
 | |
|                                   <span class="snip">.y = </span>
 | |
| </pre>
 | |
| 
 | |
| <p>"Fix-it" hints are most useful for
 | |
| working around common user errors and misconceptions. For example, C++ users
 | |
| commonly forget the syntax for explicit specialization of class templates,
 | |
| as in the error in the following example. Again, after describing the problem,
 | |
| Clang provides the fix--add <code>template<></code>--as part of the
 | |
| diagnostic.<p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang t.cpp</span>
 | |
|   <span class="loc">t.cpp:9:3:</span> <span class="err">error:</span> <span class="msg">template specialization requires 'template<>'</span>
 | |
|     struct iterator_traits<file_iterator> {
 | |
|     <span class="point">^</span>
 | |
|     <span class="snip">template<> </span>
 | |
| </pre>
 | |
| 
 | |
| <h2>Template Type Diffing</h2>
 | |
| 
 | |
| <p>Templates types can be long and difficult to read.  More so when part of an
 | |
| error message.  Instead of just printing out the type name, Clang has enough
 | |
| information to remove the common elements and highlight the differences.  To
 | |
| show the template structure more clearly, the templated type can also be
 | |
| printed as an indented text tree.</p>
 | |
| 
 | |
| Default: template diff with type elision
 | |
| <pre>
 | |
| <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;
 | |
| </pre>
 | |
| -fno-elide-type: template diff without elision
 | |
| <pre>
 | |
| <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;
 | |
| </pre>
 | |
| -fdiagnostics-show-template-tree: template tree printing with elision
 | |
| <pre>
 | |
| <span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument;
 | |
|   vector<
 | |
|     map<
 | |
|       [...],
 | |
|       [<span class="template-highlight">float</span> != <span class="template-highlight">double</span>]>>
 | |
| </pre>
 | |
| -fdiagnostics-show-template-tree -fno-elide-type: template tree printing with no elision
 | |
| <pre>
 | |
| <span class="loc">t.cc:4:5:</span> <span class="note">note:</span> candidate function not viable: no known conversion for 1st argument;
 | |
|   vector<
 | |
|     map<
 | |
|       int,
 | |
|       [<span class="template-highlight">float</span> != <span class="template-highlight">double</span>]>>
 | |
| </pre>
 | |
| 
 | |
| <h2>Automatic Macro Expansion</h2>
 | |
| 
 | |
| <p>Many errors happen in macros that are sometimes deeply nested.  With
 | |
| traditional compilers, you need to dig deep into the definition of the macro to
 | |
| understand how you got into trouble.  The following simple example shows how
 | |
| Clang helps you out by automatically printing instantiation information and
 | |
| nested range information for diagnostics as they are instantiated through macros
 | |
| and also shows how some of the other pieces work in a bigger example.</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang -fsyntax-only t.c</span>
 | |
|   <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>
 | |
|   <span class="snip">  X = MYMAX(P, F);</span>
 | |
|   <span class="point">      ^~~~~~~~~~~</span>
 | |
|   <span class="loc">t.c:76:94:</span> <span class="note">note:</span> expanded from:
 | |
|   <span class="snip">#define MYMAX(A,B)    __extension__ ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })</span>
 | |
|   <span class="point">                                                                                         ~~~ ^ ~~~</span>
 | |
| </pre>
 | |
| 
 | |
| <p>Here's another real world warning that occurs in the "window" Unix package (which
 | |
| implements the "wwopen" class of APIs):</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">clang -fsyntax-only t.c</span>
 | |
|   <span class="loc">t.c:22:2:</span> <span class="warn">warning:</span> <span class="msg">type specifier missing, defaults to 'int'</span>
 | |
|   <span class="snip">        ILPAD();</span>
 | |
|   <span class="point">        ^</span>
 | |
|   <span class="loc">t.c:17:17:</span> <span class="note">note:</span> expanded from:
 | |
|   <span class="snip">#define ILPAD() PAD((NROW - tt.tt_row) * 10)    /* 1 ms per char */</span>
 | |
|   <span class="point">                ^</span>
 | |
|   <span class="loc">t.c:14:2:</span> <span class="note">note:</span> expanded from:
 | |
|   <span class="snip">        register i; \</span>
 | |
|   <span class="point">        ^</span>
 | |
| </pre>
 | |
| 
 | |
| <p>In practice, we've found that Clang's treatment of macros is actually more useful in multiply nested
 | |
| macros than in simple ones.</p>
 | |
| 
 | |
| <h2>Quality of Implementation and Attention to Detail</h2>
 | |
| 
 | |
| <p>Finally, we have put a lot of work polishing the little things, because
 | |
| little things add up over time and contribute to a great user experience.</p>
 | |
| 
 | |
| <p>The following example shows that we recover from the simple case of
 | |
| forgetting a ; after a struct definition much better than GCC.</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">cat t.cc</span>
 | |
|   template<class T>
 | |
|   class a {};
 | |
|   struct b {}
 | |
|   a<int> c;
 | |
|   $ <span class="cmd">gcc-4.9 t.cc</span>
 | |
|   t.cc:4:8: error: invalid declarator before 'c'
 | |
|    a<int> c;
 | |
|            ^
 | |
|   $ <span class="cmd">clang t.cc</span>
 | |
|   <span class="loc">t.cc:3:12:</span> <span class="err">error:</span> <span class="msg">expected ';' after struct</span>
 | |
|   <span class="snip" >struct b {}</span>
 | |
|   <span class="point">           ^</span>
 | |
|   <span class="point">           ;</span>
 | |
| </pre>
 | |
| 
 | |
| <p>The following example shows that we diagnose and recover from a missing
 | |
| <tt>typename</tt> keyword well, even in complex circumstances where GCC
 | |
| cannot cope.</p>
 | |
| 
 | |
| <pre>
 | |
|   $ <span class="cmd">cat t.cc</span>
 | |
|   template<class T> void f(T::type) { }
 | |
|   struct A { };
 | |
|   void g()
 | |
|   {
 | |
|       A a;
 | |
|       f<A>(a);
 | |
|   }
 | |
|   $ <span class="cmd">gcc-4.9 t.cc</span>
 | |
|   t.cc:1:33: error: variable or field 'f' declared void
 | |
|    template<class T> void f(T::type) { }
 | |
|                                    ^
 | |
|   t.cc: In function 'void g()':
 | |
|   t.cc:6:5: error: 'f' was not declared in this scope
 | |
|        f<A>(a);
 | |
|        ^
 | |
|   t.cc:6:8: error: expected primary-expression before '>' token
 | |
|        f<A>(a);
 | |
|           ^
 | |
|   $ <span class="cmd">clang t.cc</span>
 | |
|   <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>
 | |
|   <span class="snip" >template<class T> void f(T::type) { }</span>
 | |
|   <span class="point">                         ^~~~~~~</span>
 | |
|   <span class="point">                         typename </span>
 | |
|   <span class="loc">t.cc:6:5:</span> <span class="err">error:</span> <span class="msg">no matching function for call to 'f'</span>
 | |
|   <span class="snip" >    f<A>(a);</span>
 | |
|   <span class="point">    ^~~~</span>
 | |
|   <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>
 | |
|   <span class="snip" >template<class T> void f(T::type) { }</span>
 | |
|   <span class="point">                       ^    ~~~~</span>
 | |
| </pre>
 | |
| 
 | |
| 
 | |
| 
 | |
| <p>While each of these details is minor, we feel that they all add up to provide
 | |
| a much more polished experience.</p>
 | |
| 
 | |
| </div>
 | |
| </body>
 | |
| </html>
 |