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.cpp
blob4be922272827a817fef42b588bc733f9c642d54c
2 //=============================================================================
3 /**
4 * @file operation.cpp
6 * Visitor generating code for Operation in the stubs file.
8 * @author Aniruddha Gokhale
9 */
10 //=============================================================================
12 #include "operation.h"
14 // ************************************************************
15 // Generic Operation visitor
16 // ************************************************************
18 be_visitor_operation::be_visitor_operation (be_visitor_context *ctx)
19 : be_visitor_scope (ctx)
23 be_visitor_operation::~be_visitor_operation ()
27 // Is the operation return type void?
28 int
29 be_visitor_operation::void_return_type (be_type *bt)
31 if (bt->node_type () == AST_Decl::NT_pre_defined)
33 be_predefined_type * const bpd =
34 dynamic_cast<be_predefined_type*> (bt);
36 if (!bpd)
37 ACE_ERROR_RETURN ((LM_ERROR,
38 "TAO_IDL (%N:%l) "
39 "dynamic_cast<be_predefined_type*> "
40 "failed\n"),
41 0);
43 AST_PredefinedType::PredefinedType const pdt = bpd->pt ();
45 if (pdt == AST_PredefinedType::PT_void)
47 return 1;
51 return 0;
54 int
55 be_visitor_operation::has_param_type (be_operation *node,
56 AST_Argument::Direction dir)
58 return (node->count_arguments_with_direction (dir) != 0);
61 size_t
62 be_visitor_operation::count_non_out_parameters (be_operation *node)
64 // @@ Once the valuetype issue discussed below is fixed we can
65 // replace this routine with:
67 // return node->count_arguments_with_direction (AST_Argument::dir_IN
68 // | AST_Argument::dir_INOUT);
70 size_t count = 0;
72 // Initialize an iterator to iterate thru our scope.
73 for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
74 !si.is_done ();
75 si.next ())
77 be_argument *bd =
78 dynamic_cast<be_argument*> (si.item ());
80 // We do not generate insertion operators for valuetypes
81 // yet. Do not include them in the count.
82 be_valuetype *vt =
83 dynamic_cast<be_valuetype*> (bd->field_type ());
85 if ((bd->direction () != AST_Argument::dir_OUT) && vt == nullptr)
87 ++count;
91 return count;
94 int
95 be_visitor_operation::is_amh_exception_holder (be_interface *node)
97 int is_an_amh_exception_holder = 0;
98 const char *amh_underbar = "AMH_";
99 const char *node_name = node->local_name ();
101 if( amh_underbar[0] == node_name[0] &&
102 amh_underbar[1] == node_name[1] &&
103 amh_underbar[2] == node_name[2] &&
104 amh_underbar[3] == node_name[3]
105 ) // node name starts with "AMH_"
107 //ACE_DEBUG ((LM_DEBUG, "Passed first test of amh_excepholder\n"));
108 const char *last_E = ACE_OS::strrchr (node->full_name (), 'E');
109 if (last_E != nullptr
110 && ACE_OS::strcmp (last_E, "ExceptionHolder") == 0)
112 //ACE_DEBUG ((LM_DEBUG, "be_visitor_operation: Passed second test of amh_excepholder\n"));
113 is_an_amh_exception_holder = 1;
117 return is_an_amh_exception_holder;
121 be_visitor_operation::gen_raise_exception (const char *exception_name,
122 const char *exception_arguments)
124 TAO_OutStream *os = this->ctx_->stream ();
126 *os << "throw "
127 << exception_name << "(" << exception_arguments << ");";
129 return 0;
133 be_visitor_operation::gen_stub_operation_body (
134 be_operation *node,
135 be_type *return_type
138 UTL_Scope *s =
139 this->ctx_->attribute ()
140 ? this->ctx_->attribute ()->defined_in ()
141 : node->defined_in ();
143 be_interface *intf = dynamic_cast<be_interface*> (s);
145 if (intf == nullptr)
147 be_porttype *pt = dynamic_cast<be_porttype*> (s);
149 if (pt == nullptr)
151 ACE_ERROR_RETURN ((LM_ERROR,
152 ACE_TEXT ("be_visitor_operation::")
153 ACE_TEXT ("gen_stub_operation_body - ")
154 ACE_TEXT ("bad scope\n")),
155 -1);
157 else
159 intf = this->ctx_->interface ();
163 TAO_OutStream *os = this->ctx_->stream ();
164 be_visitor_context ctx;
166 *os << be_nl << "{" << be_idt_nl;
168 if (node->has_native ()) // native exists => no stub
170 if (this->gen_raise_exception ("::CORBA::MARSHAL", "") == -1)
172 ACE_ERROR_RETURN ((
173 LM_ERROR,
174 "(%N:%l) be_visitor_operation_cs::"
175 "visit_operation - "
176 "codegen for native exception failed\n"
182 *os << be_uidt_nl << "}";
184 return 0;
187 if (!node->is_abstract ())
189 // If the object is lazily evaluated the proxy broker might well
190 // be null. Initialize it now.
191 *os << "if (!this->is_evaluated ())" << be_idt_nl
192 << "{" << be_idt_nl
193 << "::CORBA::Object::tao_object_initialize (this);"
194 << be_uidt_nl
195 << "}" << be_uidt_nl << be_nl;
198 // Declare return type helper class.
199 *os << "TAO::Arg_Traits< ";
201 this->gen_arg_template_param_name (node,
202 return_type,
203 os);
205 *os << ">::"
206 << (node->flags () == AST_Operation::OP_oneway &&
207 be_global->use_clonable_in_args() ? "clonable_" : "")
208 << "ret_val _tao_retval;";
210 // Declare the argument helper classes.
211 this->gen_stub_body_arglist (node, os);
213 *os << be_nl_2
214 << "TAO::Argument *_the_tao_operation_signature [] =" << be_idt_nl
215 << "{" << be_idt_nl
216 << "std::addressof(_tao_retval)";
218 AST_Argument *arg = nullptr;
220 for (UTL_ScopeActiveIterator arg_list_iter (node, UTL_Scope::IK_decls);
221 ! arg_list_iter.is_done ();
222 arg_list_iter.next ())
224 arg = dynamic_cast<AST_Argument*> (arg_list_iter.item ());
226 *os << "," << be_nl
227 << "std::addressof(_tao_" << arg->local_name () << ")";
230 *os << be_uidt_nl
231 << "};" << be_uidt;
233 if (this->gen_pre_stub_info (node) == -1)
235 ACE_ERROR_RETURN ((LM_ERROR,
236 "(%N:%l) be_visitor_operation_cs::"
237 "visit_operation - "
238 "codegen for exceptiondata failed\n"),
239 -1);
242 *os << be_nl_2
243 << "TAO::" << (node->is_abstract () ? "AbstractBase_" : "" )
244 << "Invocation_Adapter _invocation_call (" << be_idt << be_idt_nl
245 << "this," << be_nl
246 << "_the_tao_operation_signature," << be_nl
247 << node->argument_count () + 1 << "," << be_nl
248 << "\"";
250 /// This logic handles the implied IDL for attributes.
251 /// The AMI ReplyHandler version of generated get/set ops
252 /// for attributes doesn't have the leading underscore.
253 bool const escape = (node->is_attr_op () && !intf->is_ami_rh ());
254 ACE_CString opname (escape ? "_" : "");
256 /// This logic handles regular IDL for attributes. The AMI
257 /// backend preprocessing visitor doesn't set the context
258 /// member for attributes, but sets flags in the interface
259 /// and operation nodes instead.
260 if (this->ctx_->attribute ())
262 // Now check if we are a "get" or "set" operation.
263 if (node->nmembers () == 1)
265 opname += "_set_";
267 else
269 opname += "_get_";
273 opname += node->original_local_name ()->get_string ();
275 /// Some compilers can't resolve the stream operator overload.
276 const char *lname = opname.c_str ();
277 ACE_CString::size_type len = opname.length ();
279 *os << lname << "\"," << be_nl
280 << len << "," << be_nl;
282 *os << "TAO::TAO_CO_NONE";
283 if (be_global->gen_direct_collocation())
285 *os << " | TAO::TAO_CO_DIRECT_STRATEGY";
287 if (be_global->gen_thru_poa_collocation())
289 *os << " | TAO::TAO_CO_THRU_POA_STRATEGY";
292 if (node->flags () == AST_Operation::OP_oneway)
294 *os << "," << be_nl;
295 *os << "TAO::TAO_ONEWAY_INVOCATION";
298 if (node->has_in_arguments ())
300 *os << be_nl;
302 else
304 if (node->flags () != AST_Operation::OP_oneway)
306 *os << "," << be_nl;
307 *os << "TAO::TAO_TWOWAY_INVOCATION" << be_nl;
310 *os << "," << be_nl
311 << "TAO::TAO_SYNCHRONOUS_INVOCATION," << be_nl
312 << "false";
315 *os << be_uidt_nl
316 << ");" << be_uidt;
318 *os << be_nl_2;
320 // Since oneways cannot raise user exceptions, we have that
321 // case covered as well.
322 if (node->exceptions ())
324 *os << "_invocation_call.invoke (" << be_idt << be_idt_nl
325 << "_tao_" << node->flat_name ()
326 << "_exceptiondata," << be_nl
327 << node->exceptions ()->length () << be_uidt_nl
328 << ");" << be_uidt;
330 else
332 *os << "_invocation_call.invoke (nullptr, 0);";
335 if (!this->void_return_type (return_type))
337 *os << be_nl_2
338 << "return _tao_retval.retn ();";
341 *os << be_uidt_nl << "}";
343 return 0;
347 be_visitor_operation::gen_pre_stub_info (
348 be_operation *node
351 be_visitor_context ctx = *this->ctx_;
352 be_visitor_operation_exceptlist_cs visitor (&ctx);
354 if (node->accept (&visitor) == -1)
356 ACE_ERROR_RETURN ((LM_ERROR,
357 "(%N:%l) "
358 "be_visitor_operation_cs::"
359 "gen_pre_stub_info - "
360 "Exceptionlist generation error\n"),
361 -1);
364 return 0;
368 be_visitor_operation::gen_raise_interceptor_exception (
369 be_type *bt,
370 const char *excep,
371 const char *completion_status
374 TAO_OutStream *os = this->ctx_->stream ();
376 if (this->void_return_type (bt))
378 *os << "throw " << excep << "(" << completion_status << ");";
380 else
382 if (bt->size_type () == AST_Type::VARIABLE
383 || bt->base_node_type () == AST_Decl::NT_array)
385 *os << "TAO_INTERCEPTOR_THROW_RETURN (" << be_idt << be_idt_nl
386 << excep << " (" << be_idt << be_idt_nl
387 << completion_status << be_uidt_nl
388 << ")," << be_uidt_nl
389 << "0" << be_uidt_nl
390 << ");" << be_uidt;
392 else
394 *os << "TAO_INTERCEPTOR_THROW_RETURN (" << be_idt << be_idt_nl
395 << excep << " (" << be_idt << be_idt_nl
396 << completion_status << be_uidt_nl
397 << ")," << be_uidt_nl
398 << "_tao_retval" << be_uidt_nl
399 << ");" << be_uidt;
403 return 0;
406 void
407 be_visitor_operation::gen_stub_body_arglist (be_operation *node,
408 TAO_OutStream *os,
409 bool ami)
411 AST_Argument *arg = nullptr;
412 UTL_ScopeActiveIterator arg_decl_iter (node, UTL_Scope::IK_decls);
414 if (ami)
416 // Skip the reply handler (first argument).
417 arg_decl_iter.next ();
420 for (; ! arg_decl_iter.is_done (); arg_decl_iter.next ())
422 arg = dynamic_cast<AST_Argument*> (arg_decl_iter.item ());
424 *os << be_nl
425 << "TAO::Arg_Traits< ";
427 this->gen_arg_template_param_name (arg,
428 arg->field_type (),
429 os);
431 *os << ">::";
433 switch (arg->direction ())
435 case AST_Argument::dir_IN:
436 *os << "in";
437 if (be_global->use_clonable_in_args() &&
438 node->flags () == AST_Operation::OP_oneway)
440 *os << "_clonable";
442 break;
443 case AST_Argument::dir_INOUT:
444 *os << "inout";
445 break;
446 case AST_Argument::dir_OUT:
447 *os << "out";
448 default:
449 break;
452 *os << "_arg_val _tao_" << arg->local_name () << " ("
453 << arg->local_name () << ");";
457 void
458 be_visitor_operation::gen_arg_template_param_name (AST_Decl *scope,
459 AST_Type *bt,
460 TAO_OutStream *os)
462 AST_Typedef *alias = nullptr;
464 if (bt->node_type () == AST_Decl::NT_typedef)
466 alias = dynamic_cast<AST_Typedef*> (bt);
469 AST_Decl::NodeType nt = bt->unaliased_type ()->node_type ();
470 ACE_CDR::ULong bound = 0;
472 if (nt == AST_Decl::NT_string || nt == AST_Decl::NT_wstring)
474 AST_String *s =
475 dynamic_cast<AST_String*> (bt->unaliased_type ());
476 bound = s->max_size ()->ev ()->u.ulval;
478 // If the (w)string is unbounded, code is generated below by the
479 // last line of this method, whether bt is a typedef or not.
480 if (bound > 0)
482 *os << "::TAO::";
484 if (alias != nullptr)
486 *os << alias->local_name () << "_" << bound;
488 else
490 // If we have an unaliased, bounded (w)string parameter,
491 // we know that be_visitor_arg_traits has used an empty
492 // struct of a type constructed from the flat name of
493 // the parameter's 'enclosing scope' (the parameter
494 // identifier for parameters, and the operation identifier
495 // for return types) to get a unique type for the
496 // Arg_Traits<> template parameter. So we generate it
497 // the same way here, using the 'scope' argument's
498 // flat name.
499 *os << scope->flat_name ();
502 return;
506 // We need the unaliased type name to make the code block below
507 // work correctly.
508 AST_Type *ut = bt->unaliased_type ();
509 nt = ut->node_type ();
511 // For the four predefined types below, we use the helper struct
512 // type, in order to disambiguate the template parameter.
513 if (nt == AST_Decl::NT_pre_defined)
515 AST_PredefinedType *pdt =
516 dynamic_cast<AST_PredefinedType*> (ut);
518 switch (pdt->pt ())
520 case AST_PredefinedType::PT_boolean:
521 *os << "::ACE_InputCDR::to_boolean";
522 return;
523 case AST_PredefinedType::PT_octet:
524 *os << "::ACE_InputCDR::to_octet";
525 return;
526 case AST_PredefinedType::PT_char:
527 *os << "::ACE_InputCDR::to_char";
528 return;
529 case AST_PredefinedType::PT_wchar:
530 *os << "::ACE_InputCDR::to_wchar";
531 return;
532 case AST_PredefinedType::PT_uint8:
533 *os << "::ACE_InputCDR::to_uint8";
534 return;
535 case AST_PredefinedType::PT_int8:
536 *os << "::ACE_InputCDR::to_int8";
537 return;
538 case AST_PredefinedType::PT_void:
539 break;
540 default:
541 *os << "::";
542 break;
545 else if (nt != AST_Decl::NT_string)
547 // We are unbounded, since the bounded case is handled
548 // above. In this case, we want to generate 'char *'
549 // without the leading double colon.
550 *os << "::";
553 /// For now, keep a list of system operation or arg names
554 /// that may not be remapped. May decide later to regnerate
555 /// ORB code for alt mapping as well.
556 ACE_CString repo_id (scope->repoID ());
557 bool sys_val = (repo_id == "IDL:repository_id:1.0");
559 // For types other than the 4 above, don't unalias the type name
560 // in case it is a sequence or array.
561 if (nt == AST_Decl::NT_string && bound == 0)
563 if (be_global->alt_mapping () && !sys_val)
565 *os << "std::string";
567 else
569 *os << "char *";
572 else if (nt == AST_Decl::NT_sequence)
574 // In some cases (e.g., if the node is imported)
575 // the underlying sequence is still named 'sequence'.
576 *os << bt->name ();
578 else
580 *os << ut->name ();
583 if (nt == AST_Decl::NT_array)
585 *os << "_tag";