Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
430 changes: 267 additions & 163 deletions compiler/src/dmd/pragmasem.d

Large diffs are not rendered by default.

149 changes: 149 additions & 0 deletions compiler/test/compilable/pragmamangle1.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Tests for pragma mangle
module pragmamangle;

version (Posix): // Itanium C++ ABI only

string ctfe_function() { return "mangle_" ~ "ctfe_" ~ "function"; }
immutable string const_variable = "mangle_const";

// This mangle string doesn't propagate to tests that use type_symbol.
pragma(mangle, "Q_should_mangle_string_propagate")
struct type_symbol { }

class template_symbol(T) { }

/* 1. Overrides the default mangling for a symbol.
*/
pragma(mangle, "mangle_function") void test_fun1();
static assert(test_fun1.mangleof == "mangle_function");

pragma(mangle, "mangle_attribute") extern(C) { nothrow { void test_pokeattr1(); } }
static assert(test_pokeattr1.mangleof == "mangle_attribute");

/* 2a. For variables and functions there must be one AssignExpression and it
* must evaluate at compile time to a string literal
*/
pragma(mangle, ctfe_function) void test_fun2a1();
static assert(test_fun2a1.mangleof == "mangle_ctfe_function");

pragma(mangle, const_variable) void test_fun2a2();
static assert(test_fun2a2.mangleof == "mangle_const");

pragma(mangle, ctfe_function) int test_var2a1;
static assert(test_var2a1.mangleof == "mangle_ctfe_function");

pragma(mangle, const_variable) int test_var2a2;
static assert(test_var2a2.mangleof == "mangle_const");

/* 2b. For aggregates there may be one or two AssignExpressions, one of which
* must evaluate at compile time to a string literal and one which must
* evaluate to a symbol.
* [UNDOCUMENTED] The pragma(mangle) attribute only gets applied to the
* encoded parameters types of extern(C++) functions.
*/
pragma(mangle, "mangle_struct") extern(C++) { struct S1 { } }
extern(C++) void test_struct2b1(S1);
extern(D) void externD_struct2b1(S1);
static assert(test_struct2b1.mangleof == "_Z14test_struct2b113mangle_struct");
static assert(externD_struct2b1.mangleof == "_D12pragmamangle17externD_struct2b1FSQBj2S1Zv");

pragma(mangle, type_symbol, "mangle_struct") struct S2 { }
extern(C++) void test_struct2b3(S2);
extern(D) void externD_struct2b3(S2);
static assert(test_struct2b3.mangleof == "_Z14test_struct2b313mangle_struct");
static assert(externD_struct2b3.mangleof == "_D12pragmamangle17externD_struct2b3FSQBj2S2Zv");

pragma(mangle, "mangle_struct", type_symbol) struct S3 { }
extern(C++) void test_struct2b4(S3);
extern(D) void externD_struct2b4(S3);
static assert(test_struct2b4.mangleof == "_Z14test_struct2b413mangle_struct");
static assert(externD_struct2b4.mangleof == "_D12pragmamangle17externD_struct2b4FSQBj2S3Zv");

// Repeat struct tests on classes.

pragma(mangle, "mangle_class") extern(C++) { class C1 { } }
extern(C++) void test_class2b1(C1);
extern(D) void externD_class2b1(C1);
static assert(test_class2b1.mangleof == "_Z13test_class2b1P12mangle_class");
static assert(externD_class2b1.mangleof == "_D12pragmamangle16externD_class2b1FCQBi2C1Zv");

pragma(mangle, type_symbol, "mangle_class") class C2 { }
extern(C++) void test_class2b3(C2);
extern(D) void externD_class2b3(C2);
static assert(test_class2b3.mangleof == "_Z13test_class2b3P12mangle_class");
static assert(externD_class2b3.mangleof == "_D12pragmamangle16externD_class2b3FCQBi2C2Zv");

pragma(mangle, "mangle_class", type_symbol) class C3 { }
extern(C++) void test_class2b4(C3);
extern(D) void externD_class2b4(C3);
static assert(test_class2b4.mangleof == "_Z13test_class2b4P12mangle_class");
static assert(externD_class2b4.mangleof == "_D12pragmamangle16externD_class2b4FCQBi2C3Zv");

