diff --git a/src/FactUnion.cpp b/src/FactUnion.cpp index d81a74fb2..554066c1c 100644 --- a/src/FactUnion.cpp +++ b/src/FactUnion.cpp @@ -135,7 +135,7 @@ FactUnion::abstract_fact_for_assign(const std::vector& facts, const const FactUnion* fu = 0; if (v->is_union_field()) { fu = make_fact(v->field_var_of, v->get_field_id()); - } else if (v->is_inside_union_field() && v->type->has_padding()) { + } else if (v->is_inside_union_field() && (v->type->has_padding() || v->is_packed_after_bitfield())) { fu = make_fact(v->get_container_union(), BOTTOM); } diff --git a/src/Type.cpp b/src/Type.cpp index f2c7d6cac..d360d6e5e 100644 --- a/src/Type.cpp +++ b/src/Type.cpp @@ -1207,10 +1207,13 @@ Type::is_bitfield(size_t index) const bool Type::has_bitfields() const { - size_t i; - for (i = 0; i < bitfields_length_.size(); ++i) { - if (bitfields_length_[i] >= 0) + for (size_t i=0; i= 0) { return true; + } + if (fields[i]->eType == eStruct && fields[i]->has_bitfields()) { + return true; + } } return false; } diff --git a/src/Variable.cpp b/src/Variable.cpp index 66814c3d8..098205ee1 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -1360,6 +1360,25 @@ Variable::find_pointer_fields(vector& ptr_fields) const } } +/* a struct field packed after a bit-field could has nondeterministic offset due to incompatible packings between compilers */ +bool +Variable::is_packed_after_bitfield(void) const +{ + const Variable* parent = this->field_var_of; + if (parent == NULL) return false; + if (parent->type->eType == eStruct && parent->type->packed_) { + for (size_t i=0; ifield_vars.size(); i++) { + if (parent->field_vars[i] == this) { + break; + } + if (parent->type->is_bitfield(i) || parent->field_vars[i]->type->has_bitfields()) { + return true; + } + } + } + return parent->is_packed_after_bitfield(); +} + /////////////////////////////////////////////////////////////////////////////// // Local Variables: diff --git a/src/Variable.h b/src/Variable.h index b7f4f62d8..40cbf47c4 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -94,6 +94,7 @@ class Variable int get_field_id(void) const; bool is_union_field(void) const { return field_var_of != 0 && field_var_of->type->eType == eUnion; }; bool is_inside_union_field(void) const { return is_union_field() || (field_var_of && field_var_of->is_inside_union_field()); } + bool is_packed_after_bitfield(void) const; bool is_array_field(void) const; bool is_virtual(void) const; bool is_aggregate(void) const { return type && type->is_aggregate(); }