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/compatibility.html | 869 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 869 insertions(+) create mode 100644 clang/www/compatibility.html (limited to 'clang/www/compatibility.html') diff --git a/clang/www/compatibility.html b/clang/www/compatibility.html new file mode 100644 index 0000000..725c52f --- /dev/null +++ b/clang/www/compatibility.html @@ -0,0 +1,869 @@ + + + + + Language Compatibility + + + + + + + + +
+ + +

Language Compatibility

+ + +

Clang strives to both conform to current language standards (C99, + C++98) and also to implement many widely-used extensions available + in other compilers, so that most correct code will "just work" when + compiler with Clang. However, Clang is more strict than other + popular compilers, and may reject incorrect code that other + compilers allow. This page documents common compatibility and + portability issues with Clang to help you understand and fix the + problem in your code when Clang emits an error message.

+ + + + +

C compatibility

+ + + +

C99 inline functions

+ +

By default, Clang builds C code according to the C99 standard, +which provides different semantics for the inline keyword +than GCC's default behavior. For example, consider the following +code:

+
+inline int add(int i, int j) { return i + j; }
+
+int main() {
+  int i = add(4, 5);
+  return i;
+}
+
+ +

In C99, inline means that a function's definition is +provided only for inlining, and that there is another definition +(without inline) somewhere else in the program. That +means that this program is incomplete, because if add +isn't inlined (for example, when compiling without optimization), then +main will have an unresolved reference to that other +definition. Therefore we'll get a (correct) link-time error like this:

+ +
+Undefined symbols:
+  "_add", referenced from:
+      _main in cc-y1jXIr.o
+
+ +

By contrast, GCC's default behavior follows the GNU89 dialect, +which is the C89 standard plus a lot of extensions. C89 doesn't have +an inline keyword, but GCC recognizes it as an extension +and just treats it as a hint to the optimizer.

+ +

There are several ways to fix this problem:

+ + + +

All of this only applies to C code; the meaning of inline +in C++ is very different from its meaning in either GNU89 or C99.

+ + +

"missing" vector __builtin functions

+ + +

The Intel and AMD manuals document a number "<*mmintrin.h>" +header files, which define a standardized API for accessing vector operations +on X86 CPUs. These functions have names like _mm_xor_ps and +_mm256_addsub_pd. Compilers have leeway to implement these functions +however they want. Since Clang supports an excellent set of native vector operations, +the Clang headers implement these interfaces in terms of the native vector +operations. +

+ +

In contrast, GCC implements these functions mostly as a 1-to-1 mapping to +builtin function calls, like __builtin_ia32_paddw128. These builtin +functions are an internal implementation detail of GCC, and are not portable to +the Intel compiler, the Microsoft compiler, or Clang. If you get build errors +mentioning these, the fix is simple: switch to the *mmintrin.h functions.

+ +

The same issue occurs for NEON and Altivec for the ARM and PowerPC +architectures respectively. For these, make sure to use the <arm_neon.h> +and <altivec.h> headers.

+ +

For x86 architectures this script should help with +the manual migration process. It will rewrite your source files in place to +use the APIs instead of builtin function calls. Just call it like this:

+ +
+  builtins.py *.c *.h
+
+ +

and it will rewrite all of the .c and .h files in the current directory to +use the API calls instead of calls like __builtin_ia32_paddw128.

+ + +

Lvalue casts

+ + +

Old versions of GCC permit casting the left-hand side of an assignment to a +different type. Clang produces an error on similar code, e.g.,

+ +
+lvalue.c:2:3: error: assignment to cast is illegal, lvalue casts are not
+      supported
+  (int*)addr = val;
+  ^~~~~~~~~~ ~
+
+ +

To fix this problem, move the cast to the right-hand side. In this +example, one could use:

+ +
+  addr = (float *)val;
+
+ + +

Jumps to within __block variable scope

+ + +

Clang disallows jumps into the scope of a __block +variable. Variables marked with __block require special +runtime initialization. A jump into the scope of a __block +variable bypasses this initialization, leaving the variable's metadata +in an invalid state. Consider the following code fragment:

+ +
+int fetch_object_state(struct MyObject *c) {
+  if (!c->active) goto error;
+
+  __block int result;
+  run_specially_somehow(^{ result = c->state; });
+  return result;
+
+ error:
+  fprintf(stderr, "error while fetching object state");
+  return -1;
+}
+
+ +

