Learn C++ Itanium Symbol Mangling

Lesson 2: Arguments

All symbols that we have looked at so far have ended with a v. I have previously explained that the v stands for a function type with no arguments.

C++ has function overloading, which means that a function with the same name can be declared multiple times with different argument types, and the one with matching argument types will be called. If we just mangled the function name as shown previously, this wouldn't work, because we'd get multiple symbols with the same name, which is exactly what mangling is designed to avoid. Therefore, any C++ mangling scheme must encode the function argument types in the symbol name.

void a(int x);
void a(char *y);
int main() {
  a(0); // This will call the first a
}
          

The function type is encoded after the name. It contains all the arguments for the function. In some cases it will also contain the return type first, but not for the functions we are looking at right now.

void a(int x, int y, long z) {}
          

This function will be mangled as _Z1aiil. We already know what _Z1a means, but the iil is new. It represents the three arguments, an int, another int, and then a long. The primitives are just a single character, more complex types have more characters.

A function taking zero arguments is interpreted as a function taking (void), which is encoded as v.

int is i, long is l. float is f, double is d. These types are very easy to remember, many others less so. Other easy to remember frequently used types are pointers (T*) which are encoded as P followed by the pointed to type and references (T&) which encoded as R followed by the referenced type.

void a(int x, int *y, double &z) {}
          

This function is mangled as _Z1aiPiRd. It's an int (i), a int* (Pi), and a double& (Rd).

What is the mangled symbol of the following function?

void hello(int **programmer, long day, float &r) {}
            

We can combine this with our previous knowledge of nested names to mangle the following definition:

namespace outer::inner {
  void yes(int a, int b, long &c) {}
}
          

This will be mangled as _ZN5outer5inner3yesEiiRl

What is the mangled symbol of the following function?

namespace very::much::nested {
  void name(int **a, long &raw, float f, double d) {}
}
            

Let's look at a few more common types.

char is c. unsigned int is j (like i but one higher). unsigned long is m, following the same pattern. long long (64-bit) is x (you can think of it being the native integer, integer x on modern machines)- unsigned long long is y, again being one higher. short is s, with its unsigned variant being, you may have guessed it, t.

In the future there might be a part of the website where you can memorize these encodings more easily.

What is the mangled symbol of the following function?

void name(unsigned long long a, unsigned short b, char c, int d) {}
            

Good job! You have now learnt about the mangling of basic types. In the next lesson, we will use there types as template arguments.