Merge pull request #2303 from jwillemsen/jwi-803
[ACE_TAO.git] / TAO / TAO_IDL / be / be_union.cpp
blob0ad3aaa6dfdf2a554d7a33224232b5a2b76f8b4c
2 //=============================================================================
3 /**
4 * @file be_union.cpp
6 * Extension of class AST_Union that provides additional means for C++
7 * mapping.
9 * @author Copyright 1994-1995 by Sun Microsystems
10 * @author Inc. and Aniruddha Gokhale
12 //=============================================================================
14 #include "be_union.h"
15 #include "be_union_branch.h"
16 #include "be_union_label.h"
17 #include "be_visitor.h"
18 #include "be_codegen.h"
19 #include "be_helper.h"
20 #include "be_extern.h"
22 #include "ast_union_branch.h"
23 #include "ast_enum.h"
24 #include "utl_identifier.h"
25 #include "idl_defines.h"
26 #include "global_extern.h"
28 be_union::be_union (AST_ConcreteType *dt,
29 UTL_ScopedName *n,
30 bool local,
31 bool abstract)
32 : COMMON_Base (local,
33 abstract),
34 AST_Decl (AST_Decl::NT_union,
35 n),
36 AST_Type (AST_Decl::NT_union,
37 n),
38 AST_ConcreteType (AST_Decl::NT_union,
39 n),
40 UTL_Scope (AST_Decl::NT_union),
41 AST_Structure (AST_Decl::NT_union,
43 local,
44 abstract),
45 AST_Union (dt,
47 local,
48 abstract),
49 be_scope (AST_Decl::NT_union),
50 be_decl (AST_Decl::NT_union,
51 n),
52 be_type (AST_Decl::NT_union,
55 // Always the case.
56 this->has_constructor (true);
58 if (!this->imported ())
60 idl_global->aggregate_seen_ = true;
62 idl_global->union_seen_ = true;
66 void
67 be_union::redefine (AST_Structure *from)
69 be_union *bu = dynamic_cast<be_union*> (from);
70 this->common_varout_gen_ = bu->common_varout_gen_;
71 AST_Union::redefine (from);
74 bool
75 be_union::has_duplicate_case_labels ()
77 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
78 !si.is_done ();
79 si.next ())
81 AST_Decl *d = si.item ();
82 AST_UnionBranch *ub =
83 dynamic_cast<AST_UnionBranch*> (d);
85 if (ub->label_list_length () > 1)
87 return true;
91 return false;
94 void
95 be_union::gen_ostream_operator (TAO_OutStream *os,
96 bool /*use_underscore*/)
98 *os << be_nl
99 << "std::ostream& operator<< (" << be_idt << be_idt_nl
100 << "std::ostream &strm," << be_nl
101 << "const " << this->name () << " &_tao_union" << be_uidt_nl
102 << ")" << be_uidt_nl
103 << "{" << be_idt_nl
104 << "strm << \"" << this->name () << "(\";" << be_nl_2
105 << "switch (_tao_union._d ())" << be_nl
106 << "{" << be_idt;
108 for (long i = 0; i < this->pd_decls_used; ++i)
110 be_union_branch *ub =
111 dynamic_cast<be_union_branch*> (this->pd_decls[i]);
113 // We don't want any decls, just members.
114 if (ub == nullptr)
116 continue;
119 *os << be_nl;
121 unsigned long ll_len = ub->label_list_length ();
123 for (unsigned long j = 0; j < ll_len; ++j)
125 // Check if we are printing the default case.
126 if (ub->label (j)->label_kind () == AST_UnionLabel::UL_default)
128 *os << "default:";
130 else
132 *os << "case ";
134 ub->gen_label_value (os, j);
136 *os << ":";
139 if (j == ll_len - 1)
141 *os << be_idt_nl;
143 else
145 *os << be_nl;
149 ACE_CString instance_name ("_tao_union.");
150 instance_name += ub->local_name ()->get_string ();
152 *os << "strm << ";
154 be_type *ub_ft = dynamic_cast<be_type*> (ub->field_type ());
155 AST_Decl::NodeType ub_nt = ub_ft->node_type ();
156 // catch anonymous Array member types
157 bool ub_use_underscore = ub_nt == AST_Decl::NT_array;
159 ub->gen_member_ostream_operator (os,
160 instance_name.c_str (),
161 ub_use_underscore,
162 true);
164 *os << ";" << be_nl
165 << "break;" << be_uidt;
168 // Some compilers complain unless this is present, but only
169 // if not all values are covered in case statements.
170 if (this->gen_empty_default_label ())
172 *os << be_nl
173 << "default:" << be_idt_nl
174 << "break;" << be_uidt;
177 *os << be_uidt_nl
178 << "}" << be_nl_2
179 << "return strm << \")\";" << be_uidt_nl
180 << "}" << be_nl;
183 void
184 be_union::destroy ()
186 // Call the destroy methods of our base classes.
187 this->be_scope::destroy ();
188 this->be_type::destroy ();
189 this->AST_Union::destroy ();
192 // Visitor method.
194 be_union::accept (be_visitor *visitor)
196 return visitor->visit_union (this);
199 bool
200 be_union::gen_empty_default_label ()
202 // A non-empty explicit default label will be generated.
203 if (this->default_index () != -1)
205 return false;
208 AST_ConcreteType *disc = this->disc_type ();
209 if (disc == nullptr)
211 return true; // In reality this is an error.
214 AST_Decl::NodeType nt = disc->node_type ();
215 ACE_UINT64 n_labels = this->nlabels ();
217 if (nt == AST_Decl::NT_enum)
219 // Enums in CORBA are always 32bits in size, so unless
220 // there are that many enum labels in the set, it is
221 // incomplete (reguardless as to the actual member_count).
222 return (n_labels <= ACE_UINT32_MAX);
225 AST_PredefinedType *pdt = dynamic_cast<AST_PredefinedType*> (disc);
226 if (pdt == nullptr)
228 return true; // In reality this is an error.
231 switch (pdt->pt ())
233 case AST_PredefinedType::PT_boolean:
234 return (n_labels < 2);
236 case AST_PredefinedType::PT_char:
237 case AST_PredefinedType::PT_octet:
238 return (n_labels <= ACE_OCTET_MAX);
240 case AST_PredefinedType::PT_short:
241 case AST_PredefinedType::PT_ushort:
242 case AST_PredefinedType::PT_wchar:
243 return (n_labels <= ACE_UINT16_MAX);
245 case AST_PredefinedType::PT_long:
246 case AST_PredefinedType::PT_ulong:
247 return (n_labels <= ACE_UINT32_MAX);
249 case AST_PredefinedType::PT_longlong:
250 case AST_PredefinedType::PT_ulonglong:
251 // We would wrap to 0 here - we are using a 64 bit count
252 // this case is so marginal as to always be incomplete.
253 return true;
255 // Keep fussy compilers happy.
256 default:
257 break;
260 return true;
263 AST_UnionBranch *
264 be_union::be_add_union_branch (AST_UnionBranch *b)
266 return this->fe_add_union_branch (b);
269 ACE_UINT64
270 be_union::nlabels ()
272 ACE_UINT64 retval = 0;
274 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
275 !si.is_done ();
276 si.next ())
278 AST_Decl *d = si.item ();
279 AST_UnionBranch *ub =
280 dynamic_cast<AST_UnionBranch*> (d);
282 if (ub != nullptr)
284 retval += ub->label_list_length ();
288 return retval;