diff options
author | John Hodge <tpg@mutabah.net> | 2018-03-17 18:31:21 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-03-17 18:31:21 +0800 |
commit | 363e6fa172f787e970c8abc8f631b6d60d571248 (patch) | |
tree | ddd7792c8a0e3fc4c4550b004cea6f46ad073e81 | |
parent | f54d867d6f279ed65f2823f08866216d7482dd8d (diff) | |
download | mrust-363e6fa172f787e970c8abc8f631b6d60d571248.tar.gz |
Codegen C - Work around GCC5 bug by emitting a single-field struct instead of a union
Fixes #63
-rw-r--r-- | src/trans/codegen_c.cpp | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 3eff24a0..87d96abb 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -1124,8 +1124,19 @@ namespace { m_of << "// enum " << p << "\n"; m_of << "struct e_" << Trans_Mangle(p) << " {\n"; + // HACK: For NonZero optimised enums, emit a struct with a single field + // - This avoids a bug in GCC5 where it would generate incorrect code if there's a union here. + if( const auto* ve = repr->variants.opt_NonZero() ) + { + m_of << "\tstruct {\n"; + m_of << "\t\t"; + unsigned idx = 1 - ve->zero_variant; + emit_ctype(repr->fields.at(idx).ty, FMT_CB(os, os << "var_" << idx)); + m_of << ";\n"; + m_of << "\t} DATA;"; + } // If there multiple fields with the same offset, they're the data variants - if( union_fields.size() > 0 ) + else if( union_fields.size() > 0 ) { assert(1 + union_fields.size() + 1 >= repr->fields.size()); // Make the union! |