From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Mon, 24 Sep 2012 09:58:17 +1000 Subject: Add the clang library to the repo (with some of my changes, too). --- clang/www/diagnostics.html | 374 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 clang/www/diagnostics.html (limited to 'clang/www/diagnostics.html') diff --git a/clang/www/diagnostics.html b/clang/www/diagnostics.html new file mode 100644 index 0000000..45f6907 --- /dev/null +++ b/clang/www/diagnostics.html @@ -0,0 +1,374 @@ + + + + + Clang - Expressive Diagnostics + + + + + + + + +
+ + + +

Expressive Diagnostics

+ + +

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.2's output in several examples. + +

+ +

Column Numbers and Caret Diagnostics

+ +

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.) +Precise error location in the source is a feature provided by many commercial +compilers, but is generally missing from open source +compilers. This is nice because it makes it very easy to understand exactly +what is wrong in a particular piece of code

+ +

The point (the blue "^" 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.)

+ +
+  $ gcc-4.2 -fsyntax-only -Wformat format-strings.c
+  format-strings.c:91: warning: too few arguments for format
+  $ clang -fsyntax-only format-strings.c
+  format-strings.c:91:13: warning: '.*' specified field precision is missing a matching 'int' argument
+    printf("%.*d");
+              ^
+
+ +

Range Highlighting for Related Text

+ +

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 which 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.

+ +
+  $ gcc-4.2 -fsyntax-only t.c
+  t.c:7: error: invalid operands to binary + (have 'int' and 'struct A')
+  $ clang -fsyntax-only t.c
+  t.c:7:39: error: invalid operands to binary expression ('int' and 'struct A')
+    return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);
+                         ~~~~~~~~~~~~~~ ^ ~~~~~
+
+ +

Precision in Wording

+ +

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 +").

+ +

Many other examples abound. In the following example, not only do we tell you that there is a problem with the * +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.

+ +
+  $ gcc-4.2 -fsyntax-only t.c
+  t.c:5: error: invalid type argument of 'unary *'
+  $ clang -fsyntax-only t.c
+  t.c:5:11: error: indirection requires pointer operand ('int' invalid)
+    int y = *SomeA.X;
+            ^~~~~~~~
+
+ +

No Pretty Printing of Expressions in Diagnostics

+ +

Since Clang has range highlighting, it never needs to pretty print your code +back out to you. GCC can produce inscrutible error messages in some cases when +it tries to do this. In this example P and Q have type "int*":

+ +
+  $ gcc-4.2 -fsyntax-only t.c
+  #'exact_div_expr' not supported by pp_c_expression#'t.c:12: error: called object  is not a function
+  $ clang -fsyntax-only t.c
+  t.c:12:8: error: called object type 'int' is not a function or function pointer
+    (P-Q)();
+    ~~~~~^
+
+ +

This can be particularly bad in G++, which often emits errors + containing lowered vtable references. For example:

+ +
+  $ cat t.cc
+  struct a {
+    virtual int bar();
+  };
+  
+  struct foo : public virtual a {
+  };
+  
+  void test(foo *P) {
+    return P->bar() + *P;
+  }
+  $ gcc-4.2 t.cc
+  t.cc: In function 'void test(foo*)':
+  t.cc:9: error: no match for 'operator+' in '(((a*)P) + (*(long int*)(P->foo::<anonymous>.a::_vptr$a + -0x00000000000000020)))->a::bar() + * P'
+  t.cc:9: error: return-statement with a value, in function returning 'void'
+  $ clang t.cc
+  t.cc:9:18: error: invalid operands to binary expression ('int' and 'foo')
+    return P->bar() + *P;
+           ~~~~~~~~ ^ ~~
+
+ + +

Typedef Preservation and Selective Unwrapping

+ +

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.

+ +

The following example shows where it is important to preserve +a typedef in C. Here the type printed by GCC isn't even valid, but if the error +were about a very long and complicated type (as often happens in C++) the error +message would be ugly just because it was long and hard to read.

+ +
+  $ gcc-4.2 -fsyntax-only t.c
+  t.c:15: error: invalid operands to binary / (have 'float __vector__' and 'const int *')
+  $ clang -fsyntax-only t.c
+  t.c:15:11: error: can't convert between vector values of different size ('__m128' and 'int const *')
+    myvec[1]/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".

+ +
+  $ gcc-4.2 -fsyntax-only t.c
+  t.c:13: error: request for member 'x' in something not a structure or union
+  $ clang -fsyntax-only t.c
+  t.c:13:9: error: member reference base type 'pid_t' (aka 'int') is not a structure or union
+    myvar = myvar.x;
+            ~~~~~ ^
+
+ +

In C++, type preservation includes retaining any qualification written into type names. For example, if we take a small snippet of code such as: + +

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

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"): + +

