From 9b2fc9563fba142ae8d570d2eea43b4c24079326 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 17 Mar 2010 04:31:53 +0000 Subject: [PATCH] Document common clang compatibility issues. Patch by Zhanyong Wan. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98708 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/UsersManual.html | 7 ++ www/cxx_compatibility.html | 220 +++++++++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 www/cxx_compatibility.html diff --git a/docs/UsersManual.html b/docs/UsersManual.html index 41715bb2ac..e7ea133ce9 100644 --- a/docs/UsersManual.html +++ b/docs/UsersManual.html @@ -796,6 +796,13 @@ ask on the mailing list about how you can help.

Note that released Clang compilers will refuse to even try to use clang to compile C++ code unless you pass the -ccc-clang-cxx option to the driver. To turn on Clang's C++ support, please pass that flag. Clang compilers built from the Subversion trunk enable C++ support by default, and do not require the -ccc-clang-cxx flag.

+

Clang strives to strictly conform to the C++ standard. That means +it will reject invalid C++ code that another compiler may accept. If +Clang reports errors in your code, please check +the C++ +Compatibility page to see whether they are C++-conformance bugs +and how you can fix them.

+

Objective C++ Language Features

diff --git a/www/cxx_compatibility.html b/www/cxx_compatibility.html new file mode 100644 index 0000000000..c094f244df --- /dev/null +++ b/www/cxx_compatibility.html @@ -0,0 +1,220 @@ + + + + + Clang - C++ Compatibility + + + + + + + + +
+ + +

Clang's C++ Compatibility

+ + + + + +

Introduction

+ + +

Clang strives to strictly conform to the C++ standard. That means +it will reject invalid C++ code that another compiler may accept. +This page helps you decide whether a Clang error message means a +C++-conformance bug in your code and how you can fix it.

+ + +

Variable-length arrays

+ + +

GCC allows an array's size to be determined at run time. This, +however, is not standard C++. Furthermore, it is a potential security +hole as an incorrect array size may overflow the stack. If Clang tells +you "variable length arrays are not permitted in C++", here +are some ways in which you can fix it:

+ +
    +
  1. replace it 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 definition of size is a compile-time + integral constant);
  2. +
  3. use an std::string instead of a char [];
  4. +
  5. use std::vector or some other suitable container type; + or
  6. +
  7. allocate the array on the heap instead using new Type[] - + just remember to delete[] it.
  8. +
+ + +

Initialization of non-integral static const data members within a class definition

+ + +The following code is ill-formed in C++'03: + +
+class SomeClass {
+ public:
+  static const double SomeConstant = 0.5;
+};
+
+const double SomeClass::SomeConstant;
+
+ +Clang errors with something similar to: + +
+.../your_file.h:42:42: error: 'SomeConstant' can only be initialized if it is a static const integral data member
+  static const double SomeConstant = 0.5;
+                      ^              ~~~
+
+ +Only integral constant expressions are allowed as initializers +within the class definition. See C++'03 [class.static.data] p4 for the +details of this restriction. The fix here is straightforward: move +the initializer to the definition of the static data member, which +must exist outside of the class definition: + +
+class SomeClass {
+ public:
+  static const double SomeConstant;
+};
+
+const double SomeClass::SomeConstant = 0.5;
+
+ + +

Dependent name lookup into dependent bases of class templates

+ + +Some versions of GCC accept the following invalid code: + +
+template <typename T>
+class Base {
+ public:
+  void DoThis(T x) {}
+
+  static void DoThat(T x) {}
+};
+
+template <typename T>
+class Derived : public Base<T> {
+ public:
+  void Work(T x) {
+    DoThis(x);  // Invalid!
+    DoThat(x);  // Invalid!
+  }
+};
+
+void Test() {
+  Derived<int> d;
+  d.Work(42);
+}
+
+ +Clang correctly rejects it with the following errors: + +
+my_file.cpp:13:5: error: use of undeclared identifier 'DoThis'
+    DoThis(x);
+    ^
+    this->
+my_file.cpp:20:5: note: in instantiation of member function 'Derived<int>::Work' requested here
+  d.Work(42);
+    ^
+my_file.cpp:4:8: note: must qualify identifier to find this declaration in dependent base class
+  void DoThis(T x) {}
+       ^
+my_file.cpp:14:5: error: use of undeclared identifier 'DoThat'
+    DoThat(x);
+    ^
+    this->
+my_file.cpp:6:15: note: must qualify identifier to find this declaration in dependent base class
+  static void DoThat(T x) {}
+
+ +The reason the code is invalid is that in +class Derived<T>, the base class type Base<T> +depends on the template argument T (hence it's called a dependent base +class in C++ jargon), and C++ doesn't look at the members of a +dependent base class when resolving unqualified calls like DoThis(x) +and DoThat(x) (see [temp.dep] p3 for details). The fix, as Clang tells +you, is to prefix the calls with this->: + +
+...
+template <typename T>
+class Derived : public Base<T> {
+ public:
+  void Work(T x) {
+    this->DoThis(x);
+    this->DoThat(x);
+  }
+};
+...
+
+ +Alternatively, since DoThat() is a static method, you can also write + +
+  void Work(T x) {
+    this->DoThis(x);
+    Base<T>::DoThat(x);
+  }
+
+ + +

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.
+  ...
+}
+
+ +
+ + -- 2.50.1