summaryrefslogtreecommitdiffstats
path: root/www/cxx_compatibility.html
blob: e5fd63ef9c978bb19df9d77c23376864501fcad1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<!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 - C++ Compatibility</title>
  <link type="text/css" rel="stylesheet" href="menu.css" />
  <link type="text/css" rel="stylesheet" href="content.css" />
  <style type="text/css">
</style>
</head>
<body>

<!--#include virtual="menu.html.incl"-->

<div id="content">

<!-- ======================================================================= -->
<h1>Clang's C++ Compatibility</h1>
<!-- ======================================================================= -->

<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#vla">Variable-length arrays</a></li>
<li><a href="#init_static_const">Initialization of non-integral static const data members within a class definition</a></li>
<li><a href="#dep_lookup">Unqualified lookup in templates</a></li>
<li><a href="#dep_lookup_bases">Unqualified lookup into dependent bases of class templates</a></li>
<li><a href="#default_init_const">Default initialization of const variable of a class type requires user-defined default constructor</a></li>
</ul>

<!-- ======================================================================= -->
<h2 id="intro">Introduction</h2>
<!-- ======================================================================= -->

<p>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.</p>

<!-- ======================================================================= -->
<h2 id="vla">Variable-length arrays</h2>
<!-- ======================================================================= -->

<p>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 <tt>"variable length arrays are not permitted in C++"</tt>, here
are some ways in which you can fix it:</p>

<ol>
<li>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 <tt>int size = ...;</tt> to <tt>const int size
    = ...;</tt> (if the definition of <tt>size</tt> is a compile-time
    integral constant);</li>
<li>use an <tt>std::string</tt> instead of a <tt>char []</tt>;</li>
<li>use <tt>std::vector</tt> or some other suitable container type;
    or</li>
<li>allocate the array on the heap instead using <tt>new Type[]</tt> -
    just remember to <tt>delete[]</tt> it.</li>
</ol>

<!-- ======================================================================= -->
<h2 id="init_static_const">Initialization of non-integral static const data members within a class definition</h2>
<!-- ======================================================================= -->

The following code is ill-formed in C++'03:

<pre>
class SomeClass {
 public:
  static const double SomeConstant = 0.5;
};

const double SomeClass::SomeConstant;
</pre>

Clang errors with something similar to:

<pre>
.../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;
                      ^              ~~~
</pre>

Only <i>integral</i> 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:

<pre>
class SomeClass {
 public:
  static const double SomeConstant;
};

const double SomeClass::SomeConstant<b> = 0.5</b>;
</pre>

Note that the forthcoming C++0x standard will allow this.

<!-- ======================================================================= -->
<h2 id="dep_lookup">Unqualified lookup in templates</h2>
<!-- ======================================================================= -->

Some versions of GCC accept the following invalid code:

<pre>
template &lt;typename T&gt; struct Foo {
  void Work(T x) {
    func(x);
  }
};
...
void func(int x);
...
template struct Foo&lt;int&gt;; // or anything else that instantiates Foo&lt;int&gt;::Work
</pre>

The standard says that unqualified names like <tt>func</tt> are looked up
when the template is defined, not when it's instantiated.  Since
<tt>void func(int)</tt> was not declared yet when <tt>Foo</tt> was
defined, it's not considered.  The fix is usually to
declare <tt>func</tt> before <tt>Foo</tt>.

<p>This is complicated by <i>argument-dependent lookup</i> (ADL),
which is done when unqualified names are called as functions,
like <tt>func(x)</tt> above.  The standard says that ADL is performed
in both places if any of the arguments are type-dependent, like
<tt>x</tt> is in this example.  However, ADL does nothing for builtin
types like <tt>int</tt>, so the example is still invalid.  See
[basic.lookup.argdep] for more information.

<!-- ======================================================================= -->
<h2 id="dep_lookup_bases">Unqualified lookup into dependent bases of class templates</h2>
<!-- ======================================================================= -->

Some versions of GCC accept the following invalid code:

<pre>
template &lt;typename T&gt; struct Base {
  void DoThis(T x) {}
  static void DoThat(T x) {}
};

template &lt;typename T&gt; struct Derived : public Base&lt;T&gt; {
  void Work(T x) {
    DoThis(x);  // Invalid!
    DoThat(x);  // Invalid!
  }
};
</pre>

Clang correctly rejects it with the following errors
(when <tt>Derived</tt> is eventually instantiated):

<pre>
my_file.cpp:8:5: error: use of undeclared identifier 'DoThis'
    DoThis(x);
    ^
    this-&gt;
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-&gt;
my_file.cpp:3:15: note: must qualify identifier to find this declaration in dependent base class
  static void DoThat(T x) {}
</pre>

Like we said <a href="#dep_lookup">above</a>, unqualified names like
<tt>DoThis</tt> and <tt>DoThat</tt> are looked up when the template
<tt>Derived</tt> 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 <tt>Base&lt;T&gt;</tt>
because its type depends on the template argument <tt>T</tt>, so the
standard says we should just ignore it.  See [temp.dep]p3 for details.

<p>The fix, as Clang tells you, is to tell the compiler that we want a
class member by prefixing the calls with <tt>this-&gt;</tt>:

<pre>
  void Work(T x) {
    <b>this-&gt;</b>DoThis(x);
    <b>this-&gt;</b>DoThat(x);
  }
</pre>

Alternatively, you can tell the compiler exactly where to look:

<pre>
  void Work(T x) {
    <b>Base&lt;T&gt;</b>::DoThis(x);
    <b>Base&lt;T&gt;</b>::DoThat(x);
  }
</pre>

This works whether the methods are static or not, but be careful:
if <tt>DoThis</tt> is virtual, calling it this way will bypass virtual
dispatch!

<!-- ======================================================================= -->
<h2 id="default_init_const">Default initialization of const variable of a class type requires user-defined default constructor</h2>
<!-- ======================================================================= -->

If a <tt>class</tt> or <tt>struct</tt> has no user-defined default
constructor, C++ doesn't allow you to default construct a <tt>const</tt>
instance of it like this ([dcl.init], p9):

<pre>
class Foo {
 public:
  // The compiler-supplied default constructor works fine, so we
  // don't bother with defining one.
  ...
};

void Bar() {
  const Foo foo;  // Error!
  ...
}
</pre>

To fix this, you can define a default constructor for the class:

<pre>
class Foo {
 public:
  Foo() {}
  ...
};

void Bar() {
  const Foo foo;  // Now the compiler is happy.
  ...
}
</pre>

</div>
</body>
</html>
OpenPOWER on IntegriCloud