2 #include "fe_private.h"
6 #include "ast_component.h"
7 #include "ast_generator.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)
35 FE_Utils::duplicate_param_id (T_PARAMLIST_INFO
*params
)
38 size_t size
= params
->size ();
40 for (FE_Utils::T_PARAMLIST_INFO::CONST_ITERATOR
i (*params
);
42 i
.advance (), ++cur_pos
)
44 FE_Utils::T_Param_Info
*this_one
= 0;
45 FE_Utils::T_Param_Info
*that_one
= 0;
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_
)
64 FE_Utils::T_ARGLIST::destroy (void)
68 for (T_ARGLIST::ITERATOR
i (this->begin ());
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.
80 if (tmp->node_type () == AST_Decl::NT_const)
90 * Convert a PredefinedType to an ExprType
92 AST_Expression::ExprType
93 FE_Utils::PredefinedTypeToExprType (
94 AST_PredefinedType::PredefinedType 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
;
127 return AST_Expression::EV_enum
;
131 AST_PredefinedType::PredefinedType
132 FE_Utils::ExprTypeToPredefinedType (AST_Expression::ExprType 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
:
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
;
184 FE_Utils::string_to_scoped_name (const char *s
)
186 UTL_ScopedName
*retval
= 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
201 ACE_CString::size_type pos
= str
.find (':');
202 ACE_CString
lname (str
.substr (0, pos
));
204 // Construct a UTL_ScopedName segment.
206 Identifier (lname
.c_str ()),
210 UTL_ScopedName (id
, 0),
213 // Either make it the head of a new list or the tail of
224 // Update the working string.
225 str
= str
.substr (pos
);
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.
239 if (name
[1] == '\\' || name
[1] == '/')
249 FE_Utils::create_uses_multiple_stuff (AST_Component
*c
,
253 ACE_CString
struct_name (prefix
);
255 if (!struct_name
.empty ())
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 ();
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
,
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
,
299 d
= c
->lookup_by_name (&scoped_name
, true);
301 module_id
.destroy ();
305 // This would happen if we haven't included Components.idl.
306 idl_global
->err ()->lookup_error (&scoped_name
);
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
,
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
,
335 ACE_CString
seq_string (struct_name
);
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
,
347 (void) c
->fe_add_typedef (connections
);
349 // In case this call comes from the backend.
350 idl_global
->scopes ().pop ();
354 FE_Utils::create_implied_ami_uses_stuff (void)
356 if (idl_global
->included_ami_receps_done ())
361 for (ACE_Unbounded_Queue
<char *>::CONST_ITERATOR
i (
362 idl_global
->included_ami_recep_names ());
370 FE_Utils::string_to_scoped_name (*item
);
373 idl_global
->root ()->lookup_by_name (sn
, true);
377 idl_global
->err ()->lookup_error (sn
);
390 AST_Uses
*u
= dynamic_cast<AST_Uses
*> (d
);
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")));
403 if (!u
->is_multiple ())
409 dynamic_cast<AST_Component
*> (u
->defined_in ());
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")));
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
);
441 return ACE_OS::strcmp (s
, t
);
442 #endif /* defined (WIN32) */
446 FE_Utils::hasspace (const char *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
]))
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
);
475 for (FE_Utils::T_PARAMLIST_INFO::CONST_ITERATOR
i (*list
);
477 i
.advance (), ++index
)
479 FE_Utils::T_Param_Info
*param
= 0;
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
))
501 FE_Utils::open_included_file (char const * filename
,
502 char const *& directory
)
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;
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_
)
521 f
= ACE_OS::fopen (complete_filename
.c_str (), "r");
524 directory
= path_info
->path_
;
532 FE_Utils::is_include_file_found (ACE_CString
& inc_file
,
533 UTL_String
* idl_file_name
)
535 char abspath
[MAXPATHLEN
] = "";
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 ();
543 && FE_Utils::hasspace (tmp_inc_file
)
544 && tmp_inc_file
[0] == '\"')
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 ();
553 ACE_OS::realpath (inc_file
.c_str (), abspath
);
557 FILE *test
= ACE_OS::fopen (abspath
, "r");
565 // Overwrite inc_file with abspath since the later
566 // is normalized to the native OS representation.
568 ACE_OS::fclose (test
);
576 /// Validate the included idl files, some files might have been
577 /// ignored by the preprocessor.
579 FE_Utils::validate_included_idl_files (void)
581 // Flag to make sure we don't repeat things.
582 static bool already_done
= false;
591 // New number of included_idl_files.
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;
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
);
626 for (size_t j
= 0u; j
< n_pre_preproc_includes
; ++j
)
628 // Check this name with the name that we got from the
631 bool valid_file
= false;
632 full_path
= ACE_OS::realpath (pre_preproc_includes
[j
],
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.
641 else for (IDL_GlobalData::Unbounded_Paths_Queue_Iterator
iter (
642 idl_global
->include_paths ());
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])
657 pre_partial
.substr (1, pre_partial
.length () - 2u);
659 pre_partial
+= ACE_DIRECTORY_SEPARATOR_STR_A
;
660 pre_partial
+= pre_preproc_includes
[j
];
662 ACE_OS::realpath (pre_partial
.c_str (),
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.
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.
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
701 if (n_pre_preproc_includes
== 0)
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;
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
);
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 ());
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
756 if (foundpath
[0] != 0 && !path_info
->is_system_
)
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)
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 ());
785 FE_Utils::original_local_name (Identifier
*local_name
)
787 const char *lname
= local_name
->get_string ();
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
;
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
);
805 ACE_CString
tmp (lname
+ 5);
806 local_name
->replace_string (tmp
.c_str ());
812 FE_Utils::can_be_redefined (AST_Decl
*prev_decl
,
815 AST_Decl::NodeType pnt
= prev_decl
->node_type ();
816 AST_Decl::NodeType cnt
= curr_decl
->node_type ();
820 /// For these, any non-zero previous decl
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
:
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
);
847 case AST_Decl::NT_module
:
848 /// Need to check that both are modules.
849 if (cnt
!= AST_Decl::NT_module
)
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
:
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
:
902 /// What's left are the case from the previous switch statement.
903 /// Same rule applies - no overrides or redefs, ever.
910 FE_Utils::tmpl_mod_ref_check (AST_Decl
*context
,
914 || ref
->node_type () == AST_Decl::NT_param_holder
915 || idl_global
->in_tmpl_mod_alias ())
922 if (ref
->in_tmpl_mod_not_aliased ())
924 if (! context
->in_tmpl_mod_not_aliased ())
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
)
944 idl_global
->err ()->template_scope_ref_not_aliased (ref
);
950 FE_Utils::check_one_seq_of_param (FE_Utils::T_PARAMLIST_INFO
*list
,
951 ACE_CString
¶m_id
,
954 size_t local_index
= 0;
956 for (FE_Utils::T_PARAMLIST_INFO::CONST_ITERATOR
i (*list
);
958 i
.advance (), ++local_index
)
960 if (local_index
== index
)
965 FE_Utils::T_Param_Info
*info
= 0;
968 if (info
->name_
== param_id
)
977 AST_Template_Module
*
978 FE_Utils::get_tm_container (AST_Decl
*contained
)
980 AST_Decl
*d
= contained
;
984 AST_Template_Module
*tm
=
985 dynamic_cast<AST_Template_Module
*> (d
);
992 d
= ScopeAsDecl (d
->defined_in ());