Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / TAO / TAO_IDL / be / be_visitor_operation / operation_ss.cpp
blob3bccb12acba0900f2fad830fe857cffc017e6483
2 //=============================================================================
3 /**
4 * @file operation_ss.cpp
6 * Visitor generating code for Operation in the server skeleton
8 * @author Aniruddha Gokhale
9 */
10 //=============================================================================
12 #include "operation.h"
14 be_visitor_operation_ss::be_visitor_operation_ss (be_visitor_context *ctx)
15 : be_visitor_operation (ctx)
19 be_visitor_operation_ss::~be_visitor_operation_ss ()
23 int
24 be_visitor_operation_ss::visit_operation (be_operation * node)
26 /// No server-side code generation for these implied IDL nodes.
27 if (node->is_sendc_ami ())
29 return 0;
32 TAO_OutStream *os = this->ctx_->stream ();
33 be_type *bt = nullptr;
35 this->ctx_->node (node);
37 os->indent ();
39 // If there is an argument of type "native", return immediately.
40 if (node->has_native ())
42 return 0;
45 // Retrieve the operation return type.
46 bt = dynamic_cast<be_type*> (node->return_type ());
48 if (!bt)
50 ACE_ERROR_RETURN ((LM_ERROR,
51 ACE_TEXT ("be_visitor_operation_ss::")
52 ACE_TEXT ("visit_operation - ")
53 ACE_TEXT ("Bad return type\n")),
54 -1);
57 return this->gen_skel_operation_body (node, bt);
60 int
61 be_visitor_operation_ss::visit_argument (be_argument *node)
63 // This method is used to generate the ParamData table entry.
65 TAO_OutStream *os = this->ctx_->stream ();
67 // Retrieve the type for this argument.
68 be_type *bt = dynamic_cast<be_type*> (node->field_type ());
70 if (!bt)
72 ACE_ERROR_RETURN ((LM_ERROR,
73 "(%N:%l) be_visitor_operation_ss::"
74 "visit_argument - "
75 "Bad argument type\n"),
76 -1);
79 os->indent ();
80 *os << "{" << bt->tc_name () << ", ";
81 switch (node->direction ())
83 case AST_Argument::dir_IN:
84 *os << "::CORBA::ARG_IN, ";
85 break;
86 case AST_Argument::dir_INOUT:
87 *os << "::CORBA::ARG_INOUT, ";
88 break;
89 case AST_Argument::dir_OUT:
90 *os << "::CORBA::ARG_OUT, ";
91 break;
93 *os << "0}";
95 return 0;
98 int
99 be_visitor_operation_ss::gen_pre_skel_info (be_operation * node)
101 be_visitor_context ctx = *this->ctx_;
102 be_visitor_operation_exceptlist_ss visitor (&ctx);
104 if (node->accept (&visitor) == -1)
106 ACE_ERROR_RETURN ((LM_ERROR,
107 "(%N:%l) "
108 "be_visitor_operation_ss::"
109 "gen_pre_skel_info - "
110 "Exception TypeCode list generation error\n"),
111 -1);
114 return 0;
118 be_visitor_operation_ss::gen_skel_operation_body (be_operation * node,
119 be_type * return_type)
121 TAO_OutStream * const os = this->ctx_->stream ();
123 // We need the interface node in which this operation was
124 // defined. However, if this operation node was an attribute node
125 // in disguise, we get this information from the context.
126 UTL_Scope *s = this->ctx_->attribute ()
127 ? this->ctx_->attribute ()->defined_in ()
128 : node->defined_in ();
130 be_interface *intf = dynamic_cast<be_interface*> (s);
132 if (intf == nullptr)
134 ACE_ERROR_RETURN ((LM_ERROR,
135 ACE_TEXT ("be_visitor_operation_ss::")
136 ACE_TEXT ("visit_operation - ")
137 ACE_TEXT ("bad interface scope\n")),
138 -1);
141 ACE_CString upcall_command_name =
142 this->ctx_->port_prefix ()
143 + ACE_CString (node->local_name ()->get_string ()) + "_"
144 + ACE_CString (intf->local_name ());
146 // Check if we are an attribute node in disguise.
147 if (this->ctx_->attribute ())
149 // Now check if we are a "get" or "set" operation.
150 if (node->nmembers () == 1)
152 upcall_command_name = "_set_" + upcall_command_name;
154 else
156 upcall_command_name = "_get_" + upcall_command_name;
160 // Generate the local class encapsulating the actual servant upcall
161 // command/invocation.
162 be_visitor_operation_upcall_command_ss upcall_command_visitor (this->ctx_);
163 upcall_command_visitor.visit (node,
164 intf->full_skel_name (),
165 upcall_command_name.c_str ());
167 TAO_INSERT_COMMENT (os);
169 *os << "void " << intf->full_skel_name () << "::";
171 // Check if we are an attribute node in disguise.
172 if (this->ctx_->attribute ())
174 // Now check if we are a "get" or "set" operation.
175 if (node->nmembers () == 1)
177 *os << "_set_";
179 else
181 *os << "_get_";
185 *os << this->ctx_->port_prefix ().c_str () << node->local_name ()
186 << "_skel (" << be_idt_nl
187 << "TAO_ServerRequest & server_request," << be_nl
188 << "TAO::Portable_Server::Servant_Upcall *TAO_INTERCEPTOR (servant_upcall)," << be_nl
189 << "TAO_ServantBase *servant)" << be_uidt_nl;
191 // Generate the actual code for the skeleton. However, if any of the
192 // argument types is "native", we do not generate any skeleton
193 // last argument - is always CORBA::Environment.
194 *os << "{" << be_idt;
196 // Generate all the tables and other pre-skel info.
197 if (this->gen_pre_skel_info (node) == -1)
199 ACE_ERROR_RETURN ((LM_ERROR,
200 "(%N:%l) be_visitor_operation_ss::"
201 "visit_operation - "
202 "gen_pre_skel_info failed\n"),
203 -1);
206 // Declare return type helper class.
208 *os << "TAO::SArg_Traits< ";
210 this->gen_arg_template_param_name (node,
211 return_type,
212 os);
214 *os << ">::ret_val retval;";
216 // Declare the argument helper classes.
217 this->gen_skel_body_arglist (node, os);
219 *os << be_nl_2
220 << "TAO::Argument * const args[] =" << be_idt_nl
221 << "{" << be_idt_nl
222 << "std::addressof(retval)";
224 for (UTL_ScopeActiveIterator arg_list_iter (node, UTL_Scope::IK_decls);
225 ! arg_list_iter.is_done ();
226 arg_list_iter.next ())
228 AST_Argument * const arg =
229 dynamic_cast<AST_Argument*> (arg_list_iter.item ());
231 *os << "," << be_nl
232 << "std::addressof(_tao_" << arg->local_name () << ")";
235 *os << be_uidt_nl
236 << "};" << be_uidt_nl << be_nl;
238 // Get the right object implementation.
239 *os << intf->full_skel_name () << " * const impl =" << be_idt_nl
240 << "dynamic_cast<"
241 << intf->full_skel_name () << " *> (servant);" << be_uidt << be_nl_2;
243 *os << "if (!impl)" << be_idt_nl
244 << "{" << be_idt_nl
245 << "throw ::CORBA::INTERNAL ();" << be_uidt_nl
246 << "}" << be_uidt << be_nl_2;
248 // Upcall_Command instantiation.
249 *os << upcall_command_name.c_str()
250 << " command (" << be_idt_nl
251 << "impl";
253 if (!node->void_return_type () || node->argument_count () > 0)
255 // server_request.operation_details () will be non-zero in the
256 // thru-POA collocation case. Use them if available.
257 *os << "," << be_nl;
259 if (be_global->gen_thru_poa_collocation ())
260 *os << "server_request.operation_details ()," << be_nl;
262 *os << "args";
265 *os << ");" << be_uidt_nl << be_nl;
267 *os << "TAO::Upcall_Wrapper upcall_wrapper;" << be_nl
268 << "upcall_wrapper.upcall (server_request" << be_nl
269 << " , args" << be_nl
270 << " , " << (node->argument_count () + 1) << be_nl
271 << " , command"
272 << "\n#if TAO_HAS_INTERCEPTORS == 1" << be_nl
273 << " , servant_upcall" << be_nl;
275 if (node->exceptions () && be_global->tc_support ())
277 *os << " , exceptions" << be_nl
278 << " , " << node->exceptions ()->length ();
280 else
282 *os << " , nullptr" << be_nl
283 << " , 0";
286 *os << "\n#endif /* TAO_HAS_INTERCEPTORS == 1 */" << be_nl
287 << " );" << be_uidt_nl
288 << "}" << be_nl_2;
290 return 0;
293 void
294 be_visitor_operation_ss::gen_skel_body_arglist (be_operation * node,
295 TAO_OutStream * os)
297 for (UTL_ScopeActiveIterator arg_decl_iter (node, UTL_Scope::IK_decls);
298 ! arg_decl_iter.is_done ();
299 arg_decl_iter.next ())
301 AST_Argument * const arg =
302 dynamic_cast<AST_Argument*> (arg_decl_iter.item ());
304 *os << be_nl
305 << "TAO::SArg_Traits< ";
307 this->gen_arg_template_param_name (arg,
308 arg->field_type (),
309 os);
311 *os << ">::";
313 switch (arg->direction ())
315 case AST_Argument::dir_IN:
316 *os << "in";
317 break;
318 case AST_Argument::dir_INOUT:
319 *os << "inout";
320 break;
321 case AST_Argument::dir_OUT:
322 *os << "out";
323 default:
324 break;
327 *os << "_arg_val _tao_" << arg->local_name () << ";";