/* 2c. If that symbol is a TemplateInstance, the aggregate is treated as a
* template that has the signature and arguments of the TemplateInstance.
*/
template T1(C)
{
pragma(mangle, C, "mangle_template") struct T1 { }
}
extern(C++) void test_template2c3(T1!(template_symbol!int));
extern(C++) void test_template2c4(T1!(template_symbol!float));
extern(C++) void test_template2c5(T1!(type_symbol));
static assert(test_template2c3.mangleof == "_Z16test_template2c315mangle_templateIiE");
static assert(test_template2c4.mangleof == "_Z16test_template2c415mangle_templateIfE");
static assert(test_template2c5.mangleof == "_Z16test_template2c515mangle_template");

template T2(C)
{
pragma(mangle, "mangle_template", C) struct T2 { }
}
extern(C++) void test_template2c6(T2!(template_symbol!int));
extern(C++) void test_template2c7(T2!(template_symbol!float));
extern(C++) void test_template2c8(T2!(type_symbol));
static assert(test_template2c6.mangleof == "_Z16test_template2c615mangle_templateIiE");
static assert(test_template2c7.mangleof == "_Z16test_template2c715mangle_templateIfE");
static assert(test_template2c8.mangleof == "_Z16test_template2c815mangle_template");

/* 2d. The identifier of the symbol is used when no string is supplied.
*/
pragma(mangle, type_symbol) struct I1 { }
extern(C++) void test_struct2d1(I1);
static assert(test_struct2d1.mangleof == "_Z14test_struct2d111type_symbol");

pragma(mangle, type_symbol) class I2 { }
extern(C++) void test_class2d1(I2);
static assert(test_class2d1.mangleof == "_Z13test_class2d1P11type_symbol");

template I3(C)
{
pragma(mangle, C) struct I3 { }
}
extern(C++) void test_template2d1(I3!(template_symbol!int));
extern(C++) void test_template2d2(I3!(template_symbol!float));
extern(C++) void test_template2d3(I3!(type_symbol));
static assert(test_template2d1.mangleof == "_Z16test_template2d115template_symbolIiE");
static assert(test_template2d2.mangleof == "_Z16test_template2d215template_symbolIfE");
static assert(test_template2d3.mangleof == "_Z16test_template2d311type_symbol");

// ??? No template arguments encoded.

pragma(mangle, template_symbol!float) struct I4 { }
extern(C++) void test_template2d4(I4);
static assert(test_template2d4.mangleof == "_Z16test_template2d415template_symbol");

/* 3. It only applies to function and variable symbols. Other symbols are
* ignored.
*/
pragma(mangle, "mangle_alias")
alias ignored_alias = int;

pragma(mangle, "mangle_enum")
enum ignored_enum { a = 1 }

pragma(mangle, "mangle_mixed_ignored")
{
enum test_ignored1 { b }
void test_not_ignored();
alias test_ignored2 = int delegate(int);
}
static assert(test_not_ignored.mangleof == "mangle_mixed_ignored");
144 changes: 144 additions & 0 deletions compiler/test/compilable/pragmamangle2.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Tests for pragma mangle
module pragmamangle;

version (Posix): // Itanium C++ ABI only

string ctfe_function() { return "mangle_" ~ "ctfe_" ~ "function"; }
immutable string const_variable = "mangle_const";

// This mangle string doesn't propagate to tests that use type_symbol.
pragma(mangle, "Q_should_mangle_string_propagate")
struct type_symbol { }

class template_symbol(T) { }

