Chris Lattner | 7676601 | 2009-03-19 18:52:17 +0000 | [diff] [blame^] | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
| 2 | "http://www.w3.org/TR/html4/strict.dtd"> |
| 3 | <html> |
| 4 | <head> |
| 5 | <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> |
| 6 | <title>Clang - Expressive Diagnostics</title> |
| 7 | <link type="text/css" rel="stylesheet" href="menu.css" /> |
| 8 | <link type="text/css" rel="stylesheet" href="content.css" /> |
| 9 | <style type="text/css"> |
| 10 | </style> |
| 11 | </head> |
| 12 | <body> |
| 13 | |
| 14 | <!--#include virtual="menu.html.incl"--> |
| 15 | |
| 16 | <div id="content"> |
| 17 | |
| 18 | |
| 19 | <!--=======================================================================--> |
| 20 | <h1>Expressive Diagnostics</h1> |
| 21 | <!--=======================================================================--> |
| 22 | |
| 23 | <p>In addition to being fast and functional, we aim to make Clang extremely user |
| 24 | friendly. As far as a command-line compiler goes, this basically boils down to |
| 25 | making the diagnostics (error and warning messages) generated by the compiler |
| 26 | be as useful as possible. There are several ways that we do this. This section |
| 27 | talks about the experience provided by the command line compiler, contrasting |
| 28 | Clang output to GCC 4.2's output in several examples. |
| 29 | <!-- |
| 30 | Other clients |
| 31 | that embed Clang and extract equivalent information through internal APIs.--> |
| 32 | </p> |
| 33 | |
| 34 | <h2>Column Numbers and Caret Diagnostics</h2> |
| 35 | |
| 36 | <p>First, all diagnostics produced by clang include full column number |
| 37 | information, and use this to print "caret diagnostics". This is a feature |
| 38 | provided by many commercial compilers, but is generally missing from open source |
| 39 | compilers. This is nice because it makes it very easy to understand exactly |
| 40 | what is wrong in a particular piece of code, an example is:</p> |
| 41 | |
| 42 | <pre> |
| 43 | $ <b>gcc-4.2 -fsyntax-only -Wformat format-strings.c</b> |
| 44 | format-strings.c:91: warning: too few arguments for format |
| 45 | $ <b>clang -fsyntax-only format-strings.c</b> |
| 46 | format-strings.c:91:13: warning: '.*' specified field precision is missing a matching 'int' argument |
| 47 | <font color="darkgreen"> printf("%.*d");</font> |
| 48 | <font color="blue"> ^</font> |
| 49 | </pre> |
| 50 | |
| 51 | <p>The caret (the blue "^" character) exactly shows where the problem is, even |
| 52 | inside of the string. This makes it really easy to jump to the problem and |
| 53 | helps when multiple instances of the same character occur on a line. We'll |
| 54 | revisit this more in following examples.</p> |
| 55 | |
| 56 | <h2>Range Highlighting for Related Text</h2> |
| 57 | |
| 58 | <p>Clang captures and accurately tracks range information for expressions, |
| 59 | statements, and other constructs in your program and uses this to make |
| 60 | diagnostics highlight related information. For example, here's a somewhat |
| 61 | nonsensical example to illustrate this:</p> |
| 62 | |
| 63 | <pre> |
| 64 | $ <b>gcc-4.2 -fsyntax-only t.c</b> |
| 65 | t.c:7: error: invalid operands to binary + (have 'int' and 'struct A') |
| 66 | $ <b>clang -fsyntax-only t.c</b> |
| 67 | t.c:7:39: error: invalid operands to binary expression ('int' and 'struct A') |
| 68 | <font color="darkgreen"> return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);</font> |
| 69 | <font color="blue"> ~~~~~~~~~~~~~~ ^ ~~~~~</font> |
| 70 | </pre> |
| 71 | |
| 72 | <p>Here you can see that you don't even need to see the original source code to |
| 73 | understand what is wrong based on the Clang error: Because clang prints a |
| 74 | caret, you know exactly <em>which</em> plus it is complaining about. The range |
| 75 | information highlights the left and right side of the plus which makes it |
| 76 | immediately obvious what the compiler is talking about, which is very useful for |
| 77 | cases involving precedence issues and many other cases.</p> |
| 78 | |
| 79 | <h2>Precision in Wording</h2> |
| 80 | |
| 81 | <p>A detail is that we have tried really hard to make the diagnostics that come |
| 82 | out of clang contain exactly the pertinent information about what is wrong and |
| 83 | why. In the example above, we tell you what the inferred types are for |
| 84 | the left and right hand sides, and we don't repeat what is obvious from the |
| 85 | caret (that this is a "binary +"). Many other examples abound, here is a simple |
| 86 | one:</p> |
| 87 | |
| 88 | <pre> |
| 89 | $ <b>gcc-4.2 -fsyntax-only t.c</b> |
| 90 | t.c:5: error: invalid type argument of 'unary *' |
| 91 | $ <b>clang -fsyntax-only t.c</b> |
| 92 | t.c:5:11: error: indirection requires pointer operand ('int' invalid) |
| 93 | <font color="darkgreen"> int y = *SomeA.X;</font> |
| 94 | <font color="blue"> ^~~~~~~~</font> |
| 95 | </pre> |
| 96 | |
| 97 | <p>In this example, not only do we tell you that there is a problem with the * |
| 98 | and point to it, we say exactly why and tell you what the type is (in case it is |
| 99 | a complicated subexpression, such as a call to an overloaded function). This |
| 100 | sort of attention to detail makes it much easier to understand and fix problems |
| 101 | quickly.</p> |
| 102 | |
| 103 | <h2>No Pretty Printing of Expressions in Diagnostics</h2> |
| 104 | |
| 105 | <p>Since Clang has range highlighting, it never needs to pretty print your code |
| 106 | back out to you. This is particularly bad in G++ (which often emits errors |
| 107 | containing lowered vtable references), but even GCC can produce |
| 108 | inscrutible error messages in some cases when it tries to do this. In this |
| 109 | example P and Q have type "int*":</p> |
| 110 | |
| 111 | <pre> |
| 112 | $ <b>gcc-4.2 -fsyntax-only t.c</b> |
| 113 | #'exact_div_expr' not supported by pp_c_expression#'t.c:12: error: called object is not a function |
| 114 | $ <b>clang -fsyntax-only t.c</b> |
| 115 | t.c:12:8: error: called object type 'int' is not a function or function pointer |
| 116 | <font color="darkgreen"> (P-Q)();</font> |
| 117 | <font color="blue"> ~~~~~^</font> |
| 118 | </pre> |
| 119 | |
| 120 | |
| 121 | <h2>Typedef Preservation and Selective Unwrapping</h2> |
| 122 | |
| 123 | <p>Many programmers use high-level user defined types, typedefs, and other |
| 124 | syntactic sugar to refer to types in their program. This is useful because they |
| 125 | can abbreviate otherwise very long types and it is useful to preserve the |
| 126 | typename in diagnostics. However, sometimes very simple typedefs can wrap |
| 127 | trivial types and it is important to strip off the typedef to understand what |
| 128 | is going on. Clang aims to handle both cases well.<p> |
| 129 | |
| 130 | <p>For example, here is an example that shows where it is important to preserve |
| 131 | a typedef in C:</p> |
| 132 | |
| 133 | <pre> |
| 134 | $ <b>gcc-4.2 -fsyntax-only t.c</b> |
| 135 | t.c:15: error: invalid operands to binary / (have 'float __vector__' and 'const int *') |
| 136 | $ <b>clang -fsyntax-only t.c</b> |
| 137 | t.c:15:11: error: can't convert between vector values of different size ('__m128' and 'int const *') |
| 138 | <font color="darkgreen"> myvec[1]/P;</font> |
| 139 | <font color="blue"> ~~~~~~~~^~</font> |
| 140 | </pre> |
| 141 | |
| 142 | <p>Here the type printed by GCC isn't even valid, but if the error were about a |
| 143 | very long and complicated type (as often happens in C++) the error message would |
| 144 | be ugly just because it was long and hard to read. Here's an example where it |
| 145 | is useful for the compiler to expose underlying details of a typedef:</p> |
| 146 | |
| 147 | <pre> |
| 148 | $ <b>gcc-4.2 -fsyntax-only t.c</b> |
| 149 | t.c:13: error: request for member 'x' in something not a structure or union |
| 150 | $ <b>clang -fsyntax-only t.c</b> |
| 151 | t.c:13:9: error: member reference base type 'pid_t' (aka 'int') is not a structure or union |
| 152 | <font color="darkgreen"> myvar = myvar.x;</font> |
| 153 | <font color="blue"> ~~~~~ ^</font> |
| 154 | </pre> |
| 155 | |
| 156 | <p>If the user was somehow confused about how the system "pid_t" typedef is |
| 157 | defined, Clang helpfully displays it with "aka".</p> |
| 158 | |
| 159 | <h2>Fix-it Hints</h2> |
| 160 | |
| 161 | <p>simple example + template<> example</p> |
| 162 | |
| 163 | |
| 164 | <h2>Automatic Macro Expansion</h2> |
| 165 | |
| 166 | <p>Many errors happen in macros that are sometimes deeply nested. With |
| 167 | traditional compilers, you need to dig deep into the definition of the macro to |
| 168 | understand how you got into trouble. Here's a simple example that shows how |
| 169 | Clang helps you out:</p> |
| 170 | |
| 171 | <pre> |
| 172 | $ <b>gcc-4.2 -fsyntax-only t.c</b> |
| 173 | t.c: In function 'test': |
| 174 | t.c:80: error: invalid operands to binary < (have 'struct mystruct' and 'float') |
| 175 | $ <b>clang -fsyntax-only t.c</b> |
| 176 | t.c:80:3: error: invalid operands to binary expression ('typeof(P)' (aka 'struct mystruct') and 'typeof(F)' (aka 'float')) |
| 177 | <font color="darkgreen"> X = MYMAX(P, F);</font> |
| 178 | <font color="blue"> ^~~~~~~~~~~</font> |
| 179 | t.c:76:94: note: instantiated from: |
| 180 | <font color="darkgreen">#define MYMAX(A,B) __extension__ ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })</font> |
| 181 | <font color="blue"> ~~~ ^ ~~~</font> |
| 182 | </pre> |
| 183 | |
| 184 | <p>This shows how clang automatically prints instantiation information and |
| 185 | nested range information for diagnostics as they are instantiated through macros |
| 186 | and also shows how some of the other pieces work in a bigger example. Here's |
| 187 | another real world warning that occurs in the "window" Unix package (which |
| 188 | implements the "wwopen" class of APIs):</p> |
| 189 | |
| 190 | <pre> |
| 191 | $ <b>clang -fsyntax-only t.c</b> |
| 192 | t.c:22:2: warning: type specifier missing, defaults to 'int' |
| 193 | <font color="darkgreen"> ILPAD();</font> |
| 194 | <font color="blue"> ^</font> |
| 195 | t.c:17:17: note: instantiated from: |
| 196 | <font color="darkgreen">#define ILPAD() PAD((NROW - tt.tt_row) * 10) /* 1 ms per char */</font> |
| 197 | <font color="blue"> ^</font> |
| 198 | t.c:14:2: note: instantiated from: |
| 199 | <font color="darkgreen"> register i; \</font> |
| 200 | <font color="blue"> ^</font> |
| 201 | </pre> |
| 202 | |
| 203 | <p>In practice, we've found that this is actually more useful in multiply nested |
| 204 | macros that in simple ones.</p> |
| 205 | |
| 206 | <h2>C++ Fun Examples</h2> |
| 207 | |
| 208 | <p>...</p> |
| 209 | |
| 210 | |
| 211 | </div> |
| 212 | </body> |
| 213 | </html> |