|
| 1 | +// Tests for pragma mangle |
| 2 | +module pragmamangle; |
| 3 | + |
| 4 | +version (Posix): // Itanium C++ ABI only |
| 5 | + |
| 6 | +string ctfe_function() { return "mangle_" ~ "ctfe_" ~ "function"; } |
| 7 | +immutable string const_variable = "mangle_const"; |
| 8 | + |
| 9 | +// This mangle string doesn't propagate to tests that use type_symbol. |
| 10 | +pragma(mangle, "Q_should_mangle_string_propagate") |
| 11 | +struct type_symbol { } |
| 12 | + |
| 13 | +class template_symbol(T) { } |
| 14 | + |
| 15 | +/* 1. Overrides the default mangling for a symbol. |
| 16 | + */ |
| 17 | +pragma(mangle, "mangle_function") void test_fun1(); |
| 18 | +static assert(test_fun1.mangleof == "mangle_function"); |
| 19 | + |
| 20 | +pragma(mangle, "mangle_attribute") extern(C) { nothrow { void test_pokeattr1(); } } |
| 21 | +static assert(test_pokeattr1.mangleof == "mangle_attribute"); |
| 22 | + |
| 23 | +/* 2a. For variables and functions there must be one AssignExpression and it |
| 24 | + * must evaluate at compile time to a string literal |
| 25 | + */ |
| 26 | +pragma(mangle, ctfe_function) void test_fun2a1(); |
| 27 | +static assert(test_fun2a1.mangleof == "mangle_ctfe_function"); |
| 28 | + |
| 29 | +pragma(mangle, const_variable) void test_fun2a2(); |
| 30 | +static assert(test_fun2a2.mangleof == "mangle_const"); |
| 31 | + |
| 32 | +pragma(mangle, ctfe_function) int test_var2a1; |
| 33 | +static assert(test_var2a1.mangleof == "mangle_ctfe_function"); |
| 34 | + |
| 35 | +pragma(mangle, const_variable) int test_var2a2; |
| 36 | +static assert(test_var2a2.mangleof == "mangle_const"); |
| 37 | + |
| 38 | +/* 2b. For aggregates there may be one or two AssignExpressions, one of which |
| 39 | + * must evaluate at compile time to a string literal and one which must |
| 40 | + * evaluate to a symbol. |
| 41 | + * [UNDOCUMENTED] The pragma(mangle) attribute only gets applied to the |
| 42 | + * encoded parameters types of extern(C++) functions. |
| 43 | + */ |
| 44 | +pragma(mangle, "mangle_struct") extern(C++) { struct S1 { } } |
| 45 | +extern(C++) void test_struct2b1(S1); |
| 46 | +extern(D) void externD_struct2b1(S1); |
| 47 | +static assert(test_struct2b1.mangleof == "_Z14test_struct2b113mangle_struct"); |
| 48 | +static assert(externD_struct2b1.mangleof == "_D12pragmamangle17externD_struct2b1FSQBj2S1Zv"); |
| 49 | + |
| 50 | +pragma(mangle, type_symbol, "mangle_struct") struct S2 { } |
| 51 | +extern(C++) void test_struct2b3(S2); |
| 52 | +extern(D) void externD_struct2b3(S2); |
| 53 | +static assert(test_struct2b3.mangleof == "_Z14test_struct2b313mangle_struct"); |
| 54 | +static assert(externD_struct2b3.mangleof == "_D12pragmamangle17externD_struct2b3FSQBj2S2Zv"); |
| 55 | + |
| 56 | +pragma(mangle, "mangle_struct", type_symbol) struct S3 { } |
| 57 | +extern(C++) void test_struct2b4(S3); |
| 58 | +extern(D) void externD_struct2b4(S3); |
| 59 | +static assert(test_struct2b4.mangleof == "_Z14test_struct2b413mangle_struct"); |
| 60 | +static assert(externD_struct2b4.mangleof == "_D12pragmamangle17externD_struct2b4FSQBj2S3Zv"); |
| 61 | + |
| 62 | +// Repeat struct tests on classes. |
| 63 | + |
| 64 | +pragma(mangle, "mangle_class") extern(C++) { class C1 { } } |
| 65 | +extern(C++) void test_class2b1(C1); |
| 66 | +extern(D) void externD_class2b1(C1); |
| 67 | +static assert(test_class2b1.mangleof == "_Z13test_class2b1P12mangle_class"); |
| 68 | +static assert(externD_class2b1.mangleof == "_D12pragmamangle16externD_class2b1FCQBi2C1Zv"); |
| 69 | + |
| 70 | +pragma(mangle, type_symbol, "mangle_class") class C2 { } |
| 71 | +extern(C++) void test_class2b3(C2); |
| 72 | +extern(D) void externD_class2b3(C2); |
| 73 | +static assert(test_class2b3.mangleof == "_Z13test_class2b3P12mangle_class"); |
| 74 | +static assert(externD_class2b3.mangleof == "_D12pragmamangle16externD_class2b3FCQBi2C2Zv"); |
| 75 | + |
| 76 | +pragma(mangle, "mangle_class", type_symbol) class C3 { } |
| 77 | +extern(C++) void test_class2b4(C3); |
| 78 | +extern(D) void externD_class2b4(C3); |
| 79 | +static assert(test_class2b4.mangleof == "_Z13test_class2b4P12mangle_class"); |
| 80 | +static assert(externD_class2b4.mangleof == "_D12pragmamangle16externD_class2b4FCQBi2C3Zv"); |
| 81 | + |
| 82 | +/* 2c. If that symbol is a TemplateInstance, the aggregate is treated as a |
| 83 | + * template that has the signature and arguments of the TemplateInstance. |
| 84 | + */ |
| 85 | +template T1(C) |
| 86 | +{ |
| 87 | + pragma(mangle, C, "mangle_template") struct T1 { } |
| 88 | +} |
| 89 | +extern(C++) void test_template2c3(T1!(template_symbol!int)); |
| 90 | +extern(C++) void test_template2c4(T1!(template_symbol!float)); |
| 91 | +extern(C++) void test_template2c5(T1!(type_symbol)); |
| 92 | +static assert(test_template2c3.mangleof == "_Z16test_template2c315mangle_templateIiE"); |
| 93 | +static assert(test_template2c4.mangleof == "_Z16test_template2c415mangle_templateIfE"); |
| 94 | +static assert(test_template2c5.mangleof == "_Z16test_template2c515mangle_template"); |
| 95 | + |
| 96 | +template T2(C) |
| 97 | +{ |
| 98 | + pragma(mangle, "mangle_template", C) struct T2 { } |
| 99 | +} |
| 100 | +extern(C++) void test_template2c6(T2!(template_symbol!int)); |
| 101 | +extern(C++) void test_template2c7(T2!(template_symbol!float)); |
| 102 | +extern(C++) void test_template2c8(T2!(type_symbol)); |
| 103 | +static assert(test_template2c6.mangleof == "_Z16test_template2c615mangle_templateIiE"); |
| 104 | +static assert(test_template2c7.mangleof == "_Z16test_template2c715mangle_templateIfE"); |
| 105 | +static assert(test_template2c8.mangleof == "_Z16test_template2c815mangle_template"); |
| 106 | + |
| 107 | +/* 2d. The identifier of the symbol is used when no string is supplied. |
| 108 | + */ |
| 109 | +pragma(mangle, type_symbol) struct I1 { } |
| 110 | +extern(C++) void test_struct2d1(I1); |
| 111 | +static assert(test_struct2d1.mangleof == "_Z14test_struct2d111type_symbol"); |
| 112 | + |
| 113 | +pragma(mangle, type_symbol) class I2 { } |
| 114 | +extern(C++) void test_class2d1(I2); |
| 115 | +static assert(test_class2d1.mangleof == "_Z13test_class2d1P11type_symbol"); |
| 116 | + |
| 117 | +template I3(C) |
| 118 | +{ |
| 119 | + pragma(mangle, C) struct I3 { } |
| 120 | +} |
| 121 | +extern(C++) void test_template2d1(I3!(template_symbol!int)); |
| 122 | +extern(C++) void test_template2d2(I3!(template_symbol!float)); |
| 123 | +extern(C++) void test_template2d3(I3!(type_symbol)); |
| 124 | +static assert(test_template2d1.mangleof == "_Z16test_template2d115template_symbolIiE"); |
| 125 | +static assert(test_template2d2.mangleof == "_Z16test_template2d215template_symbolIfE"); |
| 126 | +static assert(test_template2d3.mangleof == "_Z16test_template2d311type_symbol"); |
| 127 | + |
| 128 | +// ??? No template arguments encoded. |
| 129 | + |
| 130 | +pragma(mangle, template_symbol!float) struct I4 { } |
| 131 | +extern(C++) void test_template2d4(I4); |
| 132 | +static assert(test_template2d4.mangleof == "_Z16test_template2d415template_symbol"); |
| 133 | + |
| 134 | +/* 3. It only applies to function and variable symbols. Other symbols are |
| 135 | + * ignored. |
| 136 | + */ |
| 137 | +pragma(mangle, "mangle_alias") |
| 138 | +alias ignored_alias = int; |
| 139 | + |
| 140 | +pragma(mangle, "mangle_enum") |
| 141 | +enum ignored_enum { a = 1 } |
| 142 | + |
| 143 | +pragma(mangle, "mangle_mixed_ignored") |
| 144 | +{ |
| 145 | + enum test_ignored1 { b } |
| 146 | + void test_not_ignored(); |
| 147 | + alias test_ignored2 = int delegate(int); |
| 148 | +} |
| 149 | +static assert(test_not_ignored.mangleof == "mangle_mixed_ignored"); |
0 commit comments