diff options
Diffstat (limited to 'TAO/TAO_IDL/ast/ast_interface.cpp')
-rw-r--r-- | TAO/TAO_IDL/ast/ast_interface.cpp | 336 |
1 files changed, 253 insertions, 83 deletions
diff --git a/TAO/TAO_IDL/ast/ast_interface.cpp b/TAO/TAO_IDL/ast/ast_interface.cpp index e39b58ecbc1..6670d175ca5 100644 --- a/TAO/TAO_IDL/ast/ast_interface.cpp +++ b/TAO/TAO_IDL/ast/ast_interface.cpp @@ -81,9 +81,12 @@ trademarks or registered trademarks of Sun Microsystems, Inc. #include "ast_enum.h" #include "ast_enum_val.h" #include "ast_union.h" +#include "ast_union_fwd.h" +#include "ast_structure_fwd.h" #include "ast_native.h" #include "ast_factory.h" #include "ast_visitor.h" +#include "ast_extern.h" #include "utl_err.h" #include "utl_identifier.h" #include "utl_indenter.h" @@ -170,7 +173,7 @@ AST_Interface::be_replace_operation (AST_Decl *old_op, void AST_Interface::be_add_operation (AST_Operation *op) { - fe_add_operation (op); + this->fe_add_operation (op); } // Add an AST_Constant node (a constant declaration) to this scope. @@ -445,42 +448,66 @@ AST_Interface::fe_add_operation (AST_Operation *t) AST_Structure * AST_Interface::fe_add_structure (AST_Structure *t) { - AST_Decl *d = 0; + AST_Decl *predef = 0; + AST_StructureFwd *fwd = 0; - // Can't add to interface which was not yet defined. - if (!this->is_defined ()) + if ((predef = this->lookup_for_add (t, I_FALSE)) != 0) { - idl_global->err ()->error2 (UTL_Error::EIDL_DECL_NOT_DEFINED, - this, - t); - return 0; - } + // Treat fwd declared interfaces specially + if (predef->node_type () == AST_Decl::NT_struct_fwd) + { + fwd = AST_StructureFwd::narrow_from_decl (predef); - // Already defined and cannot be redefined? Or already used? - if ((d = this->lookup_for_add (t, I_FALSE)) != 0) - { - if (!can_be_redefined (d)) + if (fwd == 0) + { + return 0; + } + + // Forward declared and not defined yet. + if (!fwd->is_defined ()) + { + if (fwd->defined_in () == this) + { + fwd->set_full_definition (t); + } + else + { + idl_global->err ()->error3 (UTL_Error::EIDL_SCOPE_CONFLICT, + fwd, + t, + this); + + return 0; + } + } + // OK, not illegal redef of forward declaration. Now check whether. + // it has been referenced already. + else if (this->referenced (predef, t->local_name ())) + { + idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE, + t, + this, + predef); + + return 0; + } + } + else if (!can_be_redefined (predef)) { idl_global->err ()->error3 (UTL_Error::EIDL_REDEF, t, this, - d); + predef); + return 0; } - - if (this->referenced (d, t->local_name ())) + else if (referenced (predef, t->local_name ()) && !t->is_defined ()) { idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE, t, this, - d); - return 0; - } + predef); - if (t->has_ancestor (d)) - { - idl_global->err ()->redefinition_in_scope (t, - d); return 0; } } @@ -496,6 +523,84 @@ AST_Interface::fe_add_structure (AST_Structure *t) return t; } +// Add this AST_StructureFwd node (a forward declaration of an IDL +// struct) to this scope. +AST_StructureFwd * +AST_Interface::fe_add_structure_fwd (AST_StructureFwd *t) +{ + AST_Decl *d = 0; + + // Already defined and cannot be redefined? Or already used? + if ((d = this->lookup_for_add (t, I_FALSE)) != 0) + { + AST_Decl::NodeType nt = d->node_type (); + + // There used to be another check here ANDed with the one below: + // d->defined_in () == this. But lookup_for_add() calls only + // lookup_by_name_local(), which does not bump up the scope. + if (nt == AST_Decl::NT_struct_fwd) + { + // It's legal to forward declare something more than once, + // but we need only one entry in the scope for lookup. + AST_StructureFwd *fd = AST_StructureFwd::narrow_from_decl (d); + t->destroy (); + delete t; + t = 0; + return fd; + } + else if (nt == AST_Decl::NT_struct) + { + AST_Structure *s = AST_Structure::narrow_from_decl (d); + t->set_full_definition (s); + + if (t->added () == 0) + { + t->set_added (1); + this->add_to_scope (t); + + // Must check later that all struct and union forward declarations + // are defined in the same IDL file. + AST_record_fwd_decl (t); + } + + return t; + } + else + { + if (!can_be_redefined (d)) + { + idl_global->err ()->error3 (UTL_Error::EIDL_REDEF, + t, + this, + d); + return 0; + } + + if (this->referenced (d, t->local_name ())) + { + idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE, + t, + this, + d); + return 0; + } + } + } + + // Add it to scope + this->add_to_scope (t); + + // Add it to set of locally referenced symbols + this->add_to_referenced (t, + I_FALSE, + t->local_name ()); + + // Must check later that all struct and union forward declarations + // are defined in the same IDL file. + AST_record_fwd_decl (t); + return t; +} + // Add an AST_Enum node (an enum declaration) to this scope. AST_Enum * AST_Interface::fe_add_enum (AST_Enum *t) @@ -555,42 +660,66 @@ AST_Interface::fe_add_enum (AST_Enum *t) AST_Union * AST_Interface::fe_add_union (AST_Union *t) { - AST_Decl *d = 0; + AST_Decl *predef = 0; + AST_UnionFwd *fwd = 0; - // Can't add to interface which was not yet defined. - if (!this->is_defined ()) + if ((predef = this->lookup_for_add (t, I_FALSE)) != 0) { - idl_global->err ()->error2 (UTL_Error::EIDL_DECL_NOT_DEFINED, - this, - t); - return 0; - } + // Treat fwd declared interfaces specially + if (predef->node_type () == AST_Decl::NT_union_fwd) + { + fwd = AST_UnionFwd::narrow_from_decl (predef); - // Already defined and cannot be redefined? Or already used? - if ((d = this->lookup_for_add (t, I_FALSE)) != 0) - { - if (!can_be_redefined (d)) + if (fwd == 0) + { + return 0; + } + + // Forward declared and not defined yet. + if (!fwd->is_defined ()) + { + if (fwd->defined_in () == this) + { + fwd->set_full_definition (t); + } + else + { + idl_global->err ()->error3 (UTL_Error::EIDL_SCOPE_CONFLICT, + fwd, + t, + this); + + return 0; + } + } + // OK, not illegal redef of forward declaration. Now check whether. + // it has been referenced already. + else if (this->referenced (predef, t->local_name ())) + { + idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE, + t, + this, + predef); + + return 0; + } + } + else if (!can_be_redefined (predef)) { idl_global->err ()->error3 (UTL_Error::EIDL_REDEF, t, this, - d); + predef); + return 0; } - - if (this->referenced (d, t->local_name ())) + else if (referenced (predef, t->local_name ()) && !t->is_defined ()) { idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE, t, this, - d); - return 0; - } + predef); - if (t->has_ancestor (d)) - { - idl_global->err ()->redefinition_in_scope (t, - d); return 0; } } @@ -606,6 +735,84 @@ AST_Interface::fe_add_union (AST_Union *t) return t; } +// Add this AST_UnionFwd node (a forward declaration of an IDL +// union) to this scope. +AST_UnionFwd * +AST_Interface::fe_add_union_fwd (AST_UnionFwd *t) +{ + AST_Decl *d = 0; + + // Already defined and cannot be redefined? Or already used? + if ((d = this->lookup_for_add (t, I_FALSE)) != 0) + { + AST_Decl::NodeType nt = d->node_type (); + + // There used to be another check here ANDed with the one below: + // d->defined_in () == this. But lookup_for_add() calls only + // lookup_by_name_local(), which does not bump up the scope. + if (nt == AST_Decl::NT_union_fwd) + { + // It's legal to forward declare something more than once, + // but we need only one entry in the scope for lookup. + AST_UnionFwd *fd = AST_UnionFwd::narrow_from_decl (d); + t->destroy (); + delete t; + t = 0; + return fd; + } + else if (nt == AST_Decl::NT_union) + { + AST_Union *s = AST_Union::narrow_from_decl (d); + t->set_full_definition (s); + + if (t->added () == 0) + { + t->set_added (1); + this->add_to_scope (t); + + // Must check later that all struct and union forward declarations + // are defined in the same IDL file. + AST_record_fwd_decl (t); + } + + return t; + } + else + { + if (!can_be_redefined (d)) + { + idl_global->err ()->error3 (UTL_Error::EIDL_REDEF, + t, + this, + d); + return 0; + } + + if (this->referenced (d, t->local_name ())) + { + idl_global->err ()->error3 (UTL_Error::EIDL_DEF_USE, + t, + this, + d); + return 0; + } + } + } + + // Add it to scope + this->add_to_scope (t); + + // Add it to set of locally referenced symbols + this->add_to_referenced (t, + I_FALSE, + t->local_name ()); + + // Must check later that all struct and union forward declarations + // are defined in the same IDL file. + AST_record_fwd_decl (t); + return t; +} + // Add an AST_EnumVal node (an enumerator) to this scope. // This is done to conform to the C++ scoping rules which declare // enumerators in the enclosing scope (in addition to declaring them @@ -935,8 +1142,7 @@ AST_Interface::fwd_redefinition_helper (AST_Interface *&i, // a new pointer in created, and the first term below will be // true. In that case, the scoped names must be compared. if (fd->defined_in () != s - && !AST_Interface::compare_names (fd, - i)) + && i->name ()->compare (fd->name ()) != 0) { idl_global->err ()->error2 (UTL_Error::EIDL_SCOPE_CONFLICT, i, @@ -1044,42 +1250,6 @@ AST_Interface::set_n_inherits_flat (long i) this->pd_n_inherits_flat = i; } -// Get the scoped names and, if they are the same -// length, iterate over them, comparing each term. -idl_bool -AST_Interface::compare_names (AST_Interface *that, - AST_Interface *other) -{ - UTL_ScopedName *that_name = that->name (); - UTL_ScopedName *other_name = other->name (); - - long that_length = that_name->length (); - - if (that_length != other_name->length ()) - { - return I_FALSE; - } - - Identifier *that_id = 0; - Identifier *other_id = 0; - - for (UTL_IdListActiveIterator that_iter (that_name), other_iter (other_name); - !that_iter.is_done (); - that_iter.next (), other_iter.next ()) - { - that_id = that_iter.item (); - other_id = other_iter.item (); - - if (ACE_OS::strcmp (that_id->get_string (), - other_id->get_string ())) - { - return I_FALSE; - } - } - - return I_TRUE; -} - void AST_Interface::inherited_name_clash (void) { |