Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / TAO / TAO_IDL / fe / fe_utils.cpp
blob1da6d96da19d21cf475665bfe52d59caba3e395d
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 ()
28 : type_ (AST_Decl::NT_fixed),
29 const_type_ (AST_Expression::EV_none),
30 enum_const_type_decl_ (nullptr)
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 = nullptr;
45 FE_Utils::T_Param_Info *that_one = nullptr;
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 ()
66 AST_Decl **d = nullptr;
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 case AST_PredefinedType::PT_int8:
127 return AST_Expression::EV_int8;
128 case AST_PredefinedType::PT_uint8:
129 return AST_Expression::EV_uint8;
130 default:
131 return AST_Expression::EV_enum;
135 AST_PredefinedType::PredefinedType
136 FE_Utils::ExprTypeToPredefinedType (AST_Expression::ExprType et)
138 switch (et)
140 case AST_Expression::EV_short:
141 return AST_PredefinedType::PT_short;
142 case AST_Expression::EV_ushort:
143 return AST_PredefinedType::PT_ushort;
144 case AST_Expression::EV_long:
145 return AST_PredefinedType::PT_long;
146 case AST_Expression::EV_ulong:
147 return AST_PredefinedType::PT_ulong;
148 case AST_Expression::EV_longlong:
149 return AST_PredefinedType::PT_longlong;
150 case AST_Expression::EV_ulonglong:
151 return AST_PredefinedType::PT_ulonglong;
152 case AST_Expression::EV_float:
153 return AST_PredefinedType::PT_float;
154 case AST_Expression::EV_double:
155 return AST_PredefinedType::PT_double;
156 case AST_Expression::EV_longdouble:
157 return AST_PredefinedType::PT_longdouble;
158 case AST_Expression::EV_char:
159 return AST_PredefinedType::PT_char;
160 case AST_Expression::EV_wchar:
161 return AST_PredefinedType::PT_wchar;
162 case AST_Expression::EV_octet:
163 return AST_PredefinedType::PT_octet;
164 case AST_Expression::EV_bool:
165 return AST_PredefinedType::PT_boolean;
166 case AST_Expression::EV_any:
167 return AST_PredefinedType::PT_any;
168 case AST_Expression::EV_object:
169 return AST_PredefinedType::PT_object;
170 case AST_Expression::EV_void:
171 return AST_PredefinedType::PT_void;
172 case AST_Expression::EV_int8:
173 return AST_PredefinedType::PT_int8;
174 case AST_Expression::EV_uint8:
175 return AST_PredefinedType::PT_uint8;
176 case AST_Expression::EV_enum:
177 case AST_Expression::EV_string:
178 case AST_Expression::EV_wstring:
179 case AST_Expression::EV_none:
180 default:
181 ACE_ERROR ((LM_ERROR,
182 ACE_TEXT ("FE_Utils::ExprTypeToPredefinedType - ")
183 ACE_TEXT ("no pathing PredefinedType enum value\n")));
185 /// A deliberately odd return value, so the caller can check
186 /// it and take further action if necessary.
187 return AST_PredefinedType::PT_pseudo;
191 UTL_ScopedName *
192 FE_Utils::string_to_scoped_name (const char *s)
194 UTL_ScopedName *retval = nullptr;
195 ACE_CString str (s);
196 Identifier *id = nullptr;
197 UTL_ScopedName *sn = nullptr;
199 while (! str.empty ())
201 // Skip a leading double colon.
202 if (str.find (':') == 0)
204 str = str.substr (2);
207 // Find the next double colon (if any) and get the next
208 // name segment.
209 ACE_CString::size_type pos = str.find (':');
210 ACE_CString lname (str.substr (0, pos));
212 // Construct a UTL_ScopedName segment.
213 ACE_NEW_RETURN (id,
214 Identifier (lname.c_str ()),
215 nullptr);
217 ACE_NEW_RETURN (sn,
218 UTL_ScopedName (id, nullptr),
219 nullptr);
221 // Either make it the head of a new list or the tail of
222 // an existing one.
223 if (retval == nullptr)
225 retval = sn;
227 else
229 retval->nconc (sn);
232 // Update the working string.
233 str = str.substr (pos);
236 return retval;
239 const char *
240 FE_Utils::stripped_preproc_include (const char *name)
242 // Some preprocessors prepend "./" to filenames in the
243 // working directory, some others prepend ".\". If either
244 // of these are here, we want to strip them.
245 if (name[0] == '.')
247 if (name[1] == '\\' || name[1] == '/')
249 return name + 2;
253 return name;
256 void
257 FE_Utils::create_uses_multiple_stuff (AST_Component *c,
258 AST_Uses *u,
259 const char *prefix)
261 ACE_CString struct_name (prefix);
263 if (!struct_name.empty ())
265 struct_name += '_';
268 struct_name += u->local_name ()->get_string ();
269 struct_name += "Connection";
270 Identifier struct_id (struct_name.c_str ());
271 UTL_ScopedName sn (&struct_id, nullptr);
273 // In case this call comes from the backend. We
274 // will pop the scope before returning.
275 idl_global->scopes ().push (c);
277 AST_Structure *connection =
278 idl_global->gen ()->create_structure (&sn, false, false);
280 struct_id.destroy ();
282 /// If the field type is a param holder, we want
283 /// to use the lookup to create a fresh one,
284 /// since the field will own it and destroy it.
285 UTL_ScopedName *fn = u->uses_type ()->name ();
286 AST_Decl *d =
287 idl_global->root ()->lookup_by_name (fn, true, false);
288 AST_Type *ft = dynamic_cast<AST_Type*> (d);
290 Identifier object_id ("objref");
291 UTL_ScopedName object_name (&object_id,
292 nullptr);
293 AST_Field *object_field =
294 idl_global->gen ()->create_field (ft,
295 &object_name,
296 AST_Field::vis_NA);
297 (void) DeclAsScope (connection)->fe_add_field (object_field);
298 object_id.destroy ();
300 Identifier local_id ("Cookie");
301 UTL_ScopedName local_name (&local_id,
302 nullptr);
303 Identifier module_id ("Components");
304 UTL_ScopedName scoped_name (&module_id,
305 &local_name);
307 d = c->lookup_by_name (&scoped_name, true);
308 local_id.destroy ();
309 module_id.destroy ();
311 if (d == nullptr)
313 // This would happen if we haven't included Components.idl.
314 idl_global->err ()->lookup_error (&scoped_name);
315 return;
318 AST_ValueType *cookie = dynamic_cast<AST_ValueType*> (d);
320 Identifier cookie_id ("ck");
321 UTL_ScopedName cookie_name (&cookie_id,
322 nullptr);
323 AST_Field *cookie_field =
324 idl_global->gen ()->create_field (cookie,
325 &cookie_name,
326 AST_Field::vis_NA);
327 (void) DeclAsScope (connection)->fe_add_field (cookie_field);
328 cookie_id.destroy ();
330 (void) c->fe_add_structure (connection);
332 ACE_CDR::ULong bound = 0;
333 AST_Expression *bound_expr =
334 idl_global->gen ()->create_expr (bound,
335 AST_Expression::EV_ulong);
336 AST_Sequence *sequence =
337 idl_global->gen ()->create_sequence (bound_expr,
338 connection,
339 nullptr,
340 false,
341 false);
343 ACE_CString seq_string (struct_name);
344 seq_string += 's';
345 Identifier seq_id (seq_string.c_str ());
346 UTL_ScopedName seq_name (&seq_id,
347 nullptr);
348 AST_Typedef *connections =
349 idl_global->gen ()->create_typedef (sequence,
350 &seq_name,
351 false,
352 false);
353 seq_id.destroy ();
355 (void) c->fe_add_typedef (connections);
357 // In case this call comes from the backend.
358 idl_global->scopes ().pop ();
361 void
362 FE_Utils::create_implied_ami_uses_stuff ()
364 if (idl_global->included_ami_receps_done ())
366 return;
369 for (ACE_Unbounded_Queue<char *>::CONST_ITERATOR i (
370 idl_global->included_ami_recep_names ());
371 ! i.done ();
372 i.advance ())
374 char **item = nullptr;
375 i.next (item);
377 UTL_ScopedName *sn =
378 FE_Utils::string_to_scoped_name (*item);
380 AST_Decl *d =
381 idl_global->root ()->lookup_by_name (sn, true);
383 if (d == nullptr)
385 idl_global->err ()->lookup_error (sn);
387 sn->destroy ();
388 delete sn;
389 sn = nullptr;
391 continue;
394 sn->destroy ();
395 delete sn;
396 sn = nullptr;
398 AST_Uses *u = dynamic_cast<AST_Uses*> (d);
400 if (u == nullptr)
402 ACE_ERROR ((LM_ERROR,
403 ACE_TEXT ("idl_global::create_")
404 ACE_TEXT ("implied_ami_uses_stuff - ")
405 ACE_TEXT ("narrow to receptacle ")
406 ACE_TEXT ("failed\n")));
408 continue;
411 if (!u->is_multiple ())
413 continue;
416 AST_Component *c =
417 dynamic_cast<AST_Component*> (u->defined_in ());
419 if (c == nullptr)
421 ACE_ERROR ((LM_ERROR,
422 ACE_TEXT ("idl_global::create_")
423 ACE_TEXT ("implied_ami_uses_stuff - ")
424 ACE_TEXT ("receptacle not defined")
425 ACE_TEXT ("in a component\n")));
427 continue;
430 FE_Utils::create_uses_multiple_stuff (c, u, "sendc");
433 idl_global->included_ami_receps_done (true);
437 FE_Utils::path_cmp (const char *s, const char *t)
439 #if defined (WIN32)
440 // Since Windows has case-insensitive filenames, the preprocessor,
441 // when searching using a provided relative path, will sometimes
442 // capitalize the first letter of the last segment of a path name
443 // and make the rest lowercase, regardless of how it was actually
444 // spelled when created. This 'feature' was preventing the
445 // validation of included IDL files, necessary before generating
446 // the corresponding C++ includes.
447 return ACE_OS::strcasecmp (s, t);
448 #else
449 return ACE_OS::strcmp (s, t);
450 #endif /* defined (WIN32) */
453 bool
454 FE_Utils::hasspace (const char *s)
456 if (s)
458 const size_t length = ACE_OS::strlen (s);
460 // Windows can't have a space as the first or last character
461 // but a unix filename can. Need to check all characters.
462 for (size_t i = 0u; i < length; ++i)
464 if (ACE_OS::ace_isspace (s [i]))
466 return true;
471 return false;
474 ACE_CString
475 FE_Utils::check_for_seq_of_param (FE_Utils::T_PARAMLIST_INFO *list)
477 ACE_CString id, retval;
478 const char *pattern = "sequence<";
479 size_t len = ACE_OS::strlen (pattern);
480 size_t index = 0;
483 for (FE_Utils::T_PARAMLIST_INFO::CONST_ITERATOR i (*list);
484 !i.done ();
485 i.advance (), ++index)
487 FE_Utils::T_Param_Info *param = nullptr;
488 i.next (param);
490 if (param->name_.find (pattern) == 0)
492 // Get the substring of what's between the brackets.
493 // It will have to match a previous param in the list.
494 id = param->name_.substr (len,
495 param->name_.length () - (len + 1));
497 if (!FE_Utils::check_one_seq_of_param (list, id, index))
499 retval = id;
500 break;
505 return retval;
508 FILE *
509 FE_Utils::open_included_file (char const * filename,
510 char const *& directory)
512 FILE * f = nullptr;
513 ACE_CString const the_file (ACE_CString ('/')
514 + ACE_CString (filename));
516 for (IDL_GlobalData::Unbounded_Paths_Queue_Iterator i (
517 idl_global->include_paths ());
518 !i.done () && f == nullptr;
519 i.advance ())
521 IDL_GlobalData::Include_Path_Info *path_info = nullptr;
522 (void) i.next (path_info);
524 if (path_info->path_ != nullptr)
526 ACE_CString const complete_filename (ACE_CString (path_info->path_)
527 + the_file);
529 f = ACE_OS::fopen (complete_filename.c_str (), "r");
531 if (f != nullptr)
532 directory = path_info->path_;
536 return f;
539 bool
540 FE_Utils::is_include_file_found (ACE_CString & inc_file,
541 UTL_String * idl_file_name)
543 char abspath[MAXPATHLEN] = "";
544 char *full_path = nullptr;
546 // If the include path has literal "s (because of an include
547 // of a Windows path with spaces), we must remove them here.
548 const char *tmp_inc_file = inc_file.c_str ();
550 if (tmp_inc_file
551 && FE_Utils::hasspace (tmp_inc_file)
552 && tmp_inc_file[0] == '\"')
554 inc_file =
555 inc_file.substr (1, inc_file.length () - 2);
558 inc_file += ACE_DIRECTORY_SEPARATOR_STR_A;
559 inc_file += idl_file_name->get_string ();
560 full_path =
561 ACE_OS::realpath (inc_file.c_str (), abspath);
563 if (full_path != nullptr)
565 FILE *test = ACE_OS::fopen (abspath, "r");
567 if (test == nullptr)
569 return false;
571 else
573 // Overwrite inc_file with abspath since the later
574 // is normalized to the native OS representation.
575 inc_file = abspath;
576 ACE_OS::fclose (test);
577 return true;
581 return false;
584 /// Validate the included idl files, some files might have been
585 /// ignored by the preprocessor.
586 void
587 FE_Utils::validate_included_idl_files ()
589 // Flag to make sure we don't repeat things.
590 static bool already_done = false;
592 if (already_done)
594 return;
597 already_done = true;
599 // New number of included_idl_files.
600 size_t newj = 0;
602 size_t n_pre_preproc_includes =
603 idl_global->n_included_idl_files ();
605 char **pre_preproc_includes =
606 idl_global->included_idl_files ();
608 size_t n_post_preproc_includes =
609 idl_global->n_include_file_names ();
611 UTL_String **post_preproc_includes =
612 idl_global->include_file_names ();
614 char pre_abspath [MAXPATHLEN] = "";
615 char post_abspath [MAXPATHLEN] = "";
616 IDL_GlobalData::Include_Path_Info *path_info = nullptr;
617 char *post_tmp = nullptr;
618 char *full_path = nullptr;
620 // We are going to assemble a list of the include files found in
621 // the top level file in the order that they are found in the pre-
622 // processor output here
623 // @see bug TAO#711 / Bugzilla #3513 for more
624 char** ordered_include_files =
625 new char* [n_pre_preproc_includes];
627 for (size_t i = 0u; i < n_post_preproc_includes; ++i)
629 post_tmp = post_preproc_includes [i]->get_string ();
630 full_path = ACE_OS::realpath (post_tmp, post_abspath);
632 if (full_path)
634 for (size_t j = 0u; j < n_pre_preproc_includes; ++j)
636 // Check this name with the name that we got from the
637 // preprocessor.
639 bool valid_file = false;
640 full_path = ACE_OS::realpath (pre_preproc_includes [j],
641 pre_abspath);
642 if (full_path &&
643 FE_Utils::path_cmp (pre_abspath, post_abspath) == 0 &&
644 ACE_OS::access (post_abspath, R_OK) == 0)
646 // This file name is valid.
647 valid_file = true;
649 else for (IDL_GlobalData::Unbounded_Paths_Queue_Iterator iter (
650 idl_global->include_paths ());
651 !iter.done ();
652 iter.advance ())
654 iter.next (path_info);
655 ACE_CString pre_partial (path_info->path_);
657 // If the include path has literal "s (because of an include
658 // of a Windows path with spaces), we must remove them here.
659 if (pre_partial.c_str () &&
660 2u < pre_partial.length () &&
661 '"' == pre_partial [0] &&
662 '"' == pre_partial [pre_partial.length () - 1u])
664 pre_partial =
665 pre_partial.substr (1, pre_partial.length () - 2u);
667 pre_partial += ACE_DIRECTORY_SEPARATOR_STR_A;
668 pre_partial += pre_preproc_includes [j];
669 full_path =
670 ACE_OS::realpath (pre_partial.c_str (),
671 pre_abspath);
673 if (full_path &&
674 FE_Utils::path_cmp (pre_abspath, post_abspath) == 0 &&
675 ACE_OS::access (post_abspath, R_OK) == 0)
677 // This file name is valid.
678 valid_file = true;
679 break;
683 if (valid_file)
685 // File is valid.
686 // Move to the new index position.
687 // ... in the ordered list
688 ordered_include_files [newj] =
689 pre_preproc_includes [j];
691 // Increment the new index.
692 ++newj;
694 for (size_t k = j + 1; k < n_pre_preproc_includes; ++k)
696 // Shift remaining entries down
697 pre_preproc_includes [k-1] = pre_preproc_includes [k];
700 // Reduce length and zero the discarded element
701 pre_preproc_includes [--n_pre_preproc_includes] = nullptr;
703 // Break out to next entry in pre-processor
704 // output
705 break;
709 if (n_pre_preproc_includes == 0)
711 break;
716 // Tidy up not required includes
717 for (size_t l = 0u; l < n_pre_preproc_includes; ++l)
719 delete [] pre_preproc_includes [l];
720 pre_preproc_includes [l] = nullptr;
723 // Copy list back
724 for (size_t m = 0u; m < newj; ++m)
726 pre_preproc_includes [m] = ordered_include_files [m];
729 delete [] ordered_include_files;
731 // Now adjust the count on the included_idl_files.
732 idl_global->n_included_idl_files (newj);
735 bool
736 FE_Utils::validate_orb_include (UTL_String * idl_file_name)
738 char foundpath[MAXPATHLEN] = "";
741 // Check in the current folder.
742 char abspath[MAXPATHLEN] = "";
743 ACE_CString cwd_path = ACE_OS::getcwd (abspath,
744 sizeof (abspath) / sizeof (char));
745 if (FE_Utils::is_include_file_found (cwd_path, idl_file_name))
747 ACE_OS::strcpy (foundpath, cwd_path.c_str ());
751 for (IDL_GlobalData::Unbounded_Paths_Queue_Iterator iter (
752 idl_global->include_paths ());
753 !iter.done ();
754 iter.advance ())
756 IDL_GlobalData::Include_Path_Info *path_info = nullptr;
757 iter.next (path_info);
759 ACE_CString partial = path_info->path_;
761 // We don't need to check anything if the file is already
762 // found and the folder where are currently checking is
763 // provided by user.
764 if (foundpath[0] != 0 && !path_info->is_system_)
766 continue;
769 if (FE_Utils::is_include_file_found (partial, idl_file_name))
771 if (path_info->is_system_)
773 if (foundpath[0] == 0 ||
774 ACE_OS::strcmp (foundpath, partial.c_str ()) == 0)
776 return true;
779 else
781 // We can fill in foundpath here since we are sure
782 // that it was not set before. Check above ensures that.
783 ACE_OS::strcpy (foundpath, partial.c_str ());
784 continue;
789 return false;
792 void
793 FE_Utils::original_local_name (Identifier *local_name)
795 const char *lname = local_name->get_string ();
797 // Remove _cxx_ if:
798 // 1. it occurs and
799 // 2. it occurs at the beginning of the string and
800 // 3. the rest of the string is a C++ keyword
801 if (ACE_OS::strstr (lname, "_cxx_") == lname)
803 TAO_IDL_CPP_Keyword_Table cpp_key_tbl;
805 unsigned int len =
806 static_cast<unsigned int> (ACE_OS::strlen (lname + 5));
808 const TAO_IDL_CPP_Keyword_Entry *entry =
809 cpp_key_tbl.lookup (lname + 5, len);
811 if (entry != nullptr)
813 ACE_CString tmp (lname + 5);
814 local_name->replace_string (tmp.c_str ());
819 bool
820 FE_Utils::can_be_redefined (AST_Decl *prev_decl,
821 AST_Decl *curr_decl)
823 AST_Decl::NodeType pnt = prev_decl->node_type ();
824 AST_Decl::NodeType cnt = curr_decl->node_type ();
826 switch (cnt)
828 /// For these, any non-zero previous decl
829 /// is an error.
830 case AST_Decl::NT_attr:
831 case AST_Decl::NT_op:
832 case AST_Decl::NT_ext_port:
833 case AST_Decl::NT_mirror_port:
834 case AST_Decl::NT_provides:
835 case AST_Decl::NT_publishes:
836 case AST_Decl::NT_consumes:
837 case AST_Decl::NT_uses:
838 return false;
839 default:
840 break;
843 UTL_Scope *prev_scope = prev_decl->defined_in ();
844 UTL_Scope *curr_scope = curr_decl->defined_in ();
845 AST_Structure *s = nullptr;
846 AST_StructureFwd *s_fwd = nullptr;
847 AST_Template_Module *ptm = nullptr;
848 AST_Template_Module *ctm = nullptr;
850 bool nt_eq = (pnt == cnt);
851 bool s_eq = (prev_scope == curr_scope);
853 switch (pnt)
855 case AST_Decl::NT_module:
856 /// Need to check that both are modules.
857 if (cnt != AST_Decl::NT_module)
859 return false;
862 /// Neither can be a template module.
863 ptm = dynamic_cast<AST_Template_Module*> (prev_decl);
864 ctm = dynamic_cast<AST_Template_Module*> (curr_decl);
865 return (ptm == nullptr && ctm == nullptr);
866 /// For the *_fwd types, if scopes aren't related, it's ok.
867 /// If they are related, then we need another fwd or a full decl.
868 case AST_Decl::NT_component_fwd:
869 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_component));
870 case AST_Decl::NT_eventtype_fwd:
871 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_eventtype));
872 case AST_Decl::NT_interface_fwd:
873 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_interface));
874 case AST_Decl::NT_struct_fwd:
875 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_struct));
876 case AST_Decl::NT_union_fwd:
877 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_union));
878 case AST_Decl::NT_valuetype_fwd:
879 return (!s_eq || (nt_eq || cnt == AST_Decl::NT_valuetype));
880 /// If scopes aren't related, it's ok. If they are, check
881 /// if the previous is a dummy for a fwd decl. Even a redef
882 /// in a derived interface type is ok.
883 case AST_Decl::NT_struct:
884 case AST_Decl::NT_union:
885 s = dynamic_cast<AST_Structure*> (prev_decl);
886 s_fwd = (s == nullptr ? nullptr : s->fwd_decl ());
887 return (!s_eq || s_fwd != nullptr);
888 /// Only 2 or more full definitions in the same scope are illegal,
889 /// and that is caught elsewhere.
890 case AST_Decl::NT_interface:
891 case AST_Decl::NT_component:
892 case AST_Decl::NT_eventtype:
893 case AST_Decl::NT_valuetype:
894 return true;
895 /// For connectors, factories, exceptions, constants and types, even a
896 /// redef in a derived interface type is ok. Checking for
897 /// unequal scopes covers boxed valuetypes as well.
898 case AST_Decl::NT_connector:
899 case AST_Decl::NT_valuebox:
900 case AST_Decl::NT_except:
901 case AST_Decl::NT_typedef:
902 case AST_Decl::NT_const:
903 case AST_Decl::NT_factory:
904 case AST_Decl::NT_type:
905 case AST_Decl::NT_enum:
906 case AST_Decl::NT_enum_val:
908 return !s_eq;
910 /// What's left are the case from the previous switch statement.
911 /// Same rule applies - no overrides or redefs, ever.
912 default:
913 return false;
917 void
918 FE_Utils::tmpl_mod_ref_check (AST_Decl *context,
919 AST_Decl *ref)
921 if (ref == nullptr
922 || ref->node_type () == AST_Decl::NT_param_holder
923 || idl_global->in_tmpl_mod_alias ())
925 return;
928 bool ok = true;
930 if (ref->in_tmpl_mod_not_aliased ())
932 if (! context->in_tmpl_mod_not_aliased ())
934 ok = false;
936 else
938 AST_Template_Module *context_tm =
939 FE_Utils::get_tm_container (context);
940 AST_Template_Module *ref_tm =
941 FE_Utils::get_tm_container (ref);
943 if (context_tm != ref_tm)
945 ok = false;
950 if (! ok)
952 idl_global->err ()->template_scope_ref_not_aliased (ref);
953 throw Bailout ();
957 bool
958 FE_Utils::check_one_seq_of_param (FE_Utils::T_PARAMLIST_INFO *list,
959 ACE_CString &param_id,
960 size_t index)
962 size_t local_index = 0;
964 for (FE_Utils::T_PARAMLIST_INFO::CONST_ITERATOR i (*list);
965 !i.done ();
966 i.advance (), ++local_index)
968 if (local_index == index)
970 break;
973 FE_Utils::T_Param_Info *info = nullptr;
974 i.next (info);
976 if (info->name_ == param_id)
978 return true;
982 return false;
985 AST_Template_Module *
986 FE_Utils::get_tm_container (AST_Decl *contained)
988 AST_Decl *d = contained;
990 while (d != nullptr)
992 AST_Template_Module *tm =
993 dynamic_cast<AST_Template_Module*> (d);
995 if (tm != nullptr)
997 return tm;
1000 d = ScopeAsDecl (d->defined_in ());
1003 return nullptr;