GCC accepts this code, but it produces code that will usually crash +when result goes out of scope if the jump is taken. (It's +possible for this bug to go undetected because it often won't crash if +the stack is fresh, i.e. still zeroed.) Therefore, Clang rejects this +code with a hard error:

+ +
+t.c:3:5: error: goto into protected scope
+    goto error;
+    ^
+t.c:5:15: note: jump bypasses setup of __block variable
+  __block int result;
+              ^
+
+ +

The fix is to rewrite the code to not require jumping into a +__block variable's scope, e.g. by limiting that scope:

+ +
+  {
+    __block int result;
+    run_specially_somehow(^{ result = c->state; });
+    return result;
+  }
+
+ + +

Non-initialization of __block +variables

+ + +

In the following example code, the x variable is used before it is +defined:

+
+int f0() {
+  __block int x;
+  return ^(){ return x; }();
+}
+
+ +

By an accident of implementation, GCC and llvm-gcc unintentionally always +zero initialized __block variables. However, any program which depends +on this behavior is relying on unspecified compiler behavior. Programs must +explicitly initialize all local block variables before they are used, as with +other local variables.

+ +

Clang does not zero initialize local block variables, and programs which rely +on such behavior will most likely break when built with Clang.

+ + + +

Inline assembly

+ + +

In general, Clang is highly compatible with the GCC inline assembly +extensions, allowing the same set of constraints, modifiers and operands as GCC +inline assembly.

+ +

On targets that use the integrated assembler (such as most X86 targets), +inline assembly is run through the integrated assembler instead of your system +assembler (which is most commonly "gas", the GNU assembler). The LLVM +integrated assembler is extremely compatible with GAS, but there are a couple of +minor places where it is more picky, particularly due to outright GAS bugs.

+ +

One specific example is that the assembler rejects ambiguous X86 instructions +that don't have suffixes. For example:

+ +
+  asm("add %al, (%rax)");
+  asm("addw $4, (%rax)");
+  asm("add $4, (%rax)");
+
+ +

Both clang and GAS accept the first instruction: because the first +instruction uses the 8-bit %al register as an operand, it is clear that +it is an 8-bit add. The second instruction is accepted by both because the "w" +suffix indicates that it is a 16-bit add. The last instruction is accepted by +GAS even though there is nothing that specifies the size of the instruction (and +the assembler randomly picks a 32-bit add). Because it is ambiguous, Clang +rejects the instruction with this error message: +

+ +
+<inline asm>:3:1: error: ambiguous instructions require an explicit suffix (could be 'addb', 'addw', 'addl', or 'addq')
+add $4, (%rax)
+^
+1 error generated.
+
+ +

To fix this compatibility issue, add an explicit suffix to the instruction: +this makes your code more clear and is compatible with both GCC and Clang.

+ + +

Objective-C compatibility

+ + + +

Cast of super

+ + +

GCC treats the super identifier as an expression that +can, among other things, be cast to a different type. Clang treats +super as a context-sensitive keyword, and will reject a +type-cast of super:

