summaryrefslogtreecommitdiff
path: root/TAO/TAO_IDL/be/be_valuetype.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/TAO_IDL/be/be_valuetype.cpp')
-rw-r--r--TAO/TAO_IDL/be/be_valuetype.cpp864
1 files changed, 864 insertions, 0 deletions
diff --git a/TAO/TAO_IDL/be/be_valuetype.cpp b/TAO/TAO_IDL/be/be_valuetype.cpp
new file mode 100644
index 00000000000..f97c9cf3f37
--- /dev/null
+++ b/TAO/TAO_IDL/be/be_valuetype.cpp
@@ -0,0 +1,864 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO IDL
+//
+// = FILENAME
+// be_valuetype.cpp
+//
+// = DESCRIPTION
+// Extension of class AST_Interface and be_interface that provides
+// additional means for C++ mapping of an valuetype.
+//
+// = AUTHOR
+// Torsten Kuepper <kuepper2@lfa.uni-wuppertal.de>
+// derived from be_interface.cpp
+//
+// ============================================================================
+
+#include "be_valuetype.h"
+#include "be_visitor.h"
+#include "be_extern.h"
+#include "be_helper.h"
+#include "ast_module.h"
+#include "utl_identifier.h"
+#include "idl_defines.h"
+#include "nr_extern.h"
+#include "global_extern.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID (be,
+ be_valuetype,
+ "$Id$")
+
+// Default constructor.
+be_valuetype::be_valuetype (void)
+ : COMMON_Base (),
+ AST_Decl (),
+ AST_Type (),
+ UTL_Scope (),
+ AST_Interface (),
+ be_scope (),
+ be_decl (),
+ be_type (),
+ be_interface (),
+ AST_ValueType (),
+ full_obv_skel_name_ (0)
+{
+ // Always the case.
+ this->size_type (AST_Type::VARIABLE);
+
+ AST_Module *m = AST_Module::narrow_from_scope (this->defined_in ());
+
+ if (m != 0)
+ {
+ m->set_has_nested_valuetype ();
+ }
+
+ // Always the case.
+ this->has_constructor (true);
+}
+
+// Constructor used to build the AST.
+be_valuetype::be_valuetype (UTL_ScopedName *n,
+ AST_Interface **inherits,
+ long n_inherits,
+ AST_ValueType *inherits_concrete,
+ AST_Interface **inherits_flat,
+ long n_inherits_flat,
+ AST_Interface **supports,
+ long n_supports,
+ AST_Interface *supports_concrete,
+ bool abstract,
+ bool truncatable,
+ bool custom)
+ : COMMON_Base (0,
+ abstract),
+ AST_Decl (AST_Decl::NT_valuetype,
+ n),
+ AST_Type (AST_Decl::NT_valuetype,
+ n),
+ UTL_Scope (AST_Decl::NT_valuetype),
+ AST_Interface (n,
+ inherits,
+ n_inherits,
+ inherits_flat,
+ n_inherits_flat,
+ 0,
+ abstract),
+ be_scope (AST_Decl::NT_valuetype),
+ be_decl (AST_Decl::NT_valuetype,
+ n),
+ be_type (AST_Decl::NT_valuetype,
+ n),
+ be_interface (n,
+ inherits,
+ n_inherits,
+ inherits_flat,
+ n_inherits_flat,
+ 0,
+ abstract),
+ AST_ValueType (n,
+ inherits,
+ n_inherits,
+ inherits_concrete,
+ inherits_flat,
+ n_inherits_flat,
+ supports,
+ n_supports,
+ supports_concrete,
+ abstract,
+ truncatable,
+ custom),
+ full_obv_skel_name_ (0),
+ supports_abstract_ (0),
+ var_out_seq_decls_gen_ (0)
+{
+ // Check that redefine() copies all members.
+
+ // Always the case.
+ this->size_type (AST_Type::VARIABLE);
+
+ AST_Module *m = AST_Module::narrow_from_scope (this->defined_in ());
+
+ if (m != 0)
+ {
+ m->set_has_nested_valuetype ();
+ }
+
+ // Always the case.
+ this->has_constructor (true);
+
+ for (long i = 0; i < this->pd_n_supports; ++i)
+ {
+ be_interface *intf =
+ be_interface::narrow_from_decl (this->pd_supports[i]);
+
+ if (intf->has_mixed_parentage ())
+ {
+ this->supports_abstract_ = true;
+ break;
+ }
+ }
+
+ if (this->imported ())
+ {
+ return;
+ }
+
+ // Set the flag that says we have a valuetype in this IDL file.
+ if (this->is_defined ())
+ {
+ idl_global->valuetype_seen_ = true;
+ }
+ else
+ {
+ idl_global->fwd_valuetype_seen_ = true;
+ }
+}
+
+be_valuetype::~be_valuetype (void)
+{
+}
+
+void
+be_valuetype::redefine (AST_Interface *from)
+{
+ be_valuetype *bv = be_valuetype::narrow_from_decl (from);
+ bv->var_out_seq_decls_gen_ = bv->var_out_seq_decls_gen_;
+ this->AST_ValueType::redefine (from);
+}
+
+// Is true if non-virtual accessor and modifier should be generated
+// If #pragma TAO OBV opt_accessor (todo) is used or -Wb,obv_opt_accessor.
+bool
+be_valuetype::opt_accessor (void)
+{
+ return be_global->obv_opt_accessor ();
+}
+
+// Compute stringified fully scoped skeleton name (OBV_name).
+void
+be_valuetype::compute_fullobvskelname (void)
+{
+ this->compute_full_skel_name ("OBV_",
+ this->full_obv_skel_name_);
+}
+
+// Retrieve the fully scoped skeleton name.
+const char*
+be_valuetype::full_obv_skel_name (void)
+{
+ if (0 == this->full_obv_skel_name_)
+ {
+ compute_fullobvskelname ();
+ }
+
+ return this->full_obv_skel_name_;
+}
+
+const char *
+be_valuetype::fwd_helper_name (void) const
+{
+ return this->fwd_helper_name_.fast_rep ();
+}
+
+be_valuetype::FactoryStyle
+be_valuetype::determine_factory_style (void)
+{
+ FactoryStyle factory_style = FS_UNKNOWN;
+
+
+ if (this->is_abstract ())
+ {
+ return FS_NO_FACTORY;
+ }
+
+ // Check whether we have at least one operation or not.
+ bool have_operation = this->have_operation ();
+ bool have_factory = 0;
+
+ // Try only our own scope.
+ if (this->nmembers () > 0)
+ {
+ // Initialize an iterator to iterate thru our scope
+ // Continue until each element is visited.
+ for (UTL_ScopeActiveIterator si (this,
+ UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next())
+ {
+ AST_Decl *d = si.item ();
+
+ if (!d)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_valuetype::"
+ "determine_factory_style"
+ "bad node in this scope\n"),
+ factory_style);
+
+ }
+
+ AST_Decl::NodeType node_type = d->node_type ();
+
+ if (node_type == AST_Decl::NT_factory)
+ {
+ have_factory = 1;
+ break;
+ }
+
+ } // end of for loop
+ } // end of if
+
+ if (!have_operation && !have_factory)
+ {
+ factory_style = FS_CONCRETE_FACTORY;
+ }
+ else if (have_operation && !have_factory)
+ {
+ factory_style = FS_NO_FACTORY;
+ }
+ else
+ {
+ factory_style = FS_ABSTRACT_FACTORY;
+ }
+
+ return factory_style;
+}
+
+bool
+be_valuetype::have_operation (void)
+{
+ // Check whatever scope we get for operations/attributes.
+
+ bool have_operation = false;
+
+ // Operations are either operations or attributes of:
+ // -its own
+ // -derived (abstract VT | VT | abstract iface | iface)
+ //
+
+ // First try our own scope.
+ if (this->nmembers () > 0)
+ {
+ // Initialize an iterator to iterate thru our scope
+ // Continue until each element is checked.
+ for (UTL_ScopeActiveIterator si (this,
+ UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next())
+ {
+ AST_Decl *d = si.item ();
+
+ if (!d)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_valuetype::"
+ "has_operation"
+ "bad node in this scope\n"),
+ 0);
+
+ }
+
+ AST_Decl::NodeType nt = d->node_type();
+
+ if (nt == AST_Decl::NT_op || nt == AST_Decl::NT_attr)
+ {
+ have_operation = true;
+ break;
+ }
+ } // end of for loop
+ } // end of if
+
+ if (! have_operation)
+ {
+ // Now traverse inheritance tree.
+ long i; // loop index
+ long n_inherits = this->n_inherits ();
+ AST_Interface **inherits = this->inherits ();
+
+ for (i = 0; i < n_inherits; ++i)
+ {
+ be_valuetype *vt = be_valuetype::narrow_from_decl (inherits[i]);
+
+ if (vt != 0 && vt->have_operation ())
+ {
+ have_operation = true;
+ break;
+ }
+ }
+ }
+
+ if (! have_operation)
+ {
+ // Check for operations on supported interfaces
+ AST_Interface * supported = this->supports_concrete ();
+
+ if (supported != 0)
+ {
+ be_interface *intf = be_interface::narrow_from_decl (supported);
+
+ if (intf != 0)
+ {
+ have_operation = be_valuetype::have_supported_op (intf);
+ }
+ }
+ }
+
+ return have_operation;
+}
+
+bool
+be_valuetype::have_supported_op (be_interface * node)
+{
+
+ bool have_supported_op = 0;
+
+ if (node->nmembers () == 0)
+ {
+ return false;
+ }
+
+ // Initialize an iterator for supported interface elements
+ for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
+ si.is_done ();
+ si.next())
+ {
+ AST_Decl *d = si.item ();
+
+ if (!d)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_valuetype::"
+ "have_supported_op"
+ "bad node in this scope\n"),
+ 0);
+ }
+
+ AST_Decl::NodeType nt = d->node_type ();
+
+ // Check the type of each element in the supported interface
+ if (nt == AST_Decl::NT_op || nt == AST_Decl::NT_attr)
+ {
+ have_supported_op = 1;
+ break;
+ }
+ } // end for loop
+
+ if (! have_supported_op)
+ {
+ // Now traverse inheritance tree.
+ long i; // loop index
+ long n_inherits = node->n_inherits ();
+ AST_Interface **inherits = node->inherits ();
+ for (i = 0; i < n_inherits; ++i)
+ {
+ be_interface * intf = be_interface::narrow_from_decl (inherits[i]);
+
+ if (intf != 0)
+ {
+ have_supported_op = be_valuetype::have_supported_op (intf);
+
+ if (have_supported_op)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return have_supported_op;
+}
+
+bool
+be_valuetype::will_have_factory (void)
+{
+ FactoryStyle fs = this->determine_factory_style ();
+
+ return (fs == FS_ABSTRACT_FACTORY || fs == FS_CONCRETE_FACTORY);
+}
+
+bool
+be_valuetype::has_member (void)
+{
+ AST_ValueType *parent = this->pd_inherits_concrete;
+
+ // We're looking for inherited members too.
+ if (parent != 0)
+ {
+ be_valuetype *be_parent =
+ be_valuetype::narrow_from_decl (parent);
+
+ if (be_parent->has_member ())
+ {
+ return true;
+ }
+ }
+
+ for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next())
+ {
+ if (si.item ()->node_type () == AST_Decl::NT_field)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int
+be_valuetype::gen_helper_header (char *, char *)
+{
+ TAO_OutStream *os = tao_cg->client_header ();
+
+ *os << be_nl << be_nl
+ << "// TAO_IDL - Generated from" << be_nl
+ << "// " << __FILE__ << ":" << __LINE__ << be_nl << be_nl;
+
+ *os << be_global->core_versioning_begin () << be_nl;
+
+ *os << "namespace CORBA" << be_nl
+ << "{"
+ << be_idt_nl
+ << "extern " << be_global->stub_export_macro () << " void add_ref ("
+ << this->full_name () << " *);" << be_nl
+ << "extern " << be_global->stub_export_macro () << " void remove_ref ("
+ << this->full_name () << " *);";
+
+ *os << be_uidt_nl
+ << "}";
+
+ *os << be_global->core_versioning_end () << be_nl;
+
+ return 0;
+}
+
+int
+be_valuetype::gen_helper_inline (char *, char *)
+{
+ TAO_OutStream *os = tao_cg->client_inline ();
+
+ // There is a problem, here. Looks like the if defined __ACE_INLINE
+ // is not getting generated... Actually this is a much bigger
+ // problem. Just hacking it up for the timebeing..
+
+ *os << be_nl << be_nl << "// TAO_IDL - Generated from" << be_nl
+ << "// " << __FILE__ << ":" << __LINE__ << be_nl << be_nl;
+
+ *os << "#if defined (__ACE_INLINE__)" << be_nl << be_nl
+ << be_global->core_versioning_begin () << be_nl
+ << "namespace CORBA" << be_nl
+ << "{"
+ << be_idt_nl
+ << "extern " << be_global->stub_export_macro () << " void add_ref ("
+ << this->full_name () << " *);" << be_nl
+ << "extern " << be_global->stub_export_macro () << " void remove_ref ("
+ << this->full_name () << " *);"
+ << be_uidt_nl
+ << "}" << be_nl << be_nl
+ << be_global->core_versioning_end () << be_nl
+ << "#endif /*__ACE_INLINE__*/";
+
+ return 0;
+}
+
+
+int
+be_valuetype::gen_helper_stubs (char *, char *)
+{
+ TAO_OutStream *os = tao_cg->client_stubs ();
+
+ *os << be_nl << be_nl << "// TAO_IDL - Generated from" << be_nl
+ << "// " << __FILE__ << ":" << __LINE__ << be_nl << be_nl;
+
+ *os << "void" << be_nl
+ << "CORBA::add_ref (" << this->full_name () << " * vt)" << be_nl
+ << "{" << be_idt_nl
+ << "if (vt != 0)" << be_idt_nl
+ << "{" << be_idt_nl
+ << "vt->_add_ref ();" << be_uidt_nl
+ << "}" << be_uidt << be_uidt_nl
+ << "}" << be_nl << be_nl;
+
+ *os << "void" << be_nl
+ << "CORBA::remove_ref (" << this->full_name () << " * vt)" << be_nl
+ << "{" << be_idt_nl
+ << "if (vt != 0)" << be_idt_nl
+ << "{" << be_idt_nl
+ << "vt->_remove_ref ();" << be_uidt_nl
+ << "}" << be_uidt << be_uidt_nl
+ << "}";
+
+ return 0;
+}
+
+// Generate the forward declarations and static methods used by the
+// interface _var and _out template classes, as well as by the
+// template sequence classes for object references.
+void
+be_valuetype:: gen_var_out_seq_decls (void)
+{
+ if (this->var_out_seq_decls_gen_ == 1)
+ {
+ return;
+ }
+
+ TAO_OutStream *os = tao_cg->client_header ();
+
+ *os << be_nl << be_nl << "// TAO_IDL - Generated from" << be_nl
+ << "// " << __FILE__ << ":" << __LINE__ << be_nl << be_nl;
+
+ // Generate the ifdefined macro for this interface.
+ os->gen_ifdef_macro (this->flat_name (),
+ "var_out");
+
+ const char *lname = this->local_name ();
+
+ *os << be_nl << be_nl
+ << "class " << lname << ";" << be_nl
+ << "typedef" << be_idt_nl
+ << "TAO_Value_Var_T<" << be_idt << be_idt_nl
+ << lname << be_uidt_nl
+ << ">" << be_uidt_nl
+ << lname << "_var;" << be_uidt_nl << be_nl
+ << "typedef" << be_idt_nl
+ << "TAO_Value_Out_T<" << be_idt << be_idt_nl
+ << lname << be_uidt_nl
+ << ">" << be_uidt_nl
+ << lname << "_out;" << be_uidt;
+
+ os->gen_endif ();
+
+ this->var_out_seq_decls_gen_ = 1;
+}
+
+// For building the pre and postfix of private data fields.
+const char *
+be_valuetype::field_pd_prefix (void)
+{
+ return "_pd_";
+}
+
+const char *
+be_valuetype::field_pd_postfix (void)
+{
+ return "";
+}
+
+be_valuetype *
+be_valuetype::statefull_inherit (void)
+{
+ if (this->pd_inherits_concrete != 0)
+ {
+ return be_valuetype::narrow_from_decl (this->pd_inherits_concrete);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+// Accept a visitor.
+int
+be_valuetype::accept (be_visitor *visitor)
+{
+ return visitor->visit_valuetype (this);
+}
+
+void
+be_valuetype::destroy (void)
+{
+ delete [] this->full_obv_skel_name_;
+ this->full_obv_skel_name_ = 0;
+
+ this->be_interface::destroy ();
+ this->AST_ValueType::destroy ();
+}
+
+ACE_CDR::ULong
+be_valuetype::data_members_count (AST_Field::Visibility vis)
+{
+ ACE_CDR::ULong count = 0;
+
+ for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next())
+ {
+ AST_Decl *d = si.item ();
+
+ if (!d)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_valuetype::data_members_count - "
+ "bad node in this scope\n"), 0);
+ }
+
+ AST_Field *field = AST_Field::narrow_from_decl (d);
+
+ if (!field)
+ {
+ continue;
+ }
+
+ if (vis != AST_Field::vis_NA)
+ {
+ if (vis == field->visibility ()) ++count;
+ }
+ else
+ {
+ ++count;
+ }
+ } // end of for loop
+ return count;
+}
+
+bool
+be_valuetype::supports_abstract (void) const
+{
+ return this->supports_abstract_;
+}
+
+// Template method that traverses the inheritance graph in a breadth-first
+// style. The actual work on each element in the inheritance graph is carried
+// out by the function passed as argument.
+int
+be_valuetype::traverse_supports_list_graphs (
+ be_interface::tao_code_emitter gen,
+ TAO_OutStream *os,
+ bool use_abstract_paths,
+ bool use_concrete_paths
+ )
+{
+ bool abstract_paths_only = use_abstract_paths && !use_concrete_paths;
+
+ long n_supports = this->n_supports ();
+
+ if (n_supports == 0)
+ {
+ return 0;
+ }
+
+ // Make sure the queues are empty.
+ this->insert_queue.reset ();
+ this->del_queue.reset ();
+
+ be_interface *supported_interface = 0;
+
+ for (long i = 0; i < n_supports; ++i)
+ {
+ if (! use_abstract_paths
+ && this->pd_supports[i]->is_abstract ())
+ {
+ continue;
+ }
+
+ if (! use_concrete_paths
+ && ! this->pd_supports[i]->is_abstract ())
+ {
+ continue;
+ }
+
+ supported_interface =
+ be_interface::narrow_from_decl (this->pd_supports[i]);
+
+ // Insert a supported interface in the queue.
+ if (this->insert_queue.enqueue_tail (supported_interface) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_valuetype::"
+ "traverse_supports_list_graphs - "
+ "error generating entries\n"),
+ -1);
+ }
+ }
+
+ be_code_emitter_wrapper wrapper (gen);
+
+ return this->traverse_inheritance_graph (wrapper,
+ os,
+ abstract_paths_only);
+}
+
+int
+be_valuetype::traverse_concrete_inheritance_graph (tao_code_emitter gen,
+ TAO_OutStream *os)
+{
+ AST_Interface *supported = this->supports_concrete ();
+
+ if (supported == 0)
+ {
+ return 0;
+ }
+
+ be_interface *concrete = be_interface::narrow_from_decl (supported);
+
+ // Make sure the queues are empty.
+ this->insert_queue.reset ();
+ this->del_queue.reset ();
+
+ // Insert the supported concrete interface in the queue.
+ if (this->insert_queue.enqueue_tail (concrete) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%N:%l) be_valuetype::"
+ "traverse_concrete_inheritance_graph - "
+ "error generating entries\n"),
+ -1);
+ }
+
+ be_code_emitter_wrapper wrapper (gen);
+
+ return this->traverse_inheritance_graph (wrapper,
+ os);
+}
+
+int
+be_valuetype::abstract_supports_helper (be_interface *,
+ be_interface *base,
+ TAO_OutStream *os)
+{
+ *os << "," << be_nl
+ << "public virtual "
+ << base->name ();
+
+ return 0;
+}
+
+int
+be_valuetype::gen_skel_helper (be_interface *concrete,
+ be_interface *ancestor,
+ TAO_OutStream *os)
+{
+ // If derived and ancestor are same, skip it.
+ if (concrete == ancestor)
+ {
+ return 0;
+ }
+
+ // If an operation or an attribute is abstract (declared in an
+ // abstract interface), we will either generate the full
+ // definition (if there are no concrete interfaces between the
+ // abstract ancestor and us) or, if there is a concrete ancestor
+ // in between, we will catch its definition elsewhere in this
+ // traversal.
+ if (ancestor->is_abstract ())
+ {
+ return 0;
+ }
+
+ // Else generate code that does the cast to the appropriate type.
+
+ if (ancestor->nmembers () > 0)
+ {
+ // If there are elements in ancestor scope i.e., any operations and
+ // attributes defined by "ancestor", become methods on the derived class
+ // which call the corresponding method of the base class by doing the
+ // proper casting.
+
+ for (UTL_ScopeActiveIterator si (ancestor, UTL_Scope::IK_decls);
+ !si.is_done ();
+ si.next ())
+ {
+ // Get the next AST decl node
+ AST_Decl *d = si.item ();
+
+ if (d->node_type () == AST_Decl::NT_op)
+ {
+ // Start from current indentation level.
+ os->indent ();
+
+ *os << "// TAO_IDL - Generated from" << be_nl
+ << "// " << __FILE__ << ":" << __LINE__ << be_nl << be_nl;
+
+ if (os->stream_type () == TAO_OutStream::TAO_SVR_HDR)
+ {
+ // Generate the static method corresponding to this method.
+ *os << "static void " << d->local_name ()
+ << "_skel (" << be_idt << be_idt_nl
+ << "TAO_ServerRequest &req, " << be_nl
+ << "void *obj," << be_nl
+ << "void *context" << be_uidt_nl
+ << ");" << be_uidt << "\n\n";
+ }
+ else
+ { // Generate code in the inline file.
+ // Generate the static method corresponding to this method.
+ *os << "ACE_INLINE void "
+ << concrete->full_skel_name () << "::"
+ << d->local_name ()
+ << "_skel (" << be_idt << be_idt_nl
+ << "TAO_ServerRequest &req," << be_nl
+ << "void *obj," << be_nl
+ << "void *context" << be_uidt_nl
+ << ")" << be_uidt_nl
+ << "{" << be_idt_nl;
+ *os << ancestor->full_skel_name ()
+ << "_ptr impl = ("
+ << concrete->full_skel_name ()
+ << "_ptr) obj;" << be_nl;
+ *os << ancestor->full_skel_name ()
+ << "::" << d->local_name ()
+ << "_skel (" << be_idt << be_idt_nl
+ << "req," << be_nl
+ << "(" << ancestor->full_skel_name ()
+ << "_ptr) impl," << be_nl
+ << "context" << be_uidt_nl
+ << ");" << be_uidt << be_uidt_nl
+ << "}\n";
+ }
+ }
+ } // End of scope iterator.
+ }
+
+ return 0;
+}
+
+// Narrowing.
+IMPL_NARROW_METHODS2 (be_valuetype, be_interface, AST_ValueType)
+IMPL_NARROW_FROM_DECL (be_valuetype)
+IMPL_NARROW_FROM_SCOPE (be_valuetype)