Merge pull request #1844 from jrw972/monterey
[ACE_TAO.git] / TAO / TAO_IDL / ast / ast_structure.cpp
blob46257ee4215d0395c8a99cc1a22052a2da9f2e9a
1 /*
3 COPYRIGHT
5 Copyright 1992, 1993, 1994 Sun Microsystems, Inc. Printed in the United
6 States of America. All Rights Reserved.
8 This product is protected by copyright and distributed under the following
9 license restricting its use.
11 The Interface Definition Language Compiler Front End (CFE) is made
12 available for your use provided that you include this license and copyright
13 notice on all media and documentation and the software program in which
14 this product is incorporated in whole or part. You may copy and extend
15 functionality (but may not remove functionality) of the Interface
16 Definition Language CFE without charge, but you are not authorized to
17 license or distribute it to anyone else except as part of a product or
18 program developed by you or with the express written consent of Sun
19 Microsystems, Inc. ("Sun").
21 The names of Sun Microsystems, Inc. and any of its subsidiaries or
22 affiliates may not be used in advertising or publicity pertaining to
23 distribution of Interface Definition Language CFE as permitted herein.
25 This license is effective until terminated by Sun for failure to comply
26 with this license. Upon termination, you shall destroy or return all code
27 and documentation for the Interface Definition Language CFE.
29 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED AS IS WITH NO WARRANTIES OF
30 ANY KIND INCLUDING THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR ARISING FROM A COURSE OF
32 DEALING, USAGE OR TRADE PRACTICE.
34 INTERFACE DEFINITION LANGUAGE CFE IS PROVIDED WITH NO SUPPORT AND WITHOUT
35 ANY OBLIGATION ON THE PART OF Sun OR ANY OF ITS SUBSIDIARIES OR AFFILIATES
36 TO ASSIST IN ITS USE, CORRECTION, MODIFICATION OR ENHANCEMENT.
38 SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES SHALL HAVE NO LIABILITY WITH
39 RESPECT TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY
40 INTERFACE DEFINITION LANGUAGE CFE OR ANY PART THEREOF.
42 IN NO EVENT WILL SUN OR ANY OF ITS SUBSIDIARIES OR AFFILIATES BE LIABLE FOR
43 ANY LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
44 DAMAGES, EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
46 Use, duplication, or disclosure by the government is subject to
47 restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
48 Technical Data and Computer Software clause at DFARS 252.227-7013 and FAR
49 52.227-19.
51 Sun, Sun Microsystems and the Sun logo are trademarks or registered
52 trademarks of Sun Microsystems, Inc.
54 SunSoft, Inc.
55 2550 Garcia Avenue
56 Mountain View, California 94043
58 NOTE:
60 SunOS, SunSoft, Sun, Solaris, Sun Microsystems or the Sun logo are
61 trademarks or registered trademarks of Sun Microsystems, Inc.
65 // AST_Structure nodes denote IDL struct declarations.
66 // AST_Structure is a subclass of AST_ConcreteType and of UTL_Scope (the
67 // structure's fields are managed in a scope).
69 #include "ast_union.h"
70 #include "ast_structure_fwd.h"
71 #include "ast_field.h"
72 #include "ast_enum.h"
73 #include "ast_enum_val.h"
74 #include "ast_typedef.h"
75 #include "ast_visitor.h"
77 #include "utl_string.h"
78 #include "utl_err.h"
79 #include "utl_indenter.h"
80 #include "utl_identifier.h"
82 #include "ace/Truncate.h"
84 AST_Structure::AST_Structure (UTL_ScopedName *n,
85 bool local,
86 bool abstract)
87 : COMMON_Base (local,
88 abstract),
89 AST_Decl (AST_Decl::NT_struct,
90 n),
91 AST_Type (AST_Decl::NT_struct,
92 n),
93 AST_ConcreteType (AST_Decl::NT_struct,
94 n),
95 UTL_Scope (AST_Decl::NT_struct),
96 member_count_ (-1),
97 local_struct_ (-1),
98 fwd_decl_ (0)
102 AST_Structure::AST_Structure (AST_Decl::NodeType nt,
103 UTL_ScopedName *n,
104 bool local,
105 bool abstract)
106 : COMMON_Base (local,
107 abstract),
108 AST_Decl (nt,
110 AST_Type (nt,
112 AST_ConcreteType (nt,
114 UTL_Scope (nt),
115 member_count_ (-1),
116 local_struct_ (-1),
117 fwd_decl_ (0)
121 AST_Structure::~AST_Structure (void)
123 destroy ();
126 // Are we or the parameter node involved in any recursion?
127 bool
128 AST_Structure::in_recursion (ACE_Unbounded_Queue<AST_Type *> &list)
130 bool self_test = (list.size () == 0);
132 // We should calculate this only once. If it has already been
133 // done, just return it.
134 if (self_test && this->in_recursion_ != -1)
136 return (this->in_recursion_ == 1);
139 if (list.size () > 1)
141 if (match_names (this, list))
143 // We've found ourselves outside of a sequence.
144 // This happens when we are not recursed ourselves but instead
145 // are part of another recursed type which is part of us.
146 // f.i. union containing sequence of struct containing the union as member.
147 return false;
151 list.enqueue_tail(this);
153 // Proceed if the number of members in our scope is greater than 0.
154 if (this->nmembers () > 0)
156 // Initialize an iterator to iterate over our scope.
157 // Continue until each element is visited.
158 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
159 !si.is_done ();
160 si.next ())
162 AST_Field *field = dynamic_cast<AST_Field*> (si.item ());
164 if (field == 0)
165 // This will be an enum value or other legitimate non-field
166 // member - in any case, no recursion.
168 continue;
171 AST_Type *type = field->field_type ();
173 if (type->node_type () == AST_Decl::NT_typedef)
175 AST_Typedef *td = dynamic_cast<AST_Typedef*> (type);
176 type = td->primitive_base_type ();
179 if (type == 0)
181 ACE_ERROR_RETURN ((LM_ERROR,
182 ACE_TEXT ("(%N:%l) AST_Structure::")
183 ACE_TEXT ("in_recursion - ")
184 ACE_TEXT ("bad field type\n")),
188 if (type->in_recursion (list))
190 if (self_test)
191 this->in_recursion_ = 1;
192 idl_global->recursive_type_seen_ = true;
193 return true;
198 // Not in recursion.
199 if (self_test)
200 this->in_recursion_ = 0;
201 return false;
205 AST_Structure::member_count (void)
207 if (this->member_count_ == -1)
209 this->compute_member_count ();
212 return this->member_count_;
215 ACE_CDR::ULong
216 AST_Structure::nfields (void) const
218 return ACE_Utils::truncate_cast<ACE_CDR::ULong> (this->fields_.size ());
222 AST_Structure::field (AST_Field **&result,
223 ACE_CDR::ULong slot) const
225 return this->fields_.get (result, slot);
228 bool
229 AST_Structure::is_local (void)
231 if (this->local_struct_ == -1)
233 if (this->is_local_)
235 this->local_struct_ = this->is_local_;
237 else
239 this->local_struct_ = 0;
241 if (this->nmembers () > 0)
243 // Instantiate a scope iterator.
244 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
245 !si.is_done ();
246 si.next ())
248 if (si.item ()->is_local ())
250 this->local_struct_ = true;
251 break;
258 return this->local_struct_;
262 AST_Structure::contains_wstring (void)
264 if (this->contains_wstring_ == -1)
266 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
267 !si.is_done ();
268 si.next ())
270 if (si.item ()->contains_wstring () == 1)
272 this->contains_wstring_ = 1;
273 return this->contains_wstring_;
277 this->contains_wstring_ = 0;
280 return this->contains_wstring_;
283 bool
284 AST_Structure::is_defined (void)
286 return 0 == this->fwd_decl_ || this->fwd_decl_->is_defined ();
289 bool
290 AST_Structure::legal_for_primary_key (void) const
292 bool retval = true;
294 if (!this->recursing_in_legal_pk_)
296 this->recursing_in_legal_pk_ = true;
298 for (UTL_ScopeActiveIterator si (const_cast<AST_Structure *> (this),
299 UTL_Scope::IK_decls);
300 !si.is_done ();
301 si.next ())
303 AST_Field *f = dynamic_cast<AST_Field*> (si.item ());
305 if (f != 0 && !f->field_type ()->legal_for_primary_key ())
307 retval = false;
308 break;
312 this->recursing_in_legal_pk_ = false;
315 return retval;
318 AST_StructureFwd *
319 AST_Structure::fwd_decl (void) const
321 return this->fwd_decl_;
324 void
325 AST_Structure::fwd_decl (AST_StructureFwd *node)
327 this->fwd_decl_ = node;
330 ACE_Unbounded_Queue<AST_Field *> &
331 AST_Structure::fields (void)
333 return this->fields_;
336 // Private operations.
338 AST_Field *
339 AST_Structure::fe_add_field (AST_Field *t)
341 return this->fe_add_ref_decl (t);
344 AST_Structure *
345 AST_Structure::fe_add_structure (AST_Structure *t)
347 return this->fe_add_full_struct_type (t);
350 AST_Union *
351 AST_Structure::fe_add_union (AST_Union *t)
353 return dynamic_cast<AST_Union*> (this->fe_add_full_struct_type (t));
356 AST_Enum *
357 AST_Structure::fe_add_enum (AST_Enum *t)
359 return dynamic_cast<AST_Enum*> (this->fe_add_decl (t));
362 // Add this AST_EnumVal node (an enumerator declaration) to this scope.
363 // This is done to conform to the C++ scoping rules which declare
364 // enumerators in the enclosing scope (in addition to declaring them
365 // in the enum itself).
366 AST_EnumVal *
367 AST_Structure::fe_add_enum_val (AST_EnumVal *t)
369 return dynamic_cast<AST_EnumVal*> (this->fe_add_decl (t));
372 // Compute total number of members.
374 AST_Structure::compute_member_count (void)
376 this->member_count_ = 0;
378 // If there are elements in this scope.
379 if (this->nmembers () > 0)
381 // Instantiate a scope iterator.
382 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
383 !si.is_done ();
384 si.next ())
386 ++this->member_count_;
390 return 0;
393 // Dump this AST_Structure node to the ostream o.
394 void
395 AST_Structure::dump (ACE_OSTREAM_TYPE &o)
397 if (this->is_local ())
399 this->dump_i (o, "(local) ");
402 this->dump_i (o, "struct ");
403 AST_Decl::dump (o);
404 this->dump_i (o, " {\n");
405 UTL_Scope::dump (o);
406 idl_global->indent ()->skip_to (o);
407 this->dump_i (o, "}");
410 // This serves for structs and unions.
411 void
412 AST_Structure::fwd_redefinition_helper (AST_Structure *&i,
413 UTL_Scope *s)
415 if (i == 0)
417 return;
420 // Fwd redefinition should be in the same scope, so local
421 // lookup is all that's needed.
422 AST_Decl *d =
423 s->lookup_by_name_local (i->local_name (), false);
425 AST_Structure *fd = 0;
427 if (d != 0)
429 // Full definition must have the same prefix as the forward declaration.
430 if (ACE_OS::strcmp (i->prefix (), d->prefix ()) != 0)
432 idl_global->err ()->error1 (UTL_Error::EIDL_PREFIX_CONFLICT,
435 return;
438 AST_Decl::NodeType nt = d->node_type ();
440 // If this interface has been forward declared in a previous opening
441 // of the module it's defined in, the lookup will find the
442 // forward declaration.
443 if (nt == AST_Decl::NT_struct_fwd
444 || nt == AST_Decl::NT_union_fwd)
446 AST_StructureFwd *fwd_def =
447 dynamic_cast<AST_StructureFwd*> (d);
449 fd = fwd_def->full_definition ();
451 // In all other cases, the lookup will find an interface node.
452 else if (nt == AST_Decl::NT_struct
453 || nt == AST_Decl::NT_union)
455 fd = dynamic_cast<AST_Structure*> (d);
458 // Successful?
459 if (fd == 0)
461 // Should we give an error here?
462 // No, look in fe_add_interface.
464 // If it is a forward declared interface..
465 else if (!fd->is_defined ())
467 // Check if redefining in same scope. If a module is reopened,
468 // a new pointer in created, and the first term below will be
469 // true. In that case, the scoped names must be compared.
470 if (fd->defined_in () != s
471 && i->name ()->compare (fd->name ()) != 0)
473 idl_global->err ()->error2 (UTL_Error::EIDL_SCOPE_CONFLICT,
475 fd);
477 // All OK, do the redefinition.
478 else
480 AST_Decl::NodeType fd_nt = fd->node_type ();
481 AST_Decl::NodeType i_nt = i->node_type ();
483 // Only redefinition of the same kind.
484 if (i_nt != fd_nt)
486 idl_global->err ()->error2 (UTL_Error::EIDL_REDEF,
488 fd);
489 return;
492 fd->redefine (i);
493 AST_StructureFwd *fwd = fd->fwd_decl ();
495 if (0 != fwd)
497 // So the fwd decl won't destroy us at cleanup time.
498 // Unlike interfaces, valuetypes and components, it's
499 // ok to do this here, since fwd declared structs
500 // and unions must be defined in the same translation
501 // unit.
502 fwd->set_as_defined ();
505 // Use full definition node.
506 i->destroy ();
507 delete i;
508 i = fd;
514 // This serves only for structs. It is overridden for unions.
515 void
516 AST_Structure::redefine (AST_Structure *from)
518 // We've already checked for inconsistent prefixes.
519 this->prefix (from->prefix ());
521 this->set_defined_in (from->defined_in ());
522 this->set_imported (idl_global->imported ());
523 this->set_in_main_file (idl_global->in_main_file ());
524 this->set_line (idl_global->lineno ());
525 this->set_file_name (idl_global->filename ()->get_string ());
526 this->ifr_added_ = from->ifr_added_;
527 this->ifr_fwd_added_ = from->ifr_fwd_added_;
528 this->fields_ = from->fields_;
529 this->member_count_ = from->member_count_;
530 this->local_struct_ = from->local_struct_;
533 // Compute the size type of the node in question.
535 AST_Structure::compute_size_type (void)
537 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
538 !si.is_done ();
539 si.next ())
541 // Get the next AST decl node.
542 AST_Decl *d = si.item ();
544 if (d->node_type () == AST_Decl::NT_enum_val)
546 continue;
549 AST_Field *f = dynamic_cast<AST_Field*> (d);
550 AST_Type *t = f->field_type ();
552 if (t != 0)
554 this->size_type (t->size_type ());
556 // While we're iterating, we might as well do this one too.
557 this->has_constructor (t->has_constructor ());
559 else
561 ACE_DEBUG ((LM_DEBUG,
562 "WARNING (%N:%l) be_structure::compute_size_type - "
563 "dynamic_cast returned 0\n"));
567 return 0;
571 AST_Structure::ast_accept (ast_visitor *visitor)
573 return visitor->visit_structure (this);
576 void
577 AST_Structure::destroy (void)
579 this->AST_ConcreteType::destroy ();
580 this->UTL_Scope::destroy ();
583 IMPL_NARROW_FROM_DECL(AST_Structure)
584 IMPL_NARROW_FROM_SCOPE(AST_Structure)
586 bool AST_Structure::annotatable () const
588 return true;
591 AST_Decl *
592 AST_Structure::operator[] (const size_t index)
594 size_t count = member_count_ <= 0 ? 0 : member_count_;
595 if (index >= count)
597 return 0;
599 size_t i = 0;
600 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
601 !si.is_done ();
602 si.next ())
604 if (i == index)
606 return si.item ();
608 i++;
610 return 0;
613 AST_Decl *
614 AST_Structure::operator[] (const char* name)
616 for (UTL_ScopeActiveIterator si (this, UTL_Scope::IK_decls);
617 !si.is_done ();
618 si.next ())
620 AST_Decl *field = si.item ();
621 const char *field_name = field->local_name ()->get_string ();
622 if (!ACE_OS::strcmp (name, field_name)) {
623 return field;
626 return 0;