summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-03-17 18:31:21 +0800
committerJohn Hodge <tpg@mutabah.net>2018-03-17 18:31:21 +0800
commit363e6fa172f787e970c8abc8f631b6d60d571248 (patch)
treeddd7792c8a0e3fc4c4550b004cea6f46ad073e81
parentf54d867d6f279ed65f2823f08866216d7482dd8d (diff)
downloadmrust-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.cpp13
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!