summaryrefslogtreecommitdiff
path: root/TAO/TAO_IDL/ast/ast_union.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/TAO_IDL/ast/ast_union.cpp')
-rw-r--r--TAO/TAO_IDL/ast/ast_union.cpp1263
1 files changed, 1263 insertions, 0 deletions
diff --git a/TAO/TAO_IDL/ast/ast_union.cpp b/TAO/TAO_IDL/ast/ast_union.cpp
new file mode 100644
index 00000000000..498fa278ac7
--- /dev/null
+++ b/TAO/TAO_IDL/ast/ast_union.cpp
@@ -0,0 +1,1263 @@
+// $Id$
+
+/*
+
+COPYRIGHT
+
+Copyright 1992, 1993, 1994 Sun Microsystems, Inc. Printed in the United
+States of America. All Rights Reserved.
+
+This product is protected by copyright and distributed under the following
+license restricting its use.
+
+The Interface Definition Language Compiler Front End (CFE) is made
+available for your use provided that you include this license and copyright
+notice on all media and documentation and the software program in which
+this product is incorporated in whole or part. You may copy and extend
+functionality (but may not remove functionality) of the Interface
+Definition Language CFE without charge, but you are not authorized to
+license or distribute it to anyone else except as part of a product or
+program developed by you or with the express written consent of Sun
+Microsystems, Inc. ("Sun").
+
+The names of Sun Microsystems, Inc. and any of its subsidiaries or
+affiliates may not be used in advertising or publicity pertaining to
+distribution of Interface Definition Language CFE as permitted herein.
+
+This license is effective until terminated by Sun for failure to comply
+with this license. Upon termination, you shall destroy or return all code
+and documentation for the Interface Definition Language CFE.
+
+INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF
+ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS
+FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF
+DEALING, USAGE OR TRADE PRACTICE.
+
+INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT
+ANY OBLIGATION ON THE PART OF Sun OR ANY OF ITS SUBSIDIARIES OR AFFILIATES
+TO ASSIST IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT.
+
+SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
+RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY
+INTERFACE DEFINITION LANGUAGE CFE OR ANY PART THEREOF.
+
+IN NO EVENT WILL SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR
+ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
+DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+Use, duplication, or disclosure by the government is subject to
+restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
+Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR
+52.227-19.
+
+Sun, Sun Microsystems and the Sun logo are trademarks or registered
+trademarks of Sun Microsystems, Inc.
+
+SunSoft, Inc.
+2550 Garcia Avenue
+Mountain View, California 94043
+
+NOTE:
+
+SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are
+trademarks or registered trademarks of Sun Microsystems, Inc.
+
+*/
+
+// AST_Union nodes represent IDL union declarations.
+// AST_Union is a subclass of AST_ConcreteType and of UTL_Scope (the
+// union branches are managed in a scope).
+// AST_Union nodes have a discriminator type (a subclass of AST_ConcreteType),
+// a name (an UTL_ScopedName) and a field denoting the discriminator type if
+// it is a primitive type (the value of this field is from the union
+// AST_Expression::ExprType and serves as a cache). This field is used
+// to compute coercions for labels based on the expected discriminator type.
+
+#include "ast_union.h"
+#include "ast_union_branch.h"
+#include "ast_union_label.h"
+#include "ast_field.h"
+#include "ast_predefined_type.h"
+#include "ast_enum.h"
+#include "ast_enum_val.h"
+#include "ast_visitor.h"
+#include "utl_err.h"
+#include "utl_identifier.h"
+#include "utl_indenter.h"
+#include "global_extern.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+ACE_RCSID (ast,
+ ast_union,
+ "$Id$")
+
+AST_Union::AST_Union (void)
+ : COMMON_Base (),
+ AST_Decl (),
+ AST_Type (),
+ AST_ConcreteType (),
+ UTL_Scope (),
+ AST_Structure (),
+ default_index_ (-2)
+{
+}
+
+AST_Union::AST_Union (AST_ConcreteType *dt,
+ UTL_ScopedName *n,
+ bool local,
+ bool abstract)
+ : COMMON_Base (local,
+ abstract),
+ AST_Decl (AST_Decl::NT_union,
+ n),
+ AST_Type (AST_Decl::NT_union,
+ n),
+ AST_ConcreteType (AST_Decl::NT_union,
+ n),
+ UTL_Scope (AST_Decl::NT_union),
+ AST_Structure (n,
+ local,
+ abstract),
+ default_index_ (-2)
+{
+ this->default_value_.computed_ = -2;
+
+ AST_PredefinedType *pdt = 0;
+
+ if (dt == 0)
+ {
+ this->pd_disc_type = 0;
+ this->pd_udisc_type = AST_Expression::EV_none;
+ return;
+ }
+
+ // If the discriminator type is a predefined type
+ // then install the equivalent coercion target type in
+ // the pd_udisc_type field.
+ if (dt->node_type () == AST_Decl::NT_pre_defined)
+ {
+ pdt = AST_PredefinedType::narrow_from_decl (dt);
+
+ if (pdt == 0)
+ {
+ this->pd_disc_type = 0;
+ this->pd_udisc_type = AST_Expression::EV_none;
+ return;
+ }
+
+ pd_disc_type = dt;
+
+ switch (pdt->pt ())
+ {
+ case AST_PredefinedType::PT_long:
+ this->pd_udisc_type = AST_Expression::EV_long;
+ break;
+ case AST_PredefinedType::PT_ulong:
+ this->pd_udisc_type = AST_Expression::EV_ulong;
+ break;
+ case AST_PredefinedType::PT_short:
+ this->pd_udisc_type = AST_Expression::EV_short;
+ break;
+ case AST_PredefinedType::PT_ushort:
+ this->pd_udisc_type = AST_Expression::EV_ushort;
+ break;
+ case AST_PredefinedType::PT_char:
+ this->pd_udisc_type = AST_Expression::EV_char;
+ break;
+ case AST_PredefinedType::PT_wchar:
+ this->pd_udisc_type = AST_Expression::EV_wchar;
+ break;
+ case AST_PredefinedType::PT_octet:
+ this->pd_udisc_type = AST_Expression::EV_octet;
+ break;
+ case AST_PredefinedType::PT_boolean:
+ this->pd_udisc_type = AST_Expression::EV_bool;
+ break;
+ default:
+ this->pd_udisc_type = AST_Expression::EV_none;
+ this->pd_disc_type = 0;
+ break;
+ }
+ }
+ else if (dt->node_type () == AST_Decl::NT_enum)
+ {
+ this->pd_udisc_type = AST_Expression::EV_enum;
+ this->pd_disc_type = dt;
+ }
+ else
+ {
+ this->pd_udisc_type = AST_Expression::EV_none;
+ this->pd_disc_type = 0;
+ }
+
+ if (this->pd_disc_type == 0)
+ {
+ idl_global->err ()->error2 (UTL_Error::EIDL_DISC_TYPE,
+ this,
+ dt);
+ }
+}
+
+AST_Union::~AST_Union (void)
+{
+}
+
+// Public operations.
+
+void
+AST_Union::redefine (AST_Structure *from)
+{
+ AST_Union *u = AST_Union::narrow_from_decl (from);
+
+ if (u == 0)
+ {
+ idl_global->err ()->redef_error (from->local_name ()->get_string (),
+ this->local_name ()->get_string ());
+ return;
+ }
+
+ // Copy over all the base class members.
+ this->AST_Structure::redefine (from);
+
+ this->pd_disc_type = u->pd_disc_type;
+ this->pd_udisc_type = u->pd_udisc_type;
+ this->default_index_ = u->default_index_;
+ this->default_value_ = u->default_value_;
+}
+
+// Return the default_index.
+int
+AST_Union::default_index (void)
+{
+ if (this->default_index_ == -2)
+ {
+ this->compute_default_index ();
+ }
+
+ return this->default_index_;
+}
+
+// Are we or the parameter node involved in any recursion?
+bool
+AST_Union::in_recursion (ACE_Unbounded_Queue<AST_Type *> &list)
+{
+ // Proceed if the number of members in our scope is greater than 0.
+ if (this->nmembers () > 0)
+ {
+ ACE_Unbounded_Queue<AST_Type *> scope_list = list;
+ scope_list.enqueue_tail (this);
+
+ // Initialize an iterator to iterate thru our scope.
+ // Continue until each element is visited.
+ for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ AST_UnionBranch *field =
+ AST_UnionBranch::narrow_from_decl (si.item ());
+
+ if (field == 0)
+ // This will be an enum value or other legitimate non-field
+ // member - in any case, no recursion.
+ {
+ continue;
+ }
+
+ AST_Type *type = field->field_type ();
+
+ if (type->node_type () == AST_Decl::NT_typedef)
+ {
+ AST_Typedef *td = AST_Typedef::narrow_from_decl (type);
+ type = td->primitive_base_type ();
+ }
+
+ if (type == 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%N:%l) AST_Union::")
+ ACE_TEXT ("in_recursion - ")
+ ACE_TEXT ("bad field type\n")),
+ 0);
+ }
+
+ if (type->in_recursion (scope_list))
+ {
+ this->in_recursion_ = 1;
+ idl_global->recursive_type_seen_ = true;
+ return this->in_recursion_;
+ }
+ }
+ }
+
+ // Not in recursion.
+ this->in_recursion_ = 0;
+ return this->in_recursion_;
+}
+
+// Look up the default branch in union.
+AST_UnionBranch *
+AST_Union::lookup_default (void)
+{
+ AST_UnionBranch *b = 0;
+ AST_Decl *d = 0;
+
+ for (UTL_ScopeActiveIterator i (this, UTL_Scope::IK_both);
+ !i.is_done();
+ i.next ())
+ {
+ d = i.item ();
+
+ if (d->node_type () == AST_Decl::NT_union_branch)
+ {
+ b = AST_UnionBranch::narrow_from_decl (d);
+
+ if (b == 0)
+ {
+ continue;
+ }
+
+ if (b->label () != 0
+ && b->label ()->label_kind () == AST_UnionLabel::UL_default)
+ {
+ idl_global->err ()->error2 (UTL_Error::EIDL_MULTIPLE_BRANCH,
+ this,
+ b);
+ return b;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// Look up a branch by label.
+AST_UnionBranch *
+AST_Union::lookup_label (AST_UnionBranch *b)
+{
+ AST_UnionLabel *label = b->label ();
+ AST_Expression *lv = label->label_val ();
+
+ if (label->label_val () == 0)
+ {
+ return b;
+ }
+
+ AST_Decl *d = 0;
+ AST_UnionBranch *fb = 0;
+
+ lv->set_ev (lv->coerce (this->pd_udisc_type));
+
+ if (lv->ev () == 0)
+ {
+ idl_global->err ()->eval_error (lv);
+ return b;
+ }
+
+ 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;
+}
+
+// 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;
+}
+
+// Look up a branch by value. This is the top level branch label resolution
+// entry point. It dispatches to the right lookup function depending on the
+// union discriminator type.
+AST_UnionBranch *
+AST_Union::lookup_branch (AST_UnionBranch *branch)
+{
+ AST_UnionLabel *label = 0;
+
+ if (branch != 0)
+ {
+ label = branch->label ();
+ }
+
+ if (label != 0)
+ {
+ if (label->label_kind () == AST_UnionLabel::UL_default)
+ {
+ return this->lookup_default ();
+ }
+
+ if (this->pd_udisc_type == AST_Expression::EV_enum)
+ {
+ // CONVENTION: indicates enum discriminant.
+ return this->lookup_enum (branch);
+ }
+
+ return this->lookup_label (branch);
+ }
+
+ return 0;
+}
+
+// Return the default value.
+int
+AST_Union::default_value (AST_Union::DefaultValue &dv)
+{
+ if (this->default_value_.computed_ == -2)
+ {
+ // We need to compute it.
+ if (this->compute_default_value () == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%N:%l) AST_Union::")
+ ACE_TEXT ("default_value - ")
+ ACE_TEXT ("Error computing ")
+ ACE_TEXT ("default value\n")),
+ -1);
+ }
+ }
+
+ dv = this->default_value_;
+ return 0;
+}
+
+// Determine the default value (if any).
+int
+AST_Union::compute_default_value (void)
+{
+ // Check if we really need a default value. This will be true if there is an
+ // explicit default case OR if an implicit default exists because not all
+ // values of the discriminant type are covered by the cases.
+
+ // Compute the total true "case" labels i.e., exclude the "default" case.
+ int total_case_members = 0;
+
+ // Instantiate a scope iterator.
+ for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ // Get the next AST decl node.
+ AST_UnionBranch *ub =
+ AST_UnionBranch::narrow_from_decl (si.item ());
+
+ if (ub != 0)
+ {
+ // If the label is a case label, increment by 1.
+ for (unsigned long i = 0; i < ub->label_list_length (); ++i)
+ {
+ if (ub->label (i)->label_kind () == AST_UnionLabel::UL_label)
+ {
+ ++total_case_members;
+ }
+ }
+ }
+ }
+
+ // Check if the total_case_members cover the entire
+ // range of values that are permitted by the discriminant type. If they do,
+ // then a default value is not necessary. However, if such an explicit
+ // default case is provided, it must be flagged off as an error. Our
+ // front-end is not able to handle such a case since it is a semantic error
+ // and not a syntax error. Such an error is caught here.
+
+ switch (this->udisc_type ())
+ {
+ case AST_Expression::EV_short:
+ case AST_Expression::EV_ushort:
+ if (total_case_members == ACE_UINT16_MAX + 1)
+ {
+ this->default_value_.computed_ = 0;
+ }
+
+ break;
+ case AST_Expression::EV_long:
+ case AST_Expression::EV_ulong:
+ if ((unsigned int) total_case_members > ACE_UINT32_MAX)
+ {
+ this->default_value_.computed_ = 0;
+ }
+
+ break;
+ case AST_Expression::EV_longlong:
+ case AST_Expression::EV_ulonglong:
+ // Error for now.
+ this->default_value_.computed_ = -1;
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) AST_Union::compute_default_value ")
+ ACE_TEXT ("- unimplemented discriminant type ")
+ ACE_TEXT ("(longlong or ulonglong)\n")
+ ),
+ -1
+ );
+ ACE_NOTREACHED (break;)
+ case AST_Expression::EV_char:
+ if (total_case_members == ACE_OCTET_MAX + 1)
+ {
+ this->default_value_.computed_ = 0;
+ }
+
+ break;
+ case AST_Expression::EV_wchar:
+ if (total_case_members == ACE_WCHAR_MAX + 1)
+ {
+ this->default_value_.computed_ = 0;
+ }
+
+ break;
+ case AST_Expression::EV_bool:
+ if (total_case_members == 2)
+ {
+ this->default_value_.computed_ = 0;
+ }
+
+ break;
+ case AST_Expression::EV_enum:
+ // Has to be enum.
+ {
+ AST_Decl *d = AST_Decl::narrow_from_decl (this->disc_type ());
+
+ if (d->node_type () == AST_Decl::NT_typedef)
+ {
+ AST_Typedef *bt = AST_Typedef::narrow_from_decl (d);
+ d = bt->primitive_base_type ();
+ }
+
+ AST_Enum *en = AST_Enum::narrow_from_decl (d);
+
+ if (en != 0)
+ {
+ if (total_case_members == en->member_count ())
+ {
+ this->default_value_.computed_ = 0;
+ }
+ }
+ else
+ {
+ // Error.
+ this->default_value_.computed_ = -1;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%N:%l) AST_Union::")
+ ACE_TEXT ("compute_default_value ")
+ ACE_TEXT ("- disc type not an ENUM\n")),
+ -1);
+ }
+ }
+ break;
+ default:
+ // Error.
+ this->default_value_.computed_ = -1;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%N:%l) AST_Union::compute_default_value")
+ ACE_TEXT (" - Bad discriminant type\n")),
+ -1);
+ ACE_NOTREACHED (break;)
+ } // End of switch
+
+ // If we have determined that we don't have a default case and even then a
+ // default case was provided, flag this off as error.
+ if ((this->default_value_.computed_ == 0)
+ && (this->default_index () != -1))
+ {
+ // Error.
+ this->default_value_.computed_ = -1;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%N:%l) AST_Union::compute_default_value")
+ ACE_TEXT (" - default clause is invalid here\n")),
+ -1);
+ }
+
+ // Proceed only if necessary.
+ switch (this->default_value_.computed_)
+ {
+ case -1:
+ // Error. We should never be here because errors
+ // have already been caught
+ // above.
+ return -1;
+ case 0:
+ // Nothing more to do.
+ return 0;
+ default:
+ // Proceed further down.
+ break;
+ }
+
+ // Initialization of the default value data member.
+ switch (this->udisc_type ())
+ {
+ case AST_Expression::EV_short:
+ this->default_value_.u.short_val = ACE_INT16_MIN;
+ break;
+ case AST_Expression::EV_ushort:
+ this->default_value_.u.ushort_val = 0;
+ break;
+ case AST_Expression::EV_long:
+ // The +1 is to avert a warning on many compilers.
+ this->default_value_.u.long_val = ACE_INT32_MIN + 1;
+ break;
+ case AST_Expression::EV_ulong:
+ this->default_value_.u.ulong_val = 0;
+ break;
+ case AST_Expression::EV_char:
+ this->default_value_.u.char_val = 0;
+ break;
+ case AST_Expression::EV_wchar:
+ this->default_value_.u.wchar_val = 0;
+ break;
+ case AST_Expression::EV_bool:
+ this->default_value_.u.bool_val = 0;
+ break;
+ case AST_Expression::EV_enum:
+ this->default_value_.u.enum_val = 0;
+ break;
+ case AST_Expression::EV_longlong:
+ case AST_Expression::EV_ulonglong:
+ // Unimplemented.
+ default:
+ // Error caught earlier.
+ break;
+ }
+
+ // Proceed until we have found the appropriate default value.
+ while (this->default_value_.computed_ == -2)
+ {
+ int break_loop = 0;
+
+ // Instantiate a scope iterator.
+ for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
+ !si.is_done () && break_loop == 0;
+ si.next ())
+ {
+ // Get the next AST decl node
+ AST_UnionBranch *ub =
+ AST_UnionBranch::narrow_from_decl (si.item ());
+
+ if (ub != 0)
+ {
+ for (unsigned long i = 0;
+ i < ub->label_list_length () && !break_loop;
+ ++i)
+ {
+ if (ub->label (i)->label_kind () == AST_UnionLabel::UL_label)
+ {
+ // Not a default.
+ AST_Expression *expr = ub->label (i)->label_val ();
+
+ if (expr == 0)
+ {
+ // Error.
+ this->default_value_.computed_ = -1;
+ ACE_ERROR_RETURN ((
+ LM_ERROR,
+ ACE_TEXT ("(%N:%l) AST_Union::")
+ ACE_TEXT ("compute_default_value - ")
+ ACE_TEXT ("Bad case label value\n")
+ ),
+ -1
+ );
+ }
+
+ switch (expr->ev ()->et)
+ {
+ // Check if they match in which case this
+ // cannot be the implicit default value. So
+ // start with a new value and try the whole loop
+ // again because our case labels may not be sorted.
+ case AST_Expression::EV_short:
+ if (this->default_value_.u.short_val
+ == expr->ev ()->u.sval)
+ {
+ this->default_value_.u.short_val++;
+ break_loop = 1;
+ }
+
+ break;
+ case AST_Expression::EV_ushort:
+ if (this->default_value_.u.ushort_val
+ == expr->ev ()->u.usval)
+ {
+ this->default_value_.u.ushort_val++;
+ break_loop = 1;
+ }
+
+ break;
+ case AST_Expression::EV_long:
+ if (this->default_value_.u.long_val
+ == expr->ev ()->u.lval)
+ {
+ this->default_value_.u.long_val++;
+ break_loop = 1;
+ }
+
+ break;
+ case AST_Expression::EV_ulong:
+ if (this->default_value_.u.ulong_val
+ == expr->ev ()->u.ulval)
+ {
+ this->default_value_.u.ulong_val++;
+ break_loop = 1;
+ }
+
+ break;
+ case AST_Expression::EV_char:
+ if (this->default_value_.u.char_val
+ == expr->ev ()->u.cval)
+ {
+ this->default_value_.u.char_val++;
+ break_loop = 1;
+ }
+
+ break;
+ case AST_Expression::EV_wchar:
+ if (this->default_value_.u.wchar_val
+ == expr->ev ()->u.wcval)
+ {
+ this->default_value_.u.wchar_val++;
+ break_loop = 1;
+ }
+
+ break;
+ case AST_Expression::EV_bool:
+ if (this->default_value_.u.bool_val
+ == expr->ev ()->u.bval)
+ {
+ this->default_value_.u.bool_val ^= true;
+ break_loop = 1;
+ }
+
+ break;
+ case AST_Expression::EV_enum:
+ // this is the case of enums. We maintain
+ // evaluated values which always start with 0
+ if (this->default_value_.u.enum_val
+ == expr->ev ()->u.eval)
+ {
+ this->default_value_.u.enum_val++;
+ break_loop = 1;
+ }
+
+ break;
+ case AST_Expression::EV_longlong:
+ case AST_Expression::EV_ulonglong:
+ // Unimplemented. right now - flag as error.
+ default:
+ // Error.
+ break;
+ } // End of switch.
+ } // if label_Kind == label
+ } // End of for loop going thru all labels.
+ } // If valid union branch.
+ } // End of while scope iterator loop.
+
+ // We have not aborted the inner loops which means we have found the
+ // default value.
+ if (break_loop == 0)
+ {
+ this->default_value_.computed_ = 1;
+ }
+
+ } // End of outer while (default_value.computed == -2).
+
+ return 0;
+}
+
+// Private operations.
+
+// Compute the default index.
+int
+AST_Union::compute_default_index (void)
+{
+ AST_Decl *d = 0;
+ AST_UnionBranch *ub = 0;
+ int i = 0;
+
+ // If default case does not exist, it will have a value of -1 according to
+ // the spec.
+ this->default_index_ = -1;
+
+ // If there are elements in this scope...
+ if (this->nmembers () > 0)
+ {
+ // Instantiate a scope iterator.
+ for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ // Get the next AST decl node.
+ d = si.item ();
+
+ // If an enum is declared in our scope, its members are
+ // added to our scope as well, to detect clashes.
+ if (d->node_type () == AST_Decl::NT_enum_val)
+ {
+ continue;
+ }
+
+ if (!d->imported ())
+ {
+ ub = AST_UnionBranch::narrow_from_decl (d);
+
+ for (unsigned long j = 0; j < ub->label_list_length (); ++j)
+ {
+ // Check if we are printing the default case.
+ AST_UnionLabel::UnionLabel ulk = ub->label ()->label_kind ();
+ if (ulk == AST_UnionLabel::UL_default)
+ {
+ // Zero based indexing.
+ this->default_index_ = i;
+ }
+ }
+
+ // TAO's Typecode class keeps only a member count (not
+ // a label count) so this increment has been moved
+ // out of the inner loop.
+ ++i;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// Redefinition of inherited virtual operations
+
+// Add this AST_UnionBranch node (a node representing one branch in a
+// union declaration) to this scope
+AST_UnionBranch *
+AST_Union::fe_add_union_branch (AST_UnionBranch *t)
+{
+ AST_Decl *d = 0;
+
+ // If this is a malformed branch, don't do anything with it.
+ if (t == 0 || t->label() == 0)
+ {
+ return 0;
+ }
+
+ // If branch with that label already exists, complain.
+ if (lookup_branch (t) != 0)
+ {
+ idl_global->err ()->error2 (UTL_Error::EIDL_MULTIPLE_BRANCH,
+ this,
+ t);
+ return 0;
+ }
+
+ // If branch with same field name exists, complain.
+ if ((d = this->lookup_for_add (t, false)) != 0)
+ {
+ if (!can_be_redefined (d))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_REDEF,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (this->referenced (d, t->local_name ()))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (t->has_ancestor (d))
+ {
+ idl_global->err ()->redefinition_in_scope (t,
+ d);
+ return 0;
+ }
+ }
+
+ // Add it to scope.
+ this->add_to_scope (t);
+
+ // If we have an enum discriminator, add the label names to
+ // the name_referenced list before we add the union branch,
+ // so a branch name clash with a label name will be caught.
+ if (this->pd_udisc_type == AST_Expression::EV_enum)
+ {
+ t->add_labels (this);
+ }
+
+ // Add it to set of locally referenced symbols.
+ this->add_to_referenced (t,
+ false,
+ t->local_name ());
+
+ AST_Type *ft = t->field_type ();
+ UTL_ScopedName *mru = ft->last_referenced_as ();
+
+ if (mru != 0)
+ {
+ this->add_to_referenced (ft,
+ false,
+ mru->first_component ());
+ }
+
+ this->fields_.enqueue_tail (t);
+
+ return t;
+}
+
+// Add this AST_Union (manifest union type) to this scope.
+AST_Union *
+AST_Union::fe_add_union (AST_Union *t)
+{
+ AST_Decl *d = 0;
+
+ // Already defined and cannot be redefined? Or already used?
+ if ((d = this->lookup_for_add (t, false)) != 0)
+ {
+ if (!can_be_redefined (d))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_REDEF,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (this->referenced (d, t->local_name ()))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (t->has_ancestor (d))
+ {
+ idl_global->err ()->redefinition_in_scope (t,
+ d);
+ return 0;
+ }
+ }
+
+ // Add it to local types.
+ this->add_to_local_types (t);
+
+ // Add it to set of locally referenced symbols.
+ this->add_to_referenced (t,
+ false,
+ t->local_name ());
+
+ return t;
+}
+
+// Add this AST_Structure node (manifest struct type) to this scope.
+AST_Structure *
+AST_Union::fe_add_structure (AST_Structure *t)
+{
+ AST_Decl *d = 0;
+
+ // Already defined and cannot be redefined? Or already used?
+ if ((d = this->lookup_for_add (t, false)) != 0)
+ {
+ if (!can_be_redefined (d))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_REDEF,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (this->referenced (d, t->local_name ()))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (t->has_ancestor (d))
+ {
+ idl_global->err ()->redefinition_in_scope (t,
+ d);
+ return 0;
+ }
+ }
+
+ // Add it to local types.
+ this->add_to_local_types (t);
+
+ // Add it to set of locally referenced symbols.
+ this->add_to_referenced (t,
+ false,
+ t->local_name ());
+
+ return t;
+}
+
+// Add this AST_Enum node (manifest enum type) to this scope.
+AST_Enum *
+AST_Union::fe_add_enum (AST_Enum *t)
+{
+ AST_Decl *d = 0;
+
+ // Already defined and cannot be redefined? Or already used?
+ if ((d = this->lookup_for_add (t, false)) != 0)
+ {
+ if (!can_be_redefined (d))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_REDEF,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (this->referenced (d, t->local_name ()))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (t->has_ancestor (d))
+ {
+ idl_global->err ()->redefinition_in_scope (t,
+ d);
+ return 0;
+ }
+ }
+
+ // Add it to local types.
+ this->add_to_local_types (t);
+
+ // Add it to set of locally referenced symbols.
+ this->add_to_referenced (t,
+ false,
+ t->local_name ());
+
+ return t;
+}
+
+// Add this AST_EnumVal node (enumerator declaration) to this scope.
+// This is done to conform to the C++ scoping rules which declare
+// enumerators in the enclosing scope (in addition to declaring them
+// in the enum itself).
+AST_EnumVal *
+AST_Union::fe_add_enum_val (AST_EnumVal *t)
+{
+ AST_Decl *d = 0;
+
+ // Already defined and cannot be redefined? Or already used?
+ if ((d = this->lookup_for_add (t, false)) != 0)
+ {
+ if (!can_be_redefined (d))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_REDEF,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (this->referenced (d, t->local_name ()))
+ {
+ idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE,
+ t,
+ this,
+ d);
+ return 0;
+ }
+
+ if (t->has_ancestor (d))
+ {
+ idl_global->err ()->redefinition_in_scope (t,
+ d);
+ return 0;
+ }
+ }
+
+ // Add it to scope.
+ this->add_to_scope (t);
+
+ // Add it to set of locally referenced symbols.
+ this->add_to_referenced (t,
+ false,
+ t->local_name ());
+
+ return t;
+}
+
+// Dump this AST_Union node to the ostream o.
+void
+AST_Union::dump (ACE_OSTREAM_TYPE &o)
+{
+ o << "union ";
+ this->local_name ()->dump (o);
+ o << " switch (";
+ this->pd_disc_type->local_name ()->dump (o);
+ o << ") {\n";
+ UTL_Scope::dump (o);
+ idl_global->indent ()->skip_to (o);
+ o << "}";
+}
+
+// Compute the size type of the node in question.
+int
+AST_Union::compute_size_type (void)
+{
+ for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ // Get the next AST decl node.
+ AST_Decl *d = si.item ();
+
+ if (d->node_type () == AST_Decl::NT_enum_val)
+ {
+ continue;
+ }
+
+ AST_Field *f = AST_Field::narrow_from_decl (d);
+
+ if (f != 0)
+ {
+ AST_Type *t = f->field_type ();
+ // Our sizetype depends on the sizetype of our members. Although
+ // previous value of sizetype may get overwritten, we are
+ // guaranteed by the "size_type" call that once the value reached
+ // be_decl::VARIABLE, nothing else can overwrite it.
+ this->size_type (t->size_type ());
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "WARNING (%N:%l) be_union::compute_size_type - "
+ "narrow_from_decl returned 0\n"));
+ }
+ }
+
+ return 0;
+}
+
+int
+AST_Union::ast_accept (ast_visitor *visitor)
+{
+ return visitor->visit_union (this);
+}
+
+// Data accessors.
+
+AST_ConcreteType *
+AST_Union::disc_type (void)
+{
+ return this->pd_disc_type;
+}
+
+AST_Expression::ExprType
+AST_Union::udisc_type (void)
+{
+ return this->pd_udisc_type;
+}
+
+// Narrowing.
+IMPL_NARROW_METHODS1(AST_Union, AST_Structure)
+IMPL_NARROW_FROM_DECL(AST_Union)
+IMPL_NARROW_FROM_SCOPE(AST_Union)