2 //=============================================================================
6 * Visitor generating code for Unions in the client stubs
8 * @author Aniruddha Gokhale
10 //=============================================================================
14 be_visitor_union_cs::be_visitor_union_cs (be_visitor_context
*ctx
)
15 : be_visitor_union (ctx
)
19 be_visitor_union_cs::~be_visitor_union_cs ()
23 // Visit the Union_cs node and its scope.
24 int be_visitor_union_cs::visit_union (be_union
*node
)
26 if (node
->cli_stub_gen () || node
->imported ())
31 TAO_OutStream
*os
= this->ctx_
->stream ();
33 be_visitor_context
ctx (*this->ctx_
);
34 // The discriminant type may have to be defined here if it was an enum
35 // declaration inside of the union statement. We need to generate its
38 be_type
*bt
= dynamic_cast<be_type
*> (node
->disc_type ());
42 ACE_ERROR_RETURN ((LM_ERROR
,
43 "(%N:%l) be_visitor_union_cs::"
45 "bad discriminant type\n"), -1);
48 be_visitor_union_discriminant_cs
disc_visitor (&ctx
);
50 if (bt
->accept (&disc_visitor
) == -1)
52 ACE_ERROR_RETURN ((LM_ERROR
,
53 "(%N:%l) be_visitor_union_cs::"
55 "codegen for discrminant failed\n"),
59 // First generate code for any of the members (if required, e.g.,
60 // anonymous sequences, structs, unions, arrays).
61 this->ctx_
->state (TAO_CodeGen::TAO_UNION_PUBLIC_CS
);
63 if (this->visit_scope (node
) == -1)
65 ACE_ERROR_RETURN ((LM_ERROR
,
66 "(%N:%l) be_visitor_union_cs"
68 "codegen for scope failed\n"),
72 // Now generate the operations on the union such as the copy constructor
73 // and the assignment operator.
75 TAO_INSERT_COMMENT (os
);
77 // Generate the copy constructor and the assignment operator here.
79 << node
->name () << "::" << node
->local_name () << " ()" << be_nl
81 << "ACE_OS::memset (&this->u_, 0, sizeof (this->u_));" << be_nl
;
83 // The default constructor must initialize the discriminator
84 // to the first case label value found in the union declaration
85 // so that, if the uninitialized union is inserted into an Any,
86 // the Any destructor's call to deep_free() will work properly.
88 *os
<< "this->disc_ = ";
90 UTL_ScopeActiveIterator
si (node
, UTL_Scope::IK_decls
);
91 be_union_branch
*ub
= nullptr;
93 // In case we have some bogus enum values from an enum declared
97 // Just get the union's first member.
98 AST_Decl
*d
= si
.item ();
100 ub
= dynamic_cast<be_union_branch
*> (d
);
104 // Get the first label in its list.
105 AST_UnionLabel
*ul
= ub
->label (0);
107 AST_Union::DefaultValue dv
;
108 // This can indicate an error in the return value, but it is
110 (void) node
->default_value (dv
);
112 bool test
= dv
.computed_
== 0
113 && ul
->label_kind () == AST_UnionLabel::UL_label
;
117 ub
->gen_label_value (os
);
121 ub
->gen_default_label_value (os
, node
);
126 if (dv
.computed_
== 0)
129 be_visitor_union_branch_public_constructor_cs
const_visitor (this->ctx_
);
130 if (ub
->accept (&const_visitor
) == -1)
132 ACE_ERROR_RETURN ((LM_ERROR
,
133 "(%N:%l) be_visitor_union_cs::"
135 "codegen for constructor failed\n"),
140 *os
<< be_uidt_nl
<< "}" << be_nl_2
;
142 this->ctx_
->state (TAO_CodeGen::TAO_UNION_PUBLIC_ASSIGN_CS
);
144 // So we know we are generating the copy constructor.
145 this->ctx_
->sub_state (TAO_CodeGen::TAO_UNION_COPY_CONSTRUCTOR
);
147 const bool boolDisc
= node
->udisc_type() == AST_Expression::EV_bool
;
149 *os
<< node
->name () << "::" << node
->local_name ()
150 << " (const ::" << node
->name () << " &u)"
152 *os
<< "{" << be_idt_nl
;
153 *os
<< "this->disc_ = u.disc_;" << be_nl
;
157 *os
<< "switch (this->disc_)" << be_nl
;
158 *os
<< "{" << be_idt
;
161 if (this->visit_scope (node
) == -1)
163 ACE_ERROR_RETURN ((LM_ERROR
,
164 "(%N:%l) be_visitor_union_cs"
166 "codegen for copy ctor failed\n"),
170 // If there is no explicit default case, but there
171 // is an implicit one, and the discriminant is an enum,
172 // we need this to avert warnings in some compilers that
173 // not all case values are included. If there is no
174 // implicit default case, or the discriminator is not
175 // an enum, this does no harm.
176 if (!boolDisc
&& node
->gen_empty_default_label ())
179 << "default:" << be_nl
185 *os
<< be_uidt_nl
<< "}";
188 *os
<< be_uidt_nl
<< "}" << be_nl_2
;
190 *os
<< node
->name () << "::~" << node
->local_name ()
193 << "// Finalize." << be_nl
194 << "this->_reset ();" << be_uidt_nl
197 if (be_global
->any_support ())
201 << "::_tao_any_destructor (void *_tao_void_pointer)" << be_nl
203 << node
->local_name () << " *tmp =" << be_idt_nl
205 << node
->local_name () << " *> (_tao_void_pointer);" << be_uidt_nl
206 << "delete tmp;" << be_uidt_nl
210 this->ctx_
->state (TAO_CodeGen::TAO_UNION_PUBLIC_ASSIGN_CS
);
212 // Reset this for generating the assignment operator.
213 this->ctx_
->sub_state (TAO_CodeGen::TAO_SUB_STATE_UNKNOWN
);
215 // Assignment operator.
216 *os
<< node
->name () << " &" << be_nl
;
217 *os
<< node
->name () << "::operator= (const ::"
218 << node
->name () << " &u)" << be_nl
;
219 *os
<< "{" << be_idt_nl
;
220 // First check for self-assignment.
221 *os
<< "if (std::addressof(u) == this)" << be_idt_nl
223 << "return *this;" << be_uidt_nl
224 << "}" << be_uidt_nl
<< be_nl
;
225 // Reset and set the discriminant.
226 *os
<< "this->_reset ();" << be_nl
;
227 *os
<< "this->disc_ = u.disc_;" << be_nl_2
;
228 // now switch based on the disc value
231 *os
<< "switch (this->disc_)" << be_nl
;
232 *os
<< "{" << be_idt
;
235 if (this->visit_scope (node
) == -1)
237 ACE_ERROR_RETURN ((LM_ERROR
,
238 "(%N:%l) be_visitor_union_cs"
240 "codegen for assign op failed\n"),
244 // If there is no explicit default case, but there
245 // is an implicit one, and the discriminant is an enum,
246 // we need this to avert warnings in some compilers that
247 // not all case values are included. If there is no
248 // implicit default case, or the discriminator is not
249 // an enum, this does no harm.
250 if (!boolDisc
&& node
->gen_empty_default_label ())
253 << "default:" << be_nl
259 *os
<< be_uidt_nl
<< "}" << be_nl
;
262 *os
<< be_nl
<< "return *this;" << be_uidt_nl
;
263 *os
<< "}" << be_nl_2
;
266 this->ctx_
->state (TAO_CodeGen::TAO_UNION_PUBLIC_RESET_CS
);
268 *os
<< "/// Reset method to reset old values of a union." << be_nl
;
269 *os
<< "void " << node
->name () << "::_reset ()" << be_nl
;
270 *os
<< "{" << be_idt_nl
;
274 *os
<< "switch (this->disc_)" << be_nl
;
275 *os
<< "{" << be_idt_nl
;
278 if (this->visit_scope (node
) == -1)
280 ACE_ERROR_RETURN ((LM_ERROR
,
281 "(%N:%l) be_visitor_union_cs"
283 "codegen for reset failed\n"),
287 // If there is no explicit default case, but there
288 // is an implicit one, and the discriminant is an enum,
289 // we need this to avert warnings in some compilers that
290 // not all case values are included. If there is no
291 // implicit default case, or the discriminator is not
292 // an enum, this does no harm.
293 if (!boolDisc
&& node
->gen_empty_default_label ())
296 << "default:" << be_nl
302 *os
<< be_uidt_nl
<< "}";
305 *os
<< be_uidt_nl
<< "}";
307 if (be_global
->tc_support ())
310 // ctx.sub_state (TAO_CodeGen::TAO_TC_DEFN_TYPECODE);
311 TAO::be_visitor_union_typecode
tc_visitor (&ctx
);
313 if (tc_visitor
.visit_union (node
) == -1)
315 ACE_ERROR_RETURN ((LM_ERROR
,
316 "(%N:%l) be_visitor_union_cs::"
318 "TypeCode definition failed\n"),
323 node
->cli_stub_gen (true);