+ +
+super.m:11:12: error: cannot cast 'super' (it isn't an expression)
+  [(Super*)super add:4];
+   ~~~~~~~~^
+
+ +

To fix this problem, remove the type cast, e.g.

+
+  [super add:4];
+
+ + +

Size of interfaces

+ + +

When using the "non-fragile" Objective-C ABI in use, the size of an +Objective-C class may change over time as instance variables are added +(or removed). For this reason, Clang rejects the application of the +sizeof operator to an Objective-C class when using this +ABI:

+ +
+sizeof.m:4:14: error: invalid application of 'sizeof' to interface 'NSArray' in
+      non-fragile ABI
+  int size = sizeof(NSArray);
+             ^     ~~~~~~~~~
+
+ +

Code that relies on the size of an Objective-C class is likely to +be broken anyway, since that size is not actually constant. To address +this problem, use the Objective-C runtime API function +class_getInstanceSize():

+ +
+  class_getInstanceSize([NSArray class])
+
+ + +

Internal Objective-C types

+ + +

GCC allows using pointers to internal Objective-C objects, struct objc_object*, +struct objc_selector*, and struct objc_class* in place of the types +id, SEL, and Class respectively. Clang treats the +internal Objective-C structures as implementation detail and won't do implicit conversions: + +

+t.mm:11:2: error: no matching function for call to 'f'
+        f((struct objc_object *)p);
+        ^
+t.mm:5:6: note: candidate function not viable: no known conversion from 'struct objc_object *' to 'id' for 1st argument
+void f(id x);
+     ^
+
+ +

Code should use types id, SEL, and Class +instead of the internal types.

+ + +

C variables in @interface or @protocol

+ + +

GCC allows the declaration of C variables in +an @interface or @protocol +declaration. Clang does not allow variable declarations to appear +within these declarations unless they are marked extern.

+ +

Variables may still be declared in an @implementation.

+ +
+@interface XX
+int a;         // not allowed in clang
+int b = 1;     // not allowed in clang
+extern int c;  // allowed 
+@end
+
+
+ + +

C++ compatibility

+ + + +

Variable-length arrays

+ + +

GCC and C99 allow an array's size to be determined at run +time. This extension is not permitted in standard C++. However, Clang +supports such variable length arrays in very limited circumstances for +compatibility with GNU C and C99 programs:

+ + + +

If your code uses variable length arrays in a manner that Clang doesn't support, there are several ways to fix your code: + +

    +
  1. replace the variable length array with a fixed-size array if you can + determine a reasonable upper bound at compile time; sometimes this is as + simple as changing int size = ...; to const int size + = ...; (if the initializer is a compile-time constant);
  2. +
  3. use std::vector or some other suitable container type; + or
  4. +
  5. allocate the array on the heap instead using new Type[] - + just remember to delete[] it.
  6. +
+ + +

Unqualified lookup in templates

+ + +

Some versions of GCC accept the following invalid code: + +

+template <typename T> T Squared(T x) {
+  return Multiply(x, x);
+}
+
+int Multiply(int x, int y) {
+  return x * y;
+}
+
+int main() {
+  Squared(5);
+}
+
+ +

Clang complains: + +

  my_file.cpp:2:10: error: call to function 'Multiply' that is neither visible in the template definition nor found by argument-dependent lookup
+    return Multiply(x, x);
+           ^
+  my_file.cpp:10:3: note: in instantiation of function template specialization 'Squared<int>' requested here
+    Squared(5);
+    ^
+  my_file.cpp:5:5: note: 'Multiply' should be declared prior to the call site
+  int Multiply(int x, int y) {
+      ^
+
+ +

The C++ standard says that unqualified names like Multiply +are looked up in two ways. + +

First, the compiler does unqualified lookup in the scope +where the name was written. For a template, this means the lookup is +done at the point where the template is defined, not where it's +instantiated. Since Multiply hasn't been declared yet at +this point, unqualified lookup won't find it. + +

Second, if the name is called like a function, then the compiler +also does argument-dependent lookup (ADL). (Sometimes +unqualified lookup can suppress ADL; see [basic.lookup.argdep]p3 for +more information.) In ADL, the compiler looks at the types of all the +arguments to the call. When it finds a class type, it looks up the +name in that class's namespace; the result is all the declarations it +finds in those namespaces, plus the declarations from unqualified +lookup. However, the compiler doesn't do ADL until it knows all the +argument types. + +

In our example, Multiply is called with dependent +arguments, so ADL isn't done until the template is instantiated. At +that point, the arguments both have type int, which doesn't +contain any class types, and so ADL doesn't look in any namespaces. +Since neither form of lookup found the declaration +of Multiply, the code doesn't compile. + +

Here's another example, this time using overloaded operators, +which obey very similar rules. + +

#include <iostream>
+
+template<typename T>
+void Dump(const T& value) {
+  std::cout << value << "\n";
+}
+
+namespace ns {
+  struct Data {};
+}
+
+std::ostream& operator<<(std::ostream& out, ns::Data data) {
+  return out << "Some data";
+}
+
+void Use() {
+  Dump(ns::Data());
+}
+ +

Again, Clang complains:

+ +
  my_file2.cpp:5:13: error: call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup
+    std::cout << value << "\n";
+              ^
+  my_file2.cpp:17:3: note: in instantiation of function template specialization 'Dump<ns::Data>' requested here
+    Dump(ns::Data());
+    ^
+  my_file2.cpp:12:15: note: 'operator<<' should be declared prior to the call site or in namespace 'ns'
+  std::ostream& operator<<(std::ostream& out, ns::Data data) {
+                ^
+
+ +

Just like before, unqualified lookup didn't find any declarations +with the name operator<<. Unlike before, the argument +types both contain class types: one of them is an instance of the +class template type std::basic_ostream, and the other is the +type ns::Data that we declared above. Therefore, ADL will +look in the namespaces std and ns for +an operator<<. Since one of the argument types was +still dependent during the template definition, ADL isn't done until +the template is instantiated during Use, which means that +the operator<< we want it to find has already been +declared. Unfortunately, it was declared in the global namespace, not +in either of the namespaces that ADL will look in! + +

There are two ways to fix this problem:

+
  1. Make sure the function you want to call is declared before the +template that might call it. This is the only option if none of its +argument types contain classes. You can do this either by moving the +template definition, or by moving the function definition, or by +adding a forward declaration of the function before the template.
  2. +
  3. Move the function into the same namespace as one of its arguments +so that ADL applies.
+ +

For more information about argument-dependent lookup, see +[basic.lookup.argdep]. For more information about the ordering of +lookup in templates, see [temp.dep.candidate]. + + +

Unqualified lookup into dependent bases of class templates

+ + +Some versions of GCC accept the following invalid code: + +
+template <typename T> struct Base {
+  void DoThis(T x) {}
+  static void DoThat(T x) {}
+};
+
+template <typename T> struct Derived : public Base<T> {
+  void Work(T x) {
+    DoThis(x);  // Invalid!
+    DoThat(x);  // Invalid!
+  }
+};
+
+ +Clang correctly rejects it with the following errors +(when Derived is eventually instantiated): + +
+my_file.cpp:8:5: error: use of undeclared identifier 'DoThis'
+    DoThis(x);
+    ^
+    this->
+my_file.cpp:2:8: note: must qualify identifier to find this declaration in dependent base class
+  void DoThis(T x) {}
+       ^
+my_file.cpp:9:5: error: use of undeclared identifier 'DoThat'
+    DoThat(x);
+    ^
+    this->
+my_file.cpp:3:15: note: must qualify identifier to find this declaration in dependent base class
+  static void DoThat(T x) {}
+
+ +Like we said above, unqualified names like +DoThis and DoThat are looked up when the template +Derived is defined, not when it's instantiated. When we look +up a name used in a class, we usually look into the base classes. +However, we can't look into the base class Base<T> +because its type depends on the template argument T, so the +standard says we should just ignore it. See [temp.dep]p3 for details. + +

The fix, as Clang tells you, is to tell the compiler that we want a +class member by prefixing the calls with this->: + +

+  void Work(T x) {
+    this->DoThis(x);
+    this->DoThat(x);
+  }
+
+ +Alternatively, you can tell the compiler exactly where to look: + +
+  void Work(T x) {
+    Base<T>::DoThis(x);
+    Base<T>::DoThat(x);
+  }
+
+ +This works whether the methods are static or not, but be careful: +if DoThis is virtual, calling it this way will bypass virtual +dispatch! + + +

Incomplete types in templates

+ + +The following code is invalid, but compilers are allowed to accept it: + +
+  class IOOptions;
+  template <class T> bool read(T &value) {
+    IOOptions opts;
+    return read(opts, value);
+  }
+
+  class IOOptions { bool ForceReads; };
+  bool read(const IOOptions &opts, int &x);
+  template bool read<>(int &);
+
+ +The standard says that types which don't depend on template parameters +must be complete when a template is defined if they affect the +program's behavior. However, the standard also says that compilers +are free to not enforce this rule. Most compilers enforce it to some +extent; for example, it would be an error in GCC to +write opts.ForceReads in the code above. In Clang, we feel +that enforcing the rule consistently lets us provide a better +experience, but unfortunately it also means we reject some code that +other compilers accept. + +

We've explained the rule here in very imprecise terms; see +[temp.res]p8 for details. + + +

Templates with no valid instantiations

+ + +The following code contains a typo: the programmer +meant init() but wrote innit() instead. + +
+  template <class T> class Processor {
+    ...
+    void init();
+    ...
+  };
+  ...
+  template <class T> void process() {
+    Processor<T> processor;
+    processor.innit();       // <-- should be 'init()'
+    ...
+  }
+
+ +Unfortunately, we can't flag this mistake as soon as we see it: inside +a template, we're not allowed to make assumptions about "dependent +types" like Processor<T>. Suppose that later on in +this file the programmer adds an explicit specialization +of Processor, like so: + +
+  template <> class Processor<char*> {
+    void innit();
+  };
+
+ +Now the program will work — as long as the programmer only ever +instantiates process() with T = char*! This is why +it's hard, and sometimes impossible, to diagnose mistakes in a +template definition before it's instantiated. + +

The standard says that a template with no valid instantiations is +ill-formed. Clang tries to do as much checking as possible at +definition-time instead of instantiation-time: not only does this +produce clearer diagnostics, but it also substantially improves +compile times when using pre-compiled headers. The downside to this +philosophy is that Clang sometimes fails to process files because they +contain broken templates that are no longer used. The solution is +simple: since the code is unused, just remove it. + + +

Default initialization of const variable of a class type requires user-defined default constructor

+ + +If a class or struct has no user-defined default +constructor, C++ doesn't allow you to default construct a const +instance of it like this ([dcl.init], p9): + +
+class Foo {
+ public:
+  // The compiler-supplied default constructor works fine, so we
+  // don't bother with defining one.
+  ...
+};
+
+void Bar() {
+  const Foo foo;  // Error!
+  ...
+}
+
+ +To fix this, you can define a default constructor for the class: + +
+class Foo {
+ public:
+  Foo() {}
+  ...
+};
+
+void Bar() {
+  const Foo foo;  // Now the compiler is happy.
+  ...
+}
+
+ + +

Parameter name lookup

+ + +

Due to a bug in its implementation, GCC allows the redeclaration of function parameter names within a function prototype in C++ code, e.g.

+
+
+void f(int a, int a);
+
+
+

Clang diagnoses this error (where the parameter name has been redeclared). To fix this problem, rename one of the parameters.

+ + +

C++11 compatibility

+ + + +

Deleted special member functions

+ + +

In C++11, the explicit declaration of a move constructor or a move +assignment operator within a class deletes the implicit declaration +of the copy constructor and copy assignment operator. This change came +fairly late in the C++11 standardization process, so early +implementations of C++11 (including Clang before 3.0, GCC before 4.7, +and Visual Studio 2010) do not implement this rule, leading them to +accept this ill-formed code:

+ +
+struct X {
+  X(X&&); // deletes implicit copy constructor:
+  // X(const X&) = delete;
+};
+
+void f(X x);
+void g(X x) {
+  f(x); // error: X has a deleted copy constructor
+}
+
+ +

This affects some early C++11 code, including Boost's popular shared_ptr +up to version 1.47.0. The fix for Boost's shared_ptr is +available here.

+ + +

Objective-C++ compatibility

+ + + +

Implicit downcasts

+ + +

Due to a bug in its implementation, GCC allows implicit downcasts +of Objective-C pointers (from a base class to a derived class) when +calling functions. Such code is inherently unsafe, since the object +might not actually be an instance of the derived class, and is +rejected by Clang. For example, given this code:

+ +
+@interface Base @end
+@interface Derived : Base @end
+
+void f(Derived *p);
+void g(Base *p) {
+  f(p);
+}
+
+ +

Clang produces the following error:

+ +
+downcast.mm:6:3: error: no matching function for call to 'f'
+  f(p);
+  ^
+downcast.mm:4:6: note: candidate function not viable: cannot convert from
+      superclass 'Base *' to subclass 'Derived *' for 1st argument
+void f(Derived *p);
+     ^
+
+ +

If the downcast is actually correct (e.g., because the code has +already checked that the object has the appropriate type), add an +explicit cast:

+ +
+  f((Derived *)base);
+
+ + +

Using class as a property name

+ + +

In C and Objective-C, class is a normal identifier and +can be used to name fields, ivars, methods, and so on. In +C++, class is a keyword. For compatibility with existing +code, Clang permits class to be used as part of a method +selector in Objective-C++, but this does not extend to any other part +of the language. In particular, it is impossible to use property dot +syntax in Objective-C++ with the property name class, so +the following code will fail to parse:

+ +
+@interface I {
+int cls;
+}
++ (int)class;
+@end
+
+@implementation  I
+- (int) Meth { return I.class; }
+@end
+
+ +

Use explicit message-send syntax instead, i.e. [I class].

+ +
+ + -- cgit v1.2.3