+  $ g++-4.2 -fsyntax-only t.cpp
+  t.cpp:9: error: no match for 'operator+=' in 'server += http'
+  $ clang -fsyntax-only t.cpp
+  t.cpp:9:10: error: invalid operands to binary expression ('servers::Server const' and '::services::WebService const *')
+    server += http;
+    ~~~~~~ ^  ~~~~
+
+ +

Naturally, type preservation extends to uses of templates, and Clang retains information about how a particular template specialization (like std::vector<Real>) was spelled within the source code. For example:

+ +
+  $ g++-4.2 -fsyntax-only t.cpp
+  t.cpp:12: error: no match for 'operator=' in 'str = vec'
+  $ clang -fsyntax-only t.cpp
+  t.cpp:12:7: error: incompatible type assigning 'vector<Real>', expected 'std::string' (aka 'class std::basic_string<char>')
+    str = vec;
+        ^ ~~~
+
+ +

Fix-it Hints

+ +

"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).

+ +
+  $ clang t.c
+  t.c:5:28: warning: use of GNU old-style field designator extension
+  struct point origin = { x: 0.0, y: 0.0 };
+                          ~~ ^
+                          .x = 
+  t.c:5:36: warning: use of GNU old-style field designator extension
+  struct point origin = { x: 0.0, y: 0.0 };
+                                  ~~ ^
+                                  .y = 
+
+ +

"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 template<>--as part of the +diagnostic.

+ +

+  $ clang t.cpp
+  t.cpp:9:3: error: template specialization requires 'template<>'
+    struct iterator_traits<file_iterator> {
+    ^
+    template<> 
+
+ +

Automatic Macro Expansion

+ +

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.

+ +
+  $ gcc-4.2 -fsyntax-only t.c
+  t.c: In function 'test':
+  t.c:80: error: invalid operands to binary < (have 'struct mystruct' and 'float')
+  $ clang -fsyntax-only t.c
+  t.c:80:3: error: invalid operands to binary expression ('typeof(P)' (aka 'struct mystruct') and 'typeof(F)' (aka 'float'))
+    X = MYMAX(P, F);
+        ^~~~~~~~~~~
+  t.c:76:94: note: instantiated from:
+  #define MYMAX(A,B)    __extension__ ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })
+                                                                                           ~~~ ^ ~~~
+
+ +

Here's another real world warning that occurs in the "window" Unix package (which +implements the "wwopen" class of APIs):

+ +
+  $ clang -fsyntax-only t.c
+  t.c:22:2: warning: type specifier missing, defaults to 'int'
+          ILPAD();
+          ^
+  t.c:17:17: note: instantiated from:
+  #define ILPAD() PAD((NROW - tt.tt_row) * 10)    /* 1 ms per char */
+                  ^
+  t.c:14:2: note: instantiated from:
+          register i; \
+          ^
+
+ +

In practice, we've found that Clang's treatment of macros is actually more useful in multiply nested +macros that in simple ones.

+ +

Quality of Implementation and Attention to Detail

+ +

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.

+ +

The following example shows a trivial little tweak, where we tell you to put the semicolon at +the end of the line that is missing it (line 4) instead of at the beginning of +the following line (line 5). This is particularly important with fixit hints +and point diagnostics, because otherwise you don't get the important context. +

+ +
+  $ gcc-4.2 t.c
+  t.c: In function 'foo':
+  t.c:5: error: expected ';' before '}' token
+  $ clang t.c
+  t.c:4:8: error: expected ';' after expression
+    bar()
+         ^
+         ;
+
+ +

The following example shows much better error recovery than GCC. The message coming out +of GCC is completely useless for diagnosing the problem. Clang tries much harder +and produces a much more useful diagnosis of the problem.

+ +
+  $ gcc-4.2 t.c
+  t.c:3: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token
+  $ clang t.c
+  t.c:3:1: error: unknown type name 'foo_t'
+  foo_t *P = 0;
+  ^
+
+ +

The following example shows that we recover from the simple case of +forgetting a ; after a struct definition much better than GCC.

+ +
+  $ cat t.cc
+  template<class T>
+  class a {}
+  class temp {};
+  a<temp> b;
+  struct b {
+  }
+  $ gcc-4.2 t.cc
+  t.cc:3: error: multiple types in one declaration
+  t.cc:4: error: non-template type 'a' used as a template
+  t.cc:4: error: invalid type in declaration before ';' token
+  t.cc:6: error: expected unqualified-id at end of input
+  $ clang t.cc
+  t.cc:2:11: error: expected ';' after class
+  class a {}
+            ^
+            ;
+  t.cc:6:2: error: expected ';' after struct
+  }
+   ^
+   ;
+
+ +

While each of these details is minor, we feel that they all add up to provide +a much more polished experience.

+ +
+ + -- cgit v1.2.3