int be_union_branch::gen_label_value (TAO_OutStream *os, unsigned long index) { AST_Expression *e = this->label (index)->label_val (); if (e->ec () != AST_Expression::EC_symbol) { // Easy, just a number... *os << e; return 0; } // If the enum is not in the global scope we have to prefix it. be_union *u = be_union::narrow_from_scope (this->defined_in ()); if (u == 0) { return -1; } be_type* dt = be_type::narrow_from_decl (u->disc_type ()); if (dt == 0) { return -1; } // Check if discriminator is a typedef of an integer. If so, and the // first IF block in this function didn't catch it, then we // are a constant of this type. We can't generate the constant's name, // we must generate the underlying integer value for the // label value. if (dt->node_type () == AST_Decl::NT_pre_defined) { *os << e; return 0; } // Find where was the enum defined, if it was defined in the globa // scope, then it is easy to generate the enum values.... be_scope* scope = be_scope::narrow_from_scope (dt->defined_in ()); if (scope == 0) { *os << e->n (); return 0; } // But if it was generated inside a module or something similar then // we must prefix the enum value with something... be_decl* decl = scope->decl (); *os << decl->full_name () << "::" << e->n ()->last_component (); return 0; }
void AST_UnionBranch::add_labels (AST_Union *u) { for (UTL_LabellistActiveIterator i (this->pd_ll); !i.is_done (); i.next ()) { if (AST_UnionLabel::UL_default == i.item ()->label_kind ()) { return; } } const bool enum_labels = (u->udisc_type () == AST_Expression::EV_enum); for (UTL_LabellistActiveIterator i (this->pd_ll); !i.is_done (); i.next ()) { AST_Expression *ex = i.item ()->label_val (); UTL_ScopedName *n = ex->n (); if (n) { u->add_to_name_referenced (n->first_component ()); } // If we have enum val labels, we need to set the type and // evaluate here, so the value will be available when the // default index in calculated. if (enum_labels) { ex->ev ()->et = AST_Expression::EV_enum; AST_Enum *disc = AST_Enum::narrow_from_decl (u->disc_type ()); AST_EnumVal *dval = disc->lookup_by_value (ex); if (dval == 0) { idl_global->err ()->incompatible_disc_error (disc, ex); throw Bailout (); } ex->ev ()->u.eval = dval->constant_value ()->ev ()->u.ulval; } } }
// Look up a branch in an enum which is the discriminator type for this // union, based on the label value which must be an enumerator in that // enum. AST_UnionBranch * AST_Union::lookup_enum (AST_UnionBranch *b) { AST_UnionLabel *label = b->label(); AST_Expression *lv = label->label_val (); AST_Enum *e = AST_Enum::narrow_from_decl (this->pd_disc_type); AST_Decl *d = 0; AST_UnionBranch *fb = 0; if (e == 0) { return 0; } if (lv == 0) { return b; } // Expecting a symbol label. if (lv->ec () != AST_Expression::EC_symbol) { idl_global->err ()->enum_val_expected (this, label); return b; } // See if the symbol defines a constant in the discriminator enum. UTL_ScopedName *sn = lv->n (); d = e->lookup_by_name (sn, true); if (d == 0 || d->defined_in () != e) { idl_global->err ()->enum_val_lookup_failure (this, e, sn); return b; } // OK, now see if this symbol is already used as the label of // some other branch. for (UTL_ScopeActiveIterator i (this, UTL_Scope::IK_decls); !i.is_done(); i.next ()) { d = i.item (); if (d->node_type () == AST_Decl::NT_union_branch) { fb = AST_UnionBranch::narrow_from_decl (d); if (fb == 0) { continue; } if (fb->label() != 0 && fb->label ()->label_kind () == AST_UnionLabel::UL_label && fb->label ()->label_val ()->compare (lv)) { idl_global->err ()->error2 (UTL_Error::EIDL_MULTIPLE_BRANCH, this, b); return b; } } } return 0; }