Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / TAO / TAO_IDL / be / be_sequence.cpp
blob92a118eb2bb5283688917bff1fdceedc7e710424
2 //=============================================================================
3 /**
4 * @file be_sequence.cpp
6 * Extension of class AST_Sequence 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_sequence.h"
15 #include "be_typedef.h"
16 #include "be_interface.h"
17 #include "be_interface_fwd.h"
18 #include "be_predefined_type.h"
19 #include "be_field.h"
20 #include "be_string.h"
21 #include "be_visitor.h"
22 #include "be_helper.h"
23 #include "be_extern.h"
25 #include "utl_identifier.h"
26 #include "idl_defines.h"
27 #include "nr_extern.h"
28 #include "global_extern.h"
30 #include "ace/Log_Msg.h"
32 be_sequence::be_sequence (AST_Expression *v,
33 AST_Type *t,
34 UTL_ScopedName *n,
35 bool local,
36 bool abstract)
37 : COMMON_Base (t->is_local () || local,
38 abstract),
39 AST_Decl (AST_Decl::NT_sequence,
41 true),
42 AST_Type (AST_Decl::NT_sequence,
43 n),
44 AST_ConcreteType (AST_Decl::NT_sequence,
45 n),
46 AST_Sequence (v,
49 t->is_local () || local,
50 abstract),
51 UTL_Scope (AST_Decl::NT_sequence),
52 be_scope (AST_Decl::NT_sequence),
53 be_decl (AST_Decl::NT_sequence,
54 n),
55 be_type (AST_Decl::NT_sequence,
56 n),
57 mt_ (be_sequence::MNG_UNKNOWN),
58 field_node_ (nullptr)
60 // Always the case.
61 this->has_constructor (true);
63 // Don't want to set any bits below for imported nodes.
64 if (this->imported ())
66 return;
69 // This one gets set for all sequences, in addition to any specialized
70 // one that may get set below.
71 idl_global->seq_seen_ = true;
72 idl_global->var_size_decl_seen_ = true;
74 // Don't need the return value - just set the member.
75 (void) this->managed_type ();
77 switch (this->mt_)
79 case MNG_OBJREF:
80 idl_global->iface_seq_seen_ = true;
81 break;
82 case MNG_PSEUDO:
83 idl_global->pseudo_seq_seen_ = true;
84 break;
85 case MNG_VALUE:
86 idl_global->vt_seq_seen_ = true;
87 break;
88 case MNG_STRING:
89 idl_global->string_seq_seen_ = true;
90 break;
91 case MNG_WSTRING:
92 idl_global->wstring_seq_seen_ = true;
93 break;
94 default:
95 break;
98 AST_Type *const base_type = primitive_base_type ();
99 if (base_type && base_type->node_type () == AST_Decl::NT_pre_defined)
101 AST_PredefinedType *pdt = dynamic_cast<AST_PredefinedType*> (base_type);
102 switch (pdt->pt ())
104 case AST_PredefinedType::PT_octet:
105 idl_global->octet_seq_seen_ = true;
106 break;
107 default:
108 break;
113 be_type *
114 be_sequence::base_type () const
116 return
117 dynamic_cast<be_type*> (
118 this->AST_Sequence::base_type ());
121 be_type *
122 be_sequence::primitive_base_type () const
124 be_type *type_node = base_type ();
125 if (type_node && type_node->node_type () == AST_Decl::NT_typedef)
127 be_typedef *const typedef_node = dynamic_cast<be_typedef *> (type_node);
128 if (!typedef_node) return nullptr;
129 type_node = typedef_node->primitive_base_type ();
131 return type_node;
134 // Helper to create_name.
135 char *
136 be_sequence::gen_name ()
138 char namebuf [NAMEBUFSIZE];
139 be_type *bt = nullptr;
141 // Reset the buffer.
142 ACE_OS::memset (namebuf,
143 '\0',
144 NAMEBUFSIZE);
146 // Retrieve the base type.
147 bt = dynamic_cast<be_type*> (this->base_type ());
149 if (bt == nullptr)
151 ACE_ERROR_RETURN ((LM_ERROR,
152 "(%N:%l) be_sequence::"
153 "gen_name - "
154 "bad base type\n"),
158 // If this is non-zero, add its local name to the generated name,
159 // for uniqueness.
160 be_field *fn = this->field_node_;
162 if (bt->node_type () == AST_Decl::NT_sequence)
164 // Our base type is an anonymous sequence.
165 be_sequence *seq = dynamic_cast<be_sequence*> (bt);
167 if (seq == nullptr)
169 ACE_ERROR_RETURN ((LM_ERROR,
170 "(%N:%l) be_sequence::"
171 "gen_name - "
172 "error converting base type to sequence\n"),
176 // If the nested sequence were defined in
177 // the scope of the enclosing sequence, we would have to
178 // not only define the nested class in two places, but also
179 // deal with the fact that, for the template classes, the
180 // enclosing sequence's template type is a class defined
181 // inside it. So we define the nested sequence in the next
182 // scope up, and the existing code generation works for both
183 // template and non-template implementations of IDL sequences.
184 UTL_Scope *parent = this->defined_in ();
185 seq->set_defined_in (parent);
186 char *seq_name = seq->gen_name ();
188 ACE_OS::sprintf (namebuf,
189 "_tao_seq_%s_%s",
190 seq_name,
191 fn ? fn->local_name ()->get_string () : "");
192 ACE::strdelete (seq_name);
194 else
196 ACE_OS::sprintf (namebuf,
197 "_tao_seq_%s_",
198 bt->flat_name ());
201 // Append the size (if any).
202 if (this->unbounded () == false)
204 char ulval_str [NAMEBUFSIZE];
205 ACE_OS::sprintf (ulval_str,
206 "_" ACE_UINT32_FORMAT_SPECIFIER_ASCII,
207 this->max_size ()->ev ()->u.ulval);
208 ACE_OS::strcat (namebuf,
209 ulval_str);
212 return ACE::strnew (namebuf);
215 // Create a name for ourselves.
217 be_sequence::create_name (be_typedef *node)
219 static char *namebuf = nullptr;
220 UTL_ScopedName *n = nullptr;
222 // Scope in which we are defined.
223 be_decl *scope = nullptr;
225 // If there is a typedef node, we use its name as our name.
226 if (node)
228 this->set_name (
229 dynamic_cast<UTL_ScopedName *> (node->name ()->copy ())
232 else
234 // Generate a local name.
235 namebuf = this->gen_name ();
237 // Now see if we have a fully scoped name and if so, generate one.
238 UTL_Scope *us = this->defined_in ();
240 scope = dynamic_cast<be_scope*> (us)->decl ();
242 if (scope != nullptr)
244 // Make a copy of the enclosing scope's name.
245 n = (UTL_ScopedName *) scope->name ()->copy ();
247 Identifier *id = nullptr;
248 ACE_NEW_RETURN (id,
249 Identifier (namebuf),
250 -1);
252 UTL_ScopedName *conc_name = nullptr;
253 ACE_NEW_RETURN (conc_name,
254 UTL_ScopedName (id,
255 nullptr),
256 -1);
258 // Add our local name as the last component.
259 n->nconc (conc_name);
261 // Set the fully scoped name.
262 this->set_name (n);
264 else
266 // We better be not here because we must be inside some scope,
267 // at least the ROOT scope.
268 return -1;
271 ACE::strdelete (namebuf);
274 return 0;
277 // Does this sequence have a managed type sequence element?
278 be_sequence::MANAGED_TYPE
279 be_sequence::managed_type ()
281 if (this->mt_ == be_sequence::MNG_UNKNOWN) // Not calculated yet.
283 // Base types.
284 be_type *const base_type = primitive_base_type ();
285 if (!base_type)
286 ACE_ERROR_RETURN ((LM_ERROR,
287 "TAO_IDL (%N:%l) "
288 "dynamic_cast<be_type*> "
289 "failed\n"),
290 be_sequence::MNG_UNKNOWN);
292 // Determine if we need a managed type and which one.
293 switch (base_type->node_type ())
295 case AST_Decl::NT_interface:
296 case AST_Decl::NT_interface_fwd:
297 case AST_Decl::NT_component:
298 case AST_Decl::NT_component_fwd:
299 case AST_Decl::NT_connector:
300 this->mt_ = be_sequence::MNG_OBJREF;
301 break;
302 case AST_Decl::NT_valuebox:
303 case AST_Decl::NT_valuetype:
304 case AST_Decl::NT_valuetype_fwd:
305 case AST_Decl::NT_eventtype:
306 case AST_Decl::NT_eventtype_fwd:
307 this->mt_ = be_sequence::MNG_VALUE;
308 break;
309 case AST_Decl::NT_string:
310 this->mt_ = be_sequence::MNG_STRING;
311 break;
312 case AST_Decl::NT_wstring:
313 this->mt_ = be_sequence::MNG_WSTRING;
314 break;
315 case AST_Decl::NT_pre_defined:
317 be_predefined_type * const bpd =
318 dynamic_cast<be_predefined_type*> (base_type);
320 AST_PredefinedType::PredefinedType pt = bpd->pt ();
322 switch (pt)
324 case AST_PredefinedType::PT_pseudo:
325 case AST_PredefinedType::PT_object:
326 case AST_PredefinedType::PT_abstract:
327 this->mt_ = be_sequence::MNG_PSEUDO;
328 break;
329 case AST_PredefinedType::PT_value:
330 this->mt_ = be_sequence::MNG_VALUE;
331 break;
332 default:
333 this->mt_ = be_sequence::MNG_NONE;
334 break;
337 break;
338 default:
339 this->mt_ = be_sequence::MNG_NONE;
343 return this->mt_;
346 // Add this be_sequence to the locally defined types in this scope
347 AST_Sequence *
348 be_sequence::fe_add_sequence (AST_Sequence *t)
350 if (t == nullptr)
352 return nullptr;
355 this->add_to_local_types (t);
356 return t;
359 // Overridden method
360 be_decl *
361 be_sequence::decl ()
363 return this;
366 // Overridden method
367 void
368 be_sequence::gen_ostream_operator (TAO_OutStream *os,
369 bool /* use_underscore */)
371 *os << be_nl
372 << "std::ostream& operator<< (" << be_idt << be_idt_nl
373 << "std::ostream &strm," << be_nl
374 << "const " << this->name () << " &_tao_sequence" << be_uidt_nl
375 << ")" << be_uidt_nl
376 << "{" << be_idt_nl
377 << "strm << \"" << this->name () << "[\";" << be_nl_2;
379 if (be_global->alt_mapping ())
381 *os << "for (CORBA::ULong i = 0; i < _tao_sequence.size (); ++i)";
383 else
385 *os << "for (CORBA::ULong i = 0; i < _tao_sequence.length (); ++i)";
388 *os << be_idt_nl
389 << "{" << be_idt_nl
390 << "if (i != 0)" << be_idt_nl
391 << "{" << be_idt_nl
392 << "strm << \", \";" << be_uidt_nl
393 << "}" << be_uidt_nl << be_nl
394 << "strm << _tao_sequence[i];" << be_uidt_nl
395 << "}" << be_uidt_nl << be_nl
396 << "return strm << \"]\";" << be_uidt_nl
397 << "}" << be_nl;
401 be_sequence::accept (be_visitor *visitor)
403 return visitor->visit_sequence (this);
407 const char *
408 be_sequence::instance_name ()
410 static char namebuf[NAMEBUFSIZE];
411 ACE_OS::memset (namebuf,
412 '\0',
413 NAMEBUFSIZE);
415 be_type *const prim_type = primitive_base_type ();
416 if (!prim_type)
418 ACE_ERROR ((LM_ERROR,
419 "(%N:%l) be_visitor_sequence_ch::"
420 "gen_instantiate_name - "
421 "Bad element type\n"));
423 return namebuf;
426 // Generate the appropriate sequence type.
427 switch (this->managed_type ())
429 case be_sequence::MNG_PSEUDO:
430 case be_sequence::MNG_OBJREF:
431 if (this->unbounded ())
433 ACE_OS::sprintf (namebuf,
434 "_TAO_unbounded_object_reference_sequence_%s",
435 prim_type->local_name ()->get_string ());
437 else
439 ACE_OS::sprintf (namebuf,
440 "_TAO_bounded_object_reference_sequence_%s_"
441 ACE_UINT32_FORMAT_SPECIFIER_ASCII,
442 prim_type->local_name ()->get_string (),
443 this->max_size ()->ev ()->u.ulval);
446 break;
447 case be_sequence::MNG_VALUE:
448 if (this->unbounded ())
450 ACE_OS::sprintf (namebuf,
451 "_TAO_unbounded_valuetype_sequence_%s",
452 prim_type->local_name ()->get_string ());
454 else
456 ACE_OS::sprintf (namebuf,
457 "_TAO_bounded_valuetype_sequence_%s_"
458 ACE_UINT32_FORMAT_SPECIFIER_ASCII,
459 prim_type->local_name ()->get_string (),
460 this->max_size ()->ev ()->u.ulval);
463 break;
464 case be_sequence::MNG_STRING:
465 if (this->unbounded ())
467 ACE_OS::sprintf (namebuf,
468 "::TAO::unbounded_basic_string_sequence<char>");
470 else
472 ACE_OS::sprintf (namebuf,
473 "_TAO_unbounded_string_sequence_%s",
474 prim_type->local_name ()->get_string ());
477 break;
478 case be_sequence::MNG_WSTRING:
479 if (this->unbounded ())
481 ACE_OS::sprintf (namebuf,
482 "::TAO::unbounded_basic_string_sequence<CORBA::WChar>");
484 else
486 ACE_OS::sprintf (namebuf,
487 "_TAO_bounded_wstring_sequence_%s",
488 prim_type->local_name ()->get_string ());
491 break;
492 default: // Not a managed type.
493 if (this->unbounded ())
495 // TAO provides extensions for octet sequences, first find out
496 // if the base type is an octet (or an alias for octet)
497 be_predefined_type *predef =
498 dynamic_cast<be_predefined_type*> (prim_type);
500 if (predef != nullptr
501 && predef->pt() == AST_PredefinedType::PT_octet)
503 ACE_OS::sprintf (namebuf,
504 "::TAO::unbounded_value_sequence<CORBA::Octet>");
506 else
508 ACE_OS::sprintf (namebuf,
509 "_TAO_unbounded_value_sequence_%s",
510 prim_type->local_name ()->get_string ());
513 else
515 ACE_OS::sprintf (namebuf,
516 "_TAO_bounded_value_sequence_%s_"
517 ACE_UINT32_FORMAT_SPECIFIER_ASCII,
518 prim_type->local_name ()->get_string (),
519 this->max_size ()->ev ()->u.ulval);
522 break;
525 return namebuf;
529 be_sequence::gen_base_class_name (TAO_OutStream *os,
530 const char * linebreak,
531 AST_Decl *ctx_scope)
533 be_type *elem = dynamic_cast<be_type*> (this->base_type ());
535 if (be_global->alt_mapping () && this->unbounded ())
537 *os << "std::vector<" << elem->nested_type_name (ctx_scope)
538 << ">";
540 return 0;
543 // Generate the appropriate base class type.
544 switch (this->managed_type ())
546 case be_sequence::MNG_OBJREF:
547 case be_sequence::MNG_PSEUDO:
548 if (this->unbounded ())
550 *os << "::TAO::unbounded_object_reference_sequence<" << linebreak
551 << be_idt << be_idt_nl
552 << elem->nested_type_name (ctx_scope) << "," << linebreak
553 << be_nl;
554 *os << elem->nested_type_name (ctx_scope, "_var") << linebreak
555 << be_uidt_nl
556 << ">" << be_uidt;
558 else
560 *os << "::TAO::bounded_object_reference_sequence<" << linebreak
561 << be_idt << be_idt_nl
562 << elem->nested_type_name (ctx_scope) << "," << linebreak << be_nl;
563 *os << elem->nested_type_name (ctx_scope, "_var") << ","
564 << linebreak << be_nl;
565 *os << this->max_size ()->ev ()->u.ulval << linebreak << be_uidt_nl
566 << ">" << be_uidt;
569 break;
570 case be_sequence::MNG_VALUE:
571 if (this->unbounded ())
573 *os << "::TAO::unbounded_valuetype_sequence<" << linebreak
574 << be_idt << be_idt_nl
575 << elem->nested_type_name (ctx_scope) << "," << linebreak
576 << be_nl;
577 *os << elem->nested_type_name (ctx_scope, "_var") << linebreak
578 << be_uidt_nl
579 << ">" << be_uidt;
581 else
583 *os << "::TAO::bounded_valuetype_sequence<" << linebreak
584 << be_idt << be_idt_nl
585 << elem->nested_type_name (ctx_scope) << "," << linebreak
586 << be_nl;
587 *os << elem->nested_type_name (ctx_scope, "_var") << ","
588 << linebreak << be_nl
589 << this->max_size ()->ev ()->u.ulval << linebreak << be_uidt_nl
590 << ">" << be_uidt;
593 break;
594 case be_sequence::MNG_STRING:
596 be_type *const prim_type = primitive_base_type ();
597 if (!prim_type)
599 ACE_ERROR_RETURN ((LM_ERROR,
600 "(%N:%l) be_sequence::"
601 "gen_base_class_name - "
602 "Bad element type\n"),
603 -1);
605 if (prim_type->node_type () == AST_Decl::NT_string)
607 be_string *str =
608 dynamic_cast<be_string*> (prim_type);
609 if (!str)
611 ACE_ERROR_RETURN ((LM_ERROR,
612 "(%N:%l) be_sequence::"
613 "gen_base_class_name - "
614 "bad string node\n"),
615 -1);
618 // We need to make a distinction between bounded and
619 // unbounded strings.
620 if (str->max_size ()->ev ()->u.ulval != 0)
622 if (this->unbounded ())
624 *os << "::TAO::unbounded_bd_string_sequence<char, "
625 << str->max_size ()->ev ()->u.ulval << ">";
627 else
629 *os << "::TAO::bounded_bd_string_sequence<char, "
630 << this->max_size ()->ev ()->u.ulval << ", "
631 << str->max_size ()->ev ()->u.ulval << ">";
634 else
636 if (this->unbounded ())
638 *os << "::TAO::unbounded_basic_string_sequence<char>";
640 else
642 *os << "::TAO::bounded_basic_string_sequence<char, "
643 << this->max_size ()->ev ()->u.ulval << ">";
649 break;
650 case be_sequence::MNG_WSTRING:
652 be_type *const prim_type = primitive_base_type ();
653 if (!prim_type)
655 ACE_ERROR_RETURN ((LM_ERROR,
656 "(%N:%l) be_sequence::"
657 "gen_base_class_name - "
658 "Bad element type\n"),
659 -1);
661 if (prim_type->node_type () == AST_Decl::NT_wstring)
663 be_string *str =
664 dynamic_cast<be_string*> (prim_type);
665 if (!str)
667 ACE_ERROR_RETURN ((LM_ERROR,
668 "(%N:%l) be_sequence::"
669 "gen_base_class_name - "
670 "bad string node\n"),
671 -1);
674 // We need to make a distinction between bounded and
675 // unbounded strings.
676 if (str->max_size ()->ev ()->u.ulval != 0)
678 if (this->unbounded ())
680 *os << "::TAO::unbounded_bd_string_sequence<CORBA::WChar, "
681 << str->max_size ()->ev ()->u.ulval << ">";
683 else
685 *os << "::TAO::bounded_bd_string_sequence<CORBA::WChar, "
686 << this->max_size ()->ev ()->u.ulval << ", "
687 << str->max_size ()->ev ()->u.ulval << ">";
690 else
692 if (this->unbounded ())
694 *os << "::TAO::unbounded_basic_string_sequence<CORBA::WChar>";
696 else
698 *os << "::TAO::bounded_basic_string_sequence<CORBA::WChar, "
699 << this->max_size ()->ev ()->u.ulval << ">";
705 break;
706 default: // Not a managed type.
707 switch (elem->base_node_type ())
709 case AST_Decl::NT_array:
710 if (this->unbounded ())
712 *os << "::TAO::unbounded_array_sequence<" << linebreak
713 << be_idt << be_idt_nl
714 << elem->nested_type_name (ctx_scope) << "," << linebreak
715 << be_nl;
716 *os << elem->nested_type_name (ctx_scope) << "_slice,"
717 << linebreak << be_nl
718 << elem->nested_type_name (ctx_scope) << "_tag"
719 << linebreak << be_uidt_nl
720 << ">" << be_uidt;
722 else
724 *os << "::TAO::bounded_array_sequence<" << linebreak
725 << be_idt << be_idt_nl
726 << elem->nested_type_name (ctx_scope) << "," << linebreak
727 << be_nl;
728 *os << elem->nested_type_name (ctx_scope) << "_slice,"
729 << linebreak << be_nl
730 << elem->nested_type_name (ctx_scope) << "_tag,"
731 << linebreak << be_nl
732 << this->max_size ()->ev ()->u.ulval << linebreak
733 << be_uidt_nl
734 << ">" << be_uidt;
737 break;
738 default:
740 be_type *const base_type = primitive_base_type ();
741 if (!base_type)
743 ACE_ERROR_RETURN ((LM_ERROR,
744 "(%N:%l) be_sequence::"
745 "gen_base_class_name - "
746 "Bad element type\n"),
747 -1);
750 const char *tag = "";
751 if (base_type->node_type () == AST_Decl::NT_pre_defined)
753 be_predefined_type *const predefined_type =
754 dynamic_cast<be_predefined_type*> (base_type);
755 if (!predefined_type)
756 ACE_ERROR_RETURN ((LM_ERROR,
757 "(%N:%l) be_sequence::"
758 "gen_base_class_name - "
759 "Bad element type\n"),
760 -1);
761 switch (predefined_type->pt ())
763 case AST_PredefinedType::PT_uint8:
764 tag = ", CORBA::IDLv4::UInt8_tag";
765 break;
766 case AST_PredefinedType::PT_int8:
767 tag = ", CORBA::IDLv4::Int8_tag";
768 break;
769 default:
770 break;
775 << "::TAO::" << (unbounded () ? "un" : "") << "bounded_value_sequence< "
776 << elem->nested_type_name (ctx_scope);
777 if (!unbounded ())
778 *os << "," << this->max_size ()->ev ()->u.ulval;
779 *os << tag << ">";
781 break;
784 break;
787 return 0;
790 be_field *
791 be_sequence::field_node () const
793 return this->field_node_;
796 void
797 be_sequence::field_node (be_field *node)
799 this->field_node_ = node;
802 // Overriden method.
803 void
804 be_sequence::compute_tc_name ()
806 // Sequence TypeCodes can only be accessed through an alias
807 // TypeCode. Generate a TypeCode name that is meant for internal
808 // use alone.
810 Identifier * tao_id = nullptr;
811 ACE_NEW (tao_id,
812 Identifier ("TAO"));
814 ACE_NEW (this->tc_name_,
815 UTL_ScopedName (tao_id,
816 nullptr));
818 char bound[30] = { 0 };
820 ACE_OS::sprintf (bound,
821 "_" ACE_UINT32_FORMAT_SPECIFIER_ASCII,
822 this->max_size ()->ev ()->u.ulval);
824 ACE_CString local_tc_name =
825 ACE_CString ("tc_")
826 + ACE_CString (this->flat_name ())
827 + ACE_CString (bound);
829 Identifier * typecode_scope = nullptr;
830 ACE_NEW (typecode_scope,
831 Identifier ("TypeCode"));
833 UTL_ScopedName * tc_scope_conc_name = nullptr;
834 ACE_NEW (tc_scope_conc_name,
835 UTL_ScopedName (typecode_scope,
836 nullptr));
838 this->tc_name_->nconc (tc_scope_conc_name);
840 Identifier * id = nullptr;
841 ACE_NEW (id,
842 Identifier (local_tc_name.c_str ()));
844 UTL_ScopedName * conc_name = nullptr;
845 ACE_NEW (conc_name,
846 UTL_ScopedName (id,
847 nullptr));
849 this->tc_name_->nconc (conc_name);
852 const char *
853 be_sequence::smart_fwd_helper_name (AST_Decl *ctx_scope,
854 be_type *elem)
856 if (ScopeAsDecl (elem->defined_in ()) == ctx_scope)
858 ACE_CString retval = "tao_";
859 retval += elem->local_name ()->get_string ();
860 return retval.rep ();
863 return elem->fwd_helper_name ();
866 void
867 be_sequence::destroy ()
869 // Call the destroy methods of our base classes.
870 this->be_scope::destroy ();
871 this->be_type::destroy ();
872 this->AST_Sequence::destroy ();