Merge pull request #1551 from DOCGroup/plm_jira_333
[ACE_TAO.git] / TAO / TAO_IDL / fe / fe_utils.cpp
blob32ab27879db7ef640357b9163442f834123a4f1a
1 #include "fe_utils.h"
2 #include "fe_private.h"
3 #include "fe_extern.h"
5 #include "ast_uses.h"
6 #include "ast_component.h"
7 #include "ast_generator.h"
8 #include "ast_root.h"
9 #include "ast_structure.h"
10 #include "ast_valuetype.h"
11 #include "ast_sequence.h"
12 #include "ast_template_module.h"
14 #include "global_extern.h"
16 #include "utl_scoped_name.h"
17 #include "utl_strlist.h"
18 #include "utl_namelist.h"
19 #include "utl_identifier.h"
20 #include "utl_string.h"
22 #include "ace/OS_NS_strings.h"
23 #include "ace/OS_NS_ctype.h"
24 #include "ace/OS_NS_stdio.h"
25 #include "ace/OS_NS_unistd.h"
27 FE_Utils::T_Param_Info::T_Param_Info (void)
28 : type_ (AST_Decl::NT_fixed),
29 const_type_ (AST_Expression::EV_none),
30 enum_const_type_decl_ (0)
34 bool
35 FE_Utils::duplicate_param_id (T_PARAMLIST_INFO *params)
37 size_t cur_pos = 0UL;
38 size_t size = params->size ();
40 for (FE_Utils::T_PARAMLIST_INFO::CONST_ITERATOR i (*params);
41 !i.done ();
42 i.advance (), ++cur_pos)
44 FE_Utils::T_Param_Info *this_one = 0;
45 FE_Utils::T_Param_Info *that_one = 0;
47 i.next (this_one);
49 for (size_t j = cur_pos + 1; j < size; ++j)
51 params->get (that_one, j);
53 if (this_one->name_ == that_one->name_)
55 return true;
60 return false;
63 void
64 FE_Utils::T_ARGLIST::destroy (void)
66 AST_Decl **d = 0;
68 for (T_ARGLIST::ITERATOR i (this->begin ());
69 !i.done ();
70 i.advance ())
72 i.next (d);
73 /// This is a problem - nodes that aren't NT_const have
74 /// already been destroyed. Must find some other way of
75 /// ferreting out the NT_const arglist nodes.
77 // These were created on the fly and not part of any scope
78 // so we manage their lifetime here.
79 AST_Decl *tmp = *d;
80 if (tmp->node_type () == AST_Decl::NT_const)
82 tmp->destroy ();
83 delete tmp;
84 tmp = 0;
85 } */
90 * Convert a PredefinedType to an ExprType
92 AST_Expression::ExprType
93 FE_Utils::PredefinedTypeToExprType (
94 AST_PredefinedType::PredefinedType pt)
96 switch (pt)
98 case AST_PredefinedType::PT_long:
99 return AST_Expression::EV_long;
100 case AST_PredefinedType::PT_ulong:
101 return AST_Expression::EV_ulong;
102 case AST_PredefinedType::PT_short:
103 return AST_Expression::EV_short;
104 case AST_PredefinedType::PT_ushort:
105 return AST_Expression::EV_ushort;
106 case AST_PredefinedType::PT_longlong:
107 return AST_Expression::EV_longlong;
108 case AST_PredefinedType::PT_ulonglong:
109 return AST_Expression::EV_ulonglong;
110 case AST_PredefinedType::PT_float:
111 return AST_Expression::EV_float;
112 case AST_PredefinedType::PT_double:
113 return AST_Expression::EV_double;
114 case AST_PredefinedType::PT_longdouble:
115 return AST_Expression::EV_longdouble;
116 case AST_PredefinedType::PT_char:
117 return AST_Expression::EV_char;
118 case AST_PredefinedType::PT_wchar:
119 return AST_Expression::EV_wchar;
120 case AST_PredefinedType::PT_octet:
121 return AST_Expression::EV_octet;
122 case AST_PredefinedType::PT_boolean:
123 return AST_Expression::EV_bool;
124 case AST_PredefinedType::PT_void:
125 return AST_Expression::EV_void;
126 default:
127 return AST_Expression::EV_enum;
131 AST_PredefinedType::PredefinedType
132 FE_Utils::ExprTypeToPredefinedType (AST_Expression::ExprType et)
134 switch (et)
136 case AST_Expression::EV_short:
137 return AST_PredefinedType::PT_short;
138 case AST_Expression::EV_ushort:
139 return AST_PredefinedType::PT_ushort;
140 case AST_Expression::EV_long:
141 return AST_PredefinedType::PT_long;
142 case AST_Expression::EV_ulong:
143 return AST_PredefinedType::PT_ulong;
144 case AST_Expression::EV_longlong:
145 return AST_PredefinedType::PT_longlong;
146 case AST_Expression::EV_ulonglong:
147 return AST_PredefinedType::PT_ulonglong;
148 case AST_Expression::EV_float:
149 return AST_PredefinedType::PT_float;
150 case AST_Expression::EV_double:
151 return AST_PredefinedType::PT_double;
152 case AST_Expression::EV_longdouble:
153 return AST_PredefinedType::PT_longdouble;
154 case AST_Expression::EV_char:
155 return AST_PredefinedType::PT_char;
156 case AST_Expression::EV_wchar:
157 return AST_PredefinedType::PT_wchar;
158 case AST_Expression::EV_octet:
159 return AST_PredefinedType::PT_octet;
160 case AST_Expression::EV_bool:
161 return AST_PredefinedType::PT_boolean;
162 case AST_Expression::EV_any:
163 return AST_PredefinedType::PT_any;
164 case AST_Expression::EV_object:
165 return AST_PredefinedType::PT_object;
166 case AST_Expression::EV_void:
167 return AST_PredefinedType::PT_void;
168 case AST_Expression::EV_enum:
169 case AST_Expression::EV_string:
170 case AST_Expression::EV_wstring:
171 case AST_Expression::EV_none:
172 default:
173 ACE_ERROR ((LM_ERROR,
174 ACE_TEXT ("FE_Utils::ExprTypeToPredefinedType - ")
175 ACE_TEXT ("no pathing PredefinedType enum value\n")));
177 /// A deliberately odd return value, so the caller can check
178 /// it and take further action if necessary.
179 return AST_PredefinedType::PT_pseudo;
183 UTL_ScopedName *
184 FE_Utils::string_to_scoped_name (const char *s)
186 UTL_ScopedName *retval = 0;
187 ACE_CString str (s);
188 Identifier *id = 0;
189 UTL_ScopedName *sn = 0;
191 while (! str.empty ())
193 // Skip a leading double colon.
194 if (str.find (':') == 0)
196 str = str.substr (2);
199 // Find the next double colon (if any) and get the next
200 // name segment.
201 ACE_CString::size_type pos = str.find (':');
202 ACE_CString lname (str.substr (0, pos));
204 // Construct a UTL_ScopedName segment.
205 ACE_NEW_RETURN (id,
206 Identifier (lname.c_str ()),
209 ACE_NEW_RETURN (sn,
210 UTL_ScopedName (id, 0),
213 // Either make it the head of a new list or the tail of
214 // an existing one.
215 if (retval == 0)
217 retval = sn;
219 else
221 retval->nconc (sn);
224 // Update the working string.
225 str = str.substr (pos);
228 return retval;
231 const char *
232 FE_Utils::stripped_preproc_include (const char *name)
234 // Some preprocessors prepend "./" to filenames in the
235 // working directory, some others prepend ".\". If either
236 // of these are here, we want to strip them.
237 if (name[0] == '.')
239 if (name[1] == '\\' || name[1] == '/')
241 return name + 2;
245 return name;
248 void
249 FE_Utils::create_uses_multiple_stuff (AST_Component *c,
250 AST_Uses *u,
251 const char *prefix)
253 ACE_CString struct_name (prefix);
255 if (!struct_name.empty ())
257 struct_name += '_';
260 struct_name += u->local_name ()->get_string ();
261 struct_name += "Connection";
262 Identifier struct_id (struct_name.c_str ());
263 UTL_ScopedName sn (&struct_id, 0);
265 // In case this call comes from the backend. We
266 // will pop the scope before returning.
267 idl_global->scopes ().push (c);
269 AST_Structure *connection =
270 idl_global->gen ()->create_structure (&sn, 0, 0);
272 struct_id.destroy ();
274 /// If the field type is a param holder, we want
275 /// to use the lookup to create a fresh one,
276 /// since the field will own it and destroy it.
277 UTL_ScopedName *fn = u->uses_type ()->name ();
278 AST_Decl *d =
279 idl_global->root ()->lookup_by_name (fn, true, false);
280 AST_Type *ft = dynamic_cast<AST_Type*> (d);
282 Identifier object_id ("objref");
283 UTL_ScopedName object_name (&object_id,
285 AST_Field *object_field =
286 idl_global->gen ()->create_field (ft,
287 &object_name,
288 AST_Field::vis_NA);
289 (void) DeclAsScope (connection)->fe_add_field (object_field);
290 object_id.destroy ();
292 Identifier local_id ("Cookie");
293 UTL_ScopedName local_name (&local_id,
295 Identifier module_id ("Components");
296 UTL_ScopedName scoped_name (&module_id,
297 &local_name);
299 d = c->lookup_by_name (&scoped_name, true);
300 local_id.destroy ();
301 module_id.destroy ();
303 if (d == 0)
305 // This would happen if we haven't included Components.idl.
306 idl_global->err ()->lookup_error (&scoped_name);
307 return;
310 AST_ValueType *cookie = dynamic_cast<AST_ValueType*> (d);
312 Identifier cookie_id ("ck");
313 UTL_ScopedName cookie_name (&cookie_id,
315 AST_Field *cookie_field =
316 idl_global->gen ()->create_field (cookie,
317 &cookie_name,
318 AST_Field::vis_NA);
319 (void) DeclAsScope (connection)->fe_add_field (cookie_field);
320 cookie_id.destroy ();
322 (void) c->fe_add_structure (connection);
324 ACE_CDR::ULong bound = 0;
325 AST_Expression *bound_expr =
326 idl_global->gen ()->create_expr (bound,
327 AST_Expression::EV_ulong);
328 AST_Sequence *sequence =
329 idl_global->gen ()->create_sequence (bound_expr,
330 connection,
335 ACE_CString seq_string (struct_name);
336 seq_string += 's';
337 Identifier seq_id (seq_string.c_str ());
338 UTL_ScopedName seq_name (&seq_id,
340 AST_Typedef *connections =
341 idl_global->gen ()->create_typedef (sequence,
342 &seq_name,
345 seq_id.destroy ();
347 (void) c->fe_add_typedef (connections);
349 // In case this call comes from the backend.
350 idl_global->scopes ().pop ();
353 void
354 FE_Utils::create_implied_ami_uses_stuff (void)
356 if (idl_global->included_ami_receps_done ())
358 return;
361 for (ACE_Unbounded_Queue<char *>::CONST_ITERATOR i (
362 idl_global->included_ami_recep_names ());
363 ! i.done ();
364 i.advance ())
366 char **item = 0;
367 i.next (item);
369 UTL_ScopedName *sn =
370 FE_Utils::string_to_scoped_name (*item);
372 AST_Decl *d =
373 idl_global->root ()->lookup_by_name (sn, true);
375 if (d == 0)
377 idl_global->err ()->lookup_error (sn);
379 sn->destroy ();
380 delete sn;
381 sn = 0;
383 continue;
386 sn->destroy ();
387 delete sn;
388 sn = 0;
390 AST_Uses *u = dynamic_cast<AST_Uses*> (d);
392 if (u == 0)
394 ACE_ERROR ((LM_ERROR,
395 ACE_TEXT ("idl_global::create_")
396 ACE_TEXT ("implied_ami_uses_stuff - ")
397 ACE_TEXT ("narrow to receptacle ")
398 ACE_TEXT ("failed\n")));
400 continue;
403 if (!u->is_multiple ())
405 continue;
408 AST_Component *c =
409 dynamic_cast<AST_Component*> (u->defined_in ());
411 if (c == 0)
413 ACE_ERROR ((LM_ERROR,
414 ACE_TEXT ("idl_global::create_")
415 ACE_TEXT ("implied_ami_uses_stuff - ")
416 ACE_TEXT ("receptacle not defined")
417 ACE_TEXT ("in a component\n")));
419 continue;
422 FE_Utils::create_uses_multiple_stuff (c, u, "sendc");
425 idl_global->included_ami_receps_done (true);
429 FE_Utils::path_cmp (const char *s, const char *t)
431 #if defined (WIN32) || defined (ACE_OPENVMS)
432 // Since Windows has case-insensitive filenames, the preprocessor,
433 // when searching using a provided relative path, will sometimes
434 // capitalize the first letter of the last segment of a path name
435 // and make the rest lowercase, regardless of how it was actually
436 // spelled when created. This 'feature' was preventing the
437 // validation of included IDL files, necessary before generating
438 // the corresponding C++ includes.
439 return ACE_OS::strcasecmp (s, t);
440 #else
441 return ACE_OS::strcmp (s, t);
442 #endif /* defined (WIN32) */
445 bool
446 FE_Utils::hasspace (const char *s)
448 if (s)
450 const size_t length = ACE_OS::strlen (s);
452 // Windows can't have a space as the first or last character
453 // but a unix filename can. Need to check all characters.
454 for (size_t i = 0u; i < length; ++i)
456 if (ACE_OS::ace_isspace (s [i]))
458 return true;
463 return false;
466 ACE_CString
467 FE_Utils::check_for_seq_of_param (FE_Utils::T_PARAMLIST_INFO *list)
469 ACE_CString id, retval;
470 const char *pattern = "sequence<";
471 size_t len = ACE_OS::strlen (pattern);
472 size_t index = 0;
475 for (FE_Utils::T_PARAMLIST_INFO::CONST_ITERATOR i (*list);
476 !i.done ();
477 i.advance (), ++index)
479 FE_Utils::T_Param_Info *param = 0;
480 i.next (param);
482 if (param->name_.find (pattern) == 0)
484 // Get the substring of what's between the brackets.
485 // It will have to match a previous param in the list.
486 id = param->name_.substr (len,
487 param->name_.length () - (len + 1));
489 if (!FE_Utils::check_one_seq_of_param (list, id, index))
491 retval = id;
492 break;
497 return retval;
500 FILE *
501 FE_Utils::open_included_file (char const * filename,
502 char const *& directory)
504 FILE * f = 0;
505 ACE_CString const the_file (ACE_CString ('/')
506 + ACE_CString (filename));
508 for (IDL_GlobalData::Unbounded_Paths_Queue_Iterator i (
509 idl_global->include_paths ());
510 !i.done () && f == 0;
511 i.advance ())
513 IDL_GlobalData::Include_Path_Info *path_info = 0;
514 (void) i.next (path_info);
516 if (path_info->path_ != 0)
518 ACE_CString const complete_filename (ACE_CString (path_info->path_)
519 + the_file);
521 f = ACE_OS::fopen (complete_filename.c_str (), "r");
523 if (f != 0)
524 directory = path_info->path_;
528 return f;
531 bool
532 FE_Utils::is_include_file_found (ACE_CString & inc_file,
533 UTL_String * idl_file_name)
535 char abspath[MAXPATHLEN] = "";
536 char *full_path = 0;
538 // If the include path has literal "s (because of an include
539 // of a Windows path with spaces), we must remove them here.
540 const char *tmp_inc_file = inc_file.c_str ();
542 if (tmp_inc_file
543 && FE_Utils::hasspace (tmp_inc_file)
544 && tmp_inc_file[0] == '\"')
546 inc_file =
547 inc_file.substr (1, inc_file.length () - 2);
550 inc_file += ACE_DIRECTORY_SEPARATOR_STR_A;
551 inc_file += idl_file_name->get_string ();
552 full_path =
553 ACE_OS::realpath (inc_file.c_str (), abspath);
555 if (full_path != 0)
557 FILE *test = ACE_OS::fopen (abspath, "r");
559 if (test == 0)
561 return false;
563 else
565 // Overwrite inc_file with abspath since the later
566 // is normalized to the native OS representation.
567 inc_file = abspath;
568 ACE_OS::fclose (test);
569 return true;
573 return false;
576 /// Validate the included idl files, some files might have been
577 /// ignored by the preprocessor.
578 void
579 FE_Utils::validate_included_idl_files (void)
581 // Flag to make sure we don't repeat things.
582 static bool already_done = false;
584 if (already_done)
586 return;
589 already_done = true;
591 // New number of included_idl_files.
592 size_t newj = 0;
594 size_t n_pre_preproc_includes =
595 idl_global->n_included_idl_files ();
597 char **pre_preproc_includes =
598 idl_global->included_idl_files ();
600 size_t n_post_preproc_includes =
601 idl_global->n_include_file_names ();
603 UTL_String **post_preproc_includes =
604 idl_global->include_file_names ();
606 char pre_abspath [MAXPATHLEN] = "";
607 char post_abspath [MAXPATHLEN] = "";
608 IDL_GlobalData::Include_Path_Info *path_info = 0;
609 char *post_tmp = 0;
610 char *full_path = 0;
612 // We are going to assemble a list of the include files found in
613 // the top level file in the order that they are found in the pre-
614 // processor output here
615 // @see bug TAO#711 / Bugzilla #3513 for more
616 char** ordered_include_files =
617 new char* [n_pre_preproc_includes];
619 for (size_t i = 0u; i < n_post_preproc_includes; ++i)
621 post_tmp = post_preproc_includes [i]->get_string ();
622 full_path = ACE_OS::realpath (post_tmp, post_abspath);
624 if (full_path)
626 for (size_t j = 0u; j < n_pre_preproc_includes; ++j)
628 // Check this name with the name that we got from the
629 // preprocessor.
631 bool valid_file = false;
632 full_path = ACE_OS::realpath (pre_preproc_includes [j],
633 pre_abspath);
634 if (full_path &&
635 FE_Utils::path_cmp (pre_abspath, post_abspath) == 0 &&
636 ACE_OS::access (post_abspath, R_OK) == 0)
638 // This file name is valid.
639 valid_file = true;
641 else for (IDL_GlobalData::Unbounded_Paths_Queue_Iterator iter (
642 idl_global->include_paths ());
643 !iter.done ();
644 iter.advance ())
646 iter.next (path_info);
647 ACE_CString pre_partial (path_info->path_);
649 // If the include path has literal "s (because of an include
650 // of a Windows path with spaces), we must remove them here.
651 if (pre_partial.c_str () &&
652 2u < pre_partial.length () &&
653 '"' == pre_partial [0] &&
654 '"' == pre_partial [pre_partial.length () - 1u])
656 pre_partial =
657 pre_partial.substr (1, pre_partial.length () - 2u);
659 pre_partial += ACE_DIRECTORY_SEPARATOR_STR_A;
660 pre_partial += pre_preproc_includes [j];
661 full_path =
662 ACE_OS::realpath (pre_partial.c_str (),
663 pre_abspath);
665 if (full_path &&
666 FE_Utils::path_cmp (pre_abspath, post_abspath) == 0 &&
667 ACE_OS::access (post_abspath, R_OK) == 0)
669 // This file name is valid.
670 valid_file = true;
671 break;
675 if (valid_file)
677 // File is valid.
678 // Move to the new index position.
679 // ... in the ordered list
680 ordered_include_files [newj] =
681 pre_preproc_includes [j];
683 // Increment the new index.
684 ++newj;
686 for (size_t k = j + 1; k < n_pre_preproc_includes; ++k)
688 // Shift remaining entries down
689 pre_preproc_includes [k-1] = pre_preproc_includes [k];
692 // Reduce length and zero the discarded element
693 pre_preproc_includes [--n_pre_preproc_includes] = 0;
695 // Break out to next entry in pre-processor
696 // output
697 break;
701 if (n_pre_preproc_includes == 0)
703 break;
708 // Tidy up not required includes
709 for (size_t l = 0u; l < n_pre_preproc_includes; ++l)
711 delete [] pre_preproc_includes [l];
712 pre_preproc_includes [l] = 0;
715 // Copy list back
716 for (size_t m = 0u; m < newj; ++m)
718 pre_preproc_includes [m] = ordered_include_files [m];
721 delete [] ordered_include_files;
723 // Now adjust the count on the included_idl_files.
724 idl_global->n_included_idl_files (newj);
727 bool
728 FE_Utils::validate_orb_include (UTL_String * idl_file_name)
730 char foundpath[MAXPATHLEN] = "";
733 // Check in the current folder.
734 char abspath[MAXPATHLEN] = "";
735 ACE_CString cwd_path = ACE_OS::getcwd (abspath,
736 sizeof (abspath) / sizeof (char));
737 if (FE_Utils::is_include_file_found (cwd_path, idl_file_name))
739 ACE_OS::strcpy (foundpath, cwd_path.c_str ());
743 for (IDL_GlobalData::Unbounded_Paths_Queue_Iterator iter (
744 idl_global->include_paths ());
745 !iter.done ();
746 iter.advance ())
748 IDL_GlobalData::Include_Path_Info *path_info = 0;
749 iter.next (path_info);
751 ACE_CString partial = path_info->path_;
753 // We don't need to check anything if the file is already
754 // found and the folder where are currently checking is
755 // provided by user.
756 if (foundpath[0] != 0 && !path_info->is_system_)
758 continue;
761 if (FE_Utils::is_include_file_found (partial, idl_file_name))
763 if (path_info->is_system_)
765 if (foundpath[0] == 0 ||
766 ACE_OS::strcmp (foundpath, partial.c_str ()) == 0)
768 return true;
771 else
773 // We can fill in foundpath here since we are sure
774 // that it was not set before. Check above ensures that.
775 ACE_OS::strcpy (foundpath, partial.c_str ());
776 continue;
781 return false;
784 void
785 FE_Utils::original_local_name (Identifier *local_name)
787 const char *lname = local_name->get_string ();
789 // Remove _cxx_ if:
790 // 1. it occurs and
791 // 2. it occurs at the beginning of the string and
792 // 3. the rest of the string is a C++ keyword
793 if (ACE_OS::strstr (lname, "_cxx_") == lname)
795 TAO_IDL_CPP_Keyword_Table cpp_key_tbl;
797 unsigned int len =
798 static_cast<unsigned int> (ACE_OS::strlen (lname + 5));
800 const TAO_IDL_CPP_Keyword_Entry *entry =
801 cpp_key_tbl.lookup (lname + 5, len);
803 if (entry != 0)
805 ACE_CString tmp (lname + 5);
806 local_name->replace_string (tmp.c_str ());
811 bool
812 FE_Utils::can_be_redefined (AST_Decl *prev_decl,
813 AST_Decl *curr_decl)
815 AST_Decl::NodeType pnt = prev_decl->node_type ();
816 AST_Decl::NodeType cnt = curr_decl->node_type ();
818 switch (cnt)
820 /// For these, any non-zero previous decl
821 /// is an error.
822 case AST_Decl::NT_attr:
823 case AST_Decl::NT_op:
824 case AST_Decl::NT_ext_port:
825 case AST_Decl::NT_mirror_port:
826 case AST_Decl::NT_provides:
827 case AST_Decl::NT_publishes:
828 case AST_Decl::NT_consumes:
829 case AST_Decl::NT_uses:
830 return false;
831 default:
832 break;
835 UTL_Scope *prev_scope = prev_decl->defined_in ();
836 UTL_Scope *curr_scope = curr_decl->defined_in ();
837 AST_Structure *s = 0;
838 AST_StructureFwd *s_fwd = 0;
839 AST_Template_Module *ptm = 0;
840 AST_Template_Module *ctm = 0;
842 bool nt_eq = (pnt == cnt);
843 bool s_eq = (prev_scope == curr_scope);
845 switch (pnt)
847 case AST_Decl::NT_module:
848 /// Need to check that both are modules.
849 if (cnt != AST_Decl::NT_module)
851 return false;
854 /// Neither can be a template module.
855 ptm = dynamic_cast<AST_Template_Module*> (prev_decl);
856 ctm = dynamic_cast<AST_Template_Module*> (curr_decl);
857 return (ptm == 0 && ctm == 0);
858 /// For the *_fwd types, if scopes aren't related, it's ok.
859 /// If they are related, then we need another fwd or a full decl.
860 case AST_Decl::NT_component_fwd:
861 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_component));
862 case AST_Decl::NT_eventtype_fwd:
863 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_eventtype));
864 case AST_Decl::NT_interface_fwd:
865 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_interface));
866 case AST_Decl::NT_struct_fwd:
867 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_struct));
868 case AST_Decl::NT_union_fwd:
869 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_union));
870 case AST_Decl::NT_valuetype_fwd:
871 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_valuetype));
872 /// If scopes aren't related, it's ok. If they are, check
873 /// if the previous is a dummy for a fwd decl. Even a redef
874 /// in a derived interface type is ok.
875 case AST_Decl::NT_struct:
876 case AST_Decl::NT_union:
877 s = dynamic_cast<AST_Structure*> (prev_decl);
878 s_fwd = (s == 0 ? 0 : s->fwd_decl ());
879 return (!s_eq || s_fwd != 0);
880 /// Only 2 or more full definitions in the same scope are illegal,
881 /// and that is caught elsewhere.
882 case AST_Decl::NT_interface:
883 case AST_Decl::NT_component:
884 case AST_Decl::NT_eventtype:
885 case AST_Decl::NT_valuetype:
886 return true;
887 /// For connectors, factories, exceptions, constants and types, even a
888 /// redef in a derived interface type is ok. Checking for
889 /// unequal scopes covers boxed valuetypes as well.
890 case AST_Decl::NT_connector:
891 case AST_Decl::NT_valuebox:
892 case AST_Decl::NT_except:
893 case AST_Decl::NT_typedef:
894 case AST_Decl::NT_const:
895 case AST_Decl::NT_factory:
896 case AST_Decl::NT_type:
897 case AST_Decl::NT_enum:
898 case AST_Decl::NT_enum_val:
900 return !s_eq;
902 /// What's left are the case from the previous switch statement.
903 /// Same rule applies - no overrides or redefs, ever.
904 default:
905 return false;
909 void
910 FE_Utils::tmpl_mod_ref_check (AST_Decl *context,
911 AST_Decl *ref)
913 if (ref == 0
914 || ref->node_type () == AST_Decl::NT_param_holder
915 || idl_global->in_tmpl_mod_alias ())
917 return;
920 bool ok = true;
922 if (ref->in_tmpl_mod_not_aliased ())
924 if (! context->in_tmpl_mod_not_aliased ())
926 ok = false;
928 else
930 AST_Template_Module *context_tm =
931 FE_Utils::get_tm_container (context);
932 AST_Template_Module *ref_tm =
933 FE_Utils::get_tm_container (ref);
935 if (context_tm != ref_tm)
937 ok = false;
942 if (! ok)
944 idl_global->err ()->template_scope_ref_not_aliased (ref);
945 throw Bailout ();
949 bool
950 FE_Utils::check_one_seq_of_param (FE_Utils::T_PARAMLIST_INFO *list,
951 ACE_CString &param_id,
952 size_t index)
954 size_t local_index = 0;
956 for (FE_Utils::T_PARAMLIST_INFO::CONST_ITERATOR i (*list);
957 !i.done ();
958 i.advance (), ++local_index)
960 if (local_index == index)
962 break;
965 FE_Utils::T_Param_Info *info = 0;
966 i.next (info);
968 if (info->name_ == param_id)
970 return true;
974 return false;
977 AST_Template_Module *
978 FE_Utils::get_tm_container (AST_Decl *contained)
980 AST_Decl *d = contained;
982 while (d != 0)
984 AST_Template_Module *tm =
985 dynamic_cast<AST_Template_Module*> (d);
987 if (tm != 0)
989 return tm;
992 d = ScopeAsDecl (d->defined_in ());
995 return 0;