2 //=============================================================================
6 * Visitor generating code for Operation in the stubs file.
8 * @author Aniruddha Gokhale
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?
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
);
37 ACE_ERROR_RETURN ((LM_ERROR
,
39 "dynamic_cast<be_predefined_type*> "
43 AST_PredefinedType::PredefinedType
const pdt
= bpd
->pt ();
45 if (pdt
== AST_PredefinedType::PT_void
)
55 be_visitor_operation::has_param_type (be_operation
*node
,
56 AST_Argument::Direction dir
)
58 return (node
->count_arguments_with_direction (dir
) != 0);
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);
72 // Initialize an iterator to iterate thru our scope.
73 for (UTL_ScopeActiveIterator
si (node
, UTL_Scope::IK_decls
);
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.
83 dynamic_cast<be_valuetype
*> (bd
->field_type ());
85 if ((bd
->direction () != AST_Argument::dir_OUT
) && vt
== nullptr)
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 ();
127 << exception_name
<< "(" << exception_arguments
<< ");";
133 be_visitor_operation::gen_stub_operation_body (
139 this->ctx_
->attribute ()
140 ? this->ctx_
->attribute ()->defined_in ()
141 : node
->defined_in ();
143 be_interface
*intf
= dynamic_cast<be_interface
*> (s
);
147 be_porttype
*pt
= dynamic_cast<be_porttype
*> (s
);
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")),
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)
174 "(%N:%l) be_visitor_operation_cs::"
176 "codegen for native exception failed\n"
182 *os
<< be_uidt_nl
<< "}";
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
193 << "::CORBA::Object::tao_object_initialize (this);"
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
,
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
);
214 << "TAO::Argument *_the_tao_operation_signature [] =" << 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 ());
227 << "std::addressof(_tao_" << arg
->local_name () << ")";
233 if (this->gen_pre_stub_info (node
) == -1)
235 ACE_ERROR_RETURN ((LM_ERROR
,
236 "(%N:%l) be_visitor_operation_cs::"
238 "codegen for exceptiondata failed\n"),
243 << "TAO::" << (node
->is_abstract () ? "AbstractBase_" : "" )
244 << "Invocation_Adapter _invocation_call (" << be_idt
<< be_idt_nl
246 << "_the_tao_operation_signature," << be_nl
247 << node
->argument_count () + 1 << "," << be_nl
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)
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
)
295 *os
<< "TAO::TAO_ONEWAY_INVOCATION";
298 if (node
->has_in_arguments ())
304 if (node
->flags () != AST_Operation::OP_oneway
)
307 *os
<< "TAO::TAO_TWOWAY_INVOCATION" << be_nl
;
311 << "TAO::TAO_SYNCHRONOUS_INVOCATION," << be_nl
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
332 *os
<< "_invocation_call.invoke (nullptr, 0);";
335 if (!this->void_return_type (return_type
))
338 << "return _tao_retval.retn ();";
341 *os
<< be_uidt_nl
<< "}";
347 be_visitor_operation::gen_pre_stub_info (
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
,
358 "be_visitor_operation_cs::"
359 "gen_pre_stub_info - "
360 "Exceptionlist generation error\n"),
368 be_visitor_operation::gen_raise_interceptor_exception (
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
<< ");";
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
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
407 be_visitor_operation::gen_stub_body_arglist (be_operation
*node
,
411 AST_Argument
*arg
= nullptr;
412 UTL_ScopeActiveIterator
arg_decl_iter (node
, UTL_Scope::IK_decls
);
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 ());
425 << "TAO::Arg_Traits< ";
427 this->gen_arg_template_param_name (arg
,
433 switch (arg
->direction ())
435 case AST_Argument::dir_IN
:
437 if (be_global
->use_clonable_in_args() &&
438 node
->flags () == AST_Operation::OP_oneway
)
443 case AST_Argument::dir_INOUT
:
446 case AST_Argument::dir_OUT
:
452 *os
<< "_arg_val _tao_" << arg
->local_name () << " ("
453 << arg
->local_name () << ");";
458 be_visitor_operation::gen_arg_template_param_name (AST_Decl
*scope
,
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
)
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.
484 if (alias
!= nullptr)
486 *os
<< alias
->local_name () << "_" << bound
;
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
499 *os
<< scope
->flat_name ();
506 // We need the unaliased type name to make the code block below
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
);
520 case AST_PredefinedType::PT_boolean
:
521 *os
<< "::ACE_InputCDR::to_boolean";
523 case AST_PredefinedType::PT_octet
:
524 *os
<< "::ACE_InputCDR::to_octet";
526 case AST_PredefinedType::PT_char
:
527 *os
<< "::ACE_InputCDR::to_char";
529 case AST_PredefinedType::PT_wchar
:
530 *os
<< "::ACE_InputCDR::to_wchar";
532 case AST_PredefinedType::PT_uint8
:
533 *os
<< "::ACE_InputCDR::to_uint8";
535 case AST_PredefinedType::PT_int8
:
536 *os
<< "::ACE_InputCDR::to_int8";
538 case AST_PredefinedType::PT_void
:
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.
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";
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'.
583 if (nt
== AST_Decl::NT_array
)