THRIFT-1768 unions can't have required fields (Compiler)
Patch: Jens Geyer
diff --git a/compiler/cpp/src/parse/t_struct.h b/compiler/cpp/src/parse/t_struct.h
index b82933d..ffe2af3 100644
--- a/compiler/cpp/src/parse/t_struct.h
+++ b/compiler/cpp/src/parse/t_struct.h
@@ -44,24 +44,59 @@
t_type(program),
is_xception_(false),
is_union_(false),
+ members_validated(false),
+ members_with_value(0),
xsd_all_(false) {}
t_struct(t_program* program, const std::string& name) :
t_type(program, name),
is_xception_(false),
is_union_(false),
+ members_validated(false),
+ members_with_value(0),
xsd_all_(false) {}
void set_name(const std::string& name) {
name_ = name;
+ validate_union_members();
}
void set_xception(bool is_xception) {
is_xception_ = is_xception;
}
+ void validate_union_member( t_field * field) {
+ if( is_union_ && (! name_.empty())) {
+
+ // unions can't have required fields
+ if( field->get_req() == t_field::T_REQUIRED) {
+ pwarning( 1, "Required field %s of union %s set to optional.\n", field->get_name().c_str(), name_.c_str());
+ field->set_req( t_field::T_OPTIONAL);
+ }
+
+ // unions may have up to one member defaulted, but not more
+ if( field->get_value() != NULL) {
+ if( 1 < ++members_with_value) {
+ throw "Error: Field "+field->get_name()+" provides another default value for union "+name_;
+ }
+ }
+ }
+
+ }
+
+ void validate_union_members() {
+ if( is_union_ && (! name_.empty()) && (!members_validated)) {
+ members_type::const_iterator m_iter;
+ for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) {
+ validate_union_member( *m_iter);
+ }
+ members_validated = true;
+ }
+ }
+
void set_union(bool is_union) {
is_union_ = is_union;
+ validate_union_members();
}
void set_xsd_all(bool xsd_all) {
@@ -83,6 +118,7 @@
return false;
}
members_in_id_order_.insert(bounds.second, elem);
+ validate_union_member( elem);
return true;
}
@@ -141,6 +177,8 @@
members_type members_in_id_order_;
bool is_xception_;
bool is_union_;
+ bool members_validated;
+ int members_with_value;
bool xsd_all_;
};