void pragma_statement_test()
{
/* 1. Overrides the default mangling for a symbol.
*/
pragma(mangle, "mangle_function") void test_fun1();
static assert(test_fun1.mangleof == "mangle_function");

pragma(mangle, "mangle_attribute") extern(C) nothrow void test_pokeattr1();
static assert(test_pokeattr1.mangleof == "mangle_attribute");

/* 2a. For variables and functions there must be one AssignExpression and it
* must evaluate at compile time to a string literal
*/
pragma(mangle, ctfe_function) void test_fun2a1();
static assert(test_fun2a1.mangleof == "mangle_ctfe_function");

pragma(mangle, const_variable) void test_fun2a2();
static assert(test_fun2a2.mangleof == "mangle_const");

pragma(mangle, ctfe_function) static int test_var2a1;
static assert(test_var2a1.mangleof == "mangle_ctfe_function");

pragma(mangle, const_variable) static int test_var2a2;
static assert(test_var2a2.mangleof == "mangle_const");

/* 2b. For aggregates there may be one or two AssignExpressions, one of which
* must evaluate at compile time to a string literal and one which must
* evaluate to a symbol.
* [UNDOCUMENTED] The pragma(mangle) attribute only gets applied to the
* encoded parameters types of extern(C++) functions.
*/
pragma(mangle, "mangle_struct") extern(C++) struct S1 { }
extern(C++) void test_struct2b1(S1);
extern(D) void externD_struct2b1(S1);
static assert(test_struct2b1.mangleof == "_ZN21pragma_statement_test14test_struct2b1ENS_13mangle_structE");
static assert(externD_struct2b1.mangleof == "_D12pragmamangle21pragma_statement_testFZ17externD_struct2b1MFSQCjQByFZ2S1Zv");

pragma(mangle, type_symbol, "mangle_struct") struct S2 { }
extern(C++) void test_struct2b3(S2);
extern(D) void externD_struct2b3(S2);
static assert(test_struct2b3.mangleof == "_ZN21pragma_statement_test14test_struct2b3ENS_13mangle_structE");
static assert(externD_struct2b3.mangleof == "_D12pragmamangle21pragma_statement_testFZ17externD_struct2b3MFSQCjQByFZ2S2Zv");

pragma(mangle, "mangle_struct", type_symbol) struct S3 { }
extern(C++) void test_struct2b4(S3);
extern(D) void externD_struct2b4(S3);
static assert(test_struct2b4.mangleof == "_ZN21pragma_statement_test14test_struct2b4ENS_13mangle_structE");
static assert(externD_struct2b4.mangleof == "_D12pragmamangle21pragma_statement_testFZ17externD_struct2b4MFSQCjQByFZ2S3Zv");

// Repeat struct tests on classes.

pragma(mangle, "mangle_class") extern(C++) class C1 { }
extern(C++) void test_class2b1(C1);
extern(D) void externD_class2b1(C1);
static assert(test_class2b1.mangleof == "_ZN21pragma_statement_test13test_class2b1EPNS_12mangle_classE");
static assert(externD_class2b1.mangleof == "_D12pragmamangle21pragma_statement_testFZ16externD_class2b1MFCQCiQBxFZ2C1Zv");

pragma(mangle, type_symbol, "mangle_class") class C2 { }
extern(C++) void test_class2b3(C2);
extern(D) void externD_class2b3(C2);
static assert(test_class2b3.mangleof == "_ZN21pragma_statement_test13test_class2b3EPNS_12mangle_classE");
static assert(externD_class2b3.mangleof == "_D12pragmamangle21pragma_statement_testFZ16externD_class2b3MFCQCiQBxFZ2C2Zv");

pragma(mangle, "mangle_class", type_symbol) class C3 { }
extern(C++) void test_class2b4(C3);
extern(D) void externD_class2b4(C3);
static assert(test_class2b4.mangleof == "_ZN21pragma_statement_test13test_class2b4EPNS_12mangle_classE");
static assert(externD_class2b4.mangleof == "_D12pragmamangle21pragma_statement_testFZ16externD_class2b4MFCQCiQBxFZ2C3Zv");

/* 2c. If that symbol is a TemplateInstance, the aggregate is treated as a
* template that has the signature and arguments of the TemplateInstance.
*/
template T1(C)
{
pragma(mangle, C, "mangle_template") struct T1 { }
}
extern(C++) void test_template2c3(T1!(template_symbol!int));
extern(C++) void test_template2c4(T1!(template_symbol!float));
extern(C++) void test_template2c5(T1!(type_symbol));
static assert(test_template2c3.mangleof == "_ZN21pragma_statement_test16test_template2c3ENS_15mangle_templateIiEE");
static assert(test_template2c4.mangleof == "_ZN21pragma_statement_test16test_template2c4ENS_15mangle_templateIfEE");
static assert(test_template2c5.mangleof == "_ZN21pragma_statement_test16test_template2c5ENS_15mangle_templateE");

template T2(C)
{
pragma(mangle, "mangle_template", C) struct T2 { }
}
extern(C++) void test_template2c6(T2!(template_symbol!int));
extern(C++) void test_template2c7(T2!(template_symbol!float));
extern(C++) void test_template2c8(T2!(type_symbol));
static assert(test_template2c6.mangleof == "_ZN21pragma_statement_test16test_template2c6ENS_15mangle_templateIiEE");
static assert(test_template2c7.mangleof == "_ZN21pragma_statement_test16test_template2c7ENS_15mangle_templateIfEE");
static assert(test_template2c8.mangleof == "_ZN21pragma_statement_test16test_template2c8ENS_15mangle_templateE");

/* 2d. The identifier of the symbol is used when no string is supplied.
*/
pragma(mangle, type_symbol) struct I1 { }
extern(C++) void test_struct2d1(I1);
static assert(test_struct2d1.mangleof == "_ZN21pragma_statement_test14test_struct2d1ENS_11type_symbolE");

pragma(mangle, type_symbol) class I2 { }
extern(C++) void test_class2d1(I2);
static assert(test_class2d1.mangleof == "_ZN21pragma_statement_test13test_class2d1EPNS_11type_symbolE");

template I3(C)
{
pragma(mangle, C) struct I3 { }
}
extern(C++) void test_template2d1(I3!(template_symbol!int));
extern(C++) void test_template2d2(I3!(template_symbol!float));
extern(C++) void test_template2d3(I3!(type_symbol));
static assert(test_template2d1.mangleof == "_ZN21pragma_statement_test16test_template2d1ENS_15template_symbolIiEE");
static assert(test_template2d2.mangleof == "_ZN21pragma_statement_test16test_template2d2ENS_15template_symbolIfEE");
static assert(test_template2d3.mangleof == "_ZN21pragma_statement_test16test_template2d3ENS_11type_symbolE");

// ??? No template arguments encoded.

pragma(mangle, template_symbol!float) struct I4 { }
extern(C++) void test_template2d4(I4);
static assert(test_template2d4.mangleof == "_ZN21pragma_statement_test16test_template2d4ENS_15template_symbolE");

/* 3. It only applies to function and variable symbols. Other symbols are
* ignored.
*/
pragma(mangle, "mangle_alias")
alias ignored_alias = int;

pragma(mangle, "mangle_enum")
enum ignored_enum { a = 1 }
}
2 changes: 1 addition & 1 deletion compiler/test/compilable/test3004.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// https://issues.dlang.org/show_bug.cgi?id=3004
/*
REQUIRED_ARGS: -ignore -v
TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|\(imported|semantic|entry|library|function object|function core|\s*$)")
TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|inline|.*_d_newarrayU|import|\(imported|semantic|entry|library|function object|function core|\s*$)")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't related. Failure was introduced by e33c664.

TEST_OUTPUT:
---
pragma GNU_attribute (__error)
Expand Down
8 changes: 4 additions & 4 deletions compiler/test/fail_compilation/ice13788.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice13788.d(11): Error: pragma `mangle` - string expected for mangled name
fail_compilation/ice13788.d(12): Error: `string` expected for mangled name, not `(1)` of type `int`
fail_compilation/ice13788.d(13): Error: pragma `mangle` - zero-length string not allowed for mangled name
fail_compilation/ice13788.d(14): Error: pragma `mangle` - mangled name characters can only be of type `char`
fail_compilation/ice13788.d(11): Error: `pragma(mangle)` expects string literal argument for mangled name
fail_compilation/ice13788.d(12): Error: `string` expected for pragma mangle argument, not `(1)` of type `int`
fail_compilation/ice13788.d(13): Error: `pragma(mangle)` zero-length string not allowed for mangled name
fail_compilation/ice13788.d(14): Error: `pragma(mangle)` mangled name characters can only be of type `char`
Comment thread
ibuclaw marked this conversation as resolved.
---
*/

