Policies/Binary Compatibility Examples: Difference between revisions

From KDE TechBase
m (Text replace - "<code cppqt>" to "<syntaxhighlight lang="cpp-qt">")
Line 7: Line 7:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class KDECORE_EXPORT KUrl
class KDECORE_EXPORT KUrl
{
{
Line 13: Line 13:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class KUrl
class KUrl
{
{
Line 29: Line 29:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public BaseClass
class MyClass: public BaseClass
{
{
Line 35: Line 35:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public BaseClass, public OtherBaseClass
class MyClass: public BaseClass, public OtherBaseClass
{
{
Line 42: Line 42:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public BaseClass1, public BaseClass2
class MyClass: public BaseClass1, public BaseClass2
{
{
Line 48: Line 48:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public BaseClass2, public BaseClass1
class MyClass: public BaseClass2, public BaseClass1
{
{
Line 64: Line 64:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
template<typename T1>
template<typename T1>
class MyTemplateClass
class MyTemplateClass
Line 71: Line 71:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
template<typename T1, typename T2 = void>
template<typename T1, typename T2 = void>
class MyTemplateClass
class MyTemplateClass
Line 80: Line 80:
|}
|}


<code cppqt>
<syntaxhighlight lang="cpp-qt">
// GCC mangling before: _Z3foo15MyTemplateClassIiE
// GCC mangling before: _Z3foo15MyTemplateClassIiE
//              after:  _Z3foo15MyTemplateClassIivE
//              after:  _Z3foo15MyTemplateClassIivE
Line 94: Line 94:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
Q_CORE_EXPORT const char *qVersion();
Q_CORE_EXPORT const char *qVersion();
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
const char *qVersion();
const char *qVersion();
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
namespace KSocketFactory {
namespace KSocketFactory {
     KDECORE_EXPORT QTcpSocket *connectToHost(...);
     KDECORE_EXPORT QTcpSocket *connectToHost(...);
}
}
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
namespace KSocketFactory {
namespace KSocketFactory {
     QTcpSocket *connectToHost(...);
     QTcpSocket *connectToHost(...);
Line 121: Line 121:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
int square(int n);
int square(int n);
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
inline int square(int n) { return n * n; }
inline int square(int n) { return n * n; }
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
int square(int n) { return n * n; }
int square(int n) { return n * n; }
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
inline int square(int n) { return n * n; }
inline int square(int n) { return n * n; }
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class Math
class Math
{
{
Line 145: Line 145:
{ return n * n; }
{ return n * n; }
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class Math
class Math
{
{
Line 156: Line 156:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class Math
class Math
{
{
Line 166: Line 166:
{ return n * n; }
{ return n * n; }
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class Math
class Math
{
{
Line 183: Line 183:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z11doSomethingii
// GCC mangling: _Z11doSomethingii
// MSVC mangling: ?doSomething@@YAXHH@Z
// MSVC mangling: ?doSomething@@YAXHH@Z
void doSomething(int i1, int i2);
void doSomething(int i1, int i2);
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z11doSomethingis
// GCC mangling: _Z11doSomethingis
// MSVC mangling: ?doSomething@@YAXHF@Z
// MSVC mangling: ?doSomething@@YAXHF@Z
Line 194: Line 194:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z11doSomethingii
// GCC mangling: _Z11doSomethingii
// MSVC mangling: ?doSomething@@YAXHH@Z
// MSVC mangling: ?doSomething@@YAXHH@Z
void doSomething(int i1, int i2);
void doSomething(int i1, int i2);
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z11doSomethingiii
// GCC mangling: _Z11doSomethingiii
// MSVC mangling: ?doSomething@@YAXHHH@Z
// MSVC mangling: ?doSomething@@YAXHHH@Z
Line 205: Line 205:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z11doSomethingRi
// GCC mangling: _Z11doSomethingRi
// MSVC mangling: ?doSomething@@YAXABH@Z
// MSVC mangling: ?doSomething@@YAXABH@Z
void doSomething(int &i1);
void doSomething(int &i1);
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z11doSomethingRKi
// GCC mangling: _Z11doSomethingRKi
// MSVC mangling: ?doSomething@@YAXAAH@Z
// MSVC mangling: ?doSomething@@YAXAAH@Z
Line 216: Line 216:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
void doSomething(int i1);
void doSomething(int i1);
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
void doSomething(const int i1); // breaks with Sun CC
void doSomething(const int i1); // breaks with Sun CC
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z11doSomethingPc
// GCC mangling: _Z11doSomethingPc
// MSVC mangling: ?doSomething@@YAXPAD@Z (32-bit)
// MSVC mangling: ?doSomething@@YAXPAD@Z (32-bit)
void doSomething(char *ptr);
void doSomething(char *ptr);
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z11doSomethingPKc
// GCC mangling: _Z11doSomethingPKc
// MSVC mangling: ?doSomething@@YAXPBD@Z (32-bit)
// MSVC mangling: ?doSomething@@YAXPBD@Z (32-bit)
Line 245: Line 245:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z8positionv
// GCC mangling: _Z8positionv
// MSVC mangling: ?position@@YA_JXZ
// MSVC mangling: ?position@@YA_JXZ
qint64 position();
qint64 position();
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z8positionv
// GCC mangling: _Z8positionv
// MSVC mangling: ?position@@YAHXZ
// MSVC mangling: ?position@@YAHXZ
Line 256: Line 256:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z4namev
// GCC mangling: _Z4namev
// MSVC mangling: ?position@@YAVQByteArray@@DXZ
// MSVC mangling: ?position@@YAVQByteArray@@DXZ
QByteArray name();
QByteArray name();
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z4namev
// GCC mangling: _Z4namev
// MSVC mangling: ?position@@YAVQString@@XZ
// MSVC mangling: ?position@@YAVQString@@XZ
Line 267: Line 267:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z4namev
// GCC mangling: _Z4namev
// MSVC mangling: ?position@@YAPBDXZ
// MSVC mangling: ?position@@YAPBDXZ
const char *name();
const char *name();
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z4namev
// GCC mangling: _Z4namev
// MSVC mangling: ?position@@YAVQString@@XZ
// MSVC mangling: ?position@@YAVQString@@XZ
Line 278: Line 278:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z12createDevicev
// GCC mangling: _Z12createDevicev
// MSVC mangling: ?createDevice@@YAPAVQTcpSocket@@XZ
// MSVC mangling: ?createDevice@@YAPAVQTcpSocket@@XZ
QTcpSocket *createDevice();
QTcpSocket *createDevice();
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _Z12createDevicev (unchanged)
// GCC mangling: _Z12createDevicev (unchanged)
// MSVC mangling: ?createDevice@@YAPAVQIODevice@@XZ
// MSVC mangling: ?createDevice@@YAPAVQIODevice@@XZ
Line 289: Line 289:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _ZNK10QByteArray2atEi
// GCC mangling: _ZNK10QByteArray2atEi
// MSVC mangling: ?at@QByteArray@@QBA?BDH@Z
// MSVC mangling: ?at@QByteArray@@QBA?BDH@Z
const char QByteArray::at(int) const;
const char QByteArray::at(int) const;
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _ZNK10QByteArray2atEi (unchanged)
// GCC mangling: _ZNK10QByteArray2atEi (unchanged)
// MSVC mangling: ?at@QByteArray@@QBADH@Z
// MSVC mangling: ?at@QByteArray@@QBADH@Z
Line 300: Line 300:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _ZN6QEvent17registerEventTypeEi
// GCC mangling: _ZN6QEvent17registerEventTypeEi
// MSVC mangling: ?registerEventType@QEvent@@QAAXH@Z
// MSVC mangling: ?registerEventType@QEvent@@QAAXH@Z
int QEvent::registerEventType(int)
int QEvent::registerEventType(int)
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: _ZN6QEvent17registerEventTypeEi (unchanged)
// GCC mangling: _ZN6QEvent17registerEventTypeEi (unchanged)
// MSVC mangling: ?registerEventType@QEvent@@QAAXW4Type@V0@@@Z
// MSVC mangling: ?registerEventType@QEvent@@QAAXW4Type@V0@@@Z
Line 326: Line 326:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 335: Line 335:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 354: Line 354:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 363: Line 363:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 382: Line 382:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: data (undecorated)
// GCC mangling: data (undecorated)
// MSVC mangling: ?data@@3HA
// MSVC mangling: ?data@@3HA
int data = 42;
int data = 42;
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// GCC mangling: data (undecorated)
// GCC mangling: data (undecorated)
// MSVC mangling: ?data@@3FA
// MSVC mangling: ?data@@3FA
Line 393: Line 393:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 402: Line 402:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 423: Line 423:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// MSVC mangling: ?data@@3HA
// MSVC mangling: ?data@@3HA
int data = 42;
int data = 42;
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
// MSVC mangling: ?data@@3HB
// MSVC mangling: ?data@@3HB
const int data = 42;
const int data = 42;
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 440: Line 440:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 449: Line 449:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 456: Line 456:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 476: Line 476:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
struct Data
struct Data
{
{
Line 482: Line 482:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
struct Data
struct Data
{
{
Line 499: Line 499:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 507: Line 507:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 526: Line 526:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 535: Line 535:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass
class MyClass
{
{
Line 551: Line 551:


== Override a virtual that doesn't come from a primary base ==
== Override a virtual that doesn't come from a primary base ==
<code cppqt>
<syntaxhighlight lang="cpp-qt">
class PrimaryBase
class PrimaryBase
{
{
Line 571: Line 571:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public PrimaryBase, public SecondaryBase
class MyClass: public PrimaryBase, public SecondaryBase
{
{
Line 579: Line 579:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public PrimaryBase, public SecondaryBase
class MyClass: public PrimaryBase, public SecondaryBase
{
{
Line 595: Line 595:


== Override a virtual with a covariant return with different top address ==
== Override a virtual with a covariant return with different top address ==
<code cppqt>
<syntaxhighlight lang="cpp-qt">
struct Data1 { int i; };
struct Data1 { int i; };
class BaseClass
class BaseClass
Line 612: Line 612:
! After
! After
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public BaseClass
class MyClass: public BaseClass
{
{
Line 618: Line 618:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public BaseClass
class MyClass: public BaseClass
{
{
Line 626: Line 626:
</code>
</code>
|-
|-
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public BaseClass
class MyClass: public BaseClass
{
{
Line 632: Line 632:
};
};
</code>
</code>
| <code cppqt>
| <syntaxhighlight lang="cpp-qt">
class MyClass: public BaseClass
class MyClass: public BaseClass
{
{

Revision as of 20:31, 29 June 2011

This page is meant as examples of things you cannot do in C++ when maintaining binary compatibility.

Unexport or remove a class

Before After
<syntaxhighlight lang="cpp-qt">

class KDECORE_EXPORT KUrl {

  // [...]

};

<syntaxhighlight lang="cpp-qt">

class KUrl {

  // [...]

};

Reason: the symbols for the class above are not added to the exported symbols list of the library, so other libraries and applications cannot see them.

Change the class hierarchy

Before After
<syntaxhighlight lang="cpp-qt">

class MyClass: public BaseClass {

  // [...]

};

<syntaxhighlight lang="cpp-qt">

class MyClass: public BaseClass, public OtherBaseClass {

  // [...]

};

<syntaxhighlight lang="cpp-qt">

class MyClass: public BaseClass1, public BaseClass2 {

  // [...]

};

<syntaxhighlight lang="cpp-qt">

class MyClass: public BaseClass2, public BaseClass1 {

  // [...]

};

Reason: the size and/or order of member data in the class changes, causing existing code to allocate too much or too little memory, read/write data at the wrong offsets.

Change the template arguments of a template class

Before After
<syntaxhighlight lang="cpp-qt">

template<typename T1> class MyTemplateClass {

   // [...]

};

<syntaxhighlight lang="cpp-qt">

template<typename T1, typename T2 = void> class MyTemplateClass {

   // [...]

};

<syntaxhighlight lang="cpp-qt"> // GCC mangling before: _Z3foo15MyTemplateClassIiE // after: _Z3foo15MyTemplateClassIivE void foo(MyTemplateClass<int>);

Reason: the mangling of the functions related to this template type change because its template expansion changes too. This can happen both for member functions (for example, the constructor) as well as functions that take it as a parameter.

Unexport a function

Before After
<syntaxhighlight lang="cpp-qt">

Q_CORE_EXPORT const char *qVersion();

<syntaxhighlight lang="cpp-qt">

const char *qVersion();

<syntaxhighlight lang="cpp-qt">

namespace KSocketFactory {

   KDECORE_EXPORT QTcpSocket *connectToHost(...);

}

<syntaxhighlight lang="cpp-qt">

namespace KSocketFactory {

   QTcpSocket *connectToHost(...);

}

Reason: the symbols for the functions above are not added to the exported symbols list of the library, so other libraries and applications cannot see them.

Inline a function

Before After
<syntaxhighlight lang="cpp-qt">

int square(int n);

<syntaxhighlight lang="cpp-qt">

inline int square(int n) { return n * n; }

<syntaxhighlight lang="cpp-qt">

int square(int n) { return n * n; }

<syntaxhighlight lang="cpp-qt">

inline int square(int n) { return n * n; }

<syntaxhighlight lang="cpp-qt">

class Math {

   int square(int n);

};

// the following could be in a .cpp int Math::square(int n) { return n * n; }

<syntaxhighlight lang="cpp-qt">

class Math {

   int square(int n);

};

// the following could be in a .cpp inline int Math::square(int n) { return n * n; }

<syntaxhighlight lang="cpp-qt">

class Math {

   int square(int n);

};

// the following could be in a .cpp int Math::square(int n) { return n * n; }

<syntaxhighlight lang="cpp-qt">

class Math {

   int square(int n)
   { return n * n; }

};

Reason: when a function is declared inline and the compiler does inline it at its call point, the compiler does not have to emit an out-of-line copy. Code that exists and was calling this function will therefore not be able to resolve the function anymore. Also, when compiling with GCC and -fvisibility-inlines-hidden, if the compiler does emit an out-of-line copy, it will be hidden (not added to the exported symbols table) and therefore not accessible from other libraries.

Change the parameters of a function

Before After
<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z11doSomethingii // MSVC mangling: ?doSomething@@YAXHH@Z void doSomething(int i1, int i2);

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z11doSomethingis // MSVC mangling: ?doSomething@@YAXHF@Z void doSomething(int i1, short i2);

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z11doSomethingii // MSVC mangling: ?doSomething@@YAXHH@Z void doSomething(int i1, int i2);

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z11doSomethingiii // MSVC mangling: ?doSomething@@YAXHHH@Z void doSomething(int i1, int i2, int i3 = 0);

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z11doSomethingRi // MSVC mangling: ?doSomething@@YAXABH@Z void doSomething(int &i1);

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z11doSomethingRKi // MSVC mangling: ?doSomething@@YAXAAH@Z void doSomething(const int &i1);

<syntaxhighlight lang="cpp-qt">

void doSomething(int i1);

<syntaxhighlight lang="cpp-qt">

void doSomething(const int i1); // breaks with Sun CC

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z11doSomethingPc // MSVC mangling: ?doSomething@@YAXPAD@Z (32-bit) void doSomething(char *ptr);

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z11doSomethingPKc // MSVC mangling: ?doSomething@@YAXPBD@Z (32-bit) void doSomething(const char *ptr);

Reason: changing the parameters of a function (adding new or changing existing) changes the mangled name of that function. The reason for that is that the C++ language allows overloading of functions with the same name but slightly different parameters.

I don't have the mangled name for the Sun CC example above, that compiler does enforce the constness of POD types in both declaration and implementation.

Change the return type

Before After
<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z8positionv // MSVC mangling: ?position@@YA_JXZ qint64 position();

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z8positionv // MSVC mangling: ?position@@YAHXZ int position();

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z4namev // MSVC mangling: ?position@@YAVQByteArray@@DXZ QByteArray name();

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z4namev // MSVC mangling: ?position@@YAVQString@@XZ QString name();

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z4namev // MSVC mangling: ?position@@YAPBDXZ const char *name();

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z4namev // MSVC mangling: ?position@@YAVQString@@XZ QString name();

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z12createDevicev // MSVC mangling: ?createDevice@@YAPAVQTcpSocket@@XZ QTcpSocket *createDevice();

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _Z12createDevicev (unchanged) // MSVC mangling: ?createDevice@@YAPAVQIODevice@@XZ QIODevice *createDevice();

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _ZNK10QByteArray2atEi // MSVC mangling: ?at@QByteArray@@QBA?BDH@Z const char QByteArray::at(int) const;

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _ZNK10QByteArray2atEi (unchanged) // MSVC mangling: ?at@QByteArray@@QBADH@Z char QByteArray::at(int) const;

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _ZN6QEvent17registerEventTypeEi // MSVC mangling: ?registerEventType@QEvent@@QAAXH@Z int QEvent::registerEventType(int)

<syntaxhighlight lang="cpp-qt">

// GCC mangling: _ZN6QEvent17registerEventTypeEi (unchanged) // MSVC mangling: ?registerEventType@QEvent@@QAAXW4Type@V0@@@Z QEvent::Type QEvent::registerEventType(int)

Reason: changing the return type changes the mangled name of the function names in some compilers (GCC notably does not encode the return type). However, even if the mangling doesn't change, the convention on how the return types are handled may change.

In the first example above, the return type changed from a 64- to a 32-bit integer, which means on some architectures, the upper half of the return register may contain garbage. In the second example, the return type changed from QByteArray to QString, which are two incompatible types.

In the third example, the return type changed from a simple integer (a POD) to a QString -- in this case, the compiler usually needs to pass a hidden implicit first parameter, which won't be there. In this case, existing code calling the function will more than likely crash, due to trying to dereference the implicit QString* parameter that isn't there.

In the fourth example, the return type changed from one POD type (an int) to another (an enum), which is also carried by an int. The calling sequence is most likely the same in all compilers, however the mangling of the symbol name changed, meaning that calls will fail due to an unresolved symbol.

Change the access rights

Before After
<syntaxhighlight lang="cpp-qt">

class MyClass { protected:

   // GCC mangling: _ZN7MyClass11doSomethingEv
   // MSVC mangling: ?doSomething@MyClass@@IAAXXZ
   void doSomething();

};

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   // GCC mangling: _ZN7MyClass11doSomethingEv (unchanged)
   // MSVC mangling: ?doSomething@MyClass@@QAAXXZ
   void doSomething();

};

Reason: some compilers encode the protection type of a function in its mangled name.

Change the CV-qualifiers of a member function

Before After
<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   // GCC mangling: _ZNK7MyClass9somethingEv
   // MSVC mangling: ?something@MyClass@QBAHXZ
   int something() const;

};

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   // GCC mangling: _ZN7MyClass9somethingEv
   // MSVC mangling: ?something@MyClass@QAAHXZ
   int something();

};

Reason: compilers encode the constness of a function in the mangled name. The reason they all do that is because the C++ standard allows overloading of functions that differ only by the constness.

Change the type of global data

Before After
<syntaxhighlight lang="cpp-qt">

// GCC mangling: data (undecorated) // MSVC mangling: ?data@@3HA int data = 42;

<syntaxhighlight lang="cpp-qt">

// GCC mangling: data (undecorated) // MSVC mangling: ?data@@3FA short data = 42;

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   // GCC mangling: _ZN7MyClass4dataE
   // MSVC mangling: ?data@MyClass@@2HA
   static int data;

};

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   // GCC mangling: _ZN7MyClass4dataE
   // MSVC mangling: ?data@MyClass@@2FA
   static short data;

};

Reason: some compilers encode the type of the global data in its mangled name. Especially note that some compilers mangle even for simple data types that would be allowed in C, meaning the extern "C" qualifier makes a difference too.

Even if the mangling doesn't change, changing the type often changes the size of the data as well. That means code that was accessing the global data may be access too many or too few bytes.

Change the CV-qualifiers of global data

Before After
<syntaxhighlight lang="cpp-qt">

// MSVC mangling: ?data@@3HA int data = 42;

<syntaxhighlight lang="cpp-qt">

// MSVC mangling: ?data@@3HB const int data = 42;

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   // MSVC mangling: ?data@MyClass@@2HA
   static int data;

};

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   // MSVC mangling: ?data@MyClass@@2HB
   static const int data;

};

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   static int data;

};

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   // the compiler won't even create a symbol
   static const int data = 42;

};

Reason: some compilers encode the CV-qualifiers of the global data in its mangled name. Especially note that a static const value declared in the class itself can be considered for "inlining" -- that is, the compiler doesn't need to generate an external symbol for the value since all implementations are guaranteed to know it.

Even for compilers that don't encode the CV-qualifiers of global data, adding const may make the compiler place the variable in a read-only section of memory. Code that tried to write it will probably crash.

Add a virtual member function to a class without any

Before After
<syntaxhighlight lang="cpp-qt">

struct Data {

   int i;

};

<syntaxhighlight lang="cpp-qt">

struct Data {

   int i;
   virtual int j();

};

Reason: a class without any virtual members or bases is guaranteed to be exactly like a C structure, for compatibility with that language (that is a POD structure). On some compilers, structures/classes with bases that are POD themselves are also POD. However, as soon as there's one virtual base or virtual member function, the compiler is free to arrange the structure in a C++ manner, which usually means inserting a hidden pointer at the beginning or the end of the structure, pointing to the virtual table of that class. This changes the size and offset of the elements in the structure.

Add new virtuals to a non-leaf class

Before After
<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   virtual ~MyClass();
   virtual void foo();

};

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   virtual ~MyClass();
   virtual void foo();
   virtual void bar();

};

Reason: the addition of a new virtual function to a class that is non-leaf (that is, there is at least one class deriving from this class) changes the layout of the virtual table (the virtual table is basically a list of function pointers, pointing to the functions that are active in this class level). To accommodate the new virtual, the compiler must add a new entry to this table, but existing derived classes won't know about it and will not have the entry in their virtual tables.

Change the order of the declaration of virtual functions

Before After
<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   virtual ~MyClass();
   virtual void foo();
   virtual void bar();

};

<syntaxhighlight lang="cpp-qt">

class MyClass { public:

   virtual ~MyClass();
   virtual void bar();
   virtual void foo();

};

Reason: the compiler places the pointers to the functions implementing the virtual functions in the order that they are declared in the class. By changing the order of the declaration, the order of the entries in the virtual table changes too.

Note: the order is inherited from the parent classes, so overriding a virtual will allocate the entry in the parent's order.

Override a virtual that doesn't come from a primary base

<syntaxhighlight lang="cpp-qt"> class PrimaryBase { public:

   virtual ~PrimaryBase();
   virtual void foo();

};

class SecondaryBase { public:

   virtual ~SecondaryBase();
   virtual void bar();

};

Before After
<syntaxhighlight lang="cpp-qt">

class MyClass: public PrimaryBase, public SecondaryBase { public:

   ~MyClass();
   void foo();

};

<syntaxhighlight lang="cpp-qt">

class MyClass: public PrimaryBase, public SecondaryBase { public:

   ~MyClass();
   void foo();
   void bar();

};

Reason: this is a tricky case. When dealing with multiple-inheritance of classes with virtual tables, the compiler must create multiple virtual tables to guarantee polymorphism works (that is, when your MyClass object is stored in a PrimaryBase or SecondaryBase pointer). The virtual table for the primary base is shared with the class's own virtual table, because they have the same layout at the beginning. However, if you override a virtual coming from a non-primary base, it is the same as adding a new virtual, since that primary base did not have the virtual by that name.

Note: this applies to any case of multiple-inheritance, even if it's not a direct base. In the example above, if we had MyOtherClass deriving from MyClass, the same restriction would apply.

Override a virtual with a covariant return with different top address

<syntaxhighlight lang="cpp-qt"> struct Data1 { int i; }; class BaseClass { public:

   virtual Data1 *get();

};

struct Data0 { int i; }; struct Complex1: Data0, Data1 { }; struct Complex2: virtual Data1 { };

Before After
<syntaxhighlight lang="cpp-qt">

class MyClass: public BaseClass { public: };

<syntaxhighlight lang="cpp-qt">

class MyClass: public BaseClass { public:

   Complex1 *get();

};

<syntaxhighlight lang="cpp-qt">

class MyClass: public BaseClass { public: };

<syntaxhighlight lang="cpp-qt">

class MyClass: public BaseClass { public:

   Complex2 *get();

};

Reason: this is another tricky case, like the above one and also for the same reason: the compiler must add a second entry to the virtual table, just as if a new virtual function had been added, which changes the layout of the virtual table and breaks derived classes.

Covariant calls happen when the function overriding a virtual from a parent class returns a class different from the parent (this is allowed by the C++ standard, so the code above is perfectly valid and calling p->get() with p of type BaseClass will call MyClass::get). If the more-derived type doesn't have the same top-address such as Complex1 and Complex2 above, when compared to Data1, then the compiler needs to generate a stub function (usually called a "thunk") to adjust the value of the pointer returned. It places the address to that thunk in the entry corresponding to the parent's virtual function in the virtual table. However, it also adds a new entry for calls made which return the new top-address.