Microsoft Visual C++ Name Mangling

From Wikipedia, the free encyclopedia

This page explains the specific manner in which the Microsoft Visual C++ series of compilers mangle symbol names.

MangledName ::=
    '?' OperatorName '@' TypeCode
    '?' QualifiedName '@' TypeCode

OperatorName ::=
    OperatorCode QualifiedName

QualifiedName ::=
    Identifier +

Identifier ::=
    string '@'
    '0'-'9' /* reference to previously used identifier */

OperatorCode ::=
    '?0'            /* myclass::myclass                                         unary */
    '?1'            /* myclass::~myclass                                        unary */
    '?2'            /* myclass::operator new                                          */
    '?3'            /* myclass::operator delete                                       */
    '?4'            /* myclass::operator=                                      binary */
    '?5'            /* myclass::operator>>                                     binary */
    '?6'            /* myclass::operator<<                                     binary */
    '?7'            /* myclass::operator!                                       unary */
    '?8'            /* myclass::operator==                                     binary */
    '?9'            /* myclass::operator!=                                     binary */
    '?A'            /* myclass::operator[]                                            */
    '?B'            /* myclass::(conversion)                              return only */
    '?C'            /* myclass::operator->                                     binary */
    '?D'            /* myclass::operator*                                unary/binary */
    '?E'            /* myclass::operator++                           unary (pre/post) */
    '?F'            /* myclass::operator--                           unary (pre/post) */
    '?G'            /* myclass::operator-                                unary/binary */
    '?H'            /* myclass::operator+                                unary/binary */
    '?I'            /* myclass::operator&                                unary/binary */
    '?J'            /* myclass::operator->*                                    binary */
    '?K'            /* myclass::operator/                                      binary */
    '?L'            /* myclass::operator%                                      binary */
    '?M'            /* myclass::operator<                                      binary */
    '?N'            /* myclass::operator<=                                     binary */
    '?O'            /* myclass::operator>                                      binary */
    '?P'            /* myclass::operator>=                                     binary */
    '?Q'            /* myclass::operator,                                      binary */
    '?R'            /* myclass::operator()                                            */
    '?S'            /* myclass::operator~                                       unary */
    '?T'            /* myclass::operator^                                      binary */
    '?U'            /* myclass::operator|                                      binary */
    '?V'            /* myclass::operator&&                                     binary */
    '?W'            /* myclass::operator||                                     binary */
    '?X'            /* myclass::operator*=                                     binary */
    '?Y'            /* myclass::operator+=                                     binary */
    '?Z'            /* myclass::operator-=                                     binary */
    '?_0'           /* myclass::myclass/=                                      binary */
    '?_1'           /* myclass::myclass%=                                      binary */
    '?_2'           /* myclass::operator>>=                                    binary */
    '?_3'           /* myclass::operator<<=                                    binary */
    '?_4'           /* myclass::operator&=                                     binary */
    '?_5'           /* myclass::operator|=                                     binary */
    '?_6'           /* myclass::operator^=                                     binary */
    '?_7'           /* myclass::`vftable'                                             */
    '?_C'           /* unknown                                                        */
    '?_F'           /* unknown                                                        */
    '?_O'           /* unknown                                                        */
    '?_R0?AV'       /* myclass::`RTTI Type Descriptor'                                */
    '?_R1A@?0A@EA@' /* myclass::`RTTI Base Class Descriptor at (0,-1,0,64)'           */
    '?_R2'          /* myclass::`RTTI Base Class Array'                               */
    '?_R3'          /* myclass::`RTTI Class Hierarchy Descriptor'                     */
    '?_R4'          /* myclass::`RTTI Complete Object Locator'                        */
    '?_U'           /* myclass::operator new[]                                        */
    '?_V'           /* myclass::operator delete[]                                     */

TypeCode ::=
    'A' FunctionType /* private method */
    'C' FunctionType /* private class method */
    'E' FunctionType /* public virtual method */
    'I' FunctionType /* protected virtual method */
    'K' FunctionType /* protected class method */
    'M' FunctionType /* private virtual method */
    'Q' FunctionType /* public method */
    'S' FunctionType /* public class method */
    'U' FunctionType /* public virtual method */
    'Y' FunctionType /* global function */
    '2' DataType StorageClass
    '3' DataType StorageClass

FunctionType ::=
    CallingConvention ReturnValue ArgumentList StorageClass

CallingConvention ::=
    'A'  /* __cdecl    */
    'G'  /* __stdcall  */
    'I'  /* __fastcall */
    'AA' /* __cdecl for methods ('this' in stack)*/
    'AE' /* __thiscall ('this' in ECX)*/

ReturnValue ::=
    'X'  /* void */
    DataType

ArgumentList ::=
    'X'  /* void */
    DataType+
    DataType+ '@'  /* __cdecl, without vararg */
    DataType+ 'Z'  /* __cdecl, with vararg */

DataType ::=
    SimpleDataType
    PointerDataType

SimpleDataType ::=
    'C'  /* signed char      */
    'D'  /* char             */
    'E'  /* unsigned char    */
    'F'  /* short            */
    'G'  /* unsigned short   */
    'H'  /* int              */
    'I'  /* unsigned int     */
    'J'  /* long             */
    'K'  /* unsigned long    */
    'M'  /* float            */
    'N'  /* double           */
    'O'  /* long double      */
    'T'  /* union            */ QualifiedName '@'
    'U'  /* struct           */ QualifiedName '@'
    'V'  /* class            */ QualifiedName '@'
    'W4' /* enum (4 byte)    */ QualifiedName '@'
    '_J' /* __int64          */
    '_K' /* unsigned __int64 */
    '_N' /* bool             */
    '_W' /* __wchar_t        */

PointerDataType ::=
    ReferenceOrPointer Pointer* 'A|B|C' (SimpleDataType | 'X')
    ReferenceOrPointer Pointer* '6' FunctionType
    '0'-'9' /* reference to previously used PointerDataType */
    ReferenceOrPointer Pointer* '8' FunctionType

ReferenceOrPointer ::=
    'A' /* reference to */
    'P' /* pointer to */
    'Q' /* const pointer to */
    'R' /* volatile pointer to */

Pointer ::=
    'AP' /* pointer to */
    'BQ' /* const pointer to */
    'CR' /* volatile pointer to */

StorageClass ::
    'A'  /* Normal Storage     */
    'B'  /* Volatile Storage   */
    'C'  /* Const Storage      */
    'Z'  /* Executable Storage */

Based on work by Dan Kegel. Dan Kegel also provides an additional perl-script for better understanding the mangling.