Expand Down
4 changes: 2 additions & 2 deletions compiler/test/fail_compilation/issue21203.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
REQUIRED_ARGS: -de
TEST_OUTPUT:
---
fail_compilation/issue21203.d(12): Error: pragma `mangle` cannot apply to a template declaration
fail_compilation/issue21203.d(12): use `template Class(Args...){ pragma(mangle, "other_name") class Class {} }`
fail_compilation/issue21203.d(12): Error: `pragma(mangle)` cannot apply to a template declaration
fail_compilation/issue21203.d(12): use `template F(Args...) { pragma(mangle, "gdkfjgh") ... }`
---
*/

Expand Down
9 changes: 4 additions & 5 deletions compiler/test/fail_compilation/issue22682.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/* TEST_OUTPUT:
---
fail_compilation/issue22682.d(14): Error: `pragma(mangle)` must be attached to a declaration
fail_compilation/issue22682.d(15): Error: `pragma(mangle)` takes a single argument that must be a string literal
fail_compilation/issue22682.d(16): Error: `string` expected for pragma mangle argument, not `(0)` of type `int`
fail_compilation/issue22682.d(16): Error: `pragma(mangle)` takes a single argument that must be a string literal
fail_compilation/issue22682.d(17): Error: `pragma(mangle)` must be attached to a declaration
fail_compilation/issue22682.d(13): Error: `pragma(mangle)` expects string literal argument for mangled name
fail_compilation/issue22682.d(14): Error: `pragma(mangle)` expects string literal argument for mangled name
fail_compilation/issue22682.d(15): Error: `string` expected for pragma mangle argument, not `(0)` of type `int`
fail_compilation/issue22682.d(16): Error: `pragma(mangle)` expects string literal argument for mangled name
Comment thread
ibuclaw marked this conversation as resolved.
---
*/
module issue22682;
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/mangle1.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/mangle1.d(8): Error: pragma `mangle` can only apply to a single declaration
fail_compilation/mangle1.d(8): Error: `pragma(mangle)` can only apply to a single declaration
---
*/

Expand Down
24 changes: 12 additions & 12 deletions compiler/test/fail_compilation/mangle2.d
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/*
TEST_OUTPUT:
---
fail_compilation/mangle2.d(20): Error: pragma `mangle` char 0x20 not allowed in mangled name
fail_compilation/mangle2.d(21): Error: pragma `mangle` char 0x20 not allowed in mangled name
fail_compilation/mangle2.d(24): Error: pragma `mangle` char 0x0a not allowed in mangled name
fail_compilation/mangle2.d(25): Error: pragma `mangle` char 0x0a not allowed in mangled name
fail_compilation/mangle2.d(28): Error: pragma `mangle` char 0x07 not allowed in mangled name
fail_compilation/mangle2.d(29): Error: pragma `mangle` char 0x07 not allowed in mangled name
fail_compilation/mangle2.d(32): Error: pragma `mangle` char 0x01 not allowed in mangled name
fail_compilation/mangle2.d(33): Error: pragma `mangle` char 0x01 not allowed in mangled name
fail_compilation/mangle2.d(36): Error: pragma `mangle` char 0x00 not allowed in mangled name
fail_compilation/mangle2.d(37): Error: pragma `mangle` char 0x00 not allowed in mangled name
fail_compilation/mangle2.d(40): Error: pragma `mangle` Outside Unicode code space
fail_compilation/mangle2.d(41): Error: pragma `mangle` Outside Unicode code space
fail_compilation/mangle2.d(20): Error: `pragma(mangle)` char 0x20 not allowed in mangled name
fail_compilation/mangle2.d(21): Error: `pragma(mangle)` char 0x20 not allowed in mangled name
fail_compilation/mangle2.d(24): Error: `pragma(mangle)` char 0x0a not allowed in mangled name
fail_compilation/mangle2.d(25): Error: `pragma(mangle)` char 0x0a not allowed in mangled name
fail_compilation/mangle2.d(28): Error: `pragma(mangle)` char 0x07 not allowed in mangled name
fail_compilation/mangle2.d(29): Error: `pragma(mangle)` char 0x07 not allowed in mangled name
fail_compilation/mangle2.d(32): Error: `pragma(mangle)` char 0x01 not allowed in mangled name
fail_compilation/mangle2.d(33): Error: `pragma(mangle)` char 0x01 not allowed in mangled name
fail_compilation/mangle2.d(36): Error: `pragma(mangle)` char 0x00 not allowed in mangled name
fail_compilation/mangle2.d(37): Error: `pragma(mangle)` char 0x00 not allowed in mangled name
fail_compilation/mangle2.d(40): Error: `pragma(mangle)` Outside Unicode code space
fail_compilation/mangle2.d(41): Error: `pragma(mangle)` Outside Unicode code space
---
*/

Expand Down
Loading
Loading