File: | build/gcc/objc/objc-next-runtime-abi-01.cc |
Warning: | line 876, column 3 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Next Runtime (ABI-0/1) private. | ||||
2 | Copyright (C) 2011-2023 Free Software Foundation, Inc. | ||||
3 | Contributed by Iain Sandoe (split from objc-act.cc) | ||||
4 | |||||
5 | This file is part of GCC. | ||||
6 | |||||
7 | GCC is free software; you can redistribute it and/or modify | ||||
8 | it under the terms of the GNU General Public License as published by | ||||
9 | the Free Software Foundation; either version 3, or (at your option) | ||||
10 | any later version. | ||||
11 | |||||
12 | GCC is distributed in the hope that it will be useful, | ||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | GNU General Public License for more details. | ||||
16 | |||||
17 | You should have received a copy of the GNU General Public License | ||||
18 | along with GCC; see the file COPYING3. If not see | ||||
19 | <http://www.gnu.org/licenses/>. */ | ||||
20 | |||||
21 | /* This implements the original NeXT ABI (0) used for m32 code and | ||||
22 | indicated by module version 6. It also implements the small number | ||||
23 | of additions made for properties and optional protocol methods as | ||||
24 | ABI=1 (module version 7). */ | ||||
25 | |||||
26 | #include "config.h" | ||||
27 | #include "system.h" | ||||
28 | #include "coretypes.h" | ||||
29 | #include "tree.h" | ||||
30 | #include "stringpool.h" | ||||
31 | #include "attribs.h" | ||||
32 | |||||
33 | #ifdef OBJCPLUS | ||||
34 | #include "cp/cp-tree.h" | ||||
35 | #else | ||||
36 | #include "c/c-tree.h" | ||||
37 | #include "c/c-lang.h" | ||||
38 | #endif | ||||
39 | #include "langhooks.h" | ||||
40 | #include "c-family/c-objc.h" | ||||
41 | #include "objc-act.h" | ||||
42 | #include "opts.h" | ||||
43 | |||||
44 | /* When building Objective-C++, we are not linking against the C | ||||
45 | front-end and so need to replicate the C tree-construction | ||||
46 | functions in some way. */ | ||||
47 | #ifdef OBJCPLUS | ||||
48 | #define OBJCP_REMAP_FUNCTIONS | ||||
49 | #include "objcp-decl.h" | ||||
50 | #endif /* OBJCPLUS */ | ||||
51 | |||||
52 | #include "target.h" | ||||
53 | #include "c-family/c-target.h" | ||||
54 | #include "tree-iterator.h" | ||||
55 | |||||
56 | #include "objc-runtime-hooks.h" | ||||
57 | #include "objc-runtime-shared-support.h" | ||||
58 | #include "objc-next-metadata-tags.h" | ||||
59 | #include "objc-encoding.h" | ||||
60 | |||||
61 | /* NeXT ABI 0 and 1 private definitions. */ | ||||
62 | #define DEF_CONSTANT_STRING_CLASS_NAME"NSConstantString" "NSConstantString" | ||||
63 | |||||
64 | #define TAG_GETCLASS"objc_getClass" "objc_getClass" | ||||
65 | #define TAG_GETMETACLASS"objc_getMetaClass" "objc_getMetaClass" | ||||
66 | |||||
67 | #define TAG_MSGSEND"objc_msgSend" "objc_msgSend" | ||||
68 | #define TAG_MSGSENDSUPER"objc_msgSendSuper" "objc_msgSendSuper" | ||||
69 | #define TAG_MSGSEND_STRET"objc_msgSend_stret" "objc_msgSend_stret" | ||||
70 | #define TAG_MSGSENDSUPER_STRET"objc_msgSendSuper_stret" "objc_msgSendSuper_stret" | ||||
71 | |||||
72 | /* NeXT-specific tags. */ | ||||
73 | |||||
74 | #define TAG_MSGSEND_NONNIL"objc_msgSendNonNil" "objc_msgSendNonNil" | ||||
75 | #define TAG_MSGSEND_NONNIL_STRET"objc_msgSendNonNil_stret" "objc_msgSendNonNil_stret" | ||||
76 | #define TAG_EXCEPTIONEXTRACT"objc_exception_extract" "objc_exception_extract" | ||||
77 | #define TAG_EXCEPTIONTRYENTER"objc_exception_try_enter" "objc_exception_try_enter" | ||||
78 | #define TAG_EXCEPTIONTRYEXIT"objc_exception_try_exit" "objc_exception_try_exit" | ||||
79 | #define TAG_EXCEPTIONMATCH"objc_exception_match" "objc_exception_match" | ||||
80 | #define TAG_SETJMP"_setjmp" "_setjmp" | ||||
81 | |||||
82 | #define TAG_ASSIGNIVAR"objc_assign_ivar" "objc_assign_ivar" | ||||
83 | #define TAG_ASSIGNGLOBAL"objc_assign_global" "objc_assign_global" | ||||
84 | #define TAG_ASSIGNSTRONGCAST"objc_assign_strongCast" "objc_assign_strongCast" | ||||
85 | |||||
86 | /* Branch entry points. All that matters here are the addresses; | ||||
87 | functions with these names do not really exist in libobjc. */ | ||||
88 | |||||
89 | #define TAG_MSGSEND_FAST"objc_msgSend_Fast" "objc_msgSend_Fast" | ||||
90 | #define TAG_ASSIGNIVAR_FAST"objc_assign_ivar_Fast" "objc_assign_ivar_Fast" | ||||
91 | |||||
92 | /* The version identifies which language generation and runtime the | ||||
93 | module (file) was compiled for, and is recorded in the module | ||||
94 | descriptor. */ | ||||
95 | #define OBJC_VERSION(global_options.x_flag_objc_abi >= 1 ? 7 : 6) (flag_objc_abiglobal_options.x_flag_objc_abi >= 1 ? 7 : 6) | ||||
96 | |||||
97 | #define UTAG_CLASS_EXT"_objc_class_ext" "_objc_class_ext" | ||||
98 | #define UTAG_PROPERTY_LIST"_prop_list_t" "_prop_list_t" | ||||
99 | #define UTAG_PROTOCOL_EXT"_objc_protocol_extension" "_objc_protocol_extension" | ||||
100 | |||||
101 | #define CLS_HAS_CXX_STRUCTORS0x2000L 0x2000L | ||||
102 | |||||
103 | static void next_runtime_01_initialize (void); | ||||
104 | |||||
105 | static tree next_runtime_abi_01_super_superclassfield_id (void); | ||||
106 | |||||
107 | static tree next_runtime_abi_01_class_decl (tree); | ||||
108 | static tree next_runtime_abi_01_metaclass_decl (tree); | ||||
109 | static tree next_runtime_abi_01_category_decl (tree); | ||||
110 | static tree next_runtime_abi_01_protocol_decl (tree); | ||||
111 | static tree next_runtime_abi_01_string_decl (tree, const char *, string_section); | ||||
112 | |||||
113 | static tree next_runtime_abi_01_get_class_reference (tree); | ||||
114 | static tree next_runtime_abi_01_build_selector_reference (location_t, tree, tree); | ||||
115 | static tree next_runtime_abi_01_get_protocol_reference (location_t, tree); | ||||
116 | static tree next_runtime_abi_01_build_ivar_ref (location_t, tree, tree); | ||||
117 | static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool); | ||||
118 | static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool); | ||||
119 | |||||
120 | static tree next_runtime_abi_01_receiver_is_class_object (tree); | ||||
121 | static void next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **, | ||||
122 | tree, int, int); | ||||
123 | static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree, | ||||
124 | tree, tree, tree, int); | ||||
125 | static bool next_runtime_abi_01_setup_const_string_class_decl (void); | ||||
126 | static tree next_runtime_abi_01_build_const_string_constructor (location_t, tree, int); | ||||
127 | |||||
128 | static void objc_generate_v1_next_metadata (void); | ||||
129 | |||||
130 | static void build_next_objc_exception_stuff (void); | ||||
131 | static tree objc_eh_runtime_type (tree type); | ||||
132 | static tree objc_eh_personality (void); | ||||
133 | static tree build_throw_stmt (location_t, tree, bool); | ||||
134 | static tree objc_build_exc_ptr (struct objc_try_context **); | ||||
135 | static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool); | ||||
136 | static void finish_catch (struct objc_try_context **, tree); | ||||
137 | static tree finish_try_stmt (struct objc_try_context **); | ||||
138 | |||||
139 | bool | ||||
140 | objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks) | ||||
141 | { | ||||
142 | if (flag_objc_exceptionsglobal_options.x_flag_objc_exceptions | ||||
143 | && !flag_objc_sjlj_exceptionsglobal_options.x_flag_objc_sjlj_exceptions) | ||||
144 | { | ||||
145 | warning_at (UNKNOWN_LOCATION((location_t) 0), OPT_Wall, | ||||
146 | "%<-fobjc-sjlj-exceptions%> is the only supported exceptions " | ||||
147 | "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> " | ||||
148 | "argument less than 2"); | ||||
149 | } | ||||
150 | |||||
151 | rthooks->initialize = next_runtime_01_initialize; | ||||
152 | rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME"NSConstantString"; | ||||
153 | rthooks->tag_getclass = TAG_GETCLASS"objc_getClass"; | ||||
154 | rthooks->super_superclassfield_ident = next_runtime_abi_01_super_superclassfield_id; | ||||
155 | |||||
156 | rthooks->class_decl = next_runtime_abi_01_class_decl; | ||||
157 | rthooks->metaclass_decl = next_runtime_abi_01_metaclass_decl; | ||||
158 | rthooks->category_decl = next_runtime_abi_01_category_decl; | ||||
159 | rthooks->protocol_decl = next_runtime_abi_01_protocol_decl; | ||||
160 | rthooks->string_decl = next_runtime_abi_01_string_decl; | ||||
161 | |||||
162 | rthooks->get_class_reference = next_runtime_abi_01_get_class_reference; | ||||
163 | rthooks->build_selector_reference = next_runtime_abi_01_build_selector_reference; | ||||
164 | rthooks->get_protocol_reference = next_runtime_abi_01_get_protocol_reference; | ||||
165 | rthooks->build_ivar_reference = next_runtime_abi_01_build_ivar_ref; | ||||
166 | rthooks->get_class_super_ref = next_runtime_abi_01_get_class_super_ref; | ||||
167 | rthooks->get_category_super_ref = next_runtime_abi_01_get_category_super_ref; | ||||
168 | |||||
169 | rthooks->receiver_is_class_object = next_runtime_abi_01_receiver_is_class_object; | ||||
170 | rthooks->get_arg_type_list_base = next_runtime_abi_01_get_arg_type_list_base; | ||||
171 | rthooks->build_objc_method_call = next_runtime_abi_01_build_objc_method_call; | ||||
172 | |||||
173 | rthooks->setup_const_string_class_decl = | ||||
174 | next_runtime_abi_01_setup_const_string_class_decl; | ||||
175 | rthooks->build_const_string_constructor = | ||||
176 | next_runtime_abi_01_build_const_string_constructor; | ||||
177 | |||||
178 | rthooks->build_throw_stmt = build_throw_stmt; | ||||
179 | rthooks->build_exc_ptr = objc_build_exc_ptr; | ||||
180 | rthooks->begin_catch = begin_catch; | ||||
181 | rthooks->finish_catch = finish_catch; | ||||
182 | rthooks->finish_try_stmt = finish_try_stmt; | ||||
183 | |||||
184 | rthooks->generate_metadata = objc_generate_v1_next_metadata; | ||||
185 | return true; | ||||
186 | } | ||||
187 | |||||
188 | /* We need a way to convey what kind of meta-data are represented by a | ||||
189 | given variable, since each type is expected (by the runtime) to be | ||||
190 | found in a specific named section. The solution must be usable | ||||
191 | with LTO. | ||||
192 | |||||
193 | The scheme used for NeXT ABI 0/1 (partial matching of variable | ||||
194 | names) is not satisfactory for LTO & ABI-2. We now tag ObjC | ||||
195 | meta-data with identification attributes in the front end. The | ||||
196 | back-end may choose to act on these as it requires. */ | ||||
197 | |||||
198 | static void | ||||
199 | next_runtime_abi_01_init_metadata_attributes (void) | ||||
200 | { | ||||
201 | if (!objc_metaobjc_rt_trees[OCTI_RT_OBJC_META]) | ||||
202 | objc_metaobjc_rt_trees[OCTI_RT_OBJC_META] = get_identifier ("OBJC1META")(__builtin_constant_p ("OBJC1META") ? get_identifier_with_length (("OBJC1META"), strlen ("OBJC1META")) : get_identifier ("OBJC1META" )); | ||||
203 | |||||
204 | if (!meta_baseobjc_rt_trees[OCTI_RT_META_BASE]) | ||||
205 | meta_baseobjc_rt_trees[OCTI_RT_META_BASE] = get_identifier ("V1_BASE")(__builtin_constant_p ("V1_BASE") ? get_identifier_with_length (("V1_BASE"), strlen ("V1_BASE")) : get_identifier ("V1_BASE" )); | ||||
206 | |||||
207 | meta_classobjc_rt_trees[OCTI_RT_META_CLASS] = get_identifier ("V1_CLAS")(__builtin_constant_p ("V1_CLAS") ? get_identifier_with_length (("V1_CLAS"), strlen ("V1_CLAS")) : get_identifier ("V1_CLAS" )); | ||||
208 | meta_metaclassobjc_rt_trees[OCTI_RT_META_METACLASS] = get_identifier ("V1_META")(__builtin_constant_p ("V1_META") ? get_identifier_with_length (("V1_META"), strlen ("V1_META")) : get_identifier ("V1_META" )); | ||||
209 | meta_categoryobjc_rt_trees[OCTI_RT_META_CATEGORY] = get_identifier ("V1_CATG")(__builtin_constant_p ("V1_CATG") ? get_identifier_with_length (("V1_CATG"), strlen ("V1_CATG")) : get_identifier ("V1_CATG" )); | ||||
210 | meta_protocolobjc_rt_trees[OCTI_RT_META_PROTOCOL] = get_identifier ("V1_PROT")(__builtin_constant_p ("V1_PROT") ? get_identifier_with_length (("V1_PROT"), strlen ("V1_PROT")) : get_identifier ("V1_PROT" )); | ||||
211 | |||||
212 | meta_clac_varsobjc_rt_trees[OCTI_RT_META_CLASS_CLS_VARS] = get_identifier ("V1_CLCV")(__builtin_constant_p ("V1_CLCV") ? get_identifier_with_length (("V1_CLCV"), strlen ("V1_CLCV")) : get_identifier ("V1_CLCV" )); | ||||
213 | meta_clai_varsobjc_rt_trees[OCTI_RT_META_CLASS_NST_VARS] = get_identifier ("V1_CLIV")(__builtin_constant_p ("V1_CLIV") ? get_identifier_with_length (("V1_CLIV"), strlen ("V1_CLIV")) : get_identifier ("V1_CLIV" )); | ||||
214 | |||||
215 | meta_clac_methobjc_rt_trees[OCTI_RT_META_CLASS_CLS_METH] = get_identifier ("V1_CLCM")(__builtin_constant_p ("V1_CLCM") ? get_identifier_with_length (("V1_CLCM"), strlen ("V1_CLCM")) : get_identifier ("V1_CLCM" )); | ||||
216 | meta_clai_methobjc_rt_trees[OCTI_RT_META_CLASS_NST_METH] = get_identifier ("V1_CLIM")(__builtin_constant_p ("V1_CLIM") ? get_identifier_with_length (("V1_CLIM"), strlen ("V1_CLIM")) : get_identifier ("V1_CLIM" )); | ||||
217 | meta_catc_methobjc_rt_trees[OCTI_RT_META_CATEG_CLS_METH] = get_identifier ("V1_CACM")(__builtin_constant_p ("V1_CACM") ? get_identifier_with_length (("V1_CACM"), strlen ("V1_CACM")) : get_identifier ("V1_CACM" )); | ||||
218 | meta_cati_methobjc_rt_trees[OCTI_RT_META_CATEG_NST_METH] = get_identifier ("V1_CAIM")(__builtin_constant_p ("V1_CAIM") ? get_identifier_with_length (("V1_CAIM"), strlen ("V1_CAIM")) : get_identifier ("V1_CAIM" )); | ||||
219 | meta_proto_cls_methobjc_rt_trees[OCTI_RT_META_PROTO_CLS_METH] = get_identifier ("V1_PCLM")(__builtin_constant_p ("V1_PCLM") ? get_identifier_with_length (("V1_PCLM"), strlen ("V1_PCLM")) : get_identifier ("V1_PCLM" )); | ||||
220 | meta_proto_nst_methobjc_rt_trees[OCTI_RT_META_PROTO_NST_METH] = get_identifier ("V1_PNSM")(__builtin_constant_p ("V1_PNSM") ? get_identifier_with_length (("V1_PNSM"), strlen ("V1_PNSM")) : get_identifier ("V1_PNSM" )); | ||||
221 | |||||
222 | meta_clas_protobjc_rt_trees[OCTI_RT_META_CLASS_PROT] = get_identifier ("V1_CLPR")(__builtin_constant_p ("V1_CLPR") ? get_identifier_with_length (("V1_CLPR"), strlen ("V1_CLPR")) : get_identifier ("V1_CLPR" )); | ||||
223 | meta_catg_protobjc_rt_trees[OCTI_RT_META_CATEG_PROT] = get_identifier ("V1_CAPR")(__builtin_constant_p ("V1_CAPR") ? get_identifier_with_length (("V1_CAPR"), strlen ("V1_CAPR")) : get_identifier ("V1_CAPR" )); | ||||
224 | |||||
225 | meta_class_referenceobjc_rt_trees[OCTI_RT_META_CLASS_REF] = get_identifier ("V1_CLRF")(__builtin_constant_p ("V1_CLRF") ? get_identifier_with_length (("V1_CLRF"), strlen ("V1_CLRF")) : get_identifier ("V1_CLRF" )); | ||||
226 | meta_proto_refobjc_rt_trees[OCTI_RT_META_PROT_REFS] = get_identifier ("V1_PRFS")(__builtin_constant_p ("V1_PRFS") ? get_identifier_with_length (("V1_PRFS"), strlen ("V1_PRFS")) : get_identifier ("V1_PRFS" )); | ||||
227 | meta_sel_refsobjc_rt_trees[OCTI_RT_META_SEL_REFS] = get_identifier ("V1_SRFS")(__builtin_constant_p ("V1_SRFS") ? get_identifier_with_length (("V1_SRFS"), strlen ("V1_SRFS")) : get_identifier ("V1_SRFS" )); | ||||
228 | |||||
229 | meta_class_nameobjc_rt_trees[OCTI_RT_META_CLASS_NAME] = get_identifier ("V1_CLSN")(__builtin_constant_p ("V1_CLSN") ? get_identifier_with_length (("V1_CLSN"), strlen ("V1_CLSN")) : get_identifier ("V1_CLSN" )); | ||||
230 | meta_meth_nameobjc_rt_trees[OCTI_RT_META_METHD_NAME] = get_identifier ("V1_METN")(__builtin_constant_p ("V1_METN") ? get_identifier_with_length (("V1_METN"), strlen ("V1_METN")) : get_identifier ("V1_METN" )); | ||||
231 | meta_meth_typeobjc_rt_trees[OCTI_RT_META_METHD_TYPE] = get_identifier ("V1_METT")(__builtin_constant_p ("V1_METT") ? get_identifier_with_length (("V1_METT"), strlen ("V1_METT")) : get_identifier ("V1_METT" )); | ||||
232 | meta_prop_name_attrobjc_rt_trees[OCTI_RT_META_PROPN_ATTR] = get_identifier ("V1_STRG")(__builtin_constant_p ("V1_STRG") ? get_identifier_with_length (("V1_STRG"), strlen ("V1_STRG")) : get_identifier ("V1_STRG" )); | ||||
233 | |||||
234 | meta_modulesobjc_rt_trees[OCTI_RT_META_MODULES] = get_identifier ("V1_MODU")(__builtin_constant_p ("V1_MODU") ? get_identifier_with_length (("V1_MODU"), strlen ("V1_MODU")) : get_identifier ("V1_MODU" )); | ||||
235 | meta_symtabobjc_rt_trees[OCTI_RT_META_SYMTAB] = get_identifier ("V1_SYMT")(__builtin_constant_p ("V1_SYMT") ? get_identifier_with_length (("V1_SYMT"), strlen ("V1_SYMT")) : get_identifier ("V1_SYMT" )); | ||||
236 | meta_infoobjc_rt_trees[OCTI_RT_META_INFO] = get_identifier ("V1_INFO")(__builtin_constant_p ("V1_INFO") ? get_identifier_with_length (("V1_INFO"), strlen ("V1_INFO")) : get_identifier ("V1_INFO" )); | ||||
237 | |||||
238 | meta_proplistobjc_rt_trees[OCTI_RT_META_PROPERTY_LIST] = get_identifier ("V1_PLST")(__builtin_constant_p ("V1_PLST") ? get_identifier_with_length (("V1_PLST"), strlen ("V1_PLST")) : get_identifier ("V1_PLST" )); | ||||
239 | meta_protocol_extensionobjc_rt_trees[OCTI_RT_META_PROTOCOL_EXT] = get_identifier ("V1_PEXT")(__builtin_constant_p ("V1_PEXT") ? get_identifier_with_length (("V1_PEXT"), strlen ("V1_PEXT")) : get_identifier ("V1_PEXT" )); | ||||
240 | meta_class_extensionobjc_rt_trees[OCTI_RT_META_CLASS_EXT] = get_identifier ("V1_CEXT")(__builtin_constant_p ("V1_CEXT") ? get_identifier_with_length (("V1_CEXT"), strlen ("V1_CEXT")) : get_identifier ("V1_CEXT" )); | ||||
241 | |||||
242 | meta_const_strobjc_rt_trees[OCTI_RT_META_CONST_STR] = get_identifier ("V1_CSTR")(__builtin_constant_p ("V1_CSTR") ? get_identifier_with_length (("V1_CSTR"), strlen ("V1_CSTR")) : get_identifier ("V1_CSTR" )); | ||||
243 | } | ||||
244 | |||||
245 | static void build_v1_class_template (void); | ||||
246 | static void build_v1_category_template (void); | ||||
247 | static void build_v1_protocol_template (void); | ||||
248 | |||||
249 | static void next_runtime_01_initialize (void) | ||||
250 | { | ||||
251 | tree type; | ||||
252 | |||||
253 | #ifdef OBJCPLUS | ||||
254 | /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by | ||||
255 | default. */ | ||||
256 | if (!OPTION_SET_P (flag_objc_call_cxx_cdtors)global_options_set.x_flag_objc_call_cxx_cdtors) | ||||
257 | global_options.x_flag_objc_call_cxx_cdtors = 1; | ||||
258 | #endif | ||||
259 | |||||
260 | /* Set up attributes to be attached to the meta-data so that they | ||||
261 | will be placed in the correct sections. */ | ||||
262 | next_runtime_abi_01_init_metadata_attributes (); | ||||
263 | |||||
264 | if (flag_objc_abiglobal_options.x_flag_objc_abi >= 1) | ||||
265 | objc_prop_list_ptrobjc_global_trees[OCTI_V1_PROP_LIST_TEMPL] = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
266 | get_identifier ("_prop_list_t")(__builtin_constant_p ("_prop_list_t") ? get_identifier_with_length (("_prop_list_t"), strlen ("_prop_list_t")) : get_identifier ("_prop_list_t")))); | ||||
267 | |||||
268 | /* Declare type of selector-objects that represent an operation | ||||
269 | name. */ | ||||
270 | /* `struct objc_selector *' */ | ||||
271 | objc_selector_typeobjc_global_trees[OCTI_SEL_TYPE] = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
272 | get_identifier (TAG_SELECTOR)(__builtin_constant_p ("objc_selector") ? get_identifier_with_length (("objc_selector"), strlen ("objc_selector")) : get_identifier ("objc_selector")))); | ||||
273 | |||||
274 | /* SEL typedef. */ | ||||
275 | type = lang_hooks.decls.pushdecl (build_decl (input_location, | ||||
276 | TYPE_DECL, | ||||
277 | objc_selector_nameobjc_global_trees[OCTI_SEL_NAME], | ||||
278 | objc_selector_typeobjc_global_trees[OCTI_SEL_TYPE])); | ||||
279 | suppress_warning (type); | ||||
280 | |||||
281 | build_v1_class_template (); | ||||
282 | build_super_template (); | ||||
283 | build_v1_protocol_template (); | ||||
284 | build_v1_category_template (); | ||||
285 | |||||
286 | /* NB: In order to call one of the ..._stret (struct-returning) | ||||
287 | functions, the function *MUST* first be cast to a signature that | ||||
288 | corresponds to the actual ObjC method being invoked. This is | ||||
289 | what is done by the build_objc_method_call() routine below. */ | ||||
290 | |||||
291 | /* id objc_msgSend (id, SEL, ...); */ | ||||
292 | /* id objc_msgSendNonNil (id, SEL, ...); */ | ||||
293 | /* id objc_msgSend_stret (id, SEL, ...); */ | ||||
294 | /* id objc_msgSendNonNil_stret (id, SEL, ...); */ | ||||
295 | type = build_varargs_function_type_list (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
296 | objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
297 | objc_selector_typeobjc_global_trees[OCTI_SEL_TYPE], | ||||
298 | NULL_TREE(tree) nullptr); | ||||
299 | |||||
300 | umsg_declobjc_global_trees[OCTI_UMSG_DECL] = add_builtin_function (TAG_MSGSEND"objc_msgSend", | ||||
301 | type, 0, NOT_BUILT_IN, | ||||
302 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
303 | |||||
304 | umsg_nonnil_declobjc_global_trees[OCTI_UMSG_NONNIL_DECL] = add_builtin_function (TAG_MSGSEND_NONNIL"objc_msgSendNonNil", | ||||
305 | type, 0, NOT_BUILT_IN, | ||||
306 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
307 | |||||
308 | umsg_stret_declobjc_global_trees[OCTI_UMSG_STRET_DECL] = add_builtin_function (TAG_MSGSEND_STRET"objc_msgSend_stret", | ||||
309 | type, 0, NOT_BUILT_IN, | ||||
310 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
311 | |||||
312 | umsg_nonnil_stret_declobjc_global_trees[OCTI_UMSG_NONNIL_STRET_DECL] = add_builtin_function (TAG_MSGSEND_NONNIL_STRET"objc_msgSendNonNil_stret", | ||||
313 | type, 0, NOT_BUILT_IN, | ||||
314 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
315 | |||||
316 | /* These can throw, because the function that gets called can throw | ||||
317 | in Obj-C++, or could itself call something that can throw even in | ||||
318 | Obj-C. */ | ||||
319 | TREE_NOTHROW (umsg_decl)((objc_global_trees[OCTI_UMSG_DECL])->base.nothrow_flag) = 0; | ||||
320 | TREE_NOTHROW (umsg_nonnil_decl)((objc_global_trees[OCTI_UMSG_NONNIL_DECL])->base.nothrow_flag ) = 0; | ||||
321 | TREE_NOTHROW (umsg_stret_decl)((objc_global_trees[OCTI_UMSG_STRET_DECL])->base.nothrow_flag ) = 0; | ||||
322 | TREE_NOTHROW (umsg_nonnil_stret_decl)((objc_global_trees[OCTI_UMSG_NONNIL_STRET_DECL])->base.nothrow_flag ) = 0; | ||||
323 | |||||
324 | /* id objc_msgSend_Fast (id, SEL, ...) | ||||
325 | __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */ | ||||
326 | #ifdef OFFS_MSGSEND_FAST | ||||
327 | umsg_fast_declobjc_global_trees[OCTI_UMSG_FAST_DECL] = add_builtin_function (TAG_MSGSEND_FAST"objc_msgSend_Fast", | ||||
328 | type, 0, NOT_BUILT_IN, | ||||
329 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
330 | TREE_NOTHROW (umsg_fast_decl)((objc_global_trees[OCTI_UMSG_FAST_DECL])->base.nothrow_flag ) = 0; | ||||
331 | DECL_ATTRIBUTES (umsg_fast_decl)((contains_struct_check ((objc_global_trees[OCTI_UMSG_FAST_DECL ]), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 331, __FUNCTION__))->decl_common.attributes) | ||||
332 | = tree_cons (get_identifier ("hard_coded_address")(__builtin_constant_p ("hard_coded_address") ? get_identifier_with_length (("hard_coded_address"), strlen ("hard_coded_address")) : get_identifier ("hard_coded_address")), | ||||
333 | build_int_cst (NULL_TREE(tree) nullptr, OFFS_MSGSEND_FAST), | ||||
334 | NULL_TREE(tree) nullptr); | ||||
335 | #else | ||||
336 | /* No direct dispatch available. */ | ||||
337 | umsg_fast_declobjc_global_trees[OCTI_UMSG_FAST_DECL] = umsg_declobjc_global_trees[OCTI_UMSG_DECL]; | ||||
338 | #endif | ||||
339 | |||||
340 | /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */ | ||||
341 | /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */ | ||||
342 | type = build_varargs_function_type_list (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
343 | objc_super_typeobjc_global_trees[OCTI_SUPER_TYPE], | ||||
344 | objc_selector_typeobjc_global_trees[OCTI_SEL_TYPE], | ||||
345 | NULL_TREE(tree) nullptr); | ||||
346 | umsg_super_declobjc_global_trees[OCTI_UMSG_SUPER_DECL] = add_builtin_function (TAG_MSGSENDSUPER"objc_msgSendSuper", | ||||
347 | type, 0, NOT_BUILT_IN, | ||||
348 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
349 | umsg_super_stret_declobjc_global_trees[OCTI_UMSG_SUPER_STRET_DECL] = add_builtin_function (TAG_MSGSENDSUPER_STRET"objc_msgSendSuper_stret", | ||||
350 | type, 0, NOT_BUILT_IN, 0, | ||||
351 | NULL_TREE(tree) nullptr); | ||||
352 | TREE_NOTHROW (umsg_super_decl)((objc_global_trees[OCTI_UMSG_SUPER_DECL])->base.nothrow_flag ) = 0; | ||||
353 | TREE_NOTHROW (umsg_super_stret_decl)((objc_global_trees[OCTI_UMSG_SUPER_STRET_DECL])->base.nothrow_flag ) = 0; | ||||
354 | |||||
355 | type = build_function_type_list (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
356 | const_string_type_nodec_global_trees[CTI_CONST_STRING_TYPE], | ||||
357 | NULL_TREE(tree) nullptr); | ||||
358 | |||||
359 | /* id objc_getClass (const char *); */ | ||||
360 | objc_get_class_declobjc_global_trees[OCTI_GET_CLASS_DECL] | ||||
361 | = add_builtin_function (TAG_GETCLASS"objc_getClass", type, 0, NOT_BUILT_IN, | ||||
362 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
363 | |||||
364 | /* id objc_getMetaClass (const char *); */ | ||||
365 | objc_get_meta_class_declobjc_global_trees[OCTI_GET_MCLASS_DECL] | ||||
366 | = add_builtin_function (TAG_GETMETACLASS"objc_getMetaClass", type, 0, NOT_BUILT_IN, NULLnullptr, NULL_TREE(tree) nullptr); | ||||
367 | |||||
368 | /* This is the type of all of the following functions | ||||
369 | objc_copyStruct(). */ | ||||
370 | type = build_function_type_list (void_type_nodeglobal_trees[TI_VOID_TYPE], | ||||
371 | ptr_type_nodeglobal_trees[TI_PTR_TYPE], | ||||
372 | const_ptr_type_nodeglobal_trees[TI_CONST_PTR_TYPE], | ||||
373 | ptrdiff_type_nodeglobal_trees[TI_PTRDIFF_TYPE], | ||||
374 | boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], | ||||
375 | boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], | ||||
376 | NULL_TREE(tree) nullptr); | ||||
377 | /* Declare the following function: | ||||
378 | void | ||||
379 | objc_copyStruct (void *destination, const void *source, | ||||
380 | ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */ | ||||
381 | objc_copyStruct_declobjc_global_trees[OCTI_COPY_STRUCT_DECL] = add_builtin_function ("objc_copyStruct", | ||||
382 | type, 0, NOT_BUILT_IN, | ||||
383 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
384 | TREE_NOTHROW (objc_copyStruct_decl)((objc_global_trees[OCTI_COPY_STRUCT_DECL])->base.nothrow_flag ) = 0; | ||||
385 | objc_getPropertyStruct_declobjc_global_trees[OCTI_GET_PROPERTY_STRUCT_DECL] = NULL_TREE(tree) nullptr; | ||||
386 | objc_setPropertyStruct_declobjc_global_trees[OCTI_SET_PROPERTY_STRUCT_DECL] = NULL_TREE(tree) nullptr; | ||||
387 | |||||
388 | build_next_objc_exception_stuff (); | ||||
389 | if (flag_objc_exceptionsglobal_options.x_flag_objc_exceptions && !flag_objc_sjlj_exceptionsglobal_options.x_flag_objc_sjlj_exceptions) | ||||
390 | using_eh_for_cleanups (); | ||||
391 | lang_hooks.eh_runtime_type = objc_eh_runtime_type; | ||||
392 | lang_hooks.eh_personality = objc_eh_personality; | ||||
393 | } | ||||
394 | |||||
395 | /* --- templates --- */ | ||||
396 | |||||
397 | /* struct _objc_class | ||||
398 | { | ||||
399 | struct _objc_class *isa; | ||||
400 | struct _objc_class *super_class; | ||||
401 | char *name; | ||||
402 | long version; | ||||
403 | long info; | ||||
404 | long instance_size; | ||||
405 | struct _objc_ivar_list *ivars; | ||||
406 | struct _objc_method_list *methods; | ||||
407 | struct objc_cache *cache; | ||||
408 | struct _objc_protocol_list *protocols; | ||||
409 | #if ABI=1 | ||||
410 | const char *ivar_layout; | ||||
411 | struct _objc_class_ext *ext; | ||||
412 | #else | ||||
413 | void *sel_id; | ||||
414 | void *gc_object_type; | ||||
415 | #endif | ||||
416 | }; */ | ||||
417 | |||||
418 | /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT | ||||
419 | runtime. We generate them for ABI==0 to maintain backward binary | ||||
420 | compatibility. */ | ||||
421 | |||||
422 | static void | ||||
423 | build_v1_class_template (void) | ||||
424 | { | ||||
425 | tree ptype, decls, *chain = NULLnullptr; | ||||
426 | |||||
427 | objc_class_templateobjc_global_trees[OCTI_CLS_TEMPL] = objc_start_struct (get_identifier (UTAG_CLASS)(__builtin_constant_p ("_objc_class") ? get_identifier_with_length (("_objc_class"), strlen ("_objc_class")) : get_identifier ( "_objc_class"))); | ||||
428 | |||||
429 | /* struct _objc_class *isa; */ | ||||
430 | decls = add_field_decl (build_pointer_type (objc_class_templateobjc_global_trees[OCTI_CLS_TEMPL]), | ||||
431 | "isa", &chain); | ||||
432 | |||||
433 | /* struct _objc_class *super_class; */ | ||||
434 | add_field_decl (build_pointer_type (objc_class_templateobjc_global_trees[OCTI_CLS_TEMPL]), | ||||
435 | "super_class", &chain); | ||||
436 | |||||
437 | /* char *name; */ | ||||
438 | add_field_decl (string_type_nodec_global_trees[CTI_STRING_TYPE], "name", &chain); | ||||
439 | |||||
440 | /* long version; */ | ||||
441 | add_field_decl (long_integer_type_nodeinteger_types[itk_long], "version", &chain); | ||||
442 | |||||
443 | /* long info; */ | ||||
444 | add_field_decl (long_integer_type_nodeinteger_types[itk_long], "info", &chain); | ||||
445 | |||||
446 | /* long instance_size; */ | ||||
447 | add_field_decl (long_integer_type_nodeinteger_types[itk_long], "instance_size", &chain); | ||||
448 | |||||
449 | /* struct _objc_ivar_list *ivars; */ | ||||
450 | add_field_decl (objc_ivar_list_ptrobjc_global_trees[OCTI_IVAR_LIST_TEMPL],"ivars", &chain); | ||||
451 | |||||
452 | /* struct _objc_method_list *methods; */ | ||||
453 | add_field_decl (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], "methods", &chain); | ||||
454 | |||||
455 | /* struct objc_cache *cache; */ | ||||
456 | ptype = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
457 | get_identifier ("objc_cache")(__builtin_constant_p ("objc_cache") ? get_identifier_with_length (("objc_cache"), strlen ("objc_cache")) : get_identifier ("objc_cache" )))); | ||||
458 | add_field_decl (ptype, "cache", &chain); | ||||
459 | |||||
460 | /* struct _objc_protocol **protocol_list; */ | ||||
461 | ptype = build_pointer_type (build_pointer_type | ||||
462 | (xref_tag (RECORD_TYPE, | ||||
463 | get_identifier (UTAG_PROTOCOL)(__builtin_constant_p ("_objc_protocol") ? get_identifier_with_length (("_objc_protocol"), strlen ("_objc_protocol")) : get_identifier ("_objc_protocol"))))); | ||||
464 | add_field_decl (ptype, "protocol_list", &chain); | ||||
465 | |||||
466 | if (flag_objc_abiglobal_options.x_flag_objc_abi >= 1) | ||||
467 | { | ||||
468 | /* const char *ivar_layout; */ | ||||
469 | add_field_decl (const_string_type_nodec_global_trees[CTI_CONST_STRING_TYPE], "ivar_layout", &chain); | ||||
470 | |||||
471 | /* struct _objc_class_ext *ext; */ | ||||
472 | ptype = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
473 | get_identifier (UTAG_CLASS_EXT)(__builtin_constant_p ("_objc_class_ext") ? get_identifier_with_length (("_objc_class_ext"), strlen ("_objc_class_ext")) : get_identifier ("_objc_class_ext")))); | ||||
474 | add_field_decl (ptype, "ext", &chain); | ||||
475 | } | ||||
476 | else | ||||
477 | { | ||||
478 | /* void *sel_id; */ | ||||
479 | add_field_decl (build_pointer_type (void_type_nodeglobal_trees[TI_VOID_TYPE]), "sel_id", &chain); | ||||
480 | /* void *gc_object_type; */ | ||||
481 | add_field_decl (build_pointer_type (void_type_nodeglobal_trees[TI_VOID_TYPE]), "gc_object_type", | ||||
482 | &chain); | ||||
483 | } | ||||
484 | |||||
485 | objc_finish_struct (objc_class_templateobjc_global_trees[OCTI_CLS_TEMPL], decls); | ||||
486 | } | ||||
487 | |||||
488 | /* struct _objc_category | ||||
489 | { | ||||
490 | char *category_name; | ||||
491 | char *class_name; | ||||
492 | struct _objc_method_list *instance_methods; | ||||
493 | struct _objc_method_list *class_methods; | ||||
494 | struct _objc_protocol_list *protocols; | ||||
495 | #if ABI=1 | ||||
496 | uint32_t size; // sizeof (struct _objc_category) | ||||
497 | struct _objc_property_list *instance_properties; // category's own @property decl. | ||||
498 | #endif | ||||
499 | }; */ | ||||
500 | |||||
501 | static void | ||||
502 | build_v1_category_template (void) | ||||
503 | { | ||||
504 | tree ptype, decls, *chain = NULLnullptr; | ||||
505 | |||||
506 | objc_category_templateobjc_global_trees[OCTI_CAT_TEMPL] = objc_start_struct (get_identifier (UTAG_CATEGORY)(__builtin_constant_p ("_objc_category") ? get_identifier_with_length (("_objc_category"), strlen ("_objc_category")) : get_identifier ("_objc_category"))); | ||||
507 | |||||
508 | /* char *category_name; */ | ||||
509 | decls = add_field_decl (string_type_nodec_global_trees[CTI_STRING_TYPE], "category_name", &chain); | ||||
510 | |||||
511 | /* char *class_name; */ | ||||
512 | add_field_decl (string_type_nodec_global_trees[CTI_STRING_TYPE], "class_name", &chain); | ||||
513 | |||||
514 | /* struct _objc_method_list *instance_methods; */ | ||||
515 | add_field_decl (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], "instance_methods", &chain); | ||||
516 | |||||
517 | /* struct _objc_method_list *class_methods; */ | ||||
518 | add_field_decl (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], "class_methods", &chain); | ||||
519 | |||||
520 | /* struct _objc_protocol **protocol_list; */ | ||||
521 | ptype = build_pointer_type (build_pointer_type (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL])); | ||||
522 | add_field_decl (ptype, "protocol_list", &chain); | ||||
523 | |||||
524 | if (flag_objc_abiglobal_options.x_flag_objc_abi >= 1) | ||||
525 | { | ||||
526 | add_field_decl (integer_type_nodeinteger_types[itk_int], "size", &chain); | ||||
527 | |||||
528 | /* struct _objc_property_list *instance_properties; | ||||
529 | This field describes a category's @property declarations. | ||||
530 | Properties from inherited protocols are not included. */ | ||||
531 | ptype = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
532 | get_identifier (UTAG_PROPERTY_LIST)(__builtin_constant_p ("_prop_list_t") ? get_identifier_with_length (("_prop_list_t"), strlen ("_prop_list_t")) : get_identifier ("_prop_list_t")))); | ||||
533 | add_field_decl (ptype, "instance_properties", &chain); | ||||
534 | } | ||||
535 | objc_finish_struct (objc_category_templateobjc_global_trees[OCTI_CAT_TEMPL], decls); | ||||
536 | } | ||||
537 | |||||
538 | /* Begin code generation for protocols... | ||||
539 | Modified for ObjC #1 extensions. */ | ||||
540 | |||||
541 | /* struct _objc_protocol | ||||
542 | { | ||||
543 | #if ABI=1 | ||||
544 | struct _objc_protocol_extension *isa; | ||||
545 | #else | ||||
546 | struct _objc_class *isa; | ||||
547 | #endif | ||||
548 | |||||
549 | char *protocol_name; | ||||
550 | struct _objc_protocol **protocol_list; | ||||
551 | struct _objc__method_prototype_list *instance_methods; | ||||
552 | struct _objc__method_prototype_list *class_methods; | ||||
553 | }; */ | ||||
554 | |||||
555 | static void | ||||
556 | build_v1_protocol_template (void) | ||||
557 | { | ||||
558 | tree ptype, decls, *chain = NULLnullptr; | ||||
559 | |||||
560 | objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL] = objc_start_struct (get_identifier (UTAG_PROTOCOL)(__builtin_constant_p ("_objc_protocol") ? get_identifier_with_length (("_objc_protocol"), strlen ("_objc_protocol")) : get_identifier ("_objc_protocol"))); | ||||
561 | |||||
562 | if (flag_objc_abiglobal_options.x_flag_objc_abi >= 1) | ||||
563 | /* struct _objc_protocol_extension *isa; */ | ||||
564 | ptype = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
565 | get_identifier (UTAG_PROTOCOL_EXT)(__builtin_constant_p ("_objc_protocol_extension") ? get_identifier_with_length (("_objc_protocol_extension"), strlen ("_objc_protocol_extension" )) : get_identifier ("_objc_protocol_extension")))); | ||||
566 | else | ||||
567 | /* struct _objc_class *isa; */ | ||||
568 | ptype = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
569 | get_identifier (UTAG_CLASS)(__builtin_constant_p ("_objc_class") ? get_identifier_with_length (("_objc_class"), strlen ("_objc_class")) : get_identifier ( "_objc_class")))); | ||||
570 | |||||
571 | decls = add_field_decl (ptype, "isa", &chain); | ||||
572 | |||||
573 | /* char *protocol_name; */ | ||||
574 | add_field_decl (string_type_nodec_global_trees[CTI_STRING_TYPE], "protocol_name", &chain); | ||||
575 | |||||
576 | /* struct _objc_protocol **protocol_list; */ | ||||
577 | ptype = build_pointer_type (build_pointer_type (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL])); | ||||
578 | add_field_decl (ptype, "protocol_list", &chain); | ||||
579 | |||||
580 | /* struct _objc__method_prototype_list *instance_methods; */ | ||||
581 | add_field_decl (objc_method_proto_list_ptrobjc_global_trees[OCTI_METH_PROTO_LIST_TEMPL], "instance_methods", &chain); | ||||
582 | |||||
583 | /* struct _objc__method_prototype_list *class_methods; */ | ||||
584 | add_field_decl (objc_method_proto_list_ptrobjc_global_trees[OCTI_METH_PROTO_LIST_TEMPL], "class_methods", &chain); | ||||
585 | |||||
586 | objc_finish_struct (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL], decls); | ||||
587 | } | ||||
588 | |||||
589 | /* --- names, decls identifiers --- */ | ||||
590 | |||||
591 | static tree | ||||
592 | next_runtime_abi_01_super_superclassfield_id (void) | ||||
593 | { | ||||
594 | if (!super_superclassfield_idobjc_global_trees[OCTI_SUPER_SUPERFIELD_ID]) | ||||
595 | super_superclassfield_idobjc_global_trees[OCTI_SUPER_SUPERFIELD_ID] = get_identifier ("super_class")(__builtin_constant_p ("super_class") ? get_identifier_with_length (("super_class"), strlen ("super_class")) : get_identifier ( "super_class")); | ||||
596 | return super_superclassfield_idobjc_global_trees[OCTI_SUPER_SUPERFIELD_ID]; | ||||
597 | } | ||||
598 | |||||
599 | static tree | ||||
600 | next_runtime_abi_01_class_decl (tree klass) | ||||
601 | { | ||||
602 | tree decl; | ||||
603 | char buf[BUFSIZE1024]; | ||||
604 | snprintf (buf, BUFSIZE1024, "_OBJC_Class_%s", | ||||
605 | IDENTIFIER_POINTER (CLASS_NAME (klass))((const char *) (tree_check (((((tree_class_check ((klass), ( tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 605, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 605, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
606 | decl = start_var_decl (objc_class_templateobjc_global_trees[OCTI_CLS_TEMPL], buf); | ||||
607 | OBJCMETA (decl, objc_meta, meta_class)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 607, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_CLASS ]));; | ||||
608 | return decl; | ||||
609 | } | ||||
610 | |||||
611 | static tree | ||||
612 | next_runtime_abi_01_metaclass_decl (tree klass) | ||||
613 | { | ||||
614 | tree decl; | ||||
615 | char buf[BUFSIZE1024]; | ||||
616 | snprintf (buf, BUFSIZE1024, "_OBJC_MetaClass_%s", | ||||
617 | IDENTIFIER_POINTER (CLASS_NAME (klass))((const char *) (tree_check (((((tree_class_check ((klass), ( tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 617, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 617, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
618 | decl = start_var_decl (objc_class_templateobjc_global_trees[OCTI_CLS_TEMPL], buf); | ||||
619 | OBJCMETA (decl, objc_meta, meta_metaclass)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 619, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_METACLASS ]));; | ||||
620 | return decl; | ||||
621 | } | ||||
622 | |||||
623 | static tree | ||||
624 | next_runtime_abi_01_category_decl (tree klass) | ||||
625 | { | ||||
626 | tree decl; | ||||
627 | char buf[BUFSIZE1024]; | ||||
628 | snprintf (buf, BUFSIZE1024, "_OBJC_Category_%s_on_%s", | ||||
629 | IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass))((const char *) (tree_check (((((tree_class_check ((klass), ( tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 629, __FUNCTION__))->type_common.context))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 629, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | ||||
630 | IDENTIFIER_POINTER (CLASS_NAME (klass))((const char *) (tree_check (((((tree_class_check ((klass), ( tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 630, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 630, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
631 | decl = start_var_decl (objc_category_templateobjc_global_trees[OCTI_CAT_TEMPL], buf); | ||||
632 | OBJCMETA (decl, objc_meta, meta_category)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 632, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_CATEGORY ]));; | ||||
633 | return decl; | ||||
634 | } | ||||
635 | |||||
636 | static tree | ||||
637 | next_runtime_abi_01_protocol_decl (tree p) | ||||
638 | { | ||||
639 | tree decl; | ||||
640 | char buf[BUFSIZE1024]; | ||||
641 | |||||
642 | /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */ | ||||
643 | |||||
644 | snprintf (buf, BUFSIZE1024, "_OBJC_Protocol_%s", | ||||
645 | IDENTIFIER_POINTER (PROTOCOL_NAME (p))((const char *) (tree_check (((((tree_class_check ((p), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 645, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 645, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
646 | decl = start_var_decl (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL], buf); | ||||
647 | OBJCMETA (decl, objc_meta, meta_protocol)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 647, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_PROTOCOL ]));; | ||||
648 | return decl; | ||||
649 | } | ||||
650 | |||||
651 | static tree | ||||
652 | next_runtime_abi_01_string_decl (tree type, const char *name, string_section where) | ||||
653 | { | ||||
654 | tree var = start_var_decl (type, name); | ||||
655 | switch (where) | ||||
656 | { | ||||
657 | case class_names: | ||||
658 | OBJCMETA (var, objc_meta, meta_class_name)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((var), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 658, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_CLASS_NAME ]));; | ||||
659 | break; | ||||
660 | case meth_var_names: | ||||
661 | OBJCMETA (var, objc_meta, meta_meth_name)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((var), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 661, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_METHD_NAME ]));; | ||||
662 | break; | ||||
663 | case meth_var_types: | ||||
664 | OBJCMETA (var, objc_meta, meta_meth_type)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((var), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 664, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_METHD_TYPE ]));; | ||||
665 | break; | ||||
666 | case prop_names_attr: | ||||
667 | OBJCMETA (var, objc_meta, meta_prop_name_attr)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((var), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 667, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_PROPN_ATTR ]));; | ||||
668 | break; | ||||
669 | default: | ||||
670 | OBJCMETA (var, objc_meta, meta_base)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((var), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 670, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_BASE ]));; | ||||
671 | break; | ||||
672 | } | ||||
673 | return var; | ||||
674 | } | ||||
675 | |||||
676 | /* --- entry --- */ | ||||
677 | |||||
678 | static GTY(()) int class_reference_idx; | ||||
679 | |||||
680 | static tree | ||||
681 | build_class_reference_decl (void) | ||||
682 | { | ||||
683 | tree decl; | ||||
684 | char buf[BUFSIZE1024]; | ||||
685 | |||||
686 | sprintf (buf, "_OBJC_ClassRefs_%d", class_reference_idx++); | ||||
687 | decl = start_var_decl (objc_class_typeobjc_global_trees[OCTI_CLS_TYPE], buf); | ||||
688 | |||||
689 | return decl; | ||||
690 | } | ||||
691 | |||||
692 | static tree | ||||
693 | next_runtime_abi_01_get_class_reference (tree ident) | ||||
694 | { | ||||
695 | if (!flag_zero_linkglobal_options.x_flag_zero_link) | ||||
696 | { | ||||
697 | tree *chain; | ||||
698 | tree decl; | ||||
699 | |||||
700 | for (chain = &cls_ref_chainobjc_global_trees[OCTI_CLS_REF_CHAIN]; *chain; chain = &TREE_CHAIN (*chain)((contains_struct_check ((*chain), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 700, __FUNCTION__))->common.chain)) | ||||
701 | if (TREE_VALUE (*chain)((tree_check ((*chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 701, __FUNCTION__, (TREE_LIST)))->list.value) == ident) | ||||
702 | { | ||||
703 | if (! TREE_PURPOSE (*chain)((tree_check ((*chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 703, __FUNCTION__, (TREE_LIST)))->list.purpose)) | ||||
704 | TREE_PURPOSE (*chain)((tree_check ((*chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 704, __FUNCTION__, (TREE_LIST)))->list.purpose) = build_class_reference_decl (); | ||||
705 | |||||
706 | return TREE_PURPOSE (*chain)((tree_check ((*chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 706, __FUNCTION__, (TREE_LIST)))->list.purpose); | ||||
707 | } | ||||
708 | |||||
709 | decl = build_class_reference_decl (); | ||||
710 | *chain = tree_cons (decl, ident, NULL_TREE(tree) nullptr); | ||||
711 | return decl; | ||||
712 | } | ||||
713 | else | ||||
714 | { | ||||
715 | tree params; | ||||
716 | |||||
717 | add_class_reference (ident); | ||||
718 | |||||
719 | params = build_tree_list (NULL_TREE(tree) nullptr, | ||||
720 | my_build_string_pointer | ||||
721 | (IDENTIFIER_LENGTH (ident)((tree_check ((ident), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 721, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.len ) + 1, | ||||
722 | IDENTIFIER_POINTER (ident)((const char *) (tree_check ((ident), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 722, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ))); | ||||
723 | |||||
724 | return build_function_call (input_location, objc_get_class_declobjc_global_trees[OCTI_GET_CLASS_DECL], params); | ||||
725 | } | ||||
726 | } | ||||
727 | |||||
728 | /* Used by build_function_type_for_method. Append the types for | ||||
729 | receiver & _cmd at the start of a method argument list to ARGTYPES. | ||||
730 | CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are | ||||
731 | trying to define a method or call one. SUPERFLAG says this is for a | ||||
732 | send to super. METH may be NULL, in the case that there is no | ||||
733 | prototype. */ | ||||
734 | |||||
735 | static void | ||||
736 | next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **argtypes, | ||||
737 | tree meth, int context, | ||||
738 | int superflag) | ||||
739 | { | ||||
740 | tree receiver_type; | ||||
741 | |||||
742 | if (superflag) | ||||
743 | receiver_type = objc_super_typeobjc_global_trees[OCTI_SUPER_TYPE]; | ||||
744 | else if (context == METHOD_DEF0 && TREE_CODE (meth)((enum tree_code) (meth)->base.code) == INSTANCE_METHOD_DECL) | ||||
745 | receiver_type = objc_instance_typeobjc_global_trees[OCTI_NST_TYPE]; | ||||
746 | else | ||||
747 | receiver_type = objc_object_typeobjc_global_trees[OCTI_ID_TYPE]; | ||||
748 | |||||
749 | vec_safe_push (*argtypes, receiver_type); | ||||
750 | /* Selector type - will eventually change to `int'. */ | ||||
751 | vec_safe_push (*argtypes, objc_selector_typeobjc_global_trees[OCTI_SEL_TYPE]); | ||||
752 | } | ||||
753 | |||||
754 | static tree | ||||
755 | next_runtime_abi_01_receiver_is_class_object (tree receiver) | ||||
756 | { | ||||
757 | if (TREE_CODE (receiver)((enum tree_code) (receiver)->base.code) == VAR_DECL | ||||
758 | && IS_CLASS (TREE_TYPE (receiver))(((enum tree_code) (((contains_struct_check ((receiver), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 758, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE && (((tree_class_check ((((contains_struct_check ((( (contains_struct_check ((receiver), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 758, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 758, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 758, __FUNCTION__))->type_common.main_variant) == ((contains_struct_check ((objc_global_trees[OCTI_CLS_TYPE]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 758, __FUNCTION__))->typed.type)))) | ||||
759 | { | ||||
760 | /* The receiver is a variable created by build_class_reference_decl. */ | ||||
761 | tree chain = cls_ref_chainobjc_global_trees[OCTI_CLS_REF_CHAIN] ; | ||||
762 | /* Look up the identifier in the relevant chain. */ | ||||
763 | for (; chain; chain = TREE_CHAIN (chain)((contains_struct_check ((chain), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 763, __FUNCTION__))->common.chain)) | ||||
764 | if (TREE_PURPOSE (chain)((tree_check ((chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 764, __FUNCTION__, (TREE_LIST)))->list.purpose) == receiver) | ||||
765 | return TREE_VALUE (chain)((tree_check ((chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 765, __FUNCTION__, (TREE_LIST)))->list.value); | ||||
766 | } | ||||
767 | return NULL_TREE(tree) nullptr; | ||||
768 | } | ||||
769 | |||||
770 | static tree | ||||
771 | build_selector_reference_decl (tree ident) | ||||
772 | { | ||||
773 | tree decl; | ||||
774 | char *t, buf[BUFSIZE1024]; | ||||
775 | |||||
776 | snprintf (buf, BUFSIZE1024, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident)((const char *) (tree_check ((ident), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 776, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
777 | t = buf; | ||||
778 | while (*t) | ||||
779 | { | ||||
780 | if (*t==':') | ||||
781 | *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */ | ||||
782 | t++; | ||||
783 | } | ||||
784 | decl = start_var_decl (objc_selector_typeobjc_global_trees[OCTI_SEL_TYPE], buf); | ||||
785 | OBJCMETA (decl, objc_meta, meta_sel_refs)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 785, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_SEL_REFS ]));; | ||||
786 | return decl; | ||||
787 | } | ||||
788 | |||||
789 | static tree | ||||
790 | next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | ||||
791 | tree ident, | ||||
792 | tree proto ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | ||||
793 | { | ||||
794 | tree *chain = &sel_ref_chainobjc_global_trees[OCTI_SEL_REF_CHAIN]; | ||||
795 | tree expr; | ||||
796 | |||||
797 | while (*chain) | ||||
798 | { | ||||
799 | if (TREE_VALUE (*chain)((tree_check ((*chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 799, __FUNCTION__, (TREE_LIST)))->list.value) == ident) | ||||
800 | return TREE_PURPOSE (*chain)((tree_check ((*chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 800, __FUNCTION__, (TREE_LIST)))->list.purpose); | ||||
801 | |||||
802 | chain = &TREE_CHAIN (*chain)((contains_struct_check ((*chain), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 802, __FUNCTION__))->common.chain); | ||||
803 | } | ||||
804 | |||||
805 | expr = build_selector_reference_decl (ident); | ||||
806 | |||||
807 | *chain = tree_cons (expr, ident, NULL_TREE(tree) nullptr); | ||||
808 | |||||
809 | return expr; | ||||
810 | } | ||||
811 | |||||
812 | /* Build a tree expression to send OBJECT the operation SELECTOR, | ||||
813 | looking up the method on object LOOKUP_OBJECT (often same as OBJECT), | ||||
814 | assuming the method has prototype METHOD_PROTOTYPE. | ||||
815 | (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.) | ||||
816 | LOC is the location of the expression to build. | ||||
817 | Use METHOD_PARAMS as list of args to pass to the method. | ||||
818 | If SUPER_FLAG is nonzero, we look up the superclass's method. */ | ||||
819 | |||||
820 | static tree | ||||
821 | build_objc_method_call (location_t loc, int super_flag, tree method_prototype, | ||||
822 | tree lookup_object, tree selector, | ||||
823 | tree method_params) | ||||
824 | { | ||||
825 | tree sender, sender_cast, method, t; | ||||
826 | tree rcv_p = (super_flag ? objc_super_typeobjc_global_trees[OCTI_SUPER_TYPE] : objc_object_typeobjc_global_trees[OCTI_ID_TYPE]); | ||||
827 | vec<tree, va_gc> *parms; | ||||
828 | unsigned nparm = (method_params ? list_length (method_params) : 0); | ||||
829 | |||||
830 | /* If a prototype for the method to be called exists, then cast | ||||
831 | the sender's return type and arguments to match that of the method. | ||||
832 | Otherwise, leave sender as is. */ | ||||
833 | tree ret_type | ||||
834 | = (method_prototype | ||||
835 | ? TREE_VALUE (TREE_TYPE (method_prototype))((tree_check ((((contains_struct_check ((method_prototype), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 835, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 835, __FUNCTION__, (TREE_LIST)))->list.value) | ||||
836 | : objc_object_typeobjc_global_trees[OCTI_ID_TYPE]); | ||||
837 | tree ftype = build_function_type_for_method (ret_type, method_prototype, | ||||
838 | METHOD_REF1, super_flag); | ||||
839 | |||||
840 | if (method_prototype
, 840, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_common.abstract_origin)) | ||||
841 | ftype = build_type_attribute_variant (ftype, | ||||
842 | METHOD_TYPE_ATTRIBUTES((tree_check2 ((method_prototype), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 843, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_common.abstract_origin) | ||||
843 | (method_prototype)((tree_check2 ((method_prototype), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 843, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_common.abstract_origin)); | ||||
844 | |||||
845 | sender_cast = build_pointer_type (ftype); | ||||
846 | |||||
847 | lookup_object = build_c_cast (loc, rcv_p, lookup_object); | ||||
848 | |||||
849 | /* Use SAVE_EXPR to avoid evaluating the receiver twice. */ | ||||
850 | lookup_object = save_expr (lookup_object); | ||||
851 | |||||
852 | /* Param list + 2 slots for object and selector. */ | ||||
853 | vec_alloc (parms, nparm + 2); | ||||
854 | |||||
855 | /* If we are returning a struct in memory, and the address | ||||
856 | of that memory location is passed as a hidden first | ||||
857 | argument, then change which messenger entry point this | ||||
858 | expr will call. NB: Note that sender_cast remains | ||||
859 | unchanged (it already has a struct return type). */ | ||||
860 | if (!targetm.calls.struct_value_rtx (0, 0) | ||||
861 | && (TREE_CODE (ret_type)((enum tree_code) (ret_type)->base.code) == RECORD_TYPE | ||||
862 | || TREE_CODE (ret_type)((enum tree_code) (ret_type)->base.code) == UNION_TYPE) | ||||
863 | && targetm.calls.return_in_memory (ret_type, 0)) | ||||
864 | sender = (super_flag
| ||||
865 | : flag_nil_receiversglobal_options.x_flag_nil_receivers ? umsg_stret_declobjc_global_trees[OCTI_UMSG_STRET_DECL] | ||||
866 | : umsg_nonnil_stret_declobjc_global_trees[OCTI_UMSG_NONNIL_STRET_DECL]); | ||||
867 | else | ||||
868 | sender = (super_flag ? umsg_super_declobjc_global_trees[OCTI_UMSG_SUPER_DECL] | ||||
869 | : (flag_nil_receiversglobal_options.x_flag_nil_receivers ? (flag_objc_direct_dispatchglobal_options.x_flag_objc_direct_dispatch | ||||
870 | ? umsg_fast_declobjc_global_trees[OCTI_UMSG_FAST_DECL] | ||||
871 | : umsg_declobjc_global_trees[OCTI_UMSG_DECL]) | ||||
872 | : umsg_nonnil_declobjc_global_trees[OCTI_UMSG_NONNIL_DECL])); | ||||
873 | method = build_fold_addr_expr_loc (loc, sender); | ||||
874 | |||||
875 | /* Pass the object to the method. */ | ||||
876 | parms->quick_push (lookup_object); | ||||
| |||||
877 | /* Pass the selector to the method. */ | ||||
878 | parms->quick_push (selector); | ||||
879 | /* Now append the remainder of the parms. */ | ||||
880 | if (nparm) | ||||
881 | for (; method_params; method_params = TREE_CHAIN (method_params)((contains_struct_check ((method_params), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 881, __FUNCTION__))->common.chain)) | ||||
882 | parms->quick_push (TREE_VALUE (method_params)((tree_check ((method_params), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 882, __FUNCTION__, (TREE_LIST)))->list.value)); | ||||
883 | |||||
884 | /* Build an obj_type_ref, with the correct cast for the method call. */ | ||||
885 | t = build3 (OBJ_TYPE_REF, sender_cast, method, | ||||
886 | lookup_object, build_int_cst (TREE_TYPE (lookup_object)((contains_struct_check ((lookup_object), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 886, __FUNCTION__))->typed.type), 0)); | ||||
887 | t = build_function_call_vec (loc, vNULL, t, parms, NULLnullptr); | ||||
888 | vec_free (parms); | ||||
889 | return t; | ||||
890 | } | ||||
891 | |||||
892 | static tree | ||||
893 | next_runtime_abi_01_build_objc_method_call (location_t loc, | ||||
894 | tree method_prototype, | ||||
895 | tree receiver, | ||||
896 | tree rtype ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | ||||
897 | tree sel_name, | ||||
898 | tree method_params, | ||||
899 | int super) | ||||
900 | { | ||||
901 | tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name, | ||||
902 | NULL_TREE(tree) nullptr); | ||||
903 | |||||
904 | return build_objc_method_call (loc, super, method_prototype, | ||||
| |||||
905 | receiver, selector, method_params); | ||||
906 | } | ||||
907 | |||||
908 | static tree | ||||
909 | next_runtime_abi_01_get_protocol_reference (location_t loc, tree p) | ||||
910 | { | ||||
911 | tree expr; | ||||
912 | |||||
913 | if (!PROTOCOL_FORWARD_DECL (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 913, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 913, __FUNCTION__)))))) | ||||
914 | PROTOCOL_FORWARD_DECL (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 914, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 914, __FUNCTION__))))) = next_runtime_abi_01_protocol_decl (p); | ||||
915 | |||||
916 | expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 916, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 916, __FUNCTION__))))), 0); | ||||
917 | return convert (objc_protocol_typeobjc_global_trees[OCTI_PROTO_TYPE], expr); | ||||
918 | } | ||||
919 | |||||
920 | /* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */ | ||||
921 | |||||
922 | static tree | ||||
923 | next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | ||||
924 | tree base, tree id) | ||||
925 | { | ||||
926 | return objc_build_component_ref (base, id); | ||||
927 | } | ||||
928 | |||||
929 | /* We build super class references as we need them (but keep them once | ||||
930 | built for the sake of efficiency). */ | ||||
931 | |||||
932 | static tree | ||||
933 | next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | ||||
934 | struct imp_entry *imp, bool inst_meth) | ||||
935 | { | ||||
936 | if (inst_meth) | ||||
937 | { | ||||
938 | if (!ucls_super_refobjc_global_trees[OCTI_UCLS_SUPER_REF]) | ||||
939 | ucls_super_refobjc_global_trees[OCTI_UCLS_SUPER_REF] = | ||||
940 | objc_build_component_ref (imp->class_decl, | ||||
941 | get_identifier ("super_class")(__builtin_constant_p ("super_class") ? get_identifier_with_length (("super_class"), strlen ("super_class")) : get_identifier ( "super_class"))); | ||||
942 | return ucls_super_refobjc_global_trees[OCTI_UCLS_SUPER_REF]; | ||||
943 | } | ||||
944 | else | ||||
945 | { | ||||
946 | if (!uucls_super_refobjc_global_trees[OCTI_UUCLS_SUPER_REF]) | ||||
947 | uucls_super_refobjc_global_trees[OCTI_UUCLS_SUPER_REF] = | ||||
948 | objc_build_component_ref (imp->meta_decl, | ||||
949 | get_identifier ("super_class")(__builtin_constant_p ("super_class") ? get_identifier_with_length (("super_class"), strlen ("super_class")) : get_identifier ( "super_class"))); | ||||
950 | return uucls_super_refobjc_global_trees[OCTI_UUCLS_SUPER_REF]; | ||||
951 | } | ||||
952 | } | ||||
953 | |||||
954 | static tree | ||||
955 | next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | ||||
956 | struct imp_entry *imp, bool inst_meth) | ||||
957 | { | ||||
958 | tree super_name = CLASS_SUPER_NAME (imp->imp_template)(((tree_class_check ((imp->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 958, __FUNCTION__))->type_common.context)); | ||||
959 | tree super_class; | ||||
960 | |||||
961 | if (!flag_zero_linkglobal_options.x_flag_zero_link) | ||||
962 | { | ||||
963 | super_class = objc_get_class_reference (super_name); | ||||
964 | |||||
965 | if (!inst_meth) | ||||
966 | |||||
967 | /* If we are in a class method, we must retrieve the | ||||
968 | _metaclass_ for the current class, pointed at by | ||||
969 | the class's "isa" pointer. The following assumes that | ||||
970 | "isa" is the first ivar in a class (which it must be). */ | ||||
971 | super_class = | ||||
972 | build_indirect_ref (input_location, | ||||
973 | build_c_cast (input_location, | ||||
974 | build_pointer_type (objc_class_typeobjc_global_trees[OCTI_CLS_TYPE]), | ||||
975 | super_class), | ||||
976 | RO_UNARY_STAR); | ||||
977 | return super_class; | ||||
978 | } | ||||
979 | |||||
980 | /* else do it the slow way. */ | ||||
981 | add_class_reference (super_name); | ||||
982 | super_class = (inst_meth ? objc_get_class_declobjc_global_trees[OCTI_GET_CLASS_DECL] : objc_get_meta_class_declobjc_global_trees[OCTI_GET_MCLASS_DECL]); | ||||
983 | super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name)((tree_check ((super_name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 983, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.len ) + 1, | ||||
984 | IDENTIFIER_POINTER (super_name)((const char *) (tree_check ((super_name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 984, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
985 | /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */ | ||||
986 | return build_function_call (input_location, | ||||
987 | super_class, | ||||
988 | build_tree_list (NULL_TREE(tree) nullptr, super_name)); | ||||
989 | } | ||||
990 | |||||
991 | static bool | ||||
992 | next_runtime_abi_01_setup_const_string_class_decl (void) | ||||
993 | { | ||||
994 | if (!constant_string_global_idobjc_global_trees[OCTI_CNST_STR_GLOB_ID]) | ||||
995 | { | ||||
996 | /* Hopefully, this should not represent a serious limitation. */ | ||||
997 | char buf[BUFSIZE1024]; | ||||
998 | snprintf (buf, BUFSIZE1024, "_%sClassReference", constant_string_class_name); | ||||
999 | constant_string_global_idobjc_global_trees[OCTI_CNST_STR_GLOB_ID] = get_identifier (buf)(__builtin_constant_p (buf) ? get_identifier_with_length ((buf ), strlen (buf)) : get_identifier (buf)); | ||||
1000 | } | ||||
1001 | |||||
1002 | string_class_declobjc_global_trees[OCTI_STRING_CLASS_DECL] = lookup_name (constant_string_global_idobjc_global_trees[OCTI_CNST_STR_GLOB_ID]); | ||||
1003 | |||||
1004 | return (string_class_declobjc_global_trees[OCTI_STRING_CLASS_DECL] != NULL_TREE(tree) nullptr); | ||||
1005 | } | ||||
1006 | |||||
1007 | static tree | ||||
1008 | next_runtime_abi_01_build_const_string_constructor (location_t loc, tree string, | ||||
1009 | int length) | ||||
1010 | { | ||||
1011 | tree constructor, fields, var; | ||||
1012 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
1013 | |||||
1014 | /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */ | ||||
1015 | fields = TYPE_FIELDS (internal_const_str_type)((tree_check3 ((objc_global_trees[OCTI_INTERNAL_CNST_STR_TYPE ]), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1015, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))->type_non_common.values); | ||||
1016 | CONSTRUCTOR_APPEND_ELT (v, fields,do { constructor_elt _ce___ = {fields, build_unary_op (loc, ADDR_EXPR , objc_global_trees[OCTI_STRING_CLASS_DECL], 0)}; vec_safe_push ((v), _ce___); } while (0) | ||||
1017 | build_unary_op (loc, ADDR_EXPR, string_class_decl, 0))do { constructor_elt _ce___ = {fields, build_unary_op (loc, ADDR_EXPR , objc_global_trees[OCTI_STRING_CLASS_DECL], 0)}; vec_safe_push ((v), _ce___); } while (0); | ||||
1018 | |||||
1019 | fields = DECL_CHAIN (fields)(((contains_struct_check (((contains_struct_check ((fields), ( TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1019, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1019, __FUNCTION__))->common.chain)); | ||||
1020 | CONSTRUCTOR_APPEND_ELT (v, fields,do { constructor_elt _ce___ = {fields, build_unary_op (loc, ADDR_EXPR , string, 1)}; vec_safe_push ((v), _ce___); } while (0) | ||||
1021 | build_unary_op (loc, ADDR_EXPR, string, 1))do { constructor_elt _ce___ = {fields, build_unary_op (loc, ADDR_EXPR , string, 1)}; vec_safe_push ((v), _ce___); } while (0); | ||||
1022 | |||||
1023 | /* ??? check if this should be long. */ | ||||
1024 | fields = DECL_CHAIN (fields)(((contains_struct_check (((contains_struct_check ((fields), ( TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1024, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1024, __FUNCTION__))->common.chain)); | ||||
1025 | CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length))do { constructor_elt _ce___ = {fields, build_int_cst ((tree) nullptr , length)}; vec_safe_push ((v), _ce___); } while (0); | ||||
1026 | constructor = objc_build_constructor (internal_const_str_typeobjc_global_trees[OCTI_INTERNAL_CNST_STR_TYPE], v); | ||||
1027 | |||||
1028 | var = build_decl (input_location, CONST_DECL, NULLnullptr, TREE_TYPE (constructor)((contains_struct_check ((constructor), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1028, __FUNCTION__))->typed.type)); | ||||
1029 | DECL_INITIAL (var)((contains_struct_check ((var), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1029, __FUNCTION__))->decl_common.initial) = constructor; | ||||
1030 | TREE_STATIC (var)((var)->base.static_flag) = 1; | ||||
1031 | DECL_CONTEXT (var)((contains_struct_check ((var), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1031, __FUNCTION__))->decl_minimal.context) = NULLnullptr; | ||||
1032 | OBJCMETA (var, objc_meta, meta_const_str)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((var), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1032, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_CONST_STR ]));; | ||||
1033 | return var; | ||||
1034 | } | ||||
1035 | |||||
1036 | /* --- metadata templates --- */ | ||||
1037 | |||||
1038 | /* This routine builds the following type: | ||||
1039 | struct _prop_t { | ||||
1040 | const char * const name; // property name | ||||
1041 | const char * const attributes; // comma-delimited, encoded, | ||||
1042 | // property attributes | ||||
1043 | }; | ||||
1044 | */ | ||||
1045 | |||||
1046 | static GTY(()) tree objc_v1_property_template; | ||||
1047 | |||||
1048 | static tree | ||||
1049 | build_v1_property_template (void) | ||||
1050 | { | ||||
1051 | tree prop_record; | ||||
1052 | tree decls, *chain = NULLnullptr; | ||||
1053 | |||||
1054 | prop_record = objc_start_struct (get_identifier ("_prop_t")(__builtin_constant_p ("_prop_t") ? get_identifier_with_length (("_prop_t"), strlen ("_prop_t")) : get_identifier ("_prop_t" ))); | ||||
1055 | /* const char * name */ | ||||
1056 | decls = add_field_decl (string_type_nodec_global_trees[CTI_STRING_TYPE], "name", &chain); | ||||
1057 | |||||
1058 | /* const char * attribute */ | ||||
1059 | add_field_decl (string_type_nodec_global_trees[CTI_STRING_TYPE], "attribute", &chain); | ||||
1060 | |||||
1061 | objc_finish_struct (prop_record, decls); | ||||
1062 | return prop_record; | ||||
1063 | } | ||||
1064 | |||||
1065 | /* Build the following type: | ||||
1066 | |||||
1067 | struct _objc_protocol_extension | ||||
1068 | { | ||||
1069 | uint32_t size; // sizeof (struct _objc_protocol_extension) | ||||
1070 | struct objc_method_list *optional_instance_methods; | ||||
1071 | struct objc_method_list *optional_class_methods; | ||||
1072 | struct objc_prop_list *instance_properties; | ||||
1073 | } | ||||
1074 | */ | ||||
1075 | |||||
1076 | static GTY(()) tree objc_protocol_extension_template; | ||||
1077 | |||||
1078 | static void | ||||
1079 | build_v1_objc_protocol_extension_template (void) | ||||
1080 | { | ||||
1081 | tree decls, *chain = NULLnullptr; | ||||
1082 | |||||
1083 | objc_protocol_extension_template = | ||||
1084 | objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT)(__builtin_constant_p ("_objc_protocol_extension") ? get_identifier_with_length (("_objc_protocol_extension"), strlen ("_objc_protocol_extension" )) : get_identifier ("_objc_protocol_extension"))); | ||||
1085 | |||||
1086 | /* uint32_t size; */ | ||||
1087 | decls = add_field_decl (integer_type_nodeinteger_types[itk_int], "size", &chain); | ||||
1088 | |||||
1089 | /* struct objc_method_list *optional_instance_methods; */ | ||||
1090 | add_field_decl (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], "optional_instance_methods", &chain); | ||||
1091 | |||||
1092 | /* struct objc_method_list *optional_class_methods; */ | ||||
1093 | add_field_decl (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], "optional_class_methods", &chain); | ||||
1094 | |||||
1095 | /* struct objc_prop_list *instance_properties; */ | ||||
1096 | add_field_decl (objc_prop_list_ptrobjc_global_trees[OCTI_V1_PROP_LIST_TEMPL], "instance_properties", &chain); | ||||
1097 | |||||
1098 | objc_finish_struct (objc_protocol_extension_template, decls); | ||||
1099 | } | ||||
1100 | |||||
1101 | /* This routine build following struct type: | ||||
1102 | struct _objc_class_ext | ||||
1103 | { | ||||
1104 | uint32_t size; // sizeof(struct _objc_class_ext) | ||||
1105 | const char *weak_ivar_layout; | ||||
1106 | struct _prop_list_t *properties; | ||||
1107 | } | ||||
1108 | */ | ||||
1109 | |||||
1110 | static GTY(()) tree objc_class_ext_template; | ||||
1111 | |||||
1112 | static void | ||||
1113 | build_objc_class_ext_template (void) | ||||
1114 | { | ||||
1115 | tree ptrt, decls, *chain = NULLnullptr; | ||||
1116 | |||||
1117 | objc_class_ext_template = objc_start_struct (get_identifier (UTAG_CLASS_EXT)(__builtin_constant_p ("_objc_class_ext") ? get_identifier_with_length (("_objc_class_ext"), strlen ("_objc_class_ext")) : get_identifier ("_objc_class_ext"))); | ||||
1118 | |||||
1119 | /* uint32_t size; */ | ||||
1120 | decls = add_field_decl (integer_type_nodeinteger_types[itk_int], "size", &chain); | ||||
1121 | |||||
1122 | /* const char *weak_ivar_layout; */ | ||||
1123 | add_field_decl (const_string_type_nodec_global_trees[CTI_CONST_STRING_TYPE], "weak_ivar_layout", &chain); | ||||
1124 | |||||
1125 | /* struct _prop_list_t *properties; */ | ||||
1126 | ptrt = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
1127 | get_identifier(UTAG_PROPERTY_LIST)(__builtin_constant_p ("_prop_list_t") ? get_identifier_with_length (("_prop_list_t"), strlen ("_prop_list_t")) : get_identifier ("_prop_list_t")))); | ||||
1128 | add_field_decl (ptrt, "properties", &chain); | ||||
1129 | |||||
1130 | objc_finish_struct (objc_class_ext_template, decls); | ||||
1131 | } | ||||
1132 | |||||
1133 | static void | ||||
1134 | build_metadata_templates (void) | ||||
1135 | { | ||||
1136 | |||||
1137 | if (!objc_method_templateobjc_global_trees[OCTI_METH_TEMPL]) | ||||
1138 | objc_method_templateobjc_global_trees[OCTI_METH_TEMPL] = build_method_template (); | ||||
1139 | |||||
1140 | |||||
1141 | |||||
1142 | } | ||||
1143 | |||||
1144 | /* --- emit metadata --- */ | ||||
1145 | |||||
1146 | static tree | ||||
1147 | generate_v1_meth_descriptor_table (tree chain, tree protocol, | ||||
1148 | const char *prefix, tree attr) | ||||
1149 | { | ||||
1150 | tree method_list_template, initlist, decl; | ||||
1151 | int size; | ||||
1152 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
1153 | char buf[BUFSIZE1024]; | ||||
1154 | |||||
1155 | if (!chain || !prefix) | ||||
1156 | return NULL_TREE(tree) nullptr; | ||||
1157 | |||||
1158 | if (!objc_method_prototype_templateobjc_global_trees[OCTI_METH_PROTO_TEMPL]) | ||||
1159 | objc_method_prototype_templateobjc_global_trees[OCTI_METH_PROTO_TEMPL] = build_method_prototype_template (); | ||||
1160 | |||||
1161 | size = list_length (chain); | ||||
1162 | method_list_template = | ||||
1163 | build_method_prototype_list_template (objc_method_prototype_templateobjc_global_trees[OCTI_METH_PROTO_TEMPL], | ||||
1164 | size); | ||||
1165 | snprintf (buf, BUFSIZE1024, "%s_%s", prefix, | ||||
1166 | IDENTIFIER_POINTER (PROTOCOL_NAME (protocol))((const char *) (tree_check (((((tree_class_check ((protocol) , (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1166, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1166, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1167 | |||||
1168 | decl = start_var_decl (method_list_template, buf); | ||||
1169 | |||||
1170 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( (tree) nullptr, size)}; vec_safe_push ((v), _ce___); } while ( 0); | ||||
1171 | initlist = | ||||
1172 | build_descriptor_table_initializer (objc_method_prototype_templateobjc_global_trees[OCTI_METH_PROTO_TEMPL], | ||||
1173 | chain); | ||||
1174 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist)do { constructor_elt _ce___ = {(tree) nullptr, initlist}; vec_safe_push ((v), _ce___); } while (0); | ||||
1175 | /* Get into the right section. */ | ||||
1176 | OBJCMETA (decl, objc_meta, attr)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1176, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (attr));; | ||||
1177 | finish_var_decl (decl, objc_build_constructor (method_list_template, v)); | ||||
1178 | return decl; | ||||
1179 | } | ||||
1180 | |||||
1181 | /* Build protocol ext = | ||||
1182 | {size, opt_instance_meth, opt_class_meth, instance_props}; | ||||
1183 | or NULL_TREE if none are present. */ | ||||
1184 | |||||
1185 | static tree | ||||
1186 | generate_v1_objc_protocol_extension (tree proto_interface, | ||||
1187 | tree opt_instance_meth, | ||||
1188 | tree opt_class_meth, | ||||
1189 | tree instance_props) | ||||
1190 | { | ||||
1191 | int size; | ||||
1192 | location_t loc; | ||||
1193 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
1194 | tree decl, expr; | ||||
1195 | char buf[BUFSIZE1024]; | ||||
1196 | |||||
1197 | /* If there are no extensions, then don't bother... */ | ||||
1198 | if (!opt_instance_meth && !opt_class_meth && !instance_props) | ||||
1199 | return NULL_TREE(tree) nullptr; | ||||
1200 | |||||
1201 | if (!objc_protocol_extension_template) | ||||
1202 | build_v1_objc_protocol_extension_template (); | ||||
1203 | |||||
1204 | /* uint32_t size */ | ||||
1205 | size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template))((unsigned long) (*tree_int_cst_elt_check ((((tree_class_check ((objc_protocol_extension_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1205, __FUNCTION__))->type_common.size_unit)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1205, __FUNCTION__))); | ||||
1206 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( (tree) nullptr, size)}; vec_safe_push ((v), _ce___); } while ( 0); | ||||
1207 | |||||
1208 | /* Try for meaningful diagnostics. */ | ||||
1209 | loc = DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface))((contains_struct_check (((*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((proto_interface), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1209, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1209, __FUNCTION__)))))), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1209, __FUNCTION__))->decl_minimal.locus); | ||||
1210 | |||||
1211 | /* struct objc_method_list *optional_instance_methods; */ | ||||
1212 | if (opt_instance_meth) | ||||
1213 | expr = convert (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], | ||||
1214 | build_unary_op (loc, ADDR_EXPR, opt_instance_meth, 0)); | ||||
1215 | else | ||||
1216 | expr = convert (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1217 | |||||
1218 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1219 | |||||
1220 | /* struct objc_method_list *optional_class_methods; */ | ||||
1221 | if (opt_class_meth) | ||||
1222 | expr = convert (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], | ||||
1223 | build_unary_op (loc, ADDR_EXPR, opt_class_meth, 0)); | ||||
1224 | else | ||||
1225 | expr = convert (objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL], null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1226 | |||||
1227 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1228 | /* struct objc_prop_list *instance_properties; */ | ||||
1229 | if (instance_props) | ||||
1230 | expr = convert (objc_prop_list_ptrobjc_global_trees[OCTI_V1_PROP_LIST_TEMPL], | ||||
1231 | build_unary_op (loc, ADDR_EXPR, instance_props, 0)); | ||||
1232 | else | ||||
1233 | expr = convert (objc_prop_list_ptrobjc_global_trees[OCTI_V1_PROP_LIST_TEMPL], null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1234 | |||||
1235 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1236 | snprintf (buf, BUFSIZE1024, "_OBJC_ProtocolExt_%s", | ||||
1237 | IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface))((const char *) (tree_check (((((tree_class_check ((proto_interface ), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1237, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1237, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1238 | |||||
1239 | decl = start_var_decl (objc_protocol_extension_template, buf); | ||||
1240 | expr = objc_build_constructor (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1240, __FUNCTION__))->typed.type), v); | ||||
1241 | OBJCMETA (decl, objc_meta, meta_protocol_extension)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1241, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_PROTOCOL_EXT ]));; | ||||
1242 | finish_var_decl (decl, expr); | ||||
1243 | return decl; | ||||
1244 | } | ||||
1245 | |||||
1246 | /* This routine builds the following type: | ||||
1247 | struct _prop_list_t { | ||||
1248 | uint32_t entsize; // sizeof (struct _prop_t) | ||||
1249 | uint32_t prop_count; | ||||
1250 | struct _prop_t prop_list [prop_count]; | ||||
1251 | } | ||||
1252 | */ | ||||
1253 | |||||
1254 | static tree | ||||
1255 | build_v1_property_list_template (tree list_type, int size) | ||||
1256 | { | ||||
1257 | tree property_list_t_record; | ||||
1258 | tree array_type, decls, *chain = NULLnullptr; | ||||
1259 | |||||
1260 | /* anonymous. */ | ||||
1261 | property_list_t_record = objc_start_struct (NULL_TREE(tree) nullptr); | ||||
1262 | |||||
1263 | /* uint32_t const entsize */ | ||||
1264 | decls = add_field_decl (integer_type_nodeinteger_types[itk_int], "entsize", &chain); | ||||
1265 | |||||
1266 | /* int prop_count */ | ||||
1267 | add_field_decl (integer_type_nodeinteger_types[itk_int], "prop_count", &chain); | ||||
1268 | |||||
1269 | /* struct _prop_t prop_list[]; */ | ||||
1270 | array_type = build_sized_array_type (list_type, size); | ||||
1271 | add_field_decl (array_type, "prop_list", &chain); | ||||
1272 | |||||
1273 | objc_finish_struct (property_list_t_record, decls); | ||||
1274 | return property_list_t_record; | ||||
1275 | } | ||||
1276 | |||||
1277 | /* This routine builds the initializer list to initialize the | ||||
1278 | 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */ | ||||
1279 | |||||
1280 | static tree | ||||
1281 | build_v1_property_table_initializer (tree type, tree context) | ||||
1282 | { | ||||
1283 | tree x; | ||||
1284 | vec<constructor_elt, va_gc> *inits = NULLnullptr; | ||||
1285 | |||||
1286 | if (TREE_CODE (context)((enum tree_code) (context)->base.code) == PROTOCOL_INTERFACE_TYPE) | ||||
1287 | x = CLASS_PROPERTY_DECL (context)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1287, __FUNCTION__))->type_non_common.lang_1)), (6), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1287, __FUNCTION__))))); | ||||
1288 | else | ||||
1289 | x = IMPL_PROPERTY_DECL (context)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1289, __FUNCTION__))->type_non_common.lang_1)), (6), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1289, __FUNCTION__))))); | ||||
1290 | |||||
1291 | for (; x; x = TREE_CHAIN (x)((contains_struct_check ((x), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1291, __FUNCTION__))->common.chain)) | ||||
1292 | { | ||||
1293 | vec<constructor_elt, va_gc> *elemlist = NULLnullptr; | ||||
1294 | tree attribute, name_ident = PROPERTY_NAME (x)((contains_struct_check (((tree_check ((x), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1294, __FUNCTION__, (PROPERTY_DECL)))), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1294, __FUNCTION__))->decl_minimal.name); | ||||
1295 | |||||
1296 | CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, add_objc_string (name_ident, prop_names_attr)}; vec_safe_push ((elemlist), _ce___ ); } while (0) | ||||
1297 | add_objc_string (name_ident, prop_names_attr))do { constructor_elt _ce___ = {(tree) nullptr, add_objc_string (name_ident, prop_names_attr)}; vec_safe_push ((elemlist), _ce___ ); } while (0); | ||||
1298 | |||||
1299 | attribute = objc_v2_encode_prop_attr (x); | ||||
1300 | CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, add_objc_string (attribute, prop_names_attr)}; vec_safe_push ((elemlist), _ce___ ); } while (0) | ||||
1301 | add_objc_string (attribute, prop_names_attr))do { constructor_elt _ce___ = {(tree) nullptr, add_objc_string (attribute, prop_names_attr)}; vec_safe_push ((elemlist), _ce___ ); } while (0); | ||||
1302 | |||||
1303 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, objc_build_constructor (type, elemlist)}; vec_safe_push ((inits), _ce___); } while ( 0) | ||||
1304 | objc_build_constructor (type, elemlist))do { constructor_elt _ce___ = {(tree) nullptr, objc_build_constructor (type, elemlist)}; vec_safe_push ((inits), _ce___); } while ( 0); | ||||
1305 | } | ||||
1306 | |||||
1307 | return objc_build_constructor (build_array_type (type, 0),inits); | ||||
1308 | } | ||||
1309 | |||||
1310 | /* This routine builds the 'struct _prop_list_t' variable declaration and | ||||
1311 | initializes it with its initializer list. TYPE is 'struct _prop_list_t', | ||||
1312 | NAME is the internal name of this variable, SIZE is number of properties | ||||
1313 | for this class and LIST is the initializer list for its 'prop_list' field. */ | ||||
1314 | |||||
1315 | static tree | ||||
1316 | generate_v1_property_table (tree context, tree klass_ctxt) | ||||
1317 | { | ||||
1318 | tree x, decl, initlist, property_list_template; | ||||
1319 | bool is_proto = false; | ||||
1320 | vec<constructor_elt, va_gc> *inits = NULLnullptr; | ||||
1321 | int init_val, size = 0; | ||||
1322 | char buf[BUFSIZE1024]; | ||||
1323 | |||||
1324 | if (context) | ||||
1325 | { | ||||
1326 | gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)((void)(!(((enum tree_code) (context)->base.code) == PROTOCOL_INTERFACE_TYPE ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1326, __FUNCTION__), 0 : 0)); | ||||
1327 | x = CLASS_PROPERTY_DECL (context)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1327, __FUNCTION__))->type_non_common.lang_1)), (6), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1327, __FUNCTION__))))); | ||||
1328 | is_proto = true; | ||||
1329 | } | ||||
1330 | else | ||||
1331 | x = IMPL_PROPERTY_DECL (klass_ctxt)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((klass_ctxt), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1331, __FUNCTION__))->type_non_common.lang_1)), (6), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1331, __FUNCTION__))))); | ||||
1332 | |||||
1333 | for (; x; x = TREE_CHAIN (x)((contains_struct_check ((x), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1333, __FUNCTION__))->common.chain)) | ||||
1334 | size++; | ||||
1335 | |||||
1336 | if (size == 0) | ||||
1337 | return NULL_TREE(tree) nullptr; | ||||
1338 | |||||
1339 | if (!objc_v1_property_template) | ||||
1340 | objc_v1_property_template = build_v1_property_template (); | ||||
1341 | |||||
1342 | property_list_template = | ||||
1343 | build_v1_property_list_template (objc_v1_property_template, | ||||
1344 | size); | ||||
1345 | initlist = build_v1_property_table_initializer (objc_v1_property_template, | ||||
1346 | is_proto ? context | ||||
1347 | : klass_ctxt); | ||||
1348 | |||||
1349 | init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template))((unsigned long) (*tree_int_cst_elt_check ((((tree_class_check ((objc_v1_property_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1349, __FUNCTION__))->type_common.size_unit)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1349, __FUNCTION__))); | ||||
1350 | if (is_proto) | ||||
1351 | snprintf (buf, BUFSIZE1024, "_OBJC_ProtocolPropList_%s", | ||||
1352 | IDENTIFIER_POINTER (PROTOCOL_NAME (context))((const char *) (tree_check (((((tree_class_check ((context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1352, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1352, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1353 | else | ||||
1354 | snprintf (buf, BUFSIZE1024, "_OBJC_ClassPropList_%s", | ||||
1355 | IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt))((const char *) (tree_check (((((tree_class_check ((klass_ctxt ), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1355, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1355, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1356 | |||||
1357 | decl = start_var_decl (property_list_template, buf); | ||||
1358 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, init_val))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( (tree) nullptr, init_val)}; vec_safe_push ((inits), _ce___); } while (0); | ||||
1359 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( (tree) nullptr, size)}; vec_safe_push ((inits), _ce___); } while (0); | ||||
1360 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist)do { constructor_elt _ce___ = {(tree) nullptr, initlist}; vec_safe_push ((inits), _ce___); } while (0); | ||||
1361 | x = objc_build_constructor (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1361, __FUNCTION__))->typed.type), inits); | ||||
1362 | OBJCMETA (decl, objc_meta, meta_proplist)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1362, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_PROPERTY_LIST ]));; | ||||
1363 | finish_var_decl (decl, x); | ||||
1364 | return decl; | ||||
1365 | } | ||||
1366 | |||||
1367 | static tree | ||||
1368 | generate_v1_protocol_list (tree i_or_p, tree klass_ctxt) | ||||
1369 | { | ||||
1370 | tree array_type, ptype, refs_decl, lproto, e, plist, attr; | ||||
1371 | int size = 0; | ||||
1372 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
1373 | char buf[BUFSIZE1024]; | ||||
1374 | |||||
1375 | switch (TREE_CODE (i_or_p)((enum tree_code) (i_or_p)->base.code)) | ||||
1376 | { | ||||
1377 | case CLASS_INTERFACE_TYPE: | ||||
1378 | case CATEGORY_INTERFACE_TYPE: | ||||
1379 | plist = CLASS_PROTOCOL_LIST (i_or_p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((i_or_p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1379, __FUNCTION__))->type_non_common.lang_1)), (4), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1379, __FUNCTION__))))); | ||||
1380 | break; | ||||
1381 | case PROTOCOL_INTERFACE_TYPE: | ||||
1382 | plist = PROTOCOL_LIST (i_or_p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((i_or_p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1382, __FUNCTION__))->type_non_common.lang_1)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1382, __FUNCTION__))))); | ||||
1383 | break; | ||||
1384 | default: | ||||
1385 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1385, __FUNCTION__)); | ||||
1386 | } | ||||
1387 | |||||
1388 | /* Compute size. */ | ||||
1389 | for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)((contains_struct_check ((lproto), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1389, __FUNCTION__))->common.chain)) | ||||
1390 | if (TREE_CODE (TREE_VALUE (lproto))((enum tree_code) (((tree_check ((lproto), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1390, __FUNCTION__, (TREE_LIST)))->list.value))->base .code) == PROTOCOL_INTERFACE_TYPE | ||||
1391 | && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto))(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((((tree_check ((lproto), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1391, __FUNCTION__, (TREE_LIST)))->list.value)), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1391, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1391, __FUNCTION__)))))) | ||||
1392 | size++; | ||||
1393 | |||||
1394 | /* Build initializer. */ | ||||
1395 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( (tree) nullptr, 0)}; vec_safe_push ((v), _ce___); } while (0); | ||||
1396 | e = build_int_cst (build_pointer_type (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL]), size); | ||||
1397 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e)do { constructor_elt _ce___ = {(tree) nullptr, e}; vec_safe_push ((v), _ce___); } while (0); | ||||
1398 | |||||
1399 | for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)((contains_struct_check ((lproto), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1399, __FUNCTION__))->common.chain)) | ||||
1400 | { | ||||
1401 | tree pval = TREE_VALUE (lproto)((tree_check ((lproto), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1401, __FUNCTION__, (TREE_LIST)))->list.value); | ||||
1402 | |||||
1403 | if (TREE_CODE (pval)((enum tree_code) (pval)->base.code) == PROTOCOL_INTERFACE_TYPE | ||||
1404 | && PROTOCOL_FORWARD_DECL (pval)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((pval), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1404, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1404, __FUNCTION__)))))) | ||||
1405 | { | ||||
1406 | tree fwref = PROTOCOL_FORWARD_DECL (pval)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((pval), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1406, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1406, __FUNCTION__))))); | ||||
1407 | location_t loc = DECL_SOURCE_LOCATION (fwref)((contains_struct_check ((fwref), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1407, __FUNCTION__))->decl_minimal.locus) ; | ||||
1408 | e = build_unary_op (loc, ADDR_EXPR, fwref, 0); | ||||
1409 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e)do { constructor_elt _ce___ = {(tree) nullptr, e}; vec_safe_push ((v), _ce___); } while (0); | ||||
1410 | } | ||||
1411 | } | ||||
1412 | |||||
1413 | /* static struct objc_protocol *refs[n]; */ | ||||
1414 | switch (TREE_CODE (i_or_p)((enum tree_code) (i_or_p)->base.code)) | ||||
1415 | { | ||||
1416 | case PROTOCOL_INTERFACE_TYPE: | ||||
1417 | snprintf (buf, BUFSIZE1024, "_OBJC_ProtocolRefs_%s", | ||||
1418 | IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p))((const char *) (tree_check (((((tree_class_check ((i_or_p), ( tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1418, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1418, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1419 | attr = meta_proto_refobjc_rt_trees[OCTI_RT_META_PROT_REFS]; | ||||
1420 | break; | ||||
1421 | case CLASS_INTERFACE_TYPE: | ||||
1422 | snprintf (buf, BUFSIZE1024, "_OBJC_ClassProtocols_%s", | ||||
1423 | IDENTIFIER_POINTER (CLASS_NAME (i_or_p))((const char *) (tree_check (((((tree_class_check ((i_or_p), ( tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1423, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1423, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1424 | attr = meta_clas_protobjc_rt_trees[OCTI_RT_META_CLASS_PROT]; | ||||
1425 | break; | ||||
1426 | case CATEGORY_INTERFACE_TYPE: | ||||
1427 | snprintf (buf, BUFSIZE1024, "_OBJC_CategoryProtocols_%s_%s", | ||||
1428 | IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt))((const char *) (tree_check (((((tree_class_check ((klass_ctxt ), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1428, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1428, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | ||||
1429 | IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt))((const char *) (tree_check (((((tree_class_check ((klass_ctxt ), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1429, __FUNCTION__))->type_common.context))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1429, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1430 | attr = meta_catg_protobjc_rt_trees[OCTI_RT_META_CATEG_PROT]; | ||||
1431 | break; | ||||
1432 | default: | ||||
1433 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1433, __FUNCTION__)); | ||||
1434 | } | ||||
1435 | |||||
1436 | ptype = build_pointer_type (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL]); | ||||
1437 | array_type = build_sized_array_type (ptype, size + 3); | ||||
1438 | refs_decl = start_var_decl (array_type, buf); | ||||
1439 | |||||
1440 | OBJCMETA (refs_decl, objc_meta, attr)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((refs_decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1440, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (attr));; | ||||
1441 | finish_var_decl (refs_decl, | ||||
1442 | objc_build_constructor (TREE_TYPE (refs_decl)((contains_struct_check ((refs_decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1442, __FUNCTION__))->typed.type), v)); | ||||
1443 | |||||
1444 | return refs_decl; | ||||
1445 | } | ||||
1446 | |||||
1447 | static tree | ||||
1448 | build_v1_protocol_initializer (tree type, tree protocol_name, tree protocol_list, | ||||
1449 | tree inst_methods, tree class_methods, | ||||
1450 | tree protocol_ext) | ||||
1451 | { | ||||
1452 | tree expr, ttyp; | ||||
1453 | location_t loc; | ||||
1454 | vec<constructor_elt, va_gc> *inits = NULLnullptr; | ||||
1455 | |||||
1456 | if (!objc_protocol_extension_template) | ||||
1457 | build_v1_objc_protocol_extension_template (); | ||||
1458 | |||||
1459 | /* TODO: find a better representation of location from the inputs. */ | ||||
1460 | loc = UNKNOWN_LOCATION((location_t) 0); | ||||
1461 | ttyp = build_pointer_type (objc_protocol_extension_template); | ||||
1462 | /* Instead of jamming the protocol version number into the isa, we pass | ||||
1463 | either a pointer to the protocol extension - or NULL. */ | ||||
1464 | if (protocol_ext) | ||||
1465 | expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, protocol_ext, 0)); | ||||
1466 | else | ||||
1467 | expr = convert (ttyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1468 | |||||
1469 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((inits), _ce___); } while (0); | ||||
1470 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name)do { constructor_elt _ce___ = {(tree) nullptr, protocol_name} ; vec_safe_push ((inits), _ce___); } while (0); | ||||
1471 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list)do { constructor_elt _ce___ = {(tree) nullptr, protocol_list} ; vec_safe_push ((inits), _ce___); } while (0); | ||||
1472 | |||||
1473 | ttyp = objc_method_proto_list_ptrobjc_global_trees[OCTI_METH_PROTO_LIST_TEMPL]; | ||||
1474 | if (inst_methods) | ||||
1475 | expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0)); | ||||
1476 | else | ||||
1477 | expr = convert (ttyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1478 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((inits), _ce___); } while (0); | ||||
1479 | |||||
1480 | if (class_methods) | ||||
1481 | expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0)); | ||||
1482 | else | ||||
1483 | expr = convert (ttyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1484 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((inits), _ce___); } while (0); | ||||
1485 | |||||
1486 | return objc_build_constructor (type, inits); | ||||
1487 | } | ||||
1488 | |||||
1489 | /* An updated version of generate_protocols () that emit the protocol | ||||
1490 | extension for ABI=1. */ | ||||
1491 | |||||
1492 | /* For each protocol which was referenced either from a @protocol() | ||||
1493 | expression, or because a class/category implements it (then a | ||||
1494 | pointer to the protocol is stored in the struct describing the | ||||
1495 | class/category), we create a statically allocated instance of the | ||||
1496 | Protocol class. The code is written in such a way as to generate | ||||
1497 | as few Protocol objects as possible; we generate a unique Protocol | ||||
1498 | instance for each protocol, and we don't generate a Protocol | ||||
1499 | instance if the protocol is never referenced (either from a | ||||
1500 | @protocol() or from a class/category implementation). These | ||||
1501 | statically allocated objects can be referred to via the static | ||||
1502 | (that is, private to this module) symbols _OBJC_PROTOCOL_n. | ||||
1503 | |||||
1504 | The statically allocated Protocol objects that we generate here | ||||
1505 | need to be fixed up at runtime in order to be used: the 'isa' | ||||
1506 | pointer of the objects need to be set up to point to the 'Protocol' | ||||
1507 | class, as known at runtime. | ||||
1508 | |||||
1509 | The NeXT runtime fixes up all protocols at program startup time, | ||||
1510 | before main() is entered. It uses a low-level trick to look up all | ||||
1511 | those symbols, then loops on them and fixes them up. */ | ||||
1512 | |||||
1513 | /* TODO: finish getting rid of passing stuff around in globals. */ | ||||
1514 | |||||
1515 | static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl; | ||||
1516 | static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl; | ||||
1517 | static GTY(()) tree V1_ProtocolExt_decl; | ||||
1518 | static GTY(()) tree V1_Property_decl; | ||||
1519 | |||||
1520 | static void | ||||
1521 | generate_v1_protocols (void) | ||||
1522 | { | ||||
1523 | tree p; | ||||
1524 | |||||
1525 | /* If a protocol was directly referenced, pull in indirect references. */ | ||||
1526 | for (p = protocol_chainobjc_global_trees[OCTI_PROTO_CHAIN]; p; p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1526, __FUNCTION__))->common.chain)) | ||||
1527 | if (PROTOCOL_FORWARD_DECL (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1527, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1527, __FUNCTION__))))) && PROTOCOL_LIST (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1527, __FUNCTION__))->type_non_common.lang_1)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1527, __FUNCTION__)))))) | ||||
1528 | generate_protocol_references (PROTOCOL_LIST (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1528, __FUNCTION__))->type_non_common.lang_1)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1528, __FUNCTION__)))))); | ||||
1529 | |||||
1530 | for (p = protocol_chainobjc_global_trees[OCTI_PROTO_CHAIN]; p; p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1530, __FUNCTION__))->common.chain)) | ||||
1531 | { | ||||
1532 | tree decl, encoding, initlist, protocol_name_expr; | ||||
1533 | tree refs_type, refs_decl, refs_expr; | ||||
1534 | location_t loc; | ||||
1535 | tree nst_methods = PROTOCOL_NST_METHODS (p)(((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1535, __FUNCTION__))->type_non_common.minval)); | ||||
1536 | tree cls_methods = PROTOCOL_CLS_METHODS (p)(((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1536, __FUNCTION__))->type_non_common.maxval)); | ||||
1537 | |||||
1538 | /* If protocol wasn't referenced, don't generate any code. */ | ||||
1539 | decl = PROTOCOL_FORWARD_DECL (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1539, __FUNCTION__))->type_non_common.lang_1)), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1539, __FUNCTION__))))); | ||||
1540 | |||||
1541 | if (!decl) | ||||
1542 | continue; | ||||
1543 | |||||
1544 | /* Make sure we link in the Protocol class. */ | ||||
1545 | add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME)(__builtin_constant_p ("Protocol") ? get_identifier_with_length (("Protocol"), strlen ("Protocol")) : get_identifier ("Protocol" ))); | ||||
1546 | |||||
1547 | while (nst_methods) | ||||
1548 | { | ||||
1549 | if (! METHOD_ENCODING (nst_methods)((tree_check2 ((nst_methods), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1549, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_minimal.context)) | ||||
1550 | { | ||||
1551 | encoding = encode_method_prototype (nst_methods); | ||||
1552 | METHOD_ENCODING (nst_methods)((tree_check2 ((nst_methods), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1552, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_minimal.context) = encoding; | ||||
1553 | } | ||||
1554 | nst_methods = TREE_CHAIN (nst_methods)((contains_struct_check ((nst_methods), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1554, __FUNCTION__))->common.chain); | ||||
1555 | } | ||||
1556 | |||||
1557 | UOBJC_INSTANCE_METHODS_declobjc_global_trees[OCTI_NST_METH_DECL] = | ||||
1558 | generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p)(((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1558, __FUNCTION__))->type_non_common.minval)), p, | ||||
1559 | "_OBJC_ProtocolInstanceMethods", | ||||
1560 | meta_proto_nst_methobjc_rt_trees[OCTI_RT_META_PROTO_NST_METH]); | ||||
1561 | |||||
1562 | while (cls_methods) | ||||
1563 | { | ||||
1564 | if (! METHOD_ENCODING (cls_methods)((tree_check2 ((cls_methods), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1564, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_minimal.context)) | ||||
1565 | { | ||||
1566 | encoding = encode_method_prototype (cls_methods); | ||||
1567 | METHOD_ENCODING (cls_methods)((tree_check2 ((cls_methods), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1567, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_minimal.context) = encoding; | ||||
1568 | } | ||||
1569 | |||||
1570 | cls_methods = TREE_CHAIN (cls_methods)((contains_struct_check ((cls_methods), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1570, __FUNCTION__))->common.chain); | ||||
1571 | } | ||||
1572 | |||||
1573 | UOBJC_CLASS_METHODS_declobjc_global_trees[OCTI_CLS_METH_DECL] = | ||||
1574 | generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p)(((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1574, __FUNCTION__))->type_non_common.maxval)), p, | ||||
1575 | "_OBJC_ProtocolClassMethods", | ||||
1576 | meta_proto_cls_methobjc_rt_trees[OCTI_RT_META_PROTO_CLS_METH]); | ||||
1577 | |||||
1578 | /* There should be no optional methods for ABI-0 - but we need to | ||||
1579 | check all this here before the lists are made. */ | ||||
1580 | nst_methods = PROTOCOL_OPTIONAL_NST_METHODS (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1580, __FUNCTION__))->type_non_common.lang_1)), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1580, __FUNCTION__))))); | ||||
1581 | while (nst_methods) | ||||
1582 | { | ||||
1583 | if (! METHOD_ENCODING (nst_methods)((tree_check2 ((nst_methods), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1583, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_minimal.context)) | ||||
1584 | { | ||||
1585 | encoding = encode_method_prototype (nst_methods); | ||||
1586 | METHOD_ENCODING (nst_methods)((tree_check2 ((nst_methods), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1586, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_minimal.context) = encoding; | ||||
1587 | } | ||||
1588 | nst_methods = TREE_CHAIN (nst_methods)((contains_struct_check ((nst_methods), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1588, __FUNCTION__))->common.chain); | ||||
1589 | } | ||||
1590 | |||||
1591 | V1_Protocol_OPT_NST_METHODS_decl = | ||||
1592 | generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1592, __FUNCTION__))->type_non_common.lang_1)), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1592, __FUNCTION__))))), p, | ||||
1593 | "_OBJC_OptionalProtocolInstanceMethods", | ||||
1594 | meta_proto_nst_methobjc_rt_trees[OCTI_RT_META_PROTO_NST_METH]); | ||||
1595 | |||||
1596 | cls_methods = PROTOCOL_OPTIONAL_CLS_METHODS (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1596, __FUNCTION__))->type_non_common.lang_1)), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1596, __FUNCTION__))))); | ||||
1597 | while (cls_methods) | ||||
1598 | { | ||||
1599 | if (! METHOD_ENCODING (cls_methods)((tree_check2 ((cls_methods), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1599, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_minimal.context)) | ||||
1600 | { | ||||
1601 | encoding = encode_method_prototype (cls_methods); | ||||
1602 | METHOD_ENCODING (cls_methods)((tree_check2 ((cls_methods), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1602, __FUNCTION__, (INSTANCE_METHOD_DECL), (CLASS_METHOD_DECL )))->decl_minimal.context) = encoding; | ||||
1603 | } | ||||
1604 | |||||
1605 | cls_methods = TREE_CHAIN (cls_methods)((contains_struct_check ((cls_methods), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1605, __FUNCTION__))->common.chain); | ||||
1606 | } | ||||
1607 | |||||
1608 | V1_Protocol_OPT_CLS_METHODS_decl = | ||||
1609 | generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1609, __FUNCTION__))->type_non_common.lang_1)), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1609, __FUNCTION__))))), p, | ||||
1610 | "_OBJC_OptionalProtocolClassMethods", | ||||
1611 | meta_proto_cls_methobjc_rt_trees[OCTI_RT_META_PROTO_CLS_METH]); | ||||
1612 | |||||
1613 | if (PROTOCOL_LIST (p)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1613, __FUNCTION__))->type_non_common.lang_1)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1613, __FUNCTION__)))))) | ||||
1614 | refs_decl = generate_v1_protocol_list (p, objc_implementation_contextobjc_global_trees[OCTI_IMPL_CTX]); | ||||
1615 | else | ||||
1616 | refs_decl = 0; | ||||
1617 | |||||
1618 | /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */ | ||||
1619 | protocol_name_expr = add_objc_string (PROTOCOL_NAME (p)(((tree_class_check ((p), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1619, __FUNCTION__))->type_common.name)), class_names); | ||||
1620 | /* TODO: more locations to be fixed up... */ | ||||
1621 | loc = UNKNOWN_LOCATION((location_t) 0); | ||||
1622 | refs_type = | ||||
1623 | build_pointer_type (build_pointer_type (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL])); | ||||
1624 | if (refs_decl) | ||||
1625 | refs_expr = convert (refs_type, | ||||
1626 | build_unary_op (loc, ADDR_EXPR, refs_decl, 0)); | ||||
1627 | else | ||||
1628 | refs_expr = convert (refs_type, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1629 | |||||
1630 | if (flag_objc_abiglobal_options.x_flag_objc_abi < 1) | ||||
1631 | { | ||||
1632 | /* Original ABI. */ | ||||
1633 | initlist = | ||||
1634 | build_protocol_initializer (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1634, __FUNCTION__))->typed.type), | ||||
1635 | protocol_name_expr, refs_expr, | ||||
1636 | UOBJC_INSTANCE_METHODS_declobjc_global_trees[OCTI_NST_METH_DECL], | ||||
1637 | UOBJC_CLASS_METHODS_declobjc_global_trees[OCTI_CLS_METH_DECL]); | ||||
1638 | finish_var_decl (decl, initlist); | ||||
1639 | continue; | ||||
1640 | } | ||||
1641 | |||||
1642 | /* else - V1 extensions. */ | ||||
1643 | |||||
1644 | V1_Property_decl = | ||||
1645 | generate_v1_property_table (p, NULL_TREE(tree) nullptr); | ||||
1646 | |||||
1647 | V1_ProtocolExt_decl = | ||||
1648 | generate_v1_objc_protocol_extension (p, | ||||
1649 | V1_Protocol_OPT_NST_METHODS_decl, | ||||
1650 | V1_Protocol_OPT_CLS_METHODS_decl, | ||||
1651 | V1_Property_decl); | ||||
1652 | |||||
1653 | initlist = build_v1_protocol_initializer (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1653, __FUNCTION__))->typed.type), | ||||
1654 | protocol_name_expr, refs_expr, | ||||
1655 | UOBJC_INSTANCE_METHODS_declobjc_global_trees[OCTI_NST_METH_DECL], | ||||
1656 | UOBJC_CLASS_METHODS_declobjc_global_trees[OCTI_CLS_METH_DECL], | ||||
1657 | V1_ProtocolExt_decl); | ||||
1658 | finish_var_decl (decl, initlist); | ||||
1659 | } | ||||
1660 | } | ||||
1661 | |||||
1662 | static tree | ||||
1663 | generate_dispatch_table (tree chain, const char *name, tree attr) | ||||
1664 | { | ||||
1665 | tree decl, method_list_template, initlist; | ||||
1666 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
1667 | int size; | ||||
1668 | |||||
1669 | if (!chain || !name || !(size = list_length (chain))) | ||||
1670 | return NULL_TREE(tree) nullptr; | ||||
1671 | |||||
1672 | if (!objc_method_templateobjc_global_trees[OCTI_METH_TEMPL]) | ||||
1673 | objc_method_templateobjc_global_trees[OCTI_METH_TEMPL] = build_method_template (); | ||||
1674 | |||||
1675 | method_list_template = build_method_list_template (objc_method_templateobjc_global_trees[OCTI_METH_TEMPL], | ||||
1676 | size); | ||||
1677 | initlist = build_dispatch_table_initializer (objc_method_templateobjc_global_trees[OCTI_METH_TEMPL], chain); | ||||
1678 | |||||
1679 | decl = start_var_decl (method_list_template, name); | ||||
1680 | |||||
1681 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node)do { constructor_elt _ce___ = {(tree) nullptr, global_trees[TI_INTEGER_ZERO ]}; vec_safe_push ((v), _ce___); } while (0); | ||||
1682 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_int], size)}; vec_safe_push ((v), _ce___); } while (0) | ||||
1683 | build_int_cst (integer_type_node, size))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_int], size)}; vec_safe_push ((v), _ce___); } while (0); | ||||
1684 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist)do { constructor_elt _ce___ = {(tree) nullptr, initlist}; vec_safe_push ((v), _ce___); } while (0); | ||||
1685 | |||||
1686 | OBJCMETA (decl, objc_meta, attr)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1686, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (attr));; | ||||
1687 | finish_var_decl (decl, | ||||
1688 | objc_build_constructor (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1688, __FUNCTION__))->typed.type), v)); | ||||
1689 | |||||
1690 | return decl; | ||||
1691 | } | ||||
1692 | |||||
1693 | /* Init a category. */ | ||||
1694 | static tree | ||||
1695 | build_v1_category_initializer (tree type, tree cat_name, tree class_name, | ||||
1696 | tree inst_methods, tree class_methods, | ||||
1697 | tree protocol_list, tree property_list, | ||||
1698 | location_t loc) | ||||
1699 | { | ||||
1700 | tree expr, ltyp; | ||||
1701 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
1702 | |||||
1703 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name)do { constructor_elt _ce___ = {(tree) nullptr, cat_name}; vec_safe_push ((v), _ce___); } while (0); | ||||
1704 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name)do { constructor_elt _ce___ = {(tree) nullptr, class_name}; vec_safe_push ((v), _ce___); } while (0); | ||||
1705 | |||||
1706 | ltyp = objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL]; | ||||
1707 | if (inst_methods) | ||||
1708 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0)); | ||||
1709 | else | ||||
1710 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1711 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1712 | |||||
1713 | if (class_methods) | ||||
1714 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0)); | ||||
1715 | else | ||||
1716 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1717 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1718 | |||||
1719 | /* protocol_list = */ | ||||
1720 | ltyp = build_pointer_type (build_pointer_type (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL])); | ||||
1721 | if (protocol_list) | ||||
1722 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0)); | ||||
1723 | else | ||||
1724 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1725 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1726 | |||||
1727 | if (flag_objc_abiglobal_options.x_flag_objc_abi >= 1) | ||||
1728 | { | ||||
1729 | int val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template))((unsigned long) (*tree_int_cst_elt_check ((((tree_class_check ((objc_global_trees[OCTI_CAT_TEMPL]), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1729, __FUNCTION__))->type_common.size_unit)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1729, __FUNCTION__))); | ||||
1730 | expr = build_int_cst (NULL_TREE(tree) nullptr, val); | ||||
1731 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1732 | ltyp = objc_prop_list_ptrobjc_global_trees[OCTI_V1_PROP_LIST_TEMPL]; | ||||
1733 | if (property_list) | ||||
1734 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0)); | ||||
1735 | else | ||||
1736 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1737 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1738 | } | ||||
1739 | |||||
1740 | return objc_build_constructor (type, v); | ||||
1741 | } | ||||
1742 | |||||
1743 | /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */ | ||||
1744 | /* TODO: get rid of passing stuff around in globals. */ | ||||
1745 | static void | ||||
1746 | generate_v1_category (struct imp_entry *impent) | ||||
1747 | { | ||||
1748 | tree initlist, cat_name_expr, class_name_expr; | ||||
1749 | tree protocol_decl, category, cat_decl; | ||||
1750 | tree inst_methods = NULL_TREE(tree) nullptr, class_methods = NULL_TREE(tree) nullptr; | ||||
1751 | tree cat = impent->imp_context; | ||||
1752 | location_t loc; | ||||
1753 | char buf[BUFSIZE1024]; | ||||
1754 | |||||
1755 | cat_decl = impent->class_decl; | ||||
1756 | loc = DECL_SOURCE_LOCATION (cat_decl)((contains_struct_check ((cat_decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1756, __FUNCTION__))->decl_minimal.locus); | ||||
1757 | |||||
1758 | add_class_reference (CLASS_NAME (cat)(((tree_class_check ((cat), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1758, __FUNCTION__))->type_common.name))); | ||||
1759 | cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat)(((tree_class_check ((cat), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1759, __FUNCTION__))->type_common.context)), class_names); | ||||
1760 | class_name_expr = add_objc_string (CLASS_NAME (cat)(((tree_class_check ((cat), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1760, __FUNCTION__))->type_common.name)), class_names); | ||||
1761 | |||||
1762 | category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat)(((tree_class_check ((cat), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1762, __FUNCTION__))->type_common.context))); | ||||
1763 | |||||
1764 | if (category && CLASS_PROTOCOL_LIST (category)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((category), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1764, __FUNCTION__))->type_non_common.lang_1)), (4), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1764, __FUNCTION__)))))) | ||||
1765 | { | ||||
1766 | generate_protocol_references (CLASS_PROTOCOL_LIST (category)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((category), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1766, __FUNCTION__))->type_non_common.lang_1)), (4), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1766, __FUNCTION__)))))); | ||||
1767 | protocol_decl = generate_v1_protocol_list (category, cat); | ||||
1768 | } | ||||
1769 | else | ||||
1770 | protocol_decl = 0; | ||||
1771 | |||||
1772 | if (flag_objc_abiglobal_options.x_flag_objc_abi >= 1) | ||||
1773 | V1_Property_decl = generate_v1_property_table (NULL_TREE(tree) nullptr, cat); | ||||
1774 | else | ||||
1775 | V1_Property_decl = NULL_TREE(tree) nullptr; | ||||
1776 | |||||
1777 | if (CLASS_NST_METHODS (cat)(((tree_class_check ((cat), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1777, __FUNCTION__))->type_non_common.minval))) | ||||
1778 | { | ||||
1779 | snprintf (buf, BUFSIZE1024, "_OBJC_CategoryInstanceMethods_%s_%s", | ||||
1780 | IDENTIFIER_POINTER (CLASS_NAME (cat))((const char *) (tree_check (((((tree_class_check ((cat), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1780, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1780, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | ||||
1781 | IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat))((const char *) (tree_check (((((tree_class_check ((cat), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1781, __FUNCTION__))->type_common.context))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1781, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1782 | inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat)(((tree_class_check ((cat), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1782, __FUNCTION__))->type_non_common.minval)), buf, | ||||
1783 | meta_cati_methobjc_rt_trees[OCTI_RT_META_CATEG_NST_METH]); | ||||
1784 | } | ||||
1785 | |||||
1786 | if (CLASS_CLS_METHODS (cat)(((tree_class_check ((cat), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1786, __FUNCTION__))->type_non_common.maxval))) | ||||
1787 | { | ||||
1788 | snprintf (buf, BUFSIZE1024, "_OBJC_CategoryClassMethods_%s_%s", | ||||
1789 | IDENTIFIER_POINTER (CLASS_NAME (cat))((const char *) (tree_check (((((tree_class_check ((cat), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1789, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1789, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | ||||
1790 | IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat))((const char *) (tree_check (((((tree_class_check ((cat), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1790, __FUNCTION__))->type_common.context))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1790, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1791 | class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat)(((tree_class_check ((cat), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1791, __FUNCTION__))->type_non_common.maxval)), buf, | ||||
1792 | meta_catc_methobjc_rt_trees[OCTI_RT_META_CATEG_CLS_METH]); | ||||
1793 | } | ||||
1794 | |||||
1795 | initlist = build_v1_category_initializer (TREE_TYPE (cat_decl)((contains_struct_check ((cat_decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1795, __FUNCTION__))->typed.type), | ||||
1796 | cat_name_expr, class_name_expr, | ||||
1797 | inst_methods, class_methods, | ||||
1798 | protocol_decl, V1_Property_decl, | ||||
1799 | loc); | ||||
1800 | |||||
1801 | finish_var_decl (cat_decl, initlist); | ||||
1802 | impent->class_decl = cat_decl; | ||||
1803 | } | ||||
1804 | |||||
1805 | /* This routine builds the class extension used by v1 NeXT. */ | ||||
1806 | |||||
1807 | static tree | ||||
1808 | generate_objc_class_ext (tree property_list, tree context) | ||||
1809 | { | ||||
1810 | tree decl, expr, ltyp; | ||||
1811 | tree weak_ivar_layout_tree; | ||||
1812 | int size; | ||||
1813 | location_t loc; | ||||
1814 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
1815 | char buf[BUFSIZE1024]; | ||||
1816 | |||||
1817 | /* TODO: pass the loc in or find it from args. */ | ||||
1818 | loc = UNKNOWN_LOCATION((location_t) 0); | ||||
1819 | |||||
1820 | /* const char *weak_ivar_layout | ||||
1821 | TODO: Figure the ivar layouts out... */ | ||||
1822 | weak_ivar_layout_tree = NULL_TREE(tree) nullptr; | ||||
1823 | |||||
1824 | if (!property_list && !weak_ivar_layout_tree) | ||||
1825 | return NULL_TREE(tree) nullptr; | ||||
1826 | |||||
1827 | if (!objc_class_ext_template) | ||||
1828 | build_objc_class_ext_template (); | ||||
1829 | |||||
1830 | /* uint32_t size */ | ||||
1831 | size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template))((unsigned long) (*tree_int_cst_elt_check ((((tree_class_check ((objc_class_ext_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1831, __FUNCTION__))->type_common.size_unit)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1831, __FUNCTION__))); | ||||
1832 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( (tree) nullptr, size)}; vec_safe_push ((v), _ce___); } while ( 0); | ||||
1833 | |||||
1834 | ltyp = const_string_type_nodec_global_trees[CTI_CONST_STRING_TYPE]; | ||||
1835 | if (weak_ivar_layout_tree) | ||||
1836 | expr = convert (ltyp, weak_ivar_layout_tree); | ||||
1837 | else | ||||
1838 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1839 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1840 | |||||
1841 | /* struct _prop_list_t *properties; */ | ||||
1842 | ltyp = objc_prop_list_ptrobjc_global_trees[OCTI_V1_PROP_LIST_TEMPL]; | ||||
1843 | if (property_list) | ||||
1844 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0)); | ||||
1845 | else | ||||
1846 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1847 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1848 | |||||
1849 | snprintf (buf, BUFSIZE1024, "_OBJC_ClassExt_%s", | ||||
1850 | IDENTIFIER_POINTER (CLASS_NAME (context))((const char *) (tree_check (((((tree_class_check ((context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1850, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1850, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
1851 | decl = start_var_decl (objc_class_ext_template, buf); | ||||
1852 | expr = objc_build_constructor (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1852, __FUNCTION__))->typed.type), v); | ||||
1853 | OBJCMETA (decl, objc_meta, meta_class_extension)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1853, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_CLASS_EXT ]));; | ||||
1854 | finish_var_decl (decl, expr); | ||||
1855 | return decl; | ||||
1856 | } | ||||
1857 | |||||
1858 | /* struct _objc_class { | ||||
1859 | struct objc_class *isa; | ||||
1860 | struct objc_class *super_class; | ||||
1861 | char *name; | ||||
1862 | long version; | ||||
1863 | long info; | ||||
1864 | long instance_size; | ||||
1865 | struct objc_ivar_list *ivars; | ||||
1866 | struct objc_method_list *methods; | ||||
1867 | struct objc_cache *cache; | ||||
1868 | struct objc_protocol_list *protocols; | ||||
1869 | #if ABI >= 1 | ||||
1870 | const char *ivar_layout; | ||||
1871 | struct _objc_class_ext *ext; | ||||
1872 | #else | ||||
1873 | void *sel_id; | ||||
1874 | void *gc_object_type; | ||||
1875 | #endif | ||||
1876 | }; */ | ||||
1877 | |||||
1878 | static tree | ||||
1879 | build_v1_shared_structure_initializer (tree type, tree isa, tree super, | ||||
1880 | tree name, tree size, int status, | ||||
1881 | tree dispatch_table, tree ivar_list, | ||||
1882 | tree protocol_list, tree class_ext) | ||||
1883 | { | ||||
1884 | tree expr, ltyp; | ||||
1885 | location_t loc; | ||||
1886 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
1887 | |||||
1888 | /* TODO: fish the location out of the input data. */ | ||||
1889 | loc = UNKNOWN_LOCATION((location_t) 0); | ||||
1890 | |||||
1891 | /* isa = */ | ||||
1892 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa)do { constructor_elt _ce___ = {(tree) nullptr, isa}; vec_safe_push ((v), _ce___); } while (0); | ||||
1893 | |||||
1894 | /* super_class = */ | ||||
1895 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super)do { constructor_elt _ce___ = {(tree) nullptr, super}; vec_safe_push ((v), _ce___); } while (0); | ||||
1896 | |||||
1897 | /* name = */ | ||||
1898 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name))do { constructor_elt _ce___ = {(tree) nullptr, default_conversion (name)}; vec_safe_push ((v), _ce___); } while (0); | ||||
1899 | |||||
1900 | /* version = */ | ||||
1901 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_long], 0)}; vec_safe_push ((v), _ce___); } while (0) | ||||
1902 | build_int_cst (long_integer_type_node, 0))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_long], 0)}; vec_safe_push ((v), _ce___); } while (0); | ||||
1903 | |||||
1904 | /* info = */ | ||||
1905 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_long], status)}; vec_safe_push ((v), _ce___ ); } while (0) | ||||
1906 | build_int_cst (long_integer_type_node, status))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_long], status)}; vec_safe_push ((v), _ce___ ); } while (0); | ||||
1907 | |||||
1908 | /* instance_size = */ | ||||
1909 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, convert (integer_types [itk_long], size)}; vec_safe_push ((v), _ce___); } while (0) | ||||
1910 | convert (long_integer_type_node, size))do { constructor_elt _ce___ = {(tree) nullptr, convert (integer_types [itk_long], size)}; vec_safe_push ((v), _ce___); } while (0); | ||||
1911 | |||||
1912 | /* objc_ivar_list = */ | ||||
1913 | ltyp = objc_ivar_list_ptrobjc_global_trees[OCTI_IVAR_LIST_TEMPL]; | ||||
1914 | if (ivar_list) | ||||
1915 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivar_list, 0)); | ||||
1916 | else | ||||
1917 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1918 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1919 | |||||
1920 | /* objc_method_list = */ | ||||
1921 | ltyp = objc_method_list_ptrobjc_global_trees[OCTI_METH_LIST_TEMPL]; | ||||
1922 | if (dispatch_table) | ||||
1923 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, dispatch_table, 0)); | ||||
1924 | else | ||||
1925 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1926 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1927 | |||||
1928 | ltyp = build_pointer_type (xref_tag (RECORD_TYPE, | ||||
1929 | get_identifier ("objc_cache")(__builtin_constant_p ("objc_cache") ? get_identifier_with_length (("objc_cache"), strlen ("objc_cache")) : get_identifier ("objc_cache" )))); | ||||
1930 | /* method_cache = */ | ||||
1931 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node))do { constructor_elt _ce___ = {(tree) nullptr, convert (ltyp, global_trees[TI_NULL_POINTER])}; vec_safe_push ((v), _ce___) ; } while (0); | ||||
1932 | |||||
1933 | /* protocol_list = */ | ||||
1934 | ltyp = build_pointer_type (build_pointer_type (objc_protocol_templateobjc_global_trees[OCTI_PROTO_TEMPL])); | ||||
1935 | if (protocol_list) | ||||
1936 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0)); | ||||
1937 | else | ||||
1938 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1939 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1940 | |||||
1941 | if (flag_objc_abiglobal_options.x_flag_objc_abi >= 1) | ||||
1942 | { | ||||
1943 | /* TODO: figure out the ivar_layout stuff. */ | ||||
1944 | expr = convert (const_string_type_nodec_global_trees[CTI_CONST_STRING_TYPE], null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1945 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1946 | if (!objc_class_ext_template) | ||||
1947 | build_objc_class_ext_template (); | ||||
1948 | ltyp = build_pointer_type (objc_class_ext_template); | ||||
1949 | if (class_ext) | ||||
1950 | expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_ext, 0)); | ||||
1951 | else | ||||
1952 | expr = convert (ltyp, null_pointer_nodeglobal_trees[TI_NULL_POINTER]); | ||||
1953 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
1954 | } | ||||
1955 | else | ||||
1956 | { | ||||
1957 | /* sel_id = NULL */ | ||||
1958 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node)do { constructor_elt _ce___ = {(tree) nullptr, global_trees[TI_NULL_POINTER ]}; vec_safe_push ((v), _ce___); } while (0); | ||||
1959 | |||||
1960 | /* gc_object_type = NULL */ | ||||
1961 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node)do { constructor_elt _ce___ = {(tree) nullptr, global_trees[TI_NULL_POINTER ]}; vec_safe_push ((v), _ce___); } while (0); | ||||
1962 | } | ||||
1963 | return objc_build_constructor (type, v); | ||||
1964 | } | ||||
1965 | |||||
1966 | static tree | ||||
1967 | generate_ivars_list (tree chain, const char *name, tree attr) | ||||
1968 | { | ||||
1969 | tree initlist, ivar_list_template, decl; | ||||
1970 | int size; | ||||
1971 | vec<constructor_elt, va_gc> *inits = NULLnullptr; | ||||
1972 | |||||
1973 | if (!chain) | ||||
1974 | return NULL_TREE(tree) nullptr; | ||||
1975 | |||||
1976 | if (!objc_ivar_templateobjc_global_trees[OCTI_IVAR_TEMPL]) | ||||
1977 | objc_ivar_templateobjc_global_trees[OCTI_IVAR_TEMPL] = build_ivar_template (); | ||||
1978 | |||||
1979 | size = ivar_list_length (chain); | ||||
1980 | |||||
1981 | generating_instance_variables = 1; | ||||
1982 | ivar_list_template = build_ivar_list_template (objc_ivar_templateobjc_global_trees[OCTI_IVAR_TEMPL], size); | ||||
1983 | initlist = build_ivar_list_initializer (objc_ivar_templateobjc_global_trees[OCTI_IVAR_TEMPL], chain); | ||||
1984 | generating_instance_variables = 0; | ||||
1985 | |||||
1986 | decl = start_var_decl (ivar_list_template, name); | ||||
1987 | |||||
1988 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( (tree) nullptr, size)}; vec_safe_push ((inits), _ce___); } while (0); | ||||
1989 | CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist)do { constructor_elt _ce___ = {(tree) nullptr, initlist}; vec_safe_push ((inits), _ce___); } while (0); | ||||
1990 | |||||
1991 | OBJCMETA (decl, objc_meta, attr)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1991, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (attr));; | ||||
1992 | finish_var_decl (decl, | ||||
1993 | objc_build_constructor (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 1993, __FUNCTION__))->typed.type), inits)); | ||||
1994 | |||||
1995 | return decl; | ||||
1996 | } | ||||
1997 | |||||
1998 | /* static struct objc_class _OBJC_METACLASS_Foo={ ... }; | ||||
1999 | static struct objc_class _OBJC_CLASS_Foo={ ... }; */ | ||||
2000 | |||||
2001 | static void | ||||
2002 | generate_v1_class_structs (struct imp_entry *impent) | ||||
2003 | { | ||||
2004 | tree name_expr, super_expr, root_expr, class_decl, meta_decl; | ||||
2005 | tree my_root_id, my_super_id; | ||||
2006 | tree cast_type, initlist, protocol_decl; | ||||
2007 | tree class_ext_decl = NULL_TREE(tree) nullptr, props = NULL_TREE(tree) nullptr; | ||||
2008 | tree inst_methods = NULL_TREE(tree) nullptr, class_methods = NULL_TREE(tree) nullptr; | ||||
2009 | tree chain, inst_ivars = NULL_TREE(tree) nullptr, class_ivars = NULL_TREE(tree) nullptr; | ||||
2010 | int cls_flags; | ||||
2011 | location_t loc; | ||||
2012 | char buf[BUFSIZE1024]; | ||||
2013 | |||||
2014 | /* objc_implementation_context = impent->imp_context; | ||||
2015 | implementation_template = impent->imp_template;*/ | ||||
2016 | class_decl = impent->class_decl; | ||||
2017 | meta_decl = impent->meta_decl; | ||||
2018 | cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS0x2000L : 0 ; | ||||
2019 | |||||
2020 | loc = DECL_SOURCE_LOCATION (impent->class_decl)((contains_struct_check ((impent->class_decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2020, __FUNCTION__))->decl_minimal.locus); | ||||
2021 | |||||
2022 | if (flag_objc_abiglobal_options.x_flag_objc_abi >= 1) | ||||
2023 | { | ||||
2024 | /* ABI=1 additions. */ | ||||
2025 | props = generate_v1_property_table (NULL_TREE(tree) nullptr, impent->imp_context); | ||||
2026 | class_ext_decl = generate_objc_class_ext (props, impent->imp_context); | ||||
2027 | } | ||||
2028 | |||||
2029 | my_super_id = CLASS_SUPER_NAME (impent->imp_template)(((tree_class_check ((impent->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2029, __FUNCTION__))->type_common.context)); | ||||
2030 | if (my_super_id) | ||||
2031 | { | ||||
2032 | add_class_reference (my_super_id); | ||||
2033 | |||||
2034 | /* Compute "my_root_id" - this is required for code generation. | ||||
2035 | the "isa" for all meta class structures points to the root of | ||||
2036 | the inheritance hierarchy (e.g. "__Object")... */ | ||||
2037 | my_root_id = my_super_id; | ||||
2038 | do | ||||
2039 | { | ||||
2040 | tree my_root_int = lookup_interface (my_root_id); | ||||
2041 | |||||
2042 | if (my_root_int && CLASS_SUPER_NAME (my_root_int)(((tree_class_check ((my_root_int), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2042, __FUNCTION__))->type_common.context))) | ||||
2043 | my_root_id = CLASS_SUPER_NAME (my_root_int)(((tree_class_check ((my_root_int), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2043, __FUNCTION__))->type_common.context)); | ||||
2044 | else | ||||
2045 | break; | ||||
2046 | } | ||||
2047 | while (1); | ||||
2048 | super_expr = add_objc_string (my_super_id, class_names); | ||||
2049 | } | ||||
2050 | else | ||||
2051 | { | ||||
2052 | /* No super class. */ | ||||
2053 | my_root_id = CLASS_NAME (impent->imp_template)(((tree_class_check ((impent->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2053, __FUNCTION__))->type_common.name)); | ||||
2054 | super_expr = null_pointer_nodeglobal_trees[TI_NULL_POINTER]; | ||||
2055 | } | ||||
2056 | |||||
2057 | /* Install class `isa' and `super' pointers at runtime. */ | ||||
2058 | cast_type = build_pointer_type (objc_class_templateobjc_global_trees[OCTI_CLS_TEMPL]); | ||||
2059 | super_expr = build_c_cast (loc, cast_type, super_expr); | ||||
2060 | |||||
2061 | root_expr = add_objc_string (my_root_id, class_names); | ||||
2062 | root_expr = build_c_cast (loc, cast_type, root_expr); | ||||
2063 | |||||
2064 | if (CLASS_PROTOCOL_LIST (impent->imp_template)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((impent->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2064, __FUNCTION__))->type_non_common.lang_1)), (4), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2064, __FUNCTION__)))))) | ||||
2065 | { | ||||
2066 | generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((impent->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2066, __FUNCTION__))->type_non_common.lang_1)), (4), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2066, __FUNCTION__)))))); | ||||
2067 | protocol_decl = generate_v1_protocol_list (impent->imp_template, | ||||
2068 | impent->imp_context); | ||||
2069 | } | ||||
2070 | else | ||||
2071 | protocol_decl = NULL_TREE(tree) nullptr; | ||||
2072 | |||||
2073 | if (CLASS_CLS_METHODS (impent->imp_context)(((tree_class_check ((impent->imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2073, __FUNCTION__))->type_non_common.maxval))) | ||||
2074 | { | ||||
2075 | snprintf (buf, BUFSIZE1024, "_OBJC_ClassMethods_%s", | ||||
2076 | IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))((const char *) (tree_check (((((tree_class_check ((impent-> imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2076, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2076, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
2077 | class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context)(((tree_class_check ((impent->imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2077, __FUNCTION__))->type_non_common.maxval)), | ||||
2078 | buf, meta_clac_methobjc_rt_trees[OCTI_RT_META_CLASS_CLS_METH]); | ||||
2079 | } | ||||
2080 | |||||
2081 | if (CLASS_SUPER_NAME (impent->imp_template)(((tree_class_check ((impent->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2081, __FUNCTION__))->type_common.context)) == NULL_TREE(tree) nullptr | ||||
2082 | && (chain = TYPE_FIELDS (objc_class_template)((tree_check3 ((objc_global_trees[OCTI_CLS_TEMPL]), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2082, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))->type_non_common.values))) | ||||
2083 | { | ||||
2084 | snprintf (buf, BUFSIZE1024, "_OBJC_ClassIvars_%s", | ||||
2085 | IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))((const char *) (tree_check (((((tree_class_check ((impent-> imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2085, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2085, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
2086 | class_ivars = generate_ivars_list (chain, buf, meta_clac_varsobjc_rt_trees[OCTI_RT_META_CLASS_CLS_VARS]); | ||||
2087 | } | ||||
2088 | /* TODO: get rid of hidden passing of stuff in globals. */ | ||||
2089 | /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */ | ||||
2090 | |||||
2091 | name_expr = add_objc_string (CLASS_NAME (impent->imp_template)(((tree_class_check ((impent->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2091, __FUNCTION__))->type_common.name)), class_names); | ||||
2092 | |||||
2093 | /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */ | ||||
2094 | |||||
2095 | initlist = build_v1_shared_structure_initializer | ||||
2096 | (TREE_TYPE (meta_decl)((contains_struct_check ((meta_decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2096, __FUNCTION__))->typed.type), | ||||
2097 | root_expr, super_expr, name_expr, | ||||
2098 | convert (integer_type_nodeinteger_types[itk_int], TYPE_SIZE_UNIT (objc_class_template)((tree_class_check ((objc_global_trees[OCTI_CLS_TEMPL]), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2098, __FUNCTION__))->type_common.size_unit)), | ||||
2099 | CLS_META0x0002L, class_methods, class_ivars, | ||||
2100 | protocol_decl, NULL_TREE(tree) nullptr); | ||||
2101 | |||||
2102 | finish_var_decl (meta_decl, initlist); | ||||
2103 | impent->meta_decl = meta_decl; | ||||
2104 | |||||
2105 | /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */ | ||||
2106 | if (CLASS_NST_METHODS (impent->imp_context)(((tree_class_check ((impent->imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2106, __FUNCTION__))->type_non_common.minval))) | ||||
2107 | { | ||||
2108 | snprintf (buf, BUFSIZE1024, "_OBJC_InstanceMethods_%s", | ||||
2109 | IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))((const char *) (tree_check (((((tree_class_check ((impent-> imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2109, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2109, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
2110 | inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context)(((tree_class_check ((impent->imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2110, __FUNCTION__))->type_non_common.minval)), | ||||
2111 | buf, meta_clai_methobjc_rt_trees[OCTI_RT_META_CLASS_NST_METH]); | ||||
2112 | } | ||||
2113 | |||||
2114 | if ((chain = CLASS_IVARS (impent->imp_template)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((impent->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2114, __FUNCTION__))->type_non_common.lang_1)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2114, __FUNCTION__))))))) | ||||
2115 | { | ||||
2116 | snprintf (buf, BUFSIZE1024, "_OBJC_InstanceIvars_%s", | ||||
2117 | IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))((const char *) (tree_check (((((tree_class_check ((impent-> imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2117, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2117, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
2118 | inst_ivars = generate_ivars_list (chain, buf, meta_clai_varsobjc_rt_trees[OCTI_RT_META_CLASS_NST_VARS]); | ||||
2119 | } | ||||
2120 | |||||
2121 | initlist = build_v1_shared_structure_initializer | ||||
2122 | (TREE_TYPE (class_decl)((contains_struct_check ((class_decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2122, __FUNCTION__))->typed.type), | ||||
2123 | build_unary_op (loc, ADDR_EXPR, meta_decl, 0), | ||||
2124 | super_expr, name_expr, | ||||
2125 | convert (integer_type_nodeinteger_types[itk_int], | ||||
2126 | TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent->imp_template))((tree_class_check (((*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((impent->imp_template), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2126, __FUNCTION__))->type_non_common.lang_1)), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2126, __FUNCTION__)))))), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2126, __FUNCTION__))->type_common.size_unit)), | ||||
2127 | CLS_FACTORY0x0001L | cls_flags, inst_methods, inst_ivars, | ||||
2128 | protocol_decl, class_ext_decl); | ||||
2129 | |||||
2130 | finish_var_decl (class_decl, initlist); | ||||
2131 | impent->class_decl = class_decl; | ||||
2132 | } | ||||
2133 | |||||
2134 | /* --- Output NeXT V1 Metadata --- */ | ||||
2135 | |||||
2136 | /* Create the initial value for the `defs' field of _objc_symtab. | ||||
2137 | This is a CONSTRUCTOR. */ | ||||
2138 | |||||
2139 | static tree | ||||
2140 | init_def_list (tree type) | ||||
2141 | { | ||||
2142 | tree expr; | ||||
2143 | location_t loc; | ||||
2144 | struct imp_entry *impent; | ||||
2145 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
2146 | |||||
2147 | if (imp_count) | ||||
2148 | for (impent = imp_list; impent; impent = impent->next) | ||||
2149 | { | ||||
2150 | if (TREE_CODE (impent->imp_context)((enum tree_code) (impent->imp_context)->base.code) == CLASS_IMPLEMENTATION_TYPE) | ||||
2151 | { | ||||
2152 | loc = DECL_SOURCE_LOCATION (impent->class_decl)((contains_struct_check ((impent->class_decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2152, __FUNCTION__))->decl_minimal.locus); | ||||
2153 | expr = build_unary_op (loc, | ||||
2154 | ADDR_EXPR, impent->class_decl, 0); | ||||
2155 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
2156 | } | ||||
2157 | } | ||||
2158 | |||||
2159 | if (cat_count) | ||||
2160 | for (impent = imp_list; impent; impent = impent->next) | ||||
2161 | { | ||||
2162 | if (TREE_CODE (impent->imp_context)((enum tree_code) (impent->imp_context)->base.code) == CATEGORY_IMPLEMENTATION_TYPE) | ||||
2163 | { | ||||
2164 | loc = DECL_SOURCE_LOCATION (impent->class_decl)((contains_struct_check ((impent->class_decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2164, __FUNCTION__))->decl_minimal.locus); | ||||
2165 | expr = build_unary_op (loc, | ||||
2166 | ADDR_EXPR, impent->class_decl, 0); | ||||
2167 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr)do { constructor_elt _ce___ = {(tree) nullptr, expr}; vec_safe_push ((v), _ce___); } while (0); | ||||
2168 | } | ||||
2169 | } | ||||
2170 | |||||
2171 | return objc_build_constructor (type, v); | ||||
2172 | } | ||||
2173 | |||||
2174 | /* Take care of defining and initializing _OBJC_SYMBOLS. */ | ||||
2175 | |||||
2176 | /* Predefine the following data type: | ||||
2177 | |||||
2178 | struct _objc_symtab | ||||
2179 | { | ||||
2180 | long sel_ref_cnt; | ||||
2181 | SEL *refs; | ||||
2182 | short cls_def_cnt; | ||||
2183 | short cat_def_cnt; | ||||
2184 | void *defs[cls_def_cnt + cat_def_cnt]; | ||||
2185 | }; */ | ||||
2186 | |||||
2187 | static void | ||||
2188 | build_objc_symtab_template (void) | ||||
2189 | { | ||||
2190 | tree fields, *chain = NULLnullptr; | ||||
2191 | |||||
2192 | objc_symtab_templateobjc_global_trees[OCTI_SYMTAB_TEMPL] = objc_start_struct (get_identifier (UTAG_SYMTAB)(__builtin_constant_p ("_objc_symtab") ? get_identifier_with_length (("_objc_symtab"), strlen ("_objc_symtab")) : get_identifier ("_objc_symtab"))); | ||||
2193 | |||||
2194 | /* long sel_ref_cnt; */ | ||||
2195 | fields = add_field_decl (long_integer_type_nodeinteger_types[itk_long], "sel_ref_cnt", &chain); | ||||
2196 | |||||
2197 | /* SEL *refs; */ | ||||
2198 | add_field_decl (build_pointer_type (objc_selector_typeobjc_global_trees[OCTI_SEL_TYPE]), "refs", &chain); | ||||
2199 | |||||
2200 | /* short cls_def_cnt; */ | ||||
2201 | add_field_decl (short_integer_type_nodeinteger_types[itk_short], "cls_def_cnt", &chain); | ||||
2202 | |||||
2203 | /* short cat_def_cnt; */ | ||||
2204 | add_field_decl (short_integer_type_nodeinteger_types[itk_short], "cat_def_cnt", &chain); | ||||
2205 | |||||
2206 | if (imp_count || cat_count) | ||||
2207 | { | ||||
2208 | /* void *defs[imp_count + cat_count (+ 1)]; */ | ||||
2209 | /* NB: The index is one less than the size of the array. */ | ||||
2210 | int index = imp_count + cat_count; | ||||
2211 | tree array_type = build_sized_array_type (ptr_type_nodeglobal_trees[TI_PTR_TYPE], index); | ||||
2212 | add_field_decl (array_type, "defs", &chain); | ||||
2213 | } | ||||
2214 | |||||
2215 | objc_finish_struct (objc_symtab_templateobjc_global_trees[OCTI_SYMTAB_TEMPL], fields); | ||||
2216 | } | ||||
2217 | /* Construct the initial value for all of _objc_symtab. */ | ||||
2218 | |||||
2219 | static tree | ||||
2220 | init_objc_symtab (tree type) | ||||
2221 | { | ||||
2222 | vec<constructor_elt, va_gc> *v = NULLnullptr; | ||||
2223 | |||||
2224 | /* sel_ref_cnt = { ..., 5, ... } */ | ||||
2225 | |||||
2226 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_long], 0)}; vec_safe_push ((v), _ce___); } while (0) | ||||
2227 | build_int_cst (long_integer_type_node, 0))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_long], 0)}; vec_safe_push ((v), _ce___); } while (0); | ||||
2228 | |||||
2229 | /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */ | ||||
2230 | |||||
2231 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, convert (build_pointer_type (objc_global_trees[OCTI_SEL_TYPE]), global_trees[TI_INTEGER_ZERO ])}; vec_safe_push ((v), _ce___); } while (0) | ||||
2232 | convert (build_pointer_type (objc_selector_type),do { constructor_elt _ce___ = {(tree) nullptr, convert (build_pointer_type (objc_global_trees[OCTI_SEL_TYPE]), global_trees[TI_INTEGER_ZERO ])}; vec_safe_push ((v), _ce___); } while (0) | ||||
2233 | integer_zero_node))do { constructor_elt _ce___ = {(tree) nullptr, convert (build_pointer_type (objc_global_trees[OCTI_SEL_TYPE]), global_trees[TI_INTEGER_ZERO ])}; vec_safe_push ((v), _ce___); } while (0); | ||||
2234 | |||||
2235 | /* cls_def_cnt = { ..., 5, ... } */ | ||||
2236 | |||||
2237 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_short], imp_count)}; vec_safe_push ((v), _ce___ ); } while (0) | ||||
2238 | build_int_cst (short_integer_type_node, imp_count))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_short], imp_count)}; vec_safe_push ((v), _ce___ ); } while (0); | ||||
2239 | |||||
2240 | /* cat_def_cnt = { ..., 5, ... } */ | ||||
2241 | |||||
2242 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_short], cat_count)}; vec_safe_push ((v), _ce___ ); } while (0) | ||||
2243 | build_int_cst (short_integer_type_node, cat_count))do { constructor_elt _ce___ = {(tree) nullptr, build_int_cst ( integer_types[itk_short], cat_count)}; vec_safe_push ((v), _ce___ ); } while (0); | ||||
2244 | |||||
2245 | /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */ | ||||
2246 | |||||
2247 | if (imp_count || cat_count) | ||||
2248 | { | ||||
2249 | tree field = TYPE_FIELDS (type)((tree_check3 ((type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2249, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))->type_non_common.values); | ||||
2250 | field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))))(((contains_struct_check (((contains_struct_check (((((contains_struct_check (((contains_struct_check (((((contains_struct_check (((contains_struct_check (((((contains_struct_check (((contains_struct_check ((field) , (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2250, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2250, __FUNCTION__))->common.chain))), (TS_DECL_MINIMAL) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2250, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2250, __FUNCTION__))->common.chain))), (TS_DECL_MINIMAL) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2250, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2250, __FUNCTION__))->common.chain))), (TS_DECL_MINIMAL) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2250, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2250, __FUNCTION__))->common.chain)); | ||||
2251 | |||||
2252 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)))do { constructor_elt _ce___ = {(tree) nullptr, init_def_list ( ((contains_struct_check ((field), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2252, __FUNCTION__))->typed.type))}; vec_safe_push ((v), _ce___); } while (0); | ||||
2253 | } | ||||
2254 | |||||
2255 | return objc_build_constructor (type, v); | ||||
2256 | } | ||||
2257 | |||||
2258 | /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab' | ||||
2259 | and initialized appropriately. */ | ||||
2260 | |||||
2261 | static void | ||||
2262 | generate_objc_symtab_decl (void) | ||||
2263 | { | ||||
2264 | build_objc_symtab_template (); | ||||
2265 | UOBJC_SYMBOLS_declobjc_global_trees[OCTI_SYMBOLS_DECL] = start_var_decl (objc_symtab_templateobjc_global_trees[OCTI_SYMTAB_TEMPL], "_OBJC_Symbols"); | ||||
2266 | /* Allow the runtime to mark meta-data such that it can be assigned to target | ||||
2267 | specific sections by the back-end. */ | ||||
2268 | OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_symtab)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((objc_global_trees[OCTI_SYMBOLS_DECL]), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2268, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_SYMTAB ]));; | ||||
2269 | finish_var_decl (UOBJC_SYMBOLS_declobjc_global_trees[OCTI_SYMBOLS_DECL], | ||||
2270 | init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)((contains_struct_check ((objc_global_trees[OCTI_SYMBOLS_DECL ]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2270, __FUNCTION__))->typed.type))); | ||||
2271 | } | ||||
2272 | |||||
2273 | /* Any target implementing NeXT ObjC m32 ABI has to ensure that objects | ||||
2274 | refer to, and define, symbols that enforce linkage of classes into the | ||||
2275 | executable image, preserving unix archive semantics. | ||||
2276 | |||||
2277 | At present (4.8), the only targets implementing this are Darwin; these | ||||
2278 | use top level asms to implement a scheme (see config/darwin-c.cc). The | ||||
2279 | latter method is a hack, but compatible with LTO see also PR48109 for | ||||
2280 | further discussion and other possible methods. */ | ||||
2281 | |||||
2282 | static void | ||||
2283 | handle_next_class_ref (tree chain ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | ||||
2284 | { | ||||
2285 | if (targetcm.objc_declare_unresolved_class_reference) | ||||
2286 | { | ||||
2287 | const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain))((const char *) (tree_check ((((tree_check ((chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2287, __FUNCTION__, (TREE_LIST)))->list.value)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2287, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ); | ||||
2288 | char *string = (char *) alloca (strlen (name) + 30)__builtin_alloca(strlen (name) + 30); | ||||
2289 | sprintf (string, ".objc_class_name_%s", name); | ||||
2290 | targetcm.objc_declare_unresolved_class_reference (string); | ||||
2291 | } | ||||
2292 | } | ||||
2293 | |||||
2294 | static void | ||||
2295 | handle_next_impent (struct imp_entry *impent ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | ||||
2296 | { | ||||
2297 | if (targetcm.objc_declare_class_definition) | ||||
2298 | { | ||||
2299 | char buf[BUFSIZE1024]; | ||||
2300 | |||||
2301 | switch (TREE_CODE (impent->imp_context)((enum tree_code) (impent->imp_context)->base.code)) | ||||
2302 | { | ||||
2303 | case CLASS_IMPLEMENTATION_TYPE: | ||||
2304 | snprintf (buf, BUFSIZE1024, ".objc_class_name_%s", | ||||
2305 | IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))((const char *) (tree_check (((((tree_class_check ((impent-> imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2305, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2305, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
2306 | break; | ||||
2307 | case CATEGORY_IMPLEMENTATION_TYPE: | ||||
2308 | snprintf (buf, BUFSIZE1024, "*.objc_category_name_%s_%s", | ||||
2309 | IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))((const char *) (tree_check (((((tree_class_check ((impent-> imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2309, __FUNCTION__))->type_common.name))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2309, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | ||||
2310 | IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context))((const char *) (tree_check (((((tree_class_check ((impent-> imp_context), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2310, __FUNCTION__))->type_common.context))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2310, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
2311 | break; | ||||
2312 | default: | ||||
2313 | return; | ||||
2314 | } | ||||
2315 | targetcm.objc_declare_class_definition (buf); | ||||
2316 | } | ||||
2317 | } | ||||
2318 | |||||
2319 | static void | ||||
2320 | generate_classref_translation_entry (tree chain) | ||||
2321 | { | ||||
2322 | tree expr, decl, type; | ||||
2323 | |||||
2324 | decl = TREE_PURPOSE (chain)((tree_check ((chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2324, __FUNCTION__, (TREE_LIST)))->list.purpose); | ||||
2325 | type = TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2325, __FUNCTION__))->typed.type); | ||||
2326 | |||||
2327 | expr = add_objc_string (TREE_VALUE (chain)((tree_check ((chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2327, __FUNCTION__, (TREE_LIST)))->list.value), class_names); | ||||
2328 | expr = convert (type, expr); /* cast! */ | ||||
2329 | |||||
2330 | /* This is a class reference. It is re-written by the runtime, | ||||
2331 | but will be optimized away unless we force it. */ | ||||
2332 | DECL_PRESERVE_P (decl)(contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2332, __FUNCTION__))->decl_common.preserve_flag = 1; | ||||
2333 | OBJCMETA (decl, objc_meta, meta_class_reference)if (objc_rt_trees[OCTI_RT_OBJC_META]) ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2333, __FUNCTION__))->decl_common.attributes) = build_tree_list ((objc_rt_trees[OCTI_RT_OBJC_META]), (objc_rt_trees[OCTI_RT_META_CLASS_REF ]));; | ||||
2334 | finish_var_decl (decl, expr); | ||||
2335 | return; | ||||
2336 | } | ||||
2337 | |||||
2338 | static void | ||||
2339 | objc_generate_v1_next_metadata (void) | ||||
2340 | { | ||||
2341 | struct imp_entry *impent; | ||||
2342 | tree chain, attr; | ||||
2343 | long vers; | ||||
2344 | |||||
2345 | /* FIXME: Make sure that we generate no metadata if there is nothing | ||||
2346 | to put into it. */ | ||||
2347 | |||||
2348 | if (objc_static_instancesobjc_global_trees[OCTI_STATIC_NST]) | ||||
2349 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2349, __FUNCTION__)); /* Not for NeXT */ | ||||
2350 | |||||
2351 | build_metadata_templates (); | ||||
2352 | objc_implementation_contextobjc_global_trees[OCTI_IMPL_CTX] = | ||||
2353 | implementation_templateobjc_global_trees[OCTI_IMPL_TEMPL] = | ||||
2354 | UOBJC_CLASS_declobjc_global_trees[OCTI_CLS_DECL] = | ||||
2355 | UOBJC_METACLASS_declobjc_global_trees[OCTI_MCLS_DECL] = NULL_TREE(tree) nullptr; | ||||
2356 | |||||
2357 | for (impent = imp_list; impent; impent = impent->next) | ||||
2358 | { | ||||
2359 | |||||
2360 | /* If -gen-decls is present, Dump the @interface of each class. | ||||
2361 | TODO: Dump the classes in the order they were found, rather than in | ||||
2362 | reverse order as we are doing now. */ | ||||
2363 | if (flag_gen_declarationglobal_options.x_flag_gen_declaration) | ||||
2364 | dump_interface (gen_declaration_file, impent->imp_context); | ||||
2365 | |||||
2366 | /* all of the following reference the string pool... */ | ||||
2367 | if (TREE_CODE (impent->imp_context)((enum tree_code) (impent->imp_context)->base.code) == CLASS_IMPLEMENTATION_TYPE) | ||||
2368 | generate_v1_class_structs (impent); | ||||
2369 | else | ||||
2370 | generate_v1_category (impent); | ||||
2371 | } | ||||
2372 | |||||
2373 | /* If we are using an array of selectors, we must always | ||||
2374 | finish up the array decl even if no selectors were used. */ | ||||
2375 | build_next_selector_translation_table (); | ||||
2376 | |||||
2377 | if (protocol_chainobjc_global_trees[OCTI_PROTO_CHAIN]) | ||||
2378 | generate_v1_protocols (); | ||||
2379 | |||||
2380 | /* Pass summary information to the runtime. */ | ||||
2381 | if (imp_count || cat_count) | ||||
2382 | generate_objc_symtab_decl (); | ||||
2383 | |||||
2384 | vers = OBJC_VERSION(global_options.x_flag_objc_abi >= 1 ? 7 : 6); | ||||
2385 | attr = build_tree_list (objc_metaobjc_rt_trees[OCTI_RT_OBJC_META], meta_modulesobjc_rt_trees[OCTI_RT_META_MODULES]); | ||||
2386 | build_module_descriptor (vers, attr); | ||||
2387 | |||||
2388 | /* Dump the class references. This forces the appropriate classes | ||||
2389 | to be linked into the executable image, preserving unix archive | ||||
2390 | semantics. */ | ||||
2391 | for (chain = cls_ref_chainobjc_global_trees[OCTI_CLS_REF_CHAIN]; chain; chain = TREE_CHAIN (chain)((contains_struct_check ((chain), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2391, __FUNCTION__))->common.chain)) | ||||
2392 | { | ||||
2393 | handle_next_class_ref (chain); | ||||
2394 | if (TREE_PURPOSE (chain)((tree_check ((chain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2394, __FUNCTION__, (TREE_LIST)))->list.purpose)) | ||||
2395 | generate_classref_translation_entry (chain); | ||||
2396 | } | ||||
2397 | |||||
2398 | for (impent = imp_list; impent; impent = impent->next) | ||||
2399 | handle_next_impent (impent); | ||||
2400 | |||||
2401 | /* Emit the strings tables. */ | ||||
2402 | generate_strings (); | ||||
2403 | } | ||||
2404 | |||||
2405 | /* --- exceptions stuff --- */ | ||||
2406 | |||||
2407 | /* Predefine the following data type: | ||||
2408 | |||||
2409 | struct _objc_exception_data | ||||
2410 | { | ||||
2411 | int buf[OBJC_JBLEN]; | ||||
2412 | void *pointers[4]; | ||||
2413 | }; */ | ||||
2414 | |||||
2415 | /* The following yuckiness should prevent users from having to #include | ||||
2416 | <setjmp.h> in their code... */ | ||||
2417 | |||||
2418 | /* Define to a harmless positive value so the below code doesn't die. */ | ||||
2419 | #ifndef OBJC_JBLEN18 | ||||
2420 | #define OBJC_JBLEN18 18 | ||||
2421 | #endif | ||||
2422 | |||||
2423 | static void | ||||
2424 | build_next_objc_exception_stuff (void) | ||||
2425 | { | ||||
2426 | tree decls, temp_type, *chain = NULLnullptr; | ||||
2427 | |||||
2428 | objc_exception_data_templateobjc_global_trees[OCTI_EXCDATA_TEMPL] | ||||
2429 | = objc_start_struct (get_identifier (UTAG_EXCDATA)(__builtin_constant_p ("_objc_exception_data") ? get_identifier_with_length (("_objc_exception_data"), strlen ("_objc_exception_data")) : get_identifier ("_objc_exception_data"))); | ||||
2430 | |||||
2431 | /* int buf[OBJC_JBLEN]; */ | ||||
2432 | |||||
2433 | temp_type = build_sized_array_type (integer_type_nodeinteger_types[itk_int], OBJC_JBLEN18); | ||||
2434 | decls = add_field_decl (temp_type, "buf", &chain); | ||||
2435 | |||||
2436 | /* void *pointers[4]; */ | ||||
2437 | |||||
2438 | temp_type = build_sized_array_type (ptr_type_nodeglobal_trees[TI_PTR_TYPE], 4); | ||||
2439 | add_field_decl (temp_type, "pointers", &chain); | ||||
2440 | |||||
2441 | objc_finish_struct (objc_exception_data_templateobjc_global_trees[OCTI_EXCDATA_TEMPL], decls); | ||||
2442 | |||||
2443 | /* int _setjmp(...); */ | ||||
2444 | /* If the user includes <setjmp.h>, this shall be superseded by | ||||
2445 | 'int _setjmp(jmp_buf);' */ | ||||
2446 | temp_type = build_function_type (integer_type_nodeinteger_types[itk_int], NULL_TREE(tree) nullptr); | ||||
2447 | objc_setjmp_declobjc_global_trees[OCTI_SETJMP_DECL] | ||||
2448 | = add_builtin_function (TAG_SETJMP"_setjmp", temp_type, 0, NOT_BUILT_IN, NULLnullptr, NULL_TREE(tree) nullptr); | ||||
2449 | |||||
2450 | /* id objc_exception_extract(struct _objc_exception_data *); */ | ||||
2451 | temp_type | ||||
2452 | = build_function_type_list (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
2453 | build_pointer_type (objc_exception_data_templateobjc_global_trees[OCTI_EXCDATA_TEMPL]), | ||||
2454 | NULL_TREE(tree) nullptr); | ||||
2455 | objc_exception_extract_declobjc_global_trees[OCTI_EXCEPTION_EXTRACT_DECL] | ||||
2456 | = add_builtin_function (TAG_EXCEPTIONEXTRACT"objc_exception_extract", temp_type, 0, NOT_BUILT_IN, NULLnullptr, | ||||
2457 | NULL_TREE(tree) nullptr); | ||||
2458 | /* void objc_exception_try_enter(struct _objc_exception_data *); */ | ||||
2459 | /* void objc_exception_try_exit(struct _objc_exception_data *); */ | ||||
2460 | temp_type | ||||
2461 | = build_function_type_list (void_type_nodeglobal_trees[TI_VOID_TYPE], | ||||
2462 | build_pointer_type (objc_exception_data_templateobjc_global_trees[OCTI_EXCDATA_TEMPL]), | ||||
2463 | NULL_TREE(tree) nullptr); | ||||
2464 | objc_exception_try_enter_declobjc_global_trees[OCTI_EXCEPTION_TRY_ENTER_DECL] | ||||
2465 | = add_builtin_function (TAG_EXCEPTIONTRYENTER"objc_exception_try_enter", temp_type, 0, NOT_BUILT_IN, NULLnullptr, | ||||
2466 | NULL_TREE(tree) nullptr); | ||||
2467 | objc_exception_try_exit_declobjc_global_trees[OCTI_EXCEPTION_TRY_EXIT_DECL] | ||||
2468 | = add_builtin_function (TAG_EXCEPTIONTRYEXIT"objc_exception_try_exit", temp_type, 0, NOT_BUILT_IN, NULLnullptr, | ||||
2469 | NULL_TREE(tree) nullptr); | ||||
2470 | |||||
2471 | /* int objc_exception_match(id, id); */ | ||||
2472 | temp_type | ||||
2473 | = build_function_type_list (integer_type_nodeinteger_types[itk_int], | ||||
2474 | objc_object_typeobjc_global_trees[OCTI_ID_TYPE], objc_object_typeobjc_global_trees[OCTI_ID_TYPE], NULL_TREE(tree) nullptr); | ||||
2475 | objc_exception_match_declobjc_global_trees[OCTI_EXCEPTION_MATCH_DECL] | ||||
2476 | = add_builtin_function (TAG_EXCEPTIONMATCH"objc_exception_match", temp_type, 0, NOT_BUILT_IN, NULLnullptr, | ||||
2477 | NULL_TREE(tree) nullptr); | ||||
2478 | |||||
2479 | /* id objc_assign_ivar (id, id, unsigned int); */ | ||||
2480 | /* id objc_assign_ivar_Fast (id, id, unsigned int) | ||||
2481 | __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */ | ||||
2482 | temp_type | ||||
2483 | = build_function_type_list (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
2484 | objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
2485 | objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
2486 | unsigned_type_nodeinteger_types[itk_unsigned_int], | ||||
2487 | NULL_TREE(tree) nullptr); | ||||
2488 | objc_assign_ivar_declobjc_global_trees[OCTI_ASSIGN_IVAR_DECL] | ||||
2489 | = add_builtin_function (TAG_ASSIGNIVAR"objc_assign_ivar", temp_type, 0, NOT_BUILT_IN, | ||||
2490 | NULLnullptr, NULL_TREE(tree) nullptr); | ||||
2491 | #ifdef OFFS_ASSIGNIVAR_FAST | ||||
2492 | objc_assign_ivar_fast_declobjc_global_trees[OCTI_ASSIGN_IVAR_FAST_DECL] | ||||
2493 | = add_builtin_function (TAG_ASSIGNIVAR_FAST"objc_assign_ivar_Fast", temp_type, 0, | ||||
2494 | NOT_BUILT_IN, NULLnullptr, NULL_TREE(tree) nullptr); | ||||
2495 | DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)((contains_struct_check ((objc_global_trees[OCTI_ASSIGN_IVAR_FAST_DECL ]), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2495, __FUNCTION__))->decl_common.attributes) | ||||
2496 | = tree_cons (get_identifier ("hard_coded_address")(__builtin_constant_p ("hard_coded_address") ? get_identifier_with_length (("hard_coded_address"), strlen ("hard_coded_address")) : get_identifier ("hard_coded_address")), | ||||
2497 | build_int_cst (NULL_TREE(tree) nullptr, OFFS_ASSIGNIVAR_FAST), | ||||
2498 | NULL_TREE(tree) nullptr); | ||||
2499 | #else | ||||
2500 | /* Default to slower ivar method. */ | ||||
2501 | objc_assign_ivar_fast_declobjc_global_trees[OCTI_ASSIGN_IVAR_FAST_DECL] = objc_assign_ivar_declobjc_global_trees[OCTI_ASSIGN_IVAR_DECL]; | ||||
2502 | #endif | ||||
2503 | |||||
2504 | /* id objc_assign_global (id, id *); */ | ||||
2505 | /* id objc_assign_strongCast (id, id *); */ | ||||
2506 | temp_type = build_function_type_list (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
2507 | objc_object_typeobjc_global_trees[OCTI_ID_TYPE], | ||||
2508 | build_pointer_type (objc_object_typeobjc_global_trees[OCTI_ID_TYPE]), | ||||
2509 | NULL_TREE(tree) nullptr); | ||||
2510 | objc_assign_global_declobjc_global_trees[OCTI_ASSIGN_GLOBAL_DECL] | ||||
2511 | = add_builtin_function (TAG_ASSIGNGLOBAL"objc_assign_global", temp_type, 0, NOT_BUILT_IN, NULLnullptr, | ||||
2512 | NULL_TREE(tree) nullptr); | ||||
2513 | objc_assign_strong_cast_declobjc_global_trees[OCTI_ASSIGN_STRONGCAST_DECL] | ||||
2514 | = add_builtin_function (TAG_ASSIGNSTRONGCAST"objc_assign_strongCast", temp_type, 0, NOT_BUILT_IN, NULLnullptr, | ||||
2515 | NULL_TREE(tree) nullptr); | ||||
2516 | } | ||||
2517 | |||||
2518 | /* --- NeXT V1 SJLJ Exceptions --- */ | ||||
2519 | |||||
2520 | /* Build "objc_exception_try_exit(&_stack)". */ | ||||
2521 | |||||
2522 | static tree | ||||
2523 | next_sjlj_build_try_exit (struct objc_try_context **ctcp) | ||||
2524 | { | ||||
2525 | tree t; | ||||
2526 | t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl); | ||||
2527 | t = tree_cons (NULLnullptr, t, NULLnullptr); | ||||
2528 | t = build_function_call (input_location, | ||||
2529 | objc_exception_try_exit_declobjc_global_trees[OCTI_EXCEPTION_TRY_EXIT_DECL], t); | ||||
2530 | return t; | ||||
2531 | } | ||||
2532 | |||||
2533 | /* Build | ||||
2534 | objc_exception_try_enter (&_stack); | ||||
2535 | if (_setjmp(&_stack.buf)) | ||||
2536 | ; | ||||
2537 | else | ||||
2538 | ; | ||||
2539 | Return the COND_EXPR. Note that the THEN and ELSE fields are left | ||||
2540 | empty, ready for the caller to fill them in. */ | ||||
2541 | |||||
2542 | static tree | ||||
2543 | next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp) | ||||
2544 | { | ||||
2545 | tree t, enter, sj, cond; | ||||
2546 | |||||
2547 | t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl); | ||||
2548 | t = tree_cons (NULLnullptr, t, NULLnullptr); | ||||
2549 | enter = build_function_call (input_location, | ||||
2550 | objc_exception_try_enter_declobjc_global_trees[OCTI_EXCEPTION_TRY_ENTER_DECL], t); | ||||
2551 | |||||
2552 | t = objc_build_component_ref ((*ctcp)->stack_decl, | ||||
2553 | get_identifier ("buf")(__builtin_constant_p ("buf") ? get_identifier_with_length (( "buf"), strlen ("buf")) : get_identifier ("buf"))); | ||||
2554 | t = build_fold_addr_expr_loc (input_location, t); | ||||
2555 | #ifdef OBJCPLUS | ||||
2556 | /* Convert _setjmp argument to type that is expected. */ | ||||
2557 | if (prototype_p (TREE_TYPE (objc_setjmp_decl)((contains_struct_check ((objc_global_trees[OCTI_SETJMP_DECL] ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2557, __FUNCTION__))->typed.type))) | ||||
2558 | t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl)))((tree_check ((((tree_check2 ((((contains_struct_check ((objc_global_trees [OCTI_SETJMP_DECL]), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2558, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2558, __FUNCTION__, (FUNCTION_TYPE), (METHOD_TYPE)))->type_non_common .values)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2558, __FUNCTION__, (TREE_LIST)))->list.value), t); | ||||
2559 | else | ||||
2560 | t = convert (ptr_type_nodeglobal_trees[TI_PTR_TYPE], t); | ||||
2561 | #else | ||||
2562 | t = convert (ptr_type_nodeglobal_trees[TI_PTR_TYPE], t); | ||||
2563 | #endif | ||||
2564 | t = tree_cons (NULLnullptr, t, NULLnullptr); | ||||
2565 | sj = build_function_call (input_location, | ||||
2566 | objc_setjmp_declobjc_global_trees[OCTI_SETJMP_DECL], t); | ||||
2567 | |||||
2568 | cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj)((contains_struct_check ((sj), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2568, __FUNCTION__))->typed.type), enter, sj); | ||||
2569 | cond = c_common_truthvalue_conversion (input_location, cond); | ||||
2570 | |||||
2571 | return build3 (COND_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], cond, NULLnullptr, NULLnullptr); | ||||
2572 | } | ||||
2573 | |||||
2574 | /* Build: | ||||
2575 | |||||
2576 | DECL = objc_exception_extract(&_stack); */ | ||||
2577 | |||||
2578 | static tree | ||||
2579 | next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl) | ||||
2580 | { | ||||
2581 | tree t; | ||||
2582 | |||||
2583 | t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl); | ||||
2584 | t = tree_cons (NULLnullptr, t, NULLnullptr); | ||||
2585 | t = build_function_call (input_location, | ||||
2586 | objc_exception_extract_declobjc_global_trees[OCTI_EXCEPTION_EXTRACT_DECL], t); | ||||
2587 | t = convert (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2587, __FUNCTION__))->typed.type), t); | ||||
2588 | t = build2 (MODIFY_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], decl, t); | ||||
2589 | |||||
2590 | return t; | ||||
2591 | } | ||||
2592 | |||||
2593 | /* Build | ||||
2594 | if (objc_exception_match(obj_get_class(TYPE), _caught) | ||||
2595 | BODY | ||||
2596 | else if (...) | ||||
2597 | ... | ||||
2598 | else | ||||
2599 | { | ||||
2600 | _rethrow = _caught; | ||||
2601 | objc_exception_try_exit(&_stack); | ||||
2602 | } | ||||
2603 | from the sequence of CATCH_EXPRs in the current try context. */ | ||||
2604 | |||||
2605 | static tree | ||||
2606 | next_sjlj_build_catch_list (struct objc_try_context **ctcp) | ||||
2607 | { | ||||
2608 | tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list); | ||||
2609 | tree catch_seq, t; | ||||
2610 | tree *last = &catch_seq; | ||||
2611 | bool saw_id = false; | ||||
2612 | |||||
2613 | for (; !tsi_end_p (i); tsi_next (&i)) | ||||
2614 | { | ||||
2615 | tree stmt = tsi_stmt (i); | ||||
2616 | tree type = CATCH_TYPES (stmt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((stmt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2616, __FUNCTION__, (CATCH_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2616, __FUNCTION__))))); | ||||
2617 | tree body = CATCH_BODY (stmt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((stmt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2617, __FUNCTION__, (CATCH_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2617, __FUNCTION__))))); | ||||
2618 | |||||
2619 | if (type != error_mark_nodeglobal_trees[TI_ERROR_MARK] | ||||
2620 | && objc_is_object_id (TREE_TYPE (type))(((tree_class_check ((((contains_struct_check ((type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2620, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2620, __FUNCTION__))->type_common.name) == objc_global_trees [OCTI_OBJ_ID])) | ||||
2621 | { | ||||
2622 | *last = body; | ||||
2623 | saw_id = true; | ||||
2624 | break; | ||||
2625 | } | ||||
2626 | else | ||||
2627 | { | ||||
2628 | tree args, cond; | ||||
2629 | |||||
2630 | if (type == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | ||||
2631 | cond = error_mark_nodeglobal_trees[TI_ERROR_MARK]; | ||||
2632 | else | ||||
2633 | { | ||||
2634 | args = tree_cons (NULLnullptr, (*ctcp)->caught_decl, NULLnullptr); | ||||
2635 | t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type))((tree_class_check ((((contains_struct_check ((type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2635, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2635, __FUNCTION__))->type_common.name)); | ||||
2636 | args = tree_cons (NULLnullptr, t, args); | ||||
2637 | t = build_function_call (input_location, | ||||
2638 | objc_exception_match_declobjc_global_trees[OCTI_EXCEPTION_MATCH_DECL], args); | ||||
2639 | cond = c_common_truthvalue_conversion (input_location, t); | ||||
2640 | } | ||||
2641 | t = build3 (COND_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], cond, body, NULLnullptr); | ||||
2642 | SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt))(expr_check (((t)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2642, __FUNCTION__))->exp.locus = (((((stmt)) && ((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((stmt))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((stmt))->base.code))]) <= tcc_expression)) ? (stmt)->exp.locus : ((location_t) 0))); | ||||
2643 | |||||
2644 | *last = t; | ||||
2645 | last = &COND_EXPR_ELSE (t)((*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2645, __FUNCTION__, (COND_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2645, __FUNCTION__)))))); | ||||
2646 | } | ||||
2647 | } | ||||
2648 | |||||
2649 | if (!saw_id) | ||||
2650 | { | ||||
2651 | t = build2 (MODIFY_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], (*ctcp)->rethrow_decl, | ||||
2652 | (*ctcp)->caught_decl); | ||||
2653 | SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus)(expr_check (((t)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2653, __FUNCTION__))->exp.locus = ((*ctcp)->end_catch_locus ); | ||||
2654 | append_to_statement_list (t, last); | ||||
2655 | |||||
2656 | t = next_sjlj_build_try_exit (ctcp); | ||||
2657 | SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus)(expr_check (((t)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2657, __FUNCTION__))->exp.locus = ((*ctcp)->end_catch_locus ); | ||||
2658 | append_to_statement_list (t, last); | ||||
2659 | } | ||||
2660 | |||||
2661 | return catch_seq; | ||||
2662 | } | ||||
2663 | |||||
2664 | /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp | ||||
2665 | exception handling. We aim to build: | ||||
2666 | |||||
2667 | { | ||||
2668 | struct _objc_exception_data _stack; | ||||
2669 | id _rethrow = 0; | ||||
2670 | try | ||||
2671 | { | ||||
2672 | objc_exception_try_enter (&_stack); | ||||
2673 | if (_setjmp(&_stack.buf)) | ||||
2674 | { | ||||
2675 | id _caught = objc_exception_extract(&_stack); | ||||
2676 | objc_exception_try_enter (&_stack); | ||||
2677 | if (_setjmp(&_stack.buf)) | ||||
2678 | _rethrow = objc_exception_extract(&_stack); | ||||
2679 | else | ||||
2680 | CATCH-LIST | ||||
2681 | } | ||||
2682 | else | ||||
2683 | TRY-BLOCK | ||||
2684 | } | ||||
2685 | finally | ||||
2686 | { | ||||
2687 | if (!_rethrow) | ||||
2688 | objc_exception_try_exit(&_stack); | ||||
2689 | FINALLY-BLOCK | ||||
2690 | if (_rethrow) | ||||
2691 | objc_exception_throw(_rethrow); | ||||
2692 | } | ||||
2693 | } | ||||
2694 | |||||
2695 | If CATCH-LIST is empty, we can omit all of the block containing | ||||
2696 | "_caught" except for the setting of _rethrow. Note the use of | ||||
2697 | a real TRY_FINALLY_EXPR here, which is not involved in EH per-se, | ||||
2698 | but handles goto and other exits from the block. */ | ||||
2699 | |||||
2700 | static tree | ||||
2701 | next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp) | ||||
2702 | { | ||||
2703 | tree rethrow_decl, stack_decl, t; | ||||
2704 | tree catch_seq, try_fin, bind; | ||||
2705 | struct objc_try_context *cur_try_context = *ctcp; | ||||
2706 | |||||
2707 | /* Create the declarations involved. */ | ||||
2708 | t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA)(__builtin_constant_p ("_objc_exception_data") ? get_identifier_with_length (("_objc_exception_data"), strlen ("_objc_exception_data")) : get_identifier ("_objc_exception_data"))); | ||||
2709 | stack_decl = objc_create_temporary_var (t, NULLnullptr); | ||||
2710 | cur_try_context->stack_decl = stack_decl; | ||||
2711 | |||||
2712 | rethrow_decl = objc_create_temporary_var (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], NULLnullptr); | ||||
2713 | cur_try_context->rethrow_decl = rethrow_decl; | ||||
2714 | TREE_CHAIN (rethrow_decl)((contains_struct_check ((rethrow_decl), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2714, __FUNCTION__))->common.chain) = stack_decl; | ||||
2715 | |||||
2716 | /* Build the outermost variable binding level. */ | ||||
2717 | bind = build3 (BIND_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], rethrow_decl, NULLnullptr, NULLnullptr); | ||||
2718 | SET_EXPR_LOCATION (bind, cur_try_context->try_locus)(expr_check (((bind)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2718, __FUNCTION__))->exp.locus = (cur_try_context->try_locus ); | ||||
2719 | TREE_SIDE_EFFECTS (bind)((non_type_check ((bind), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2719, __FUNCTION__))->base.side_effects_flag) = 1; | ||||
2720 | |||||
2721 | /* Initialize rethrow_decl. */ | ||||
2722 | t = build2 (MODIFY_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], rethrow_decl, | ||||
2723 | convert (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], null_pointer_nodeglobal_trees[TI_NULL_POINTER])); | ||||
2724 | SET_EXPR_LOCATION (t, cur_try_context->try_locus)(expr_check (((t)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2724, __FUNCTION__))->exp.locus = (cur_try_context->try_locus ); | ||||
2725 | append_to_statement_list (t, &BIND_EXPR_BODY (bind)((*((const_cast<tree*> (tree_operand_check (((tree_check ((bind), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2725, __FUNCTION__, (BIND_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2725, __FUNCTION__))))))); | ||||
2726 | |||||
2727 | /* Build the outermost TRY_FINALLY_EXPR. */ | ||||
2728 | try_fin = build2 (TRY_FINALLY_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], NULLnullptr, NULLnullptr); | ||||
2729 | SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus)(expr_check (((try_fin)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2729, __FUNCTION__))->exp.locus = (cur_try_context->try_locus ); | ||||
2730 | TREE_SIDE_EFFECTS (try_fin)((non_type_check ((try_fin), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2730, __FUNCTION__))->base.side_effects_flag) = 1; | ||||
2731 | append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind)((*((const_cast<tree*> (tree_operand_check (((tree_check ((bind), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2731, __FUNCTION__, (BIND_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2731, __FUNCTION__))))))); | ||||
2732 | |||||
2733 | /* Create the complete catch sequence. */ | ||||
2734 | if (cur_try_context->catch_list) | ||||
2735 | { | ||||
2736 | tree caught_decl = objc_build_exc_ptr (ctcp); | ||||
2737 | catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULLnullptr, NULLnullptr); | ||||
2738 | TREE_SIDE_EFFECTS (catch_seq)((non_type_check ((catch_seq), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2738, __FUNCTION__))->base.side_effects_flag) = 1; | ||||
2739 | |||||
2740 | t = next_sjlj_build_exc_extract (ctcp, caught_decl); | ||||
2741 | append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq)((*((const_cast<tree*> (tree_operand_check (((tree_check ((catch_seq), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2741, __FUNCTION__, (BIND_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2741, __FUNCTION__))))))); | ||||
2742 | |||||
2743 | t = next_sjlj_build_enter_and_setjmp (ctcp); | ||||
2744 | COND_EXPR_THEN (t)((*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2744, __FUNCTION__, (COND_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2744, __FUNCTION__)))))) = next_sjlj_build_exc_extract (ctcp, rethrow_decl); | ||||
2745 | COND_EXPR_ELSE (t)((*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2745, __FUNCTION__, (COND_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2745, __FUNCTION__)))))) = next_sjlj_build_catch_list (ctcp); | ||||
2746 | append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq)((*((const_cast<tree*> (tree_operand_check (((tree_check ((catch_seq), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2746, __FUNCTION__, (BIND_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2746, __FUNCTION__))))))); | ||||
2747 | } | ||||
2748 | else | ||||
2749 | catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl); | ||||
2750 | SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus)(expr_check (((catch_seq)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2750, __FUNCTION__))->exp.locus = (cur_try_context->end_try_locus ); | ||||
2751 | |||||
2752 | /* Build the main register-and-try if statement. */ | ||||
2753 | t = next_sjlj_build_enter_and_setjmp (ctcp); | ||||
2754 | SET_EXPR_LOCATION (t, cur_try_context->try_locus)(expr_check (((t)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2754, __FUNCTION__))->exp.locus = (cur_try_context->try_locus ); | ||||
2755 | COND_EXPR_THEN (t)((*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2755, __FUNCTION__, (COND_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2755, __FUNCTION__)))))) = catch_seq; | ||||
2756 | COND_EXPR_ELSE (t)((*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2756, __FUNCTION__, (COND_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2756, __FUNCTION__)))))) = cur_try_context->try_body; | ||||
2757 | TREE_OPERAND (try_fin, 0)(*((const_cast<tree*> (tree_operand_check ((try_fin), ( 0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2757, __FUNCTION__))))) = t; | ||||
2758 | |||||
2759 | /* Build the complete FINALLY statement list. */ | ||||
2760 | t = next_sjlj_build_try_exit (ctcp); | ||||
2761 | t = build_stmt (input_location, COND_EXPR, | ||||
2762 | c_common_truthvalue_conversion | ||||
2763 | (input_location, rethrow_decl), | ||||
2764 | NULLnullptr, t); | ||||
2765 | SET_EXPR_LOCATION (t, cur_try_context->finally_locus)(expr_check (((t)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2765, __FUNCTION__))->exp.locus = (cur_try_context->finally_locus ); | ||||
2766 | append_to_statement_list (t, &TREE_OPERAND (try_fin, 1)(*((const_cast<tree*> (tree_operand_check ((try_fin), ( 1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2766, __FUNCTION__)))))); | ||||
2767 | |||||
2768 | append_to_statement_list (cur_try_context->finally_body, | ||||
2769 | &TREE_OPERAND (try_fin, 1)(*((const_cast<tree*> (tree_operand_check ((try_fin), ( 1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2769, __FUNCTION__)))))); | ||||
2770 | |||||
2771 | t = tree_cons (NULLnullptr, rethrow_decl, NULLnullptr); | ||||
2772 | t = build_function_call (input_location, | ||||
2773 | objc_exception_throw_declobjc_global_trees[OCTI_EXCEPTION_THROW_DECL], t); | ||||
2774 | t = build_stmt (input_location, COND_EXPR, | ||||
2775 | c_common_truthvalue_conversion (input_location, | ||||
2776 | rethrow_decl), | ||||
2777 | t, NULLnullptr); | ||||
2778 | SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus)(expr_check (((t)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2778, __FUNCTION__))->exp.locus = (cur_try_context->end_finally_locus ); | ||||
2779 | append_to_statement_list (t, &TREE_OPERAND (try_fin, 1)(*((const_cast<tree*> (tree_operand_check ((try_fin), ( 1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2779, __FUNCTION__)))))); | ||||
2780 | |||||
2781 | return bind; | ||||
2782 | } | ||||
2783 | |||||
2784 | /* We do not expect this to be used at the moment. | ||||
2785 | If (a) it is possible to implement unwinder exceptions. | ||||
2786 | (b) we do it... then it might be possibly useful. | ||||
2787 | */ | ||||
2788 | static GTY(()) tree objc_eh_personality_decl; | ||||
2789 | |||||
2790 | static tree | ||||
2791 | objc_eh_runtime_type (tree type) | ||||
2792 | { | ||||
2793 | tree ident, eh_id, decl, str; | ||||
2794 | |||||
2795 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2795, __FUNCTION__)); | ||||
2796 | if (type == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | ||||
2797 | { | ||||
2798 | /* Use 'ErrorMarkNode' as class name when error_mark_node is found | ||||
2799 | to prevent an ICE. Note that we know that the compiler will | ||||
2800 | terminate with an error and this 'ErrorMarkNode' class name will | ||||
2801 | never be actually used. */ | ||||
2802 | ident = get_identifier ("ErrorMarkNode")(__builtin_constant_p ("ErrorMarkNode") ? get_identifier_with_length (("ErrorMarkNode"), strlen ("ErrorMarkNode")) : get_identifier ("ErrorMarkNode")); | ||||
2803 | goto make_err_class; | ||||
2804 | } | ||||
2805 | |||||
2806 | if (POINTER_TYPE_P (type)(((enum tree_code) (type)->base.code) == POINTER_TYPE || ( (enum tree_code) (type)->base.code) == REFERENCE_TYPE) && objc_is_object_id (TREE_TYPE (type))(((tree_class_check ((((contains_struct_check ((type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2806, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2806, __FUNCTION__))->type_common.name) == objc_global_trees [OCTI_OBJ_ID])) | ||||
2807 | { | ||||
2808 | ident = get_identifier ("id")(__builtin_constant_p ("id") ? get_identifier_with_length (("id" ), strlen ("id")) : get_identifier ("id")); | ||||
2809 | goto make_err_class; | ||||
2810 | } | ||||
2811 | |||||
2812 | if (!POINTER_TYPE_P (type)(((enum tree_code) (type)->base.code) == POINTER_TYPE || ( (enum tree_code) (type)->base.code) == REFERENCE_TYPE) || !TYPED_OBJECT (TREE_TYPE (type))(((enum tree_code) (((contains_struct_check ((type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2812, __FUNCTION__))->typed.type))->base.code) == RECORD_TYPE && (((tree_class_check ((((contains_struct_check ((type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2812, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2812, __FUNCTION__))->type_with_lang_specific.lang_specific ) && ((tree_class_check ((((contains_struct_check ((type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2812, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2812, __FUNCTION__))->type_with_lang_specific.lang_specific )->objc_info) && (*((const_cast<tree *> (tree_vec_elt_check ((((tree_class_check ((((contains_struct_check ((type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2812, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2812, __FUNCTION__))->type_with_lang_specific.lang_specific )->objc_info), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2812, __FUNCTION__))))))) | ||||
2813 | { | ||||
2814 | #ifdef OBJCPLUS | ||||
2815 | /* This routine is also called for c++'s catch clause; in which case, | ||||
2816 | we use c++'s typeinfo decl. */ | ||||
2817 | return build_eh_type_type (type); | ||||
2818 | #else | ||||
2819 | error ("non-objective-c type %qT cannot be caught", type); | ||||
2820 | ident = get_identifier ("ErrorMarkNode")(__builtin_constant_p ("ErrorMarkNode") ? get_identifier_with_length (("ErrorMarkNode"), strlen ("ErrorMarkNode")) : get_identifier ("ErrorMarkNode")); | ||||
2821 | goto make_err_class; | ||||
2822 | #endif | ||||
2823 | } | ||||
2824 | else | ||||
2825 | ident = OBJC_TYPE_NAME (TREE_TYPE (type))((tree_class_check ((((contains_struct_check ((type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2825, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2825, __FUNCTION__))->type_common.name); | ||||
2826 | |||||
2827 | make_err_class: | ||||
2828 | /* If this class was already referenced, then it will be output during | ||||
2829 | meta-data emission, so we don't need to do it here. */ | ||||
2830 | decl = get_objc_string_decl (ident, class_names); | ||||
2831 | eh_id = add_objc_string (ident, class_names); | ||||
2832 | if (!decl) | ||||
2833 | { | ||||
2834 | /* Not found ... so we need to build it - from the freshly-entered id. */ | ||||
2835 | decl = get_objc_string_decl (ident, class_names); | ||||
2836 | str = my_build_string (IDENTIFIER_LENGTH (ident)((tree_check ((ident), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2836, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.len ) + 1, | ||||
2837 | IDENTIFIER_POINTER (ident)((const char *) (tree_check ((ident), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2837, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | ||||
2838 | /* We have to finalize this var here, because this might be called after | ||||
2839 | all the other metadata strings have been emitted. */ | ||||
2840 | finish_var_decl (decl, str); | ||||
2841 | } | ||||
2842 | return eh_id; | ||||
2843 | } | ||||
2844 | |||||
2845 | /* For NeXT ABI 0 and 1, the personality routines are just those of the | ||||
2846 | underlying language. */ | ||||
2847 | |||||
2848 | static tree | ||||
2849 | objc_eh_personality (void) | ||||
2850 | { | ||||
2851 | if (!objc_eh_personality_decl) | ||||
2852 | #ifndef OBJCPLUS | ||||
2853 | objc_eh_personality_decl = build_personality_function ("gcc"); | ||||
2854 | #else | ||||
2855 | objc_eh_personality_decl = build_personality_function ("gxx"); | ||||
2856 | #endif | ||||
2857 | return objc_eh_personality_decl; | ||||
2858 | } | ||||
2859 | |||||
2860 | /* --- interfaces --- */ | ||||
2861 | |||||
2862 | static tree | ||||
2863 | build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | ||||
2864 | { | ||||
2865 | tree t; | ||||
2866 | vec<tree, va_gc> *parms; | ||||
2867 | vec_alloc (parms, 1); | ||||
2868 | /* A throw is just a call to the runtime throw function with the | ||||
2869 | object as a parameter. */ | ||||
2870 | parms->quick_push (throw_expr); | ||||
2871 | t = build_function_call_vec (loc, vNULL, objc_exception_throw_declobjc_global_trees[OCTI_EXCEPTION_THROW_DECL], parms, | ||||
2872 | NULLnullptr); | ||||
2873 | vec_free (parms); | ||||
2874 | return add_stmt (t); | ||||
2875 | } | ||||
2876 | |||||
2877 | /* Build __builtin_eh_pointer, or the moral equivalent. In the case | ||||
2878 | of Darwin, we'll arrange for it to be initialized (and associated | ||||
2879 | with a binding) later. */ | ||||
2880 | |||||
2881 | static tree | ||||
2882 | objc_build_exc_ptr (struct objc_try_context **cur_try_context) | ||||
2883 | { | ||||
2884 | if (flag_objc_sjlj_exceptionsglobal_options.x_flag_objc_sjlj_exceptions) | ||||
2885 | { | ||||
2886 | tree var = (*cur_try_context)->caught_decl; | ||||
2887 | if (!var) | ||||
2888 | { | ||||
2889 | var = objc_create_temporary_var (objc_object_typeobjc_global_trees[OCTI_ID_TYPE], NULLnullptr); | ||||
2890 | (*cur_try_context)->caught_decl = var; | ||||
2891 | } | ||||
2892 | return var; | ||||
2893 | } | ||||
2894 | else | ||||
2895 | { | ||||
2896 | tree t; | ||||
2897 | t = builtin_decl_explicit (BUILT_IN_EH_POINTER); | ||||
2898 | t = build_call_expr (t, 1, integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]); | ||||
2899 | return fold_convert (objc_object_type, t)fold_convert_loc (((location_t) 0), objc_global_trees[OCTI_ID_TYPE ], t); | ||||
2900 | } | ||||
2901 | } | ||||
2902 | |||||
2903 | static tree | ||||
2904 | begin_catch (struct objc_try_context **cur_try_context, tree type, | ||||
2905 | tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | ||||
2906 | { | ||||
2907 | tree t; | ||||
2908 | /* Record the data for the catch in the try context so that we can | ||||
2909 | finalize it later. We treat ellipsis the same way as catching | ||||
2910 | with 'id xyz'. */ | ||||
2911 | t = build_stmt (input_location, CATCH_EXPR, type, compound); | ||||
2912 | (*cur_try_context)->current_catch = t; | ||||
2913 | |||||
2914 | /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */ | ||||
2915 | t = objc_build_exc_ptr (cur_try_context); | ||||
2916 | t = convert (TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/objc/objc-next-runtime-abi-01.cc" , 2916, __FUNCTION__))->typed.type), t); | ||||
2917 | return build2 (MODIFY_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], decl, t); | ||||
2918 | } | ||||
2919 | |||||
2920 | static void | ||||
2921 | finish_catch (struct objc_try_context **cur_try_context, tree current_catch) | ||||
2922 | { | ||||
2923 | append_to_statement_list (current_catch, &((*cur_try_context)->catch_list)); | ||||
2924 | } | ||||
2925 | |||||
2926 | static tree | ||||
2927 | finish_try_stmt (struct objc_try_context **cur_try_context) | ||||
2928 | { | ||||
2929 | tree stmt; | ||||
2930 | struct objc_try_context *c = *cur_try_context; | ||||
2931 | /* If we're doing Darwin setjmp exceptions, build the big nasty. */ | ||||
2932 | if (flag_objc_sjlj_exceptionsglobal_options.x_flag_objc_sjlj_exceptions) | ||||
2933 | { | ||||
2934 | bool save = in_late_binary_op; | ||||
2935 | in_late_binary_op = true; | ||||
2936 | if (!c->finally_body) | ||||
2937 | { | ||||
2938 | c->finally_locus = input_location; | ||||
2939 | c->end_finally_locus = input_location; | ||||
2940 | } | ||||
2941 | stmt = next_sjlj_build_try_catch_finally (cur_try_context); | ||||
2942 | in_late_binary_op = save; | ||||
2943 | } | ||||
2944 | else | ||||
2945 | /* This doesn't happen at the moment... but maybe one day... */ | ||||
2946 | { | ||||
2947 | /* Otherwise, nest the CATCH inside a FINALLY. */ | ||||
2948 | stmt = c->try_body; | ||||
2949 | if (c->catch_list) | ||||
2950 | stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list); | ||||
2951 | if (c->finally_body) | ||||
2952 | stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body); | ||||
2953 | } | ||||
2954 | return stmt; | ||||
2955 | } | ||||
2956 | |||||
2957 | #include "gt-objc-objc-next-runtime-abi-01.h" |
1 | /* Vector API for GNU compiler. | ||||
2 | Copyright (C) 2004-2023 Free Software Foundation, Inc. | ||||
3 | Contributed by Nathan Sidwell <nathan@codesourcery.com> | ||||
4 | Re-implemented in C++ by Diego Novillo <dnovillo@google.com> | ||||
5 | |||||
6 | This file is part of GCC. | ||||
7 | |||||
8 | GCC is free software; you can redistribute it and/or modify it under | ||||
9 | the terms of the GNU General Public License as published by the Free | ||||
10 | Software Foundation; either version 3, or (at your option) any later | ||||
11 | version. | ||||
12 | |||||
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||||
16 | for more details. | ||||
17 | |||||
18 | You should have received a copy of the GNU General Public License | ||||
19 | along with GCC; see the file COPYING3. If not see | ||||
20 | <http://www.gnu.org/licenses/>. */ | ||||
21 | |||||
22 | #ifndef GCC_VEC_H | ||||
23 | #define GCC_VEC_H | ||||
24 | |||||
25 | /* Some gen* file have no ggc support as the header file gtype-desc.h is | ||||
26 | missing. Provide these definitions in case ggc.h has not been included. | ||||
27 | This is not a problem because any code that runs before gengtype is built | ||||
28 | will never need to use GC vectors.*/ | ||||
29 | |||||
30 | extern void ggc_free (void *); | ||||
31 | extern size_t ggc_round_alloc_size (size_t requested_size); | ||||
32 | extern void *ggc_realloc (void *, size_t MEM_STAT_DECL); | ||||
33 | |||||
34 | /* Templated vector type and associated interfaces. | ||||
35 | |||||
36 | The interface functions are typesafe and use inline functions, | ||||
37 | sometimes backed by out-of-line generic functions. The vectors are | ||||
38 | designed to interoperate with the GTY machinery. | ||||
39 | |||||
40 | There are both 'index' and 'iterate' accessors. The index accessor | ||||
41 | is implemented by operator[]. The iterator returns a boolean | ||||
42 | iteration condition and updates the iteration variable passed by | ||||
43 | reference. Because the iterator will be inlined, the address-of | ||||
44 | can be optimized away. | ||||
45 | |||||
46 | Each operation that increases the number of active elements is | ||||
47 | available in 'quick' and 'safe' variants. The former presumes that | ||||
48 | there is sufficient allocated space for the operation to succeed | ||||
49 | (it dies if there is not). The latter will reallocate the | ||||
50 | vector, if needed. Reallocation causes an exponential increase in | ||||
51 | vector size. If you know you will be adding N elements, it would | ||||
52 | be more efficient to use the reserve operation before adding the | ||||
53 | elements with the 'quick' operation. This will ensure there are at | ||||
54 | least as many elements as you ask for, it will exponentially | ||||
55 | increase if there are too few spare slots. If you want reserve a | ||||
56 | specific number of slots, but do not want the exponential increase | ||||
57 | (for instance, you know this is the last allocation), use the | ||||
58 | reserve_exact operation. You can also create a vector of a | ||||
59 | specific size from the get go. | ||||
60 | |||||
61 | You should prefer the push and pop operations, as they append and | ||||
62 | remove from the end of the vector. If you need to remove several | ||||
63 | items in one go, use the truncate operation. The insert and remove | ||||
64 | operations allow you to change elements in the middle of the | ||||
65 | vector. There are two remove operations, one which preserves the | ||||
66 | element ordering 'ordered_remove', and one which does not | ||||
67 | 'unordered_remove'. The latter function copies the end element | ||||
68 | into the removed slot, rather than invoke a memmove operation. The | ||||
69 | 'lower_bound' function will determine where to place an item in the | ||||
70 | array using insert that will maintain sorted order. | ||||
71 | |||||
72 | Vectors are template types with three arguments: the type of the | ||||
73 | elements in the vector, the allocation strategy, and the physical | ||||
74 | layout to use | ||||
75 | |||||
76 | Four allocation strategies are supported: | ||||
77 | |||||
78 | - Heap: allocation is done using malloc/free. This is the | ||||
79 | default allocation strategy. | ||||
80 | |||||
81 | - GC: allocation is done using ggc_alloc/ggc_free. | ||||
82 | |||||
83 | - GC atomic: same as GC with the exception that the elements | ||||
84 | themselves are assumed to be of an atomic type that does | ||||
85 | not need to be garbage collected. This means that marking | ||||
86 | routines do not need to traverse the array marking the | ||||
87 | individual elements. This increases the performance of | ||||
88 | GC activities. | ||||
89 | |||||
90 | Two physical layouts are supported: | ||||
91 | |||||
92 | - Embedded: The vector is structured using the trailing array | ||||
93 | idiom. The last member of the structure is an array of size | ||||
94 | 1. When the vector is initially allocated, a single memory | ||||
95 | block is created to hold the vector's control data and the | ||||
96 | array of elements. These vectors cannot grow without | ||||
97 | reallocation (see discussion on embeddable vectors below). | ||||
98 | |||||
99 | - Space efficient: The vector is structured as a pointer to an | ||||
100 | embedded vector. This is the default layout. It means that | ||||
101 | vectors occupy a single word of storage before initial | ||||
102 | allocation. Vectors are allowed to grow (the internal | ||||
103 | pointer is reallocated but the main vector instance does not | ||||
104 | need to relocate). | ||||
105 | |||||
106 | The type, allocation and layout are specified when the vector is | ||||
107 | declared. | ||||
108 | |||||
109 | If you need to directly manipulate a vector, then the 'address' | ||||
110 | accessor will return the address of the start of the vector. Also | ||||
111 | the 'space' predicate will tell you whether there is spare capacity | ||||
112 | in the vector. You will not normally need to use these two functions. | ||||
113 | |||||
114 | Notes on the different layout strategies | ||||
115 | |||||
116 | * Embeddable vectors (vec<T, A, vl_embed>) | ||||
117 | |||||
118 | These vectors are suitable to be embedded in other data | ||||
119 | structures so that they can be pre-allocated in a contiguous | ||||
120 | memory block. | ||||
121 | |||||
122 | Embeddable vectors are implemented using the trailing array | ||||
123 | idiom, thus they are not resizeable without changing the address | ||||
124 | of the vector object itself. This means you cannot have | ||||
125 | variables or fields of embeddable vector type -- always use a | ||||
126 | pointer to a vector. The one exception is the final field of a | ||||
127 | structure, which could be a vector type. | ||||
128 | |||||
129 | You will have to use the embedded_size & embedded_init calls to | ||||
130 | create such objects, and they will not be resizeable (so the | ||||
131 | 'safe' allocation variants are not available). | ||||
132 | |||||
133 | Properties of embeddable vectors: | ||||
134 | |||||
135 | - The whole vector and control data are allocated in a single | ||||
136 | contiguous block. It uses the trailing-vector idiom, so | ||||
137 | allocation must reserve enough space for all the elements | ||||
138 | in the vector plus its control data. | ||||
139 | - The vector cannot be re-allocated. | ||||
140 | - The vector cannot grow nor shrink. | ||||
141 | - No indirections needed for access/manipulation. | ||||
142 | - It requires 2 words of storage (prior to vector allocation). | ||||
143 | |||||
144 | |||||
145 | * Space efficient vector (vec<T, A, vl_ptr>) | ||||
146 | |||||
147 | These vectors can grow dynamically and are allocated together | ||||
148 | with their control data. They are suited to be included in data | ||||
149 | structures. Prior to initial allocation, they only take a single | ||||
150 | word of storage. | ||||
151 | |||||
152 | These vectors are implemented as a pointer to embeddable vectors. | ||||
153 | The semantics allow for this pointer to be NULL to represent | ||||
154 | empty vectors. This way, empty vectors occupy minimal space in | ||||
155 | the structure containing them. | ||||
156 | |||||
157 | Properties: | ||||
158 | |||||
159 | - The whole vector and control data are allocated in a single | ||||
160 | contiguous block. | ||||
161 | - The whole vector may be re-allocated. | ||||
162 | - Vector data may grow and shrink. | ||||
163 | - Access and manipulation requires a pointer test and | ||||
164 | indirection. | ||||
165 | - It requires 1 word of storage (prior to vector allocation). | ||||
166 | |||||
167 | An example of their use would be, | ||||
168 | |||||
169 | struct my_struct { | ||||
170 | // A space-efficient vector of tree pointers in GC memory. | ||||
171 | vec<tree, va_gc, vl_ptr> v; | ||||
172 | }; | ||||
173 | |||||
174 | struct my_struct *s; | ||||
175 | |||||
176 | if (s->v.length ()) { we have some contents } | ||||
177 | s->v.safe_push (decl); // append some decl onto the end | ||||
178 | for (ix = 0; s->v.iterate (ix, &elt); ix++) | ||||
179 | { do something with elt } | ||||
180 | */ | ||||
181 | |||||
182 | /* Support function for statistics. */ | ||||
183 | extern void dump_vec_loc_statistics (void); | ||||
184 | |||||
185 | /* Hashtable mapping vec addresses to descriptors. */ | ||||
186 | extern htab_t vec_mem_usage_hash; | ||||
187 | |||||
188 | /* Control data for vectors. This contains the number of allocated | ||||
189 | and used slots inside a vector. */ | ||||
190 | |||||
191 | struct vec_prefix | ||||
192 | { | ||||
193 | /* FIXME - These fields should be private, but we need to cater to | ||||
194 | compilers that have stricter notions of PODness for types. */ | ||||
195 | |||||
196 | /* Memory allocation support routines in vec.cc. */ | ||||
197 | void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO); | ||||
198 | void release_overhead (void *, size_t, size_t, bool CXX_MEM_STAT_INFO); | ||||
199 | static unsigned calculate_allocation (vec_prefix *, unsigned, bool); | ||||
200 | static unsigned calculate_allocation_1 (unsigned, unsigned); | ||||
201 | |||||
202 | /* Note that vec_prefix should be a base class for vec, but we use | ||||
203 | offsetof() on vector fields of tree structures (e.g., | ||||
204 | tree_binfo::base_binfos), and offsetof only supports base types. | ||||
205 | |||||
206 | To compensate, we make vec_prefix a field inside vec and make | ||||
207 | vec a friend class of vec_prefix so it can access its fields. */ | ||||
208 | template <typename, typename, typename> friend struct vec; | ||||
209 | |||||
210 | /* The allocator types also need access to our internals. */ | ||||
211 | friend struct va_gc; | ||||
212 | friend struct va_gc_atomic; | ||||
213 | friend struct va_heap; | ||||
214 | |||||
215 | unsigned m_alloc : 31; | ||||
216 | unsigned m_using_auto_storage : 1; | ||||
217 | unsigned m_num; | ||||
218 | }; | ||||
219 | |||||
220 | /* Calculate the number of slots to reserve a vector, making sure that | ||||
221 | RESERVE slots are free. If EXACT grow exactly, otherwise grow | ||||
222 | exponentially. PFX is the control data for the vector. */ | ||||
223 | |||||
224 | inline unsigned | ||||
225 | vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve, | ||||
226 | bool exact) | ||||
227 | { | ||||
228 | if (exact) | ||||
229 | return (pfx ? pfx->m_num : 0) + reserve; | ||||
230 | else if (!pfx) | ||||
231 | return MAX (4, reserve)((4) > (reserve) ? (4) : (reserve)); | ||||
232 | return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve); | ||||
233 | } | ||||
234 | |||||
235 | template<typename, typename, typename> struct vec; | ||||
236 | |||||
237 | /* Valid vector layouts | ||||
238 | |||||
239 | vl_embed - Embeddable vector that uses the trailing array idiom. | ||||
240 | vl_ptr - Space efficient vector that uses a pointer to an | ||||
241 | embeddable vector. */ | ||||
242 | struct vl_embed { }; | ||||
243 | struct vl_ptr { }; | ||||
244 | |||||
245 | |||||
246 | /* Types of supported allocations | ||||
247 | |||||
248 | va_heap - Allocation uses malloc/free. | ||||
249 | va_gc - Allocation uses ggc_alloc. | ||||
250 | va_gc_atomic - Same as GC, but individual elements of the array | ||||
251 | do not need to be marked during collection. */ | ||||
252 | |||||
253 | /* Allocator type for heap vectors. */ | ||||
254 | struct va_heap | ||||
255 | { | ||||
256 | /* Heap vectors are frequently regular instances, so use the vl_ptr | ||||
257 | layout for them. */ | ||||
258 | typedef vl_ptr default_layout; | ||||
259 | |||||
260 | template<typename T> | ||||
261 | static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool | ||||
262 | CXX_MEM_STAT_INFO); | ||||
263 | |||||
264 | template<typename T> | ||||
265 | static void release (vec<T, va_heap, vl_embed> *&); | ||||
266 | }; | ||||
267 | |||||
268 | |||||
269 | /* Allocator for heap memory. Ensure there are at least RESERVE free | ||||
270 | slots in V. If EXACT is true, grow exactly, else grow | ||||
271 | exponentially. As a special case, if the vector had not been | ||||
272 | allocated and RESERVE is 0, no vector will be created. */ | ||||
273 | |||||
274 | template<typename T> | ||||
275 | inline void | ||||
276 | va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact | ||||
277 | MEM_STAT_DECL) | ||||
278 | { | ||||
279 | size_t elt_size = sizeof (T); | ||||
280 | unsigned alloc | ||||
281 | = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact); | ||||
282 | gcc_checking_assert (alloc)((void)(!(alloc) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 282, __FUNCTION__), 0 : 0)); | ||||
283 | |||||
284 | if (GATHER_STATISTICS0 && v) | ||||
285 | v->m_vecpfx.release_overhead (v, elt_size * v->allocated (), | ||||
286 | v->allocated (), false); | ||||
287 | |||||
288 | size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc); | ||||
289 | unsigned nelem = v ? v->length () : 0; | ||||
290 | v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size)); | ||||
291 | v->embedded_init (alloc, nelem); | ||||
292 | |||||
293 | if (GATHER_STATISTICS0) | ||||
294 | v->m_vecpfx.register_overhead (v, alloc, elt_size PASS_MEM_STAT); | ||||
295 | } | ||||
296 | |||||
297 | |||||
298 | #if GCC_VERSION(4 * 1000 + 2) >= 4007 | ||||
299 | #pragma GCC diagnostic push | ||||
300 | #pragma GCC diagnostic ignored "-Wfree-nonheap-object" | ||||
301 | #endif | ||||
302 | |||||
303 | /* Free the heap space allocated for vector V. */ | ||||
304 | |||||
305 | template<typename T> | ||||
306 | void | ||||
307 | va_heap::release (vec<T, va_heap, vl_embed> *&v) | ||||
308 | { | ||||
309 | size_t elt_size = sizeof (T); | ||||
310 | if (v == NULLnullptr) | ||||
311 | return; | ||||
312 | |||||
313 | if (GATHER_STATISTICS0) | ||||
314 | v->m_vecpfx.release_overhead (v, elt_size * v->allocated (), | ||||
315 | v->allocated (), true); | ||||
316 | ::free (v); | ||||
317 | v = NULLnullptr; | ||||
318 | } | ||||
319 | |||||
320 | #if GCC_VERSION(4 * 1000 + 2) >= 4007 | ||||
321 | #pragma GCC diagnostic pop | ||||
322 | #endif | ||||
323 | |||||
324 | /* Allocator type for GC vectors. Notice that we need the structure | ||||
325 | declaration even if GC is not enabled. */ | ||||
326 | |||||
327 | struct va_gc | ||||
328 | { | ||||
329 | /* Use vl_embed as the default layout for GC vectors. Due to GTY | ||||
330 | limitations, GC vectors must always be pointers, so it is more | ||||
331 | efficient to use a pointer to the vl_embed layout, rather than | ||||
332 | using a pointer to a pointer as would be the case with vl_ptr. */ | ||||
333 | typedef vl_embed default_layout; | ||||
334 | |||||
335 | template<typename T, typename A> | ||||
336 | static void reserve (vec<T, A, vl_embed> *&, unsigned, bool | ||||
337 | CXX_MEM_STAT_INFO); | ||||
338 | |||||
339 | template<typename T, typename A> | ||||
340 | static void release (vec<T, A, vl_embed> *&v); | ||||
341 | }; | ||||
342 | |||||
343 | |||||
344 | /* Free GC memory used by V and reset V to NULL. */ | ||||
345 | |||||
346 | template<typename T, typename A> | ||||
347 | inline void | ||||
348 | va_gc::release (vec<T, A, vl_embed> *&v) | ||||
349 | { | ||||
350 | if (v) | ||||
351 | ::ggc_free (v); | ||||
352 | v = NULLnullptr; | ||||
353 | } | ||||
354 | |||||
355 | |||||
356 | /* Allocator for GC memory. Ensure there are at least RESERVE free | ||||
357 | slots in V. If EXACT is true, grow exactly, else grow | ||||
358 | exponentially. As a special case, if the vector had not been | ||||
359 | allocated and RESERVE is 0, no vector will be created. */ | ||||
360 | |||||
361 | template<typename T, typename A> | ||||
362 | void | ||||
363 | va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact | ||||
364 | MEM_STAT_DECL) | ||||
365 | { | ||||
366 | unsigned alloc | ||||
367 | = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact); | ||||
368 | if (!alloc) | ||||
369 | { | ||||
370 | ::ggc_free (v); | ||||
371 | v = NULLnullptr; | ||||
372 | return; | ||||
373 | } | ||||
374 | |||||
375 | /* Calculate the amount of space we want. */ | ||||
376 | size_t size = vec<T, A, vl_embed>::embedded_size (alloc); | ||||
377 | |||||
378 | /* Ask the allocator how much space it will really give us. */ | ||||
379 | size = ::ggc_round_alloc_size (size); | ||||
380 | |||||
381 | /* Adjust the number of slots accordingly. */ | ||||
382 | size_t vec_offset = sizeof (vec_prefix); | ||||
383 | size_t elt_size = sizeof (T); | ||||
384 | alloc = (size - vec_offset) / elt_size; | ||||
385 | |||||
386 | /* And finally, recalculate the amount of space we ask for. */ | ||||
387 | size = vec_offset + alloc * elt_size; | ||||
388 | |||||
389 | unsigned nelem = v ? v->length () : 0; | ||||
390 | v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size | ||||
391 | PASS_MEM_STAT)); | ||||
392 | v->embedded_init (alloc, nelem); | ||||
393 | } | ||||
394 | |||||
395 | |||||
396 | /* Allocator type for GC vectors. This is for vectors of types | ||||
397 | atomics w.r.t. collection, so allocation and deallocation is | ||||
398 | completely inherited from va_gc. */ | ||||
399 | struct va_gc_atomic : va_gc | ||||
400 | { | ||||
401 | }; | ||||
402 | |||||
403 | |||||
404 | /* Generic vector template. Default values for A and L indicate the | ||||
405 | most commonly used strategies. | ||||
406 | |||||
407 | FIXME - Ideally, they would all be vl_ptr to encourage using regular | ||||
408 | instances for vectors, but the existing GTY machinery is limited | ||||
409 | in that it can only deal with GC objects that are pointers | ||||
410 | themselves. | ||||
411 | |||||
412 | This means that vector operations that need to deal with | ||||
413 | potentially NULL pointers, must be provided as free | ||||
414 | functions (see the vec_safe_* functions above). */ | ||||
415 | template<typename T, | ||||
416 | typename A = va_heap, | ||||
417 | typename L = typename A::default_layout> | ||||
418 | struct GTY((user)) vec | ||||
419 | { | ||||
420 | }; | ||||
421 | |||||
422 | /* Allow C++11 range-based 'for' to work directly on vec<T>*. */ | ||||
423 | template<typename T, typename A, typename L> | ||||
424 | T* begin (vec<T,A,L> *v) { return v ? v->begin () : nullptr; } | ||||
425 | template<typename T, typename A, typename L> | ||||
426 | T* end (vec<T,A,L> *v) { return v ? v->end () : nullptr; } | ||||
427 | template<typename T, typename A, typename L> | ||||
428 | const T* begin (const vec<T,A,L> *v) { return v ? v->begin () : nullptr; } | ||||
429 | template<typename T, typename A, typename L> | ||||
430 | const T* end (const vec<T,A,L> *v) { return v ? v->end () : nullptr; } | ||||
431 | |||||
432 | /* Generic vec<> debug helpers. | ||||
433 | |||||
434 | These need to be instantiated for each vec<TYPE> used throughout | ||||
435 | the compiler like this: | ||||
436 | |||||
437 | DEFINE_DEBUG_VEC (TYPE) | ||||
438 | |||||
439 | The reason we have a debug_helper() is because GDB can't | ||||
440 | disambiguate a plain call to debug(some_vec), and it must be called | ||||
441 | like debug<TYPE>(some_vec). */ | ||||
442 | |||||
443 | template<typename T> | ||||
444 | void | ||||
445 | debug_helper (vec<T> &ref) | ||||
446 | { | ||||
447 | unsigned i; | ||||
448 | for (i = 0; i < ref.length (); ++i) | ||||
449 | { | ||||
450 | fprintf (stderrstderr, "[%d] = ", i); | ||||
451 | debug_slim (ref[i]); | ||||
452 | fputc ('\n', stderrstderr); | ||||
453 | } | ||||
454 | } | ||||
455 | |||||
456 | /* We need a separate va_gc variant here because default template | ||||
457 | argument for functions cannot be used in c++-98. Once this | ||||
458 | restriction is removed, those variant should be folded with the | ||||
459 | above debug_helper. */ | ||||
460 | |||||
461 | template<typename T> | ||||
462 | void | ||||
463 | debug_helper (vec<T, va_gc> &ref) | ||||
464 | { | ||||
465 | unsigned i; | ||||
466 | for (i = 0; i < ref.length (); ++i) | ||||
467 | { | ||||
468 | fprintf (stderrstderr, "[%d] = ", i); | ||||
469 | debug_slim (ref[i]); | ||||
470 | fputc ('\n', stderrstderr); | ||||
471 | } | ||||
472 | } | ||||
473 | |||||
474 | /* Macro to define debug(vec<T>) and debug(vec<T, va_gc>) helper | ||||
475 | functions for a type T. */ | ||||
476 | |||||
477 | #define DEFINE_DEBUG_VEC(T)template void debug_helper (vec<T> &); template void debug_helper (vec<T, va_gc> &); __attribute__ ((__used__ )) void debug (vec<T> &ref) { debug_helper <T> (ref); } __attribute__ ((__used__)) void debug (vec<T> *ptr) { if (ptr) debug (*ptr); else fprintf (stderr, "<nil>\n" ); } __attribute__ ((__used__)) void debug (vec<T, va_gc> &ref) { debug_helper <T> (ref); } __attribute__ (( __used__)) void debug (vec<T, va_gc> *ptr) { if (ptr) debug (*ptr); else fprintf (stderr, "<nil>\n"); } \ | ||||
478 | template void debug_helper (vec<T> &); \ | ||||
479 | template void debug_helper (vec<T, va_gc> &); \ | ||||
480 | /* Define the vec<T> debug functions. */ \ | ||||
481 | DEBUG_FUNCTION__attribute__ ((__used__)) void \ | ||||
482 | debug (vec<T> &ref) \ | ||||
483 | { \ | ||||
484 | debug_helper <T> (ref); \ | ||||
485 | } \ | ||||
486 | DEBUG_FUNCTION__attribute__ ((__used__)) void \ | ||||
487 | debug (vec<T> *ptr) \ | ||||
488 | { \ | ||||
489 | if (ptr) \ | ||||
490 | debug (*ptr); \ | ||||
491 | else \ | ||||
492 | fprintf (stderrstderr, "<nil>\n"); \ | ||||
493 | } \ | ||||
494 | /* Define the vec<T, va_gc> debug functions. */ \ | ||||
495 | DEBUG_FUNCTION__attribute__ ((__used__)) void \ | ||||
496 | debug (vec<T, va_gc> &ref) \ | ||||
497 | { \ | ||||
498 | debug_helper <T> (ref); \ | ||||
499 | } \ | ||||
500 | DEBUG_FUNCTION__attribute__ ((__used__)) void \ | ||||
501 | debug (vec<T, va_gc> *ptr) \ | ||||
502 | { \ | ||||
503 | if (ptr) \ | ||||
504 | debug (*ptr); \ | ||||
505 | else \ | ||||
506 | fprintf (stderrstderr, "<nil>\n"); \ | ||||
507 | } | ||||
508 | |||||
509 | /* Default-construct N elements in DST. */ | ||||
510 | |||||
511 | template <typename T> | ||||
512 | inline void | ||||
513 | vec_default_construct (T *dst, unsigned n) | ||||
514 | { | ||||
515 | #ifdef BROKEN_VALUE_INITIALIZATION | ||||
516 | /* Versions of GCC before 4.4 sometimes leave certain objects | ||||
517 | uninitialized when value initialized, though if the type has | ||||
518 | user defined default ctor, that ctor is invoked. As a workaround | ||||
519 | perform clearing first and then the value initialization, which | ||||
520 | fixes the case when value initialization doesn't initialize due to | ||||
521 | the bugs and should initialize to all zeros, but still allows | ||||
522 | vectors for types with user defined default ctor that initializes | ||||
523 | some or all elements to non-zero. If T has no user defined | ||||
524 | default ctor and some non-static data members have user defined | ||||
525 | default ctors that initialize to non-zero the workaround will | ||||
526 | still not work properly; in that case we just need to provide | ||||
527 | user defined default ctor. */ | ||||
528 | memset (dst, '\0', sizeof (T) * n); | ||||
529 | #endif | ||||
530 | for ( ; n; ++dst, --n) | ||||
531 | ::new (static_cast<void*>(dst)) T (); | ||||
532 | } | ||||
533 | |||||
534 | /* Copy-construct N elements in DST from *SRC. */ | ||||
535 | |||||
536 | template <typename T> | ||||
537 | inline void | ||||
538 | vec_copy_construct (T *dst, const T *src, unsigned n) | ||||
539 | { | ||||
540 | for ( ; n; ++dst, ++src, --n) | ||||
541 | ::new (static_cast<void*>(dst)) T (*src); | ||||
542 | } | ||||
543 | |||||
544 | /* Type to provide zero-initialized values for vec<T, A, L>. This is | ||||
545 | used to provide nil initializers for vec instances. Since vec must | ||||
546 | be a trivially copyable type that can be copied by memcpy and zeroed | ||||
547 | out by memset, it must have defaulted default and copy ctor and copy | ||||
548 | assignment. To initialize a vec either use value initialization | ||||
549 | (e.g., vec() or vec v{ };) or assign it the value vNULL. This isn't | ||||
550 | needed for file-scope and function-local static vectors, which are | ||||
551 | zero-initialized by default. */ | ||||
552 | struct vnull { }; | ||||
553 | constexpr vnull vNULL{ }; | ||||
554 | |||||
555 | |||||
556 | /* Embeddable vector. These vectors are suitable to be embedded | ||||
557 | in other data structures so that they can be pre-allocated in a | ||||
558 | contiguous memory block. | ||||
559 | |||||
560 | Embeddable vectors are implemented using the trailing array idiom, | ||||
561 | thus they are not resizeable without changing the address of the | ||||
562 | vector object itself. This means you cannot have variables or | ||||
563 | fields of embeddable vector type -- always use a pointer to a | ||||
564 | vector. The one exception is the final field of a structure, which | ||||
565 | could be a vector type. | ||||
566 | |||||
567 | You will have to use the embedded_size & embedded_init calls to | ||||
568 | create such objects, and they will not be resizeable (so the 'safe' | ||||
569 | allocation variants are not available). | ||||
570 | |||||
571 | Properties: | ||||
572 | |||||
573 | - The whole vector and control data are allocated in a single | ||||
574 | contiguous block. It uses the trailing-vector idiom, so | ||||
575 | allocation must reserve enough space for all the elements | ||||
576 | in the vector plus its control data. | ||||
577 | - The vector cannot be re-allocated. | ||||
578 | - The vector cannot grow nor shrink. | ||||
579 | - No indirections needed for access/manipulation. | ||||
580 | - It requires 2 words of storage (prior to vector allocation). */ | ||||
581 | |||||
582 | template<typename T, typename A> | ||||
583 | struct GTY((user)) vec<T, A, vl_embed> | ||||
584 | { | ||||
585 | public: | ||||
586 | unsigned allocated (void) const { return m_vecpfx.m_alloc; } | ||||
587 | unsigned length (void) const { return m_vecpfx.m_num; } | ||||
588 | bool is_empty (void) const { return m_vecpfx.m_num == 0; } | ||||
589 | T *address (void) { return reinterpret_cast <T *> (this + 1); } | ||||
590 | const T *address (void) const | ||||
591 | { return reinterpret_cast <const T *> (this + 1); } | ||||
592 | T *begin () { return address (); } | ||||
593 | const T *begin () const { return address (); } | ||||
594 | T *end () { return address () + length (); } | ||||
595 | const T *end () const { return address () + length (); } | ||||
596 | const T &operator[] (unsigned) const; | ||||
597 | T &operator[] (unsigned); | ||||
598 | T &last (void); | ||||
599 | bool space (unsigned) const; | ||||
600 | bool iterate (unsigned, T *) const; | ||||
601 | bool iterate (unsigned, T **) const; | ||||
602 | vec *copy (ALONE_CXX_MEM_STAT_INFO) const; | ||||
603 | void splice (const vec &); | ||||
604 | void splice (const vec *src); | ||||
605 | T *quick_push (const T &); | ||||
606 | T &pop (void); | ||||
607 | void truncate (unsigned); | ||||
608 | void quick_insert (unsigned, const T &); | ||||
609 | void ordered_remove (unsigned); | ||||
610 | void unordered_remove (unsigned); | ||||
611 | void block_remove (unsigned, unsigned); | ||||
612 | void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *)); | ||||
613 | void sort (int (*) (const void *, const void *, void *), void *); | ||||
614 | void stablesort (int (*) (const void *, const void *, void *), void *); | ||||
615 | T *bsearch (const void *key, int (*compar) (const void *, const void *)); | ||||
616 | T *bsearch (const void *key, | ||||
617 | int (*compar)(const void *, const void *, void *), void *); | ||||
618 | unsigned lower_bound (const T &, bool (*) (const T &, const T &)) const; | ||||
619 | bool contains (const T &search) const; | ||||
620 | static size_t embedded_size (unsigned); | ||||
621 | void embedded_init (unsigned, unsigned = 0, unsigned = 0); | ||||
622 | void quick_grow (unsigned len); | ||||
623 | void quick_grow_cleared (unsigned len); | ||||
624 | |||||
625 | /* vec class can access our internal data and functions. */ | ||||
626 | template <typename, typename, typename> friend struct vec; | ||||
627 | |||||
628 | /* The allocator types also need access to our internals. */ | ||||
629 | friend struct va_gc; | ||||
630 | friend struct va_gc_atomic; | ||||
631 | friend struct va_heap; | ||||
632 | |||||
633 | /* FIXME - This field should be private, but we need to cater to | ||||
634 | compilers that have stricter notions of PODness for types. */ | ||||
635 | /* Align m_vecpfx to simplify address (). */ | ||||
636 | alignas (T) alignas (vec_prefix) vec_prefix m_vecpfx; | ||||
637 | }; | ||||
638 | |||||
639 | |||||
640 | /* Convenience wrapper functions to use when dealing with pointers to | ||||
641 | embedded vectors. Some functionality for these vectors must be | ||||
642 | provided via free functions for these reasons: | ||||
643 | |||||
644 | 1- The pointer may be NULL (e.g., before initial allocation). | ||||
645 | |||||
646 | 2- When the vector needs to grow, it must be reallocated, so | ||||
647 | the pointer will change its value. | ||||
648 | |||||
649 | Because of limitations with the current GC machinery, all vectors | ||||
650 | in GC memory *must* be pointers. */ | ||||
651 | |||||
652 | |||||
653 | /* If V contains no room for NELEMS elements, return false. Otherwise, | ||||
654 | return true. */ | ||||
655 | template<typename T, typename A> | ||||
656 | inline bool | ||||
657 | vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems) | ||||
658 | { | ||||
659 | return v ? v->space (nelems) : nelems == 0; | ||||
660 | } | ||||
661 | |||||
662 | |||||
663 | /* If V is NULL, return 0. Otherwise, return V->length(). */ | ||||
664 | template<typename T, typename A> | ||||
665 | inline unsigned | ||||
666 | vec_safe_length (const vec<T, A, vl_embed> *v) | ||||
667 | { | ||||
668 | return v ? v->length () : 0; | ||||
669 | } | ||||
670 | |||||
671 | |||||
672 | /* If V is NULL, return NULL. Otherwise, return V->address(). */ | ||||
673 | template<typename T, typename A> | ||||
674 | inline T * | ||||
675 | vec_safe_address (vec<T, A, vl_embed> *v) | ||||
676 | { | ||||
677 | return v ? v->address () : NULLnullptr; | ||||
678 | } | ||||
679 | |||||
680 | |||||
681 | /* If V is NULL, return true. Otherwise, return V->is_empty(). */ | ||||
682 | template<typename T, typename A> | ||||
683 | inline bool | ||||
684 | vec_safe_is_empty (vec<T, A, vl_embed> *v) | ||||
685 | { | ||||
686 | return v ? v->is_empty () : true; | ||||
687 | } | ||||
688 | |||||
689 | /* If V does not have space for NELEMS elements, call | ||||
690 | V->reserve(NELEMS, EXACT). */ | ||||
691 | template<typename T, typename A> | ||||
692 | inline bool | ||||
693 | vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false | ||||
694 | CXX_MEM_STAT_INFO) | ||||
695 | { | ||||
696 | bool extend = nelems ? !vec_safe_space (v, nelems) : false; | ||||
697 | if (extend
| ||||
698 | A::reserve (v, nelems, exact PASS_MEM_STAT); | ||||
699 | return extend; | ||||
700 | } | ||||
701 | |||||
702 | template<typename T, typename A> | ||||
703 | inline bool | ||||
704 | vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems | ||||
705 | CXX_MEM_STAT_INFO) | ||||
706 | { | ||||
707 | return vec_safe_reserve (v, nelems, true PASS_MEM_STAT); | ||||
708 | } | ||||
709 | |||||
710 | |||||
711 | /* Allocate GC memory for V with space for NELEMS slots. If NELEMS | ||||
712 | is 0, V is initialized to NULL. */ | ||||
713 | |||||
714 | template<typename T, typename A> | ||||
715 | inline void | ||||
716 | vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO) | ||||
717 | { | ||||
718 | v = NULLnullptr; | ||||
719 | vec_safe_reserve (v, nelems, false PASS_MEM_STAT); | ||||
720 | } | ||||
721 | |||||
722 | |||||
723 | /* Free the GC memory allocated by vector V and set it to NULL. */ | ||||
724 | |||||
725 | template<typename T, typename A> | ||||
726 | inline void | ||||
727 | vec_free (vec<T, A, vl_embed> *&v) | ||||
728 | { | ||||
729 | A::release (v); | ||||
730 | } | ||||
731 | |||||
732 | |||||
733 | /* Grow V to length LEN. Allocate it, if necessary. */ | ||||
734 | template<typename T, typename A> | ||||
735 | inline void | ||||
736 | vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len, | ||||
737 | bool exact = false CXX_MEM_STAT_INFO) | ||||
738 | { | ||||
739 | unsigned oldlen = vec_safe_length (v); | ||||
740 | gcc_checking_assert (len >= oldlen)((void)(!(len >= oldlen) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 740, __FUNCTION__), 0 : 0)); | ||||
741 | vec_safe_reserve (v, len - oldlen, exact PASS_MEM_STAT); | ||||
742 | v->quick_grow (len); | ||||
743 | } | ||||
744 | |||||
745 | |||||
746 | /* If V is NULL, allocate it. Call V->safe_grow_cleared(LEN). */ | ||||
747 | template<typename T, typename A> | ||||
748 | inline void | ||||
749 | vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len, | ||||
750 | bool exact = false CXX_MEM_STAT_INFO) | ||||
751 | { | ||||
752 | unsigned oldlen = vec_safe_length (v); | ||||
753 | vec_safe_grow (v, len, exact PASS_MEM_STAT); | ||||
754 | vec_default_construct (v->address () + oldlen, len - oldlen); | ||||
755 | } | ||||
756 | |||||
757 | |||||
758 | /* Assume V is not NULL. */ | ||||
759 | |||||
760 | template<typename T> | ||||
761 | inline void | ||||
762 | vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v, | ||||
763 | unsigned len, bool exact = false CXX_MEM_STAT_INFO) | ||||
764 | { | ||||
765 | v->safe_grow_cleared (len, exact PASS_MEM_STAT); | ||||
766 | } | ||||
767 | |||||
768 | /* If V does not have space for NELEMS elements, call | ||||
769 | V->reserve(NELEMS, EXACT). */ | ||||
770 | |||||
771 | template<typename T> | ||||
772 | inline bool | ||||
773 | vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false | ||||
774 | CXX_MEM_STAT_INFO) | ||||
775 | { | ||||
776 | return v->reserve (nelems, exact); | ||||
777 | } | ||||
778 | |||||
779 | |||||
780 | /* If V is NULL return false, otherwise return V->iterate(IX, PTR). */ | ||||
781 | template<typename T, typename A> | ||||
782 | inline bool | ||||
783 | vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr) | ||||
784 | { | ||||
785 | if (v) | ||||
786 | return v->iterate (ix, ptr); | ||||
787 | else | ||||
788 | { | ||||
789 | *ptr = 0; | ||||
790 | return false; | ||||
791 | } | ||||
792 | } | ||||
793 | |||||
794 | template<typename T, typename A> | ||||
795 | inline bool | ||||
796 | vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr) | ||||
797 | { | ||||
798 | if (v) | ||||
799 | return v->iterate (ix, ptr); | ||||
800 | else | ||||
801 | { | ||||
802 | *ptr = 0; | ||||
803 | return false; | ||||
804 | } | ||||
805 | } | ||||
806 | |||||
807 | |||||
808 | /* If V has no room for one more element, reallocate it. Then call | ||||
809 | V->quick_push(OBJ). */ | ||||
810 | template<typename T, typename A> | ||||
811 | inline T * | ||||
812 | vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO) | ||||
813 | { | ||||
814 | vec_safe_reserve (v, 1, false PASS_MEM_STAT); | ||||
815 | return v->quick_push (obj); | ||||
816 | } | ||||
817 | |||||
818 | |||||
819 | /* if V has no room for one more element, reallocate it. Then call | ||||
820 | V->quick_insert(IX, OBJ). */ | ||||
821 | template<typename T, typename A> | ||||
822 | inline void | ||||
823 | vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj | ||||
824 | CXX_MEM_STAT_INFO) | ||||
825 | { | ||||
826 | vec_safe_reserve (v, 1, false PASS_MEM_STAT); | ||||
827 | v->quick_insert (ix, obj); | ||||
828 | } | ||||
829 | |||||
830 | |||||
831 | /* If V is NULL, do nothing. Otherwise, call V->truncate(SIZE). */ | ||||
832 | template<typename T, typename A> | ||||
833 | inline void | ||||
834 | vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size) | ||||
835 | { | ||||
836 | if (v) | ||||
837 | v->truncate (size); | ||||
838 | } | ||||
839 | |||||
840 | |||||
841 | /* If SRC is not NULL, return a pointer to a copy of it. */ | ||||
842 | template<typename T, typename A> | ||||
843 | inline vec<T, A, vl_embed> * | ||||
844 | vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO) | ||||
845 | { | ||||
846 | return src ? src->copy (ALONE_PASS_MEM_STAT) : NULLnullptr; | ||||
847 | } | ||||
848 | |||||
849 | /* Copy the elements from SRC to the end of DST as if by memcpy. | ||||
850 | Reallocate DST, if necessary. */ | ||||
851 | template<typename T, typename A> | ||||
852 | inline void | ||||
853 | vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src | ||||
854 | CXX_MEM_STAT_INFO) | ||||
855 | { | ||||
856 | unsigned src_len = vec_safe_length (src); | ||||
857 | if (src_len) | ||||
858 | { | ||||
859 | vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len | ||||
860 | PASS_MEM_STAT); | ||||
861 | dst->splice (*src); | ||||
862 | } | ||||
863 | } | ||||
864 | |||||
865 | /* Return true if SEARCH is an element of V. Note that this is O(N) in the | ||||
866 | size of the vector and so should be used with care. */ | ||||
867 | |||||
868 | template<typename T, typename A> | ||||
869 | inline bool | ||||
870 | vec_safe_contains (vec<T, A, vl_embed> *v, const T &search) | ||||
871 | { | ||||
872 | return v ? v->contains (search) : false; | ||||
873 | } | ||||
874 | |||||
875 | /* Index into vector. Return the IX'th element. IX must be in the | ||||
876 | domain of the vector. */ | ||||
877 | |||||
878 | template<typename T, typename A> | ||||
879 | inline const T & | ||||
880 | vec<T, A, vl_embed>::operator[] (unsigned ix) const | ||||
881 | { | ||||
882 | gcc_checking_assert (ix < m_vecpfx.m_num)((void)(!(ix < m_vecpfx.m_num) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 882, __FUNCTION__), 0 : 0)); | ||||
883 | return address ()[ix]; | ||||
884 | } | ||||
885 | |||||
886 | template<typename T, typename A> | ||||
887 | inline T & | ||||
888 | vec<T, A, vl_embed>::operator[] (unsigned ix) | ||||
889 | { | ||||
890 | gcc_checking_assert (ix < m_vecpfx.m_num)((void)(!(ix < m_vecpfx.m_num) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 890, __FUNCTION__), 0 : 0)); | ||||
891 | return address ()[ix]; | ||||
892 | } | ||||
893 | |||||
894 | |||||
895 | /* Get the final element of the vector, which must not be empty. */ | ||||
896 | |||||
897 | template<typename T, typename A> | ||||
898 | inline T & | ||||
899 | vec<T, A, vl_embed>::last (void) | ||||
900 | { | ||||
901 | gcc_checking_assert (m_vecpfx.m_num > 0)((void)(!(m_vecpfx.m_num > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 901, __FUNCTION__), 0 : 0)); | ||||
902 | return (*this)[m_vecpfx.m_num - 1]; | ||||
903 | } | ||||
904 | |||||
905 | |||||
906 | /* If this vector has space for NELEMS additional entries, return | ||||
907 | true. You usually only need to use this if you are doing your | ||||
908 | own vector reallocation, for instance on an embedded vector. This | ||||
909 | returns true in exactly the same circumstances that vec::reserve | ||||
910 | will. */ | ||||
911 | |||||
912 | template<typename T, typename A> | ||||
913 | inline bool | ||||
914 | vec<T, A, vl_embed>::space (unsigned nelems) const | ||||
915 | { | ||||
916 | return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems; | ||||
917 | } | ||||
918 | |||||
919 | |||||
920 | /* Return iteration condition and update *PTR to (a copy of) the IX'th | ||||
921 | element of this vector. Use this to iterate over the elements of a | ||||
922 | vector as follows, | ||||
923 | |||||
924 | for (ix = 0; v->iterate (ix, &val); ix++) | ||||
925 | continue; */ | ||||
926 | |||||
927 | template<typename T, typename A> | ||||
928 | inline bool | ||||
929 | vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const | ||||
930 | { | ||||
931 | if (ix < m_vecpfx.m_num) | ||||
932 | { | ||||
933 | *ptr = address ()[ix]; | ||||
934 | return true; | ||||
935 | } | ||||
936 | else | ||||
937 | { | ||||
938 | *ptr = 0; | ||||
939 | return false; | ||||
940 | } | ||||
941 | } | ||||
942 | |||||
943 | |||||
944 | /* Return iteration condition and update *PTR to point to the | ||||
945 | IX'th element of this vector. Use this to iterate over the | ||||
946 | elements of a vector as follows, | ||||
947 | |||||
948 | for (ix = 0; v->iterate (ix, &ptr); ix++) | ||||
949 | continue; | ||||
950 | |||||
951 | This variant is for vectors of objects. */ | ||||
952 | |||||
953 | template<typename T, typename A> | ||||
954 | inline bool | ||||
955 | vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const | ||||
956 | { | ||||
957 | if (ix < m_vecpfx.m_num) | ||||
958 | { | ||||
959 | *ptr = CONST_CAST (T *, &address ()[ix])(const_cast<T *> ((&address ()[ix]))); | ||||
960 | return true; | ||||
961 | } | ||||
962 | else | ||||
963 | { | ||||
964 | *ptr = 0; | ||||
965 | return false; | ||||
966 | } | ||||
967 | } | ||||
968 | |||||
969 | |||||
970 | /* Return a pointer to a copy of this vector. */ | ||||
971 | |||||
972 | template<typename T, typename A> | ||||
973 | inline vec<T, A, vl_embed> * | ||||
974 | vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECLvoid) const | ||||
975 | { | ||||
976 | vec<T, A, vl_embed> *new_vec = NULLnullptr; | ||||
977 | unsigned len = length (); | ||||
978 | if (len) | ||||
979 | { | ||||
980 | vec_alloc (new_vec, len PASS_MEM_STAT); | ||||
981 | new_vec->embedded_init (len, len); | ||||
982 | vec_copy_construct (new_vec->address (), address (), len); | ||||
983 | } | ||||
984 | return new_vec; | ||||
985 | } | ||||
986 | |||||
987 | |||||
988 | /* Copy the elements from SRC to the end of this vector as if by memcpy. | ||||
989 | The vector must have sufficient headroom available. */ | ||||
990 | |||||
991 | template<typename T, typename A> | ||||
992 | inline void | ||||
993 | vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src) | ||||
994 | { | ||||
995 | unsigned len = src.length (); | ||||
996 | if (len) | ||||
997 | { | ||||
998 | gcc_checking_assert (space (len))((void)(!(space (len)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 998, __FUNCTION__), 0 : 0)); | ||||
999 | vec_copy_construct (end (), src.address (), len); | ||||
1000 | m_vecpfx.m_num += len; | ||||
1001 | } | ||||
1002 | } | ||||
1003 | |||||
1004 | template<typename T, typename A> | ||||
1005 | inline void | ||||
1006 | vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src) | ||||
1007 | { | ||||
1008 | if (src) | ||||
1009 | splice (*src); | ||||
1010 | } | ||||
1011 | |||||
1012 | |||||
1013 | /* Push OBJ (a new element) onto the end of the vector. There must be | ||||
1014 | sufficient space in the vector. Return a pointer to the slot | ||||
1015 | where OBJ was inserted. */ | ||||
1016 | |||||
1017 | template<typename T, typename A> | ||||
1018 | inline T * | ||||
1019 | vec<T, A, vl_embed>::quick_push (const T &obj) | ||||
1020 | { | ||||
1021 | gcc_checking_assert (space (1))((void)(!(space (1)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1021, __FUNCTION__), 0 : 0)); | ||||
1022 | T *slot = &address ()[m_vecpfx.m_num++]; | ||||
1023 | *slot = obj; | ||||
1024 | return slot; | ||||
1025 | } | ||||
1026 | |||||
1027 | |||||
1028 | /* Pop and return the last element off the end of the vector. */ | ||||
1029 | |||||
1030 | template<typename T, typename A> | ||||
1031 | inline T & | ||||
1032 | vec<T, A, vl_embed>::pop (void) | ||||
1033 | { | ||||
1034 | gcc_checking_assert (length () > 0)((void)(!(length () > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1034, __FUNCTION__), 0 : 0)); | ||||
1035 | return address ()[--m_vecpfx.m_num]; | ||||
1036 | } | ||||
1037 | |||||
1038 | |||||
1039 | /* Set the length of the vector to SIZE. The new length must be less | ||||
1040 | than or equal to the current length. This is an O(1) operation. */ | ||||
1041 | |||||
1042 | template<typename T, typename A> | ||||
1043 | inline void | ||||
1044 | vec<T, A, vl_embed>::truncate (unsigned size) | ||||
1045 | { | ||||
1046 | gcc_checking_assert (length () >= size)((void)(!(length () >= size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1046, __FUNCTION__), 0 : 0)); | ||||
1047 | m_vecpfx.m_num = size; | ||||
1048 | } | ||||
1049 | |||||
1050 | |||||
1051 | /* Insert an element, OBJ, at the IXth position of this vector. There | ||||
1052 | must be sufficient space. */ | ||||
1053 | |||||
1054 | template<typename T, typename A> | ||||
1055 | inline void | ||||
1056 | vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj) | ||||
1057 | { | ||||
1058 | gcc_checking_assert (length () < allocated ())((void)(!(length () < allocated ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1058, __FUNCTION__), 0 : 0)); | ||||
1059 | gcc_checking_assert (ix <= length ())((void)(!(ix <= length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1059, __FUNCTION__), 0 : 0)); | ||||
1060 | T *slot = &address ()[ix]; | ||||
1061 | memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T)); | ||||
1062 | *slot = obj; | ||||
1063 | } | ||||
1064 | |||||
1065 | |||||
1066 | /* Remove an element from the IXth position of this vector. Ordering of | ||||
1067 | remaining elements is preserved. This is an O(N) operation due to | ||||
1068 | memmove. */ | ||||
1069 | |||||
1070 | template<typename T, typename A> | ||||
1071 | inline void | ||||
1072 | vec<T, A, vl_embed>::ordered_remove (unsigned ix) | ||||
1073 | { | ||||
1074 | gcc_checking_assert (ix < length ())((void)(!(ix < length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1074, __FUNCTION__), 0 : 0)); | ||||
1075 | T *slot = &address ()[ix]; | ||||
1076 | memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T)); | ||||
1077 | } | ||||
1078 | |||||
1079 | |||||
1080 | /* Remove elements in [START, END) from VEC for which COND holds. Ordering of | ||||
1081 | remaining elements is preserved. This is an O(N) operation. */ | ||||
1082 | |||||
1083 | #define VEC_ORDERED_REMOVE_IF_FROM_TO(vec, read_index, write_index, \{ ((void)(!((end) <= (vec).length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1084, __FUNCTION__), 0 : 0)); for (read_index = write_index = (start); read_index < (end); ++read_index) { elem_ptr = &(vec)[read_index]; bool remove_p = (cond); if (remove_p ) continue; if (read_index != write_index) (vec)[write_index] = (vec)[read_index]; write_index++; } if (read_index - write_index > 0) (vec).block_remove (write_index, read_index - write_index ); } | ||||
1084 | elem_ptr, start, end, cond){ ((void)(!((end) <= (vec).length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1084, __FUNCTION__), 0 : 0)); for (read_index = write_index = (start); read_index < (end); ++read_index) { elem_ptr = &(vec)[read_index]; bool remove_p = (cond); if (remove_p ) continue; if (read_index != write_index) (vec)[write_index] = (vec)[read_index]; write_index++; } if (read_index - write_index > 0) (vec).block_remove (write_index, read_index - write_index ); } \ | ||||
1085 | { \ | ||||
1086 | gcc_assert ((end) <= (vec).length ())((void)(!((end) <= (vec).length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1086, __FUNCTION__), 0 : 0)); \ | ||||
1087 | for (read_index = write_index = (start); read_index < (end); \ | ||||
1088 | ++read_index) \ | ||||
1089 | { \ | ||||
1090 | elem_ptr = &(vec)[read_index]; \ | ||||
1091 | bool remove_p = (cond); \ | ||||
1092 | if (remove_p) \ | ||||
1093 | continue; \ | ||||
1094 | \ | ||||
1095 | if (read_index != write_index) \ | ||||
1096 | (vec)[write_index] = (vec)[read_index]; \ | ||||
1097 | \ | ||||
1098 | write_index++; \ | ||||
1099 | } \ | ||||
1100 | \ | ||||
1101 | if (read_index - write_index > 0) \ | ||||
1102 | (vec).block_remove (write_index, read_index - write_index); \ | ||||
1103 | } | ||||
1104 | |||||
1105 | |||||
1106 | /* Remove elements from VEC for which COND holds. Ordering of remaining | ||||
1107 | elements is preserved. This is an O(N) operation. */ | ||||
1108 | |||||
1109 | #define VEC_ORDERED_REMOVE_IF(vec, read_index, write_index, elem_ptr, \{ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1110, __FUNCTION__), 0 : 0)); for (read_index = write_index = (0); read_index < ((vec).length ()); ++read_index) { elem_ptr = &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p ) continue; if (read_index != write_index) ((vec))[write_index ] = ((vec))[read_index]; write_index++; } if (read_index - write_index > 0) ((vec)).block_remove (write_index, read_index - write_index ); } | ||||
1110 | cond){ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1110, __FUNCTION__), 0 : 0)); for (read_index = write_index = (0); read_index < ((vec).length ()); ++read_index) { elem_ptr = &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p ) continue; if (read_index != write_index) ((vec))[write_index ] = ((vec))[read_index]; write_index++; } if (read_index - write_index > 0) ((vec)).block_remove (write_index, read_index - write_index ); } \ | ||||
1111 | VEC_ORDERED_REMOVE_IF_FROM_TO ((vec), read_index, write_index, \{ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1112, __FUNCTION__), 0 : 0)); for (read_index = write_index = (0); read_index < ((vec).length ()); ++read_index) { elem_ptr = &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p ) continue; if (read_index != write_index) ((vec))[write_index ] = ((vec))[read_index]; write_index++; } if (read_index - write_index > 0) ((vec)).block_remove (write_index, read_index - write_index ); } | ||||
1112 | elem_ptr, 0, (vec).length (), (cond)){ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1112, __FUNCTION__), 0 : 0)); for (read_index = write_index = (0); read_index < ((vec).length ()); ++read_index) { elem_ptr = &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p ) continue; if (read_index != write_index) ((vec))[write_index ] = ((vec))[read_index]; write_index++; } if (read_index - write_index > 0) ((vec)).block_remove (write_index, read_index - write_index ); } | ||||
1113 | |||||
1114 | /* Remove an element from the IXth position of this vector. Ordering of | ||||
1115 | remaining elements is destroyed. This is an O(1) operation. */ | ||||
1116 | |||||
1117 | template<typename T, typename A> | ||||
1118 | inline void | ||||
1119 | vec<T, A, vl_embed>::unordered_remove (unsigned ix) | ||||
1120 | { | ||||
1121 | gcc_checking_assert (ix < length ())((void)(!(ix < length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1121, __FUNCTION__), 0 : 0)); | ||||
1122 | T *p = address (); | ||||
1123 | p[ix] = p[--m_vecpfx.m_num]; | ||||
1124 | } | ||||
1125 | |||||
1126 | |||||
1127 | /* Remove LEN elements starting at the IXth. Ordering is retained. | ||||
1128 | This is an O(N) operation due to memmove. */ | ||||
1129 | |||||
1130 | template<typename T, typename A> | ||||
1131 | inline void | ||||
1132 | vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len) | ||||
1133 | { | ||||
1134 | gcc_checking_assert (ix + len <= length ())((void)(!(ix + len <= length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1134, __FUNCTION__), 0 : 0)); | ||||
1135 | T *slot = &address ()[ix]; | ||||
1136 | m_vecpfx.m_num -= len; | ||||
1137 | memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T)); | ||||
1138 | } | ||||
1139 | |||||
1140 | |||||
1141 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
1142 | function to pass to qsort. */ | ||||
1143 | |||||
1144 | template<typename T, typename A> | ||||
1145 | inline void | ||||
1146 | vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *)) | ||||
1147 | { | ||||
1148 | if (length () > 1) | ||||
1149 | gcc_qsort (address (), length (), sizeof (T), cmp); | ||||
1150 | } | ||||
1151 | |||||
1152 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
1153 | function to pass to qsort. */ | ||||
1154 | |||||
1155 | template<typename T, typename A> | ||||
1156 | inline void | ||||
1157 | vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *), | ||||
1158 | void *data) | ||||
1159 | { | ||||
1160 | if (length () > 1) | ||||
1161 | gcc_sort_r (address (), length (), sizeof (T), cmp, data); | ||||
1162 | } | ||||
1163 | |||||
1164 | /* Sort the contents of this vector with gcc_stablesort_r. CMP is the | ||||
1165 | comparison function to pass to qsort. */ | ||||
1166 | |||||
1167 | template<typename T, typename A> | ||||
1168 | inline void | ||||
1169 | vec<T, A, vl_embed>::stablesort (int (*cmp) (const void *, const void *, | ||||
1170 | void *), void *data) | ||||
1171 | { | ||||
1172 | if (length () > 1) | ||||
1173 | gcc_stablesort_r (address (), length (), sizeof (T), cmp, data); | ||||
1174 | } | ||||
1175 | |||||
1176 | /* Search the contents of the sorted vector with a binary search. | ||||
1177 | CMP is the comparison function to pass to bsearch. */ | ||||
1178 | |||||
1179 | template<typename T, typename A> | ||||
1180 | inline T * | ||||
1181 | vec<T, A, vl_embed>::bsearch (const void *key, | ||||
1182 | int (*compar) (const void *, const void *)) | ||||
1183 | { | ||||
1184 | const void *base = this->address (); | ||||
1185 | size_t nmemb = this->length (); | ||||
1186 | size_t size = sizeof (T); | ||||
1187 | /* The following is a copy of glibc stdlib-bsearch.h. */ | ||||
1188 | size_t l, u, idx; | ||||
1189 | const void *p; | ||||
1190 | int comparison; | ||||
1191 | |||||
1192 | l = 0; | ||||
1193 | u = nmemb; | ||||
1194 | while (l < u) | ||||
1195 | { | ||||
1196 | idx = (l + u) / 2; | ||||
1197 | p = (const void *) (((const char *) base) + (idx * size)); | ||||
1198 | comparison = (*compar) (key, p); | ||||
1199 | if (comparison < 0) | ||||
1200 | u = idx; | ||||
1201 | else if (comparison > 0) | ||||
1202 | l = idx + 1; | ||||
1203 | else | ||||
1204 | return (T *)const_cast<void *>(p); | ||||
1205 | } | ||||
1206 | |||||
1207 | return NULLnullptr; | ||||
1208 | } | ||||
1209 | |||||
1210 | /* Search the contents of the sorted vector with a binary search. | ||||
1211 | CMP is the comparison function to pass to bsearch. */ | ||||
1212 | |||||
1213 | template<typename T, typename A> | ||||
1214 | inline T * | ||||
1215 | vec<T, A, vl_embed>::bsearch (const void *key, | ||||
1216 | int (*compar) (const void *, const void *, | ||||
1217 | void *), void *data) | ||||
1218 | { | ||||
1219 | const void *base = this->address (); | ||||
1220 | size_t nmemb = this->length (); | ||||
1221 | size_t size = sizeof (T); | ||||
1222 | /* The following is a copy of glibc stdlib-bsearch.h. */ | ||||
1223 | size_t l, u, idx; | ||||
1224 | const void *p; | ||||
1225 | int comparison; | ||||
1226 | |||||
1227 | l = 0; | ||||
1228 | u = nmemb; | ||||
1229 | while (l < u) | ||||
1230 | { | ||||
1231 | idx = (l + u) / 2; | ||||
1232 | p = (const void *) (((const char *) base) + (idx * size)); | ||||
1233 | comparison = (*compar) (key, p, data); | ||||
1234 | if (comparison < 0) | ||||
1235 | u = idx; | ||||
1236 | else if (comparison > 0) | ||||
1237 | l = idx + 1; | ||||
1238 | else | ||||
1239 | return (T *)const_cast<void *>(p); | ||||
1240 | } | ||||
1241 | |||||
1242 | return NULLnullptr; | ||||
1243 | } | ||||
1244 | |||||
1245 | /* Return true if SEARCH is an element of V. Note that this is O(N) in the | ||||
1246 | size of the vector and so should be used with care. */ | ||||
1247 | |||||
1248 | template<typename T, typename A> | ||||
1249 | inline bool | ||||
1250 | vec<T, A, vl_embed>::contains (const T &search) const | ||||
1251 | { | ||||
1252 | unsigned int len = length (); | ||||
1253 | const T *p = address (); | ||||
1254 | for (unsigned int i = 0; i < len; i++) | ||||
1255 | { | ||||
1256 | const T *slot = &p[i]; | ||||
1257 | if (*slot == search) | ||||
1258 | return true; | ||||
1259 | } | ||||
1260 | |||||
1261 | return false; | ||||
1262 | } | ||||
1263 | |||||
1264 | /* Find and return the first position in which OBJ could be inserted | ||||
1265 | without changing the ordering of this vector. LESSTHAN is a | ||||
1266 | function that returns true if the first argument is strictly less | ||||
1267 | than the second. */ | ||||
1268 | |||||
1269 | template<typename T, typename A> | ||||
1270 | unsigned | ||||
1271 | vec<T, A, vl_embed>::lower_bound (const T &obj, | ||||
1272 | bool (*lessthan)(const T &, const T &)) | ||||
1273 | const | ||||
1274 | { | ||||
1275 | unsigned int len = length (); | ||||
1276 | unsigned int half, middle; | ||||
1277 | unsigned int first = 0; | ||||
1278 | while (len > 0) | ||||
1279 | { | ||||
1280 | half = len / 2; | ||||
1281 | middle = first; | ||||
1282 | middle += half; | ||||
1283 | const T &middle_elem = address ()[middle]; | ||||
1284 | if (lessthan (middle_elem, obj)) | ||||
1285 | { | ||||
1286 | first = middle; | ||||
1287 | ++first; | ||||
1288 | len = len - half - 1; | ||||
1289 | } | ||||
1290 | else | ||||
1291 | len = half; | ||||
1292 | } | ||||
1293 | return first; | ||||
1294 | } | ||||
1295 | |||||
1296 | |||||
1297 | /* Return the number of bytes needed to embed an instance of an | ||||
1298 | embeddable vec inside another data structure. | ||||
1299 | |||||
1300 | Use these methods to determine the required size and initialization | ||||
1301 | of a vector V of type T embedded within another structure (as the | ||||
1302 | final member): | ||||
1303 | |||||
1304 | size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc); | ||||
1305 | void v->embedded_init (unsigned alloc, unsigned num); | ||||
1306 | |||||
1307 | These allow the caller to perform the memory allocation. */ | ||||
1308 | |||||
1309 | template<typename T, typename A> | ||||
1310 | inline size_t | ||||
1311 | vec<T, A, vl_embed>::embedded_size (unsigned alloc) | ||||
1312 | { | ||||
1313 | struct alignas (T) U { char data[sizeof (T)]; }; | ||||
1314 | typedef vec<U, A, vl_embed> vec_embedded; | ||||
1315 | typedef typename std::conditional<std::is_standard_layout<T>::value, | ||||
1316 | vec, vec_embedded>::type vec_stdlayout; | ||||
1317 | static_assert (sizeof (vec_stdlayout) == sizeof (vec), ""); | ||||
1318 | static_assert (alignof (vec_stdlayout) == alignof (vec), ""); | ||||
1319 | return sizeof (vec_stdlayout) + alloc * sizeof (T); | ||||
1320 | } | ||||
1321 | |||||
1322 | |||||
1323 | /* Initialize the vector to contain room for ALLOC elements and | ||||
1324 | NUM active elements. */ | ||||
1325 | |||||
1326 | template<typename T, typename A> | ||||
1327 | inline void | ||||
1328 | vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut) | ||||
1329 | { | ||||
1330 | m_vecpfx.m_alloc = alloc; | ||||
1331 | m_vecpfx.m_using_auto_storage = aut; | ||||
1332 | m_vecpfx.m_num = num; | ||||
1333 | } | ||||
1334 | |||||
1335 | |||||
1336 | /* Grow the vector to a specific length. LEN must be as long or longer than | ||||
1337 | the current length. The new elements are uninitialized. */ | ||||
1338 | |||||
1339 | template<typename T, typename A> | ||||
1340 | inline void | ||||
1341 | vec<T, A, vl_embed>::quick_grow (unsigned len) | ||||
1342 | { | ||||
1343 | gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc)((void)(!(length () <= len && len <= m_vecpfx.m_alloc ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1343, __FUNCTION__), 0 : 0)); | ||||
1344 | m_vecpfx.m_num = len; | ||||
1345 | } | ||||
1346 | |||||
1347 | |||||
1348 | /* Grow the vector to a specific length. LEN must be as long or longer than | ||||
1349 | the current length. The new elements are initialized to zero. */ | ||||
1350 | |||||
1351 | template<typename T, typename A> | ||||
1352 | inline void | ||||
1353 | vec<T, A, vl_embed>::quick_grow_cleared (unsigned len) | ||||
1354 | { | ||||
1355 | unsigned oldlen = length (); | ||||
1356 | size_t growby = len - oldlen; | ||||
1357 | quick_grow (len); | ||||
1358 | if (growby != 0) | ||||
1359 | vec_default_construct (address () + oldlen, growby); | ||||
1360 | } | ||||
1361 | |||||
1362 | /* Garbage collection support for vec<T, A, vl_embed>. */ | ||||
1363 | |||||
1364 | template<typename T> | ||||
1365 | void | ||||
1366 | gt_ggc_mx (vec<T, va_gc> *v) | ||||
1367 | { | ||||
1368 | extern void gt_ggc_mx (T &); | ||||
1369 | for (unsigned i = 0; i < v->length (); i++) | ||||
1370 | gt_ggc_mx ((*v)[i]); | ||||
1371 | } | ||||
1372 | |||||
1373 | template<typename T> | ||||
1374 | void | ||||
1375 | gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | ||||
1376 | { | ||||
1377 | /* Nothing to do. Vectors of atomic types wrt GC do not need to | ||||
1378 | be traversed. */ | ||||
1379 | } | ||||
1380 | |||||
1381 | |||||
1382 | /* PCH support for vec<T, A, vl_embed>. */ | ||||
1383 | |||||
1384 | template<typename T, typename A> | ||||
1385 | void | ||||
1386 | gt_pch_nx (vec<T, A, vl_embed> *v) | ||||
1387 | { | ||||
1388 | extern void gt_pch_nx (T &); | ||||
1389 | for (unsigned i = 0; i < v->length (); i++) | ||||
1390 | gt_pch_nx ((*v)[i]); | ||||
1391 | } | ||||
1392 | |||||
1393 | template<typename T, typename A> | ||||
1394 | void | ||||
1395 | gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie) | ||||
1396 | { | ||||
1397 | for (unsigned i = 0; i < v->length (); i++) | ||||
1398 | op (&((*v)[i]), NULLnullptr, cookie); | ||||
1399 | } | ||||
1400 | |||||
1401 | template<typename T, typename A> | ||||
1402 | void | ||||
1403 | gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie) | ||||
1404 | { | ||||
1405 | extern void gt_pch_nx (T *, gt_pointer_operator, void *); | ||||
1406 | for (unsigned i = 0; i < v->length (); i++) | ||||
1407 | gt_pch_nx (&((*v)[i]), op, cookie); | ||||
1408 | } | ||||
1409 | |||||
1410 | |||||
1411 | /* Space efficient vector. These vectors can grow dynamically and are | ||||
1412 | allocated together with their control data. They are suited to be | ||||
1413 | included in data structures. Prior to initial allocation, they | ||||
1414 | only take a single word of storage. | ||||
1415 | |||||
1416 | These vectors are implemented as a pointer to an embeddable vector. | ||||
1417 | The semantics allow for this pointer to be NULL to represent empty | ||||
1418 | vectors. This way, empty vectors occupy minimal space in the | ||||
1419 | structure containing them. | ||||
1420 | |||||
1421 | Properties: | ||||
1422 | |||||
1423 | - The whole vector and control data are allocated in a single | ||||
1424 | contiguous block. | ||||
1425 | - The whole vector may be re-allocated. | ||||
1426 | - Vector data may grow and shrink. | ||||
1427 | - Access and manipulation requires a pointer test and | ||||
1428 | indirection. | ||||
1429 | - It requires 1 word of storage (prior to vector allocation). | ||||
1430 | |||||
1431 | |||||
1432 | Limitations: | ||||
1433 | |||||
1434 | These vectors must be PODs because they are stored in unions. | ||||
1435 | (http://en.wikipedia.org/wiki/Plain_old_data_structures). | ||||
1436 | As long as we use C++03, we cannot have constructors nor | ||||
1437 | destructors in classes that are stored in unions. */ | ||||
1438 | |||||
1439 | template<typename T, size_t N = 0> | ||||
1440 | class auto_vec; | ||||
1441 | |||||
1442 | template<typename T> | ||||
1443 | struct vec<T, va_heap, vl_ptr> | ||||
1444 | { | ||||
1445 | public: | ||||
1446 | /* Default ctors to ensure triviality. Use value-initialization | ||||
1447 | (e.g., vec() or vec v{ };) or vNULL to create a zero-initialized | ||||
1448 | instance. */ | ||||
1449 | vec () = default; | ||||
1450 | vec (const vec &) = default; | ||||
1451 | /* Initialization from the generic vNULL. */ | ||||
1452 | vec (vnull): m_vec () { } | ||||
1453 | /* Same as default ctor: vec storage must be released manually. */ | ||||
1454 | ~vec () = default; | ||||
1455 | |||||
1456 | /* Defaulted same as copy ctor. */ | ||||
1457 | vec& operator= (const vec &) = default; | ||||
1458 | |||||
1459 | /* Prevent implicit conversion from auto_vec. Use auto_vec::to_vec() | ||||
1460 | instead. */ | ||||
1461 | template <size_t N> | ||||
1462 | vec (auto_vec<T, N> &) = delete; | ||||
1463 | |||||
1464 | template <size_t N> | ||||
1465 | void operator= (auto_vec<T, N> &) = delete; | ||||
1466 | |||||
1467 | /* Memory allocation and deallocation for the embedded vector. | ||||
1468 | Needed because we cannot have proper ctors/dtors defined. */ | ||||
1469 | void create (unsigned nelems CXX_MEM_STAT_INFO); | ||||
1470 | void release (void); | ||||
1471 | |||||
1472 | /* Vector operations. */ | ||||
1473 | bool exists (void) const | ||||
1474 | { return m_vec != NULLnullptr; } | ||||
1475 | |||||
1476 | bool is_empty (void) const | ||||
1477 | { return m_vec ? m_vec->is_empty () : true; } | ||||
1478 | |||||
1479 | unsigned allocated (void) const | ||||
1480 | { return m_vec ? m_vec->allocated () : 0; } | ||||
1481 | |||||
1482 | unsigned length (void) const | ||||
1483 | { return m_vec ? m_vec->length () : 0; } | ||||
1484 | |||||
1485 | T *address (void) | ||||
1486 | { return m_vec ? m_vec->address () : NULLnullptr; } | ||||
1487 | |||||
1488 | const T *address (void) const | ||||
1489 | { return m_vec ? m_vec->address () : NULLnullptr; } | ||||
1490 | |||||
1491 | T *begin () { return address (); } | ||||
1492 | const T *begin () const { return address (); } | ||||
1493 | T *end () { return begin () + length (); } | ||||
1494 | const T *end () const { return begin () + length (); } | ||||
1495 | const T &operator[] (unsigned ix) const | ||||
1496 | { return (*m_vec)[ix]; } | ||||
1497 | |||||
1498 | bool operator!=(const vec &other) const | ||||
1499 | { return !(*this == other); } | ||||
1500 | |||||
1501 | bool operator==(const vec &other) const | ||||
1502 | { return address () == other.address (); } | ||||
1503 | |||||
1504 | T &operator[] (unsigned ix) | ||||
1505 | { return (*m_vec)[ix]; } | ||||
1506 | |||||
1507 | T &last (void) | ||||
1508 | { return m_vec->last (); } | ||||
1509 | |||||
1510 | bool space (int nelems) const | ||||
1511 | { return m_vec ? m_vec->space (nelems) : nelems == 0; } | ||||
1512 | |||||
1513 | bool iterate (unsigned ix, T *p) const; | ||||
1514 | bool iterate (unsigned ix, T **p) const; | ||||
1515 | vec copy (ALONE_CXX_MEM_STAT_INFO) const; | ||||
1516 | bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO); | ||||
1517 | bool reserve_exact (unsigned CXX_MEM_STAT_INFO); | ||||
1518 | void splice (const vec &); | ||||
1519 | void safe_splice (const vec & CXX_MEM_STAT_INFO); | ||||
1520 | T *quick_push (const T &); | ||||
1521 | T *safe_push (const T &CXX_MEM_STAT_INFO); | ||||
1522 | T &pop (void); | ||||
1523 | void truncate (unsigned); | ||||
1524 | void safe_grow (unsigned, bool = false CXX_MEM_STAT_INFO); | ||||
1525 | void safe_grow_cleared (unsigned, bool = false CXX_MEM_STAT_INFO); | ||||
1526 | void quick_grow (unsigned); | ||||
1527 | void quick_grow_cleared (unsigned); | ||||
1528 | void quick_insert (unsigned, const T &); | ||||
1529 | void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO); | ||||
1530 | void ordered_remove (unsigned); | ||||
1531 | void unordered_remove (unsigned); | ||||
1532 | void block_remove (unsigned, unsigned); | ||||
1533 | void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *)); | ||||
1534 | void sort (int (*) (const void *, const void *, void *), void *); | ||||
1535 | void stablesort (int (*) (const void *, const void *, void *), void *); | ||||
1536 | T *bsearch (const void *key, int (*compar)(const void *, const void *)); | ||||
1537 | T *bsearch (const void *key, | ||||
1538 | int (*compar)(const void *, const void *, void *), void *); | ||||
1539 | unsigned lower_bound (T, bool (*)(const T &, const T &)) const; | ||||
1540 | bool contains (const T &search) const; | ||||
1541 | void reverse (void); | ||||
1542 | |||||
1543 | bool using_auto_storage () const; | ||||
1544 | |||||
1545 | /* FIXME - This field should be private, but we need to cater to | ||||
1546 | compilers that have stricter notions of PODness for types. */ | ||||
1547 | vec<T, va_heap, vl_embed> *m_vec; | ||||
1548 | }; | ||||
1549 | |||||
1550 | |||||
1551 | /* auto_vec is a subclass of vec that automatically manages creating and | ||||
1552 | releasing the internal vector. If N is non zero then it has N elements of | ||||
1553 | internal storage. The default is no internal storage, and you probably only | ||||
1554 | want to ask for internal storage for vectors on the stack because if the | ||||
1555 | size of the vector is larger than the internal storage that space is wasted. | ||||
1556 | */ | ||||
1557 | template<typename T, size_t N /* = 0 */> | ||||
1558 | class auto_vec : public vec<T, va_heap> | ||||
1559 | { | ||||
1560 | public: | ||||
1561 | auto_vec () | ||||
1562 | { | ||||
1563 | m_auto.embedded_init (N, 0, 1); | ||||
1564 | /* ??? Instead of initializing m_vec from &m_auto directly use an | ||||
1565 | expression that avoids refering to a specific member of 'this' | ||||
1566 | to derail the -Wstringop-overflow diagnostic code, avoiding | ||||
1567 | the impression that data accesses are supposed to be to the | ||||
1568 | m_auto member storage. */ | ||||
1569 | size_t off = (char *) &m_auto - (char *) this; | ||||
1570 | this->m_vec = (vec<T, va_heap, vl_embed> *) ((char *) this + off); | ||||
1571 | } | ||||
1572 | |||||
1573 | auto_vec (size_t s CXX_MEM_STAT_INFO) | ||||
1574 | { | ||||
1575 | if (s > N) | ||||
1576 | { | ||||
1577 | this->create (s PASS_MEM_STAT); | ||||
1578 | return; | ||||
1579 | } | ||||
1580 | |||||
1581 | m_auto.embedded_init (N, 0, 1); | ||||
1582 | /* ??? See above. */ | ||||
1583 | size_t off = (char *) &m_auto - (char *) this; | ||||
1584 | this->m_vec = (vec<T, va_heap, vl_embed> *) ((char *) this + off); | ||||
1585 | } | ||||
1586 | |||||
1587 | ~auto_vec () | ||||
1588 | { | ||||
1589 | this->release (); | ||||
1590 | } | ||||
1591 | |||||
1592 | /* Explicitly convert to the base class. There is no conversion | ||||
1593 | from a const auto_vec because a copy of the returned vec can | ||||
1594 | be used to modify *THIS. | ||||
1595 | This is a legacy function not to be used in new code. */ | ||||
1596 | vec<T, va_heap> to_vec_legacy () { | ||||
1597 | return *static_cast<vec<T, va_heap> *>(this); | ||||
1598 | } | ||||
1599 | |||||
1600 | private: | ||||
1601 | vec<T, va_heap, vl_embed> m_auto; | ||||
1602 | unsigned char m_data[sizeof (T) * N]; | ||||
1603 | }; | ||||
1604 | |||||
1605 | /* auto_vec is a sub class of vec whose storage is released when it is | ||||
1606 | destroyed. */ | ||||
1607 | template<typename T> | ||||
1608 | class auto_vec<T, 0> : public vec<T, va_heap> | ||||
1609 | { | ||||
1610 | public: | ||||
1611 | auto_vec () { this->m_vec = NULLnullptr; } | ||||
1612 | auto_vec (size_t n CXX_MEM_STAT_INFO) { this->create (n PASS_MEM_STAT); } | ||||
1613 | ~auto_vec () { this->release (); } | ||||
1614 | |||||
1615 | auto_vec (vec<T, va_heap>&& r) | ||||
1616 | { | ||||
1617 | gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1617, __FUNCTION__), 0 : 0)); | ||||
1618 | this->m_vec = r.m_vec; | ||||
1619 | r.m_vec = NULLnullptr; | ||||
1620 | } | ||||
1621 | |||||
1622 | auto_vec (auto_vec<T> &&r) | ||||
1623 | { | ||||
1624 | gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1624, __FUNCTION__), 0 : 0)); | ||||
1625 | this->m_vec = r.m_vec; | ||||
1626 | r.m_vec = NULLnullptr; | ||||
1627 | } | ||||
1628 | |||||
1629 | auto_vec& operator= (vec<T, va_heap>&& r) | ||||
1630 | { | ||||
1631 | if (this == &r) | ||||
1632 | return *this; | ||||
1633 | |||||
1634 | gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1634, __FUNCTION__), 0 : 0)); | ||||
1635 | this->release (); | ||||
1636 | this->m_vec = r.m_vec; | ||||
1637 | r.m_vec = NULLnullptr; | ||||
1638 | return *this; | ||||
1639 | } | ||||
1640 | |||||
1641 | auto_vec& operator= (auto_vec<T> &&r) | ||||
1642 | { | ||||
1643 | if (this == &r) | ||||
1644 | return *this; | ||||
1645 | |||||
1646 | gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1646, __FUNCTION__), 0 : 0)); | ||||
1647 | this->release (); | ||||
1648 | this->m_vec = r.m_vec; | ||||
1649 | r.m_vec = NULLnullptr; | ||||
1650 | return *this; | ||||
1651 | } | ||||
1652 | |||||
1653 | /* Explicitly convert to the base class. There is no conversion | ||||
1654 | from a const auto_vec because a copy of the returned vec can | ||||
1655 | be used to modify *THIS. | ||||
1656 | This is a legacy function not to be used in new code. */ | ||||
1657 | vec<T, va_heap> to_vec_legacy () { | ||||
1658 | return *static_cast<vec<T, va_heap> *>(this); | ||||
1659 | } | ||||
1660 | |||||
1661 | // You probably don't want to copy a vector, so these are deleted to prevent | ||||
1662 | // unintentional use. If you really need a copy of the vectors contents you | ||||
1663 | // can use copy (). | ||||
1664 | auto_vec(const auto_vec &) = delete; | ||||
1665 | auto_vec &operator= (const auto_vec &) = delete; | ||||
1666 | }; | ||||
1667 | |||||
1668 | |||||
1669 | /* Allocate heap memory for pointer V and create the internal vector | ||||
1670 | with space for NELEMS elements. If NELEMS is 0, the internal | ||||
1671 | vector is initialized to empty. */ | ||||
1672 | |||||
1673 | template<typename T> | ||||
1674 | inline void | ||||
1675 | vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO) | ||||
1676 | { | ||||
1677 | v = new vec<T>; | ||||
1678 | v->create (nelems PASS_MEM_STAT); | ||||
1679 | } | ||||
1680 | |||||
1681 | |||||
1682 | /* A subclass of auto_vec <char *> that frees all of its elements on | ||||
1683 | deletion. */ | ||||
1684 | |||||
1685 | class auto_string_vec : public auto_vec <char *> | ||||
1686 | { | ||||
1687 | public: | ||||
1688 | ~auto_string_vec (); | ||||
1689 | }; | ||||
1690 | |||||
1691 | /* A subclass of auto_vec <T *> that deletes all of its elements on | ||||
1692 | destruction. | ||||
1693 | |||||
1694 | This is a crude way for a vec to "own" the objects it points to | ||||
1695 | and clean up automatically. | ||||
1696 | |||||
1697 | For example, no attempt is made to delete elements when an item | ||||
1698 | within the vec is overwritten. | ||||
1699 | |||||
1700 | We can't rely on gnu::unique_ptr within a container, | ||||
1701 | since we can't rely on move semantics in C++98. */ | ||||
1702 | |||||
1703 | template <typename T> | ||||
1704 | class auto_delete_vec : public auto_vec <T *> | ||||
1705 | { | ||||
1706 | public: | ||||
1707 | auto_delete_vec () {} | ||||
1708 | auto_delete_vec (size_t s) : auto_vec <T *> (s) {} | ||||
1709 | |||||
1710 | ~auto_delete_vec (); | ||||
1711 | |||||
1712 | private: | ||||
1713 | DISABLE_COPY_AND_ASSIGN(auto_delete_vec)auto_delete_vec (const auto_delete_vec&) = delete; void operator = (const auto_delete_vec &) = delete; | ||||
1714 | }; | ||||
1715 | |||||
1716 | /* Conditionally allocate heap memory for VEC and its internal vector. */ | ||||
1717 | |||||
1718 | template<typename T> | ||||
1719 | inline void | ||||
1720 | vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO) | ||||
1721 | { | ||||
1722 | if (!vec) | ||||
1723 | vec_alloc (vec, nelems PASS_MEM_STAT); | ||||
1724 | } | ||||
1725 | |||||
1726 | |||||
1727 | /* Free the heap memory allocated by vector V and set it to NULL. */ | ||||
1728 | |||||
1729 | template<typename T> | ||||
1730 | inline void | ||||
1731 | vec_free (vec<T> *&v) | ||||
1732 | { | ||||
1733 | if (v == NULLnullptr) | ||||
1734 | return; | ||||
1735 | |||||
1736 | v->release (); | ||||
1737 | delete v; | ||||
1738 | v = NULLnullptr; | ||||
1739 | } | ||||
1740 | |||||
1741 | |||||
1742 | /* Return iteration condition and update PTR to point to the IX'th | ||||
1743 | element of this vector. Use this to iterate over the elements of a | ||||
1744 | vector as follows, | ||||
1745 | |||||
1746 | for (ix = 0; v.iterate (ix, &ptr); ix++) | ||||
1747 | continue; */ | ||||
1748 | |||||
1749 | template<typename T> | ||||
1750 | inline bool | ||||
1751 | vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const | ||||
1752 | { | ||||
1753 | if (m_vec) | ||||
1754 | return m_vec->iterate (ix, ptr); | ||||
1755 | else | ||||
1756 | { | ||||
1757 | *ptr = 0; | ||||
1758 | return false; | ||||
1759 | } | ||||
1760 | } | ||||
1761 | |||||
1762 | |||||
1763 | /* Return iteration condition and update *PTR to point to the | ||||
1764 | IX'th element of this vector. Use this to iterate over the | ||||
1765 | elements of a vector as follows, | ||||
1766 | |||||
1767 | for (ix = 0; v->iterate (ix, &ptr); ix++) | ||||
1768 | continue; | ||||
1769 | |||||
1770 | This variant is for vectors of objects. */ | ||||
1771 | |||||
1772 | template<typename T> | ||||
1773 | inline bool | ||||
1774 | vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const | ||||
1775 | { | ||||
1776 | if (m_vec) | ||||
1777 | return m_vec->iterate (ix, ptr); | ||||
1778 | else | ||||
1779 | { | ||||
1780 | *ptr = 0; | ||||
1781 | return false; | ||||
1782 | } | ||||
1783 | } | ||||
1784 | |||||
1785 | |||||
1786 | /* Convenience macro for forward iteration. */ | ||||
1787 | #define FOR_EACH_VEC_ELT(V, I, P)for (I = 0; (V).iterate ((I), &(P)); ++(I)) \ | ||||
1788 | for (I = 0; (V).iterate ((I), &(P)); ++(I)) | ||||
1789 | |||||
1790 | #define FOR_EACH_VEC_SAFE_ELT(V, I, P)for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I)) \ | ||||
1791 | for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I)) | ||||
1792 | |||||
1793 | /* Likewise, but start from FROM rather than 0. */ | ||||
1794 | #define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM)for (I = (FROM); (V).iterate ((I), &(P)); ++(I)) \ | ||||
1795 | for (I = (FROM); (V).iterate ((I), &(P)); ++(I)) | ||||
1796 | |||||
1797 | /* Convenience macro for reverse iteration. */ | ||||
1798 | #define FOR_EACH_VEC_ELT_REVERSE(V, I, P)for (I = (V).length () - 1; (V).iterate ((I), &(P)); (I)-- ) \ | ||||
1799 | for (I = (V).length () - 1; \ | ||||
1800 | (V).iterate ((I), &(P)); \ | ||||
1801 | (I)--) | ||||
1802 | |||||
1803 | #define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P)for (I = vec_safe_length (V) - 1; vec_safe_iterate ((V), (I), &(P)); (I)--) \ | ||||
1804 | for (I = vec_safe_length (V) - 1; \ | ||||
1805 | vec_safe_iterate ((V), (I), &(P)); \ | ||||
1806 | (I)--) | ||||
1807 | |||||
1808 | /* auto_string_vec's dtor, freeing all contained strings, automatically | ||||
1809 | chaining up to ~auto_vec <char *>, which frees the internal buffer. */ | ||||
1810 | |||||
1811 | inline | ||||
1812 | auto_string_vec::~auto_string_vec () | ||||
1813 | { | ||||
1814 | int i; | ||||
1815 | char *str; | ||||
1816 | FOR_EACH_VEC_ELT (*this, i, str)for (i = 0; (*this).iterate ((i), &(str)); ++(i)) | ||||
1817 | free (str); | ||||
1818 | } | ||||
1819 | |||||
1820 | /* auto_delete_vec's dtor, deleting all contained items, automatically | ||||
1821 | chaining up to ~auto_vec <T*>, which frees the internal buffer. */ | ||||
1822 | |||||
1823 | template <typename T> | ||||
1824 | inline | ||||
1825 | auto_delete_vec<T>::~auto_delete_vec () | ||||
1826 | { | ||||
1827 | int i; | ||||
1828 | T *item; | ||||
1829 | FOR_EACH_VEC_ELT (*this, i, item)for (i = 0; (*this).iterate ((i), &(item)); ++(i)) | ||||
1830 | delete item; | ||||
1831 | } | ||||
1832 | |||||
1833 | |||||
1834 | /* Return a copy of this vector. */ | ||||
1835 | |||||
1836 | template<typename T> | ||||
1837 | inline vec<T, va_heap, vl_ptr> | ||||
1838 | vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECLvoid) const | ||||
1839 | { | ||||
1840 | vec<T, va_heap, vl_ptr> new_vec{ }; | ||||
1841 | if (length ()) | ||||
1842 | new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT); | ||||
1843 | return new_vec; | ||||
1844 | } | ||||
1845 | |||||
1846 | |||||
1847 | /* Ensure that the vector has at least RESERVE slots available (if | ||||
1848 | EXACT is false), or exactly RESERVE slots available (if EXACT is | ||||
1849 | true). | ||||
1850 | |||||
1851 | This may create additional headroom if EXACT is false. | ||||
1852 | |||||
1853 | Note that this can cause the embedded vector to be reallocated. | ||||
1854 | Returns true iff reallocation actually occurred. */ | ||||
1855 | |||||
1856 | template<typename T> | ||||
1857 | inline bool | ||||
1858 | vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL) | ||||
1859 | { | ||||
1860 | if (space (nelems)) | ||||
1861 | return false; | ||||
1862 | |||||
1863 | /* For now play a game with va_heap::reserve to hide our auto storage if any, | ||||
1864 | this is necessary because it doesn't have enough information to know the | ||||
1865 | embedded vector is in auto storage, and so should not be freed. */ | ||||
1866 | vec<T, va_heap, vl_embed> *oldvec = m_vec; | ||||
1867 | unsigned int oldsize = 0; | ||||
1868 | bool handle_auto_vec = m_vec && using_auto_storage (); | ||||
1869 | if (handle_auto_vec) | ||||
1870 | { | ||||
1871 | m_vec = NULLnullptr; | ||||
1872 | oldsize = oldvec->length (); | ||||
1873 | nelems += oldsize; | ||||
1874 | } | ||||
1875 | |||||
1876 | va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT); | ||||
1877 | if (handle_auto_vec) | ||||
1878 | { | ||||
1879 | vec_copy_construct (m_vec->address (), oldvec->address (), oldsize); | ||||
1880 | m_vec->m_vecpfx.m_num = oldsize; | ||||
1881 | } | ||||
1882 | |||||
1883 | return true; | ||||
1884 | } | ||||
1885 | |||||
1886 | |||||
1887 | /* Ensure that this vector has exactly NELEMS slots available. This | ||||
1888 | will not create additional headroom. Note this can cause the | ||||
1889 | embedded vector to be reallocated. Returns true iff reallocation | ||||
1890 | actually occurred. */ | ||||
1891 | |||||
1892 | template<typename T> | ||||
1893 | inline bool | ||||
1894 | vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL) | ||||
1895 | { | ||||
1896 | return reserve (nelems, true PASS_MEM_STAT); | ||||
1897 | } | ||||
1898 | |||||
1899 | |||||
1900 | /* Create the internal vector and reserve NELEMS for it. This is | ||||
1901 | exactly like vec::reserve, but the internal vector is | ||||
1902 | unconditionally allocated from scratch. The old one, if it | ||||
1903 | existed, is lost. */ | ||||
1904 | |||||
1905 | template<typename T> | ||||
1906 | inline void | ||||
1907 | vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL) | ||||
1908 | { | ||||
1909 | m_vec = NULLnullptr; | ||||
1910 | if (nelems > 0) | ||||
1911 | reserve_exact (nelems PASS_MEM_STAT); | ||||
1912 | } | ||||
1913 | |||||
1914 | |||||
1915 | /* Free the memory occupied by the embedded vector. */ | ||||
1916 | |||||
1917 | template<typename T> | ||||
1918 | inline void | ||||
1919 | vec<T, va_heap, vl_ptr>::release (void) | ||||
1920 | { | ||||
1921 | if (!m_vec) | ||||
1922 | return; | ||||
1923 | |||||
1924 | if (using_auto_storage ()) | ||||
1925 | { | ||||
1926 | m_vec->m_vecpfx.m_num = 0; | ||||
1927 | return; | ||||
1928 | } | ||||
1929 | |||||
1930 | va_heap::release (m_vec); | ||||
1931 | } | ||||
1932 | |||||
1933 | /* Copy the elements from SRC to the end of this vector as if by memcpy. | ||||
1934 | SRC and this vector must be allocated with the same memory | ||||
1935 | allocation mechanism. This vector is assumed to have sufficient | ||||
1936 | headroom available. */ | ||||
1937 | |||||
1938 | template<typename T> | ||||
1939 | inline void | ||||
1940 | vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src) | ||||
1941 | { | ||||
1942 | if (src.length ()) | ||||
1943 | m_vec->splice (*(src.m_vec)); | ||||
1944 | } | ||||
1945 | |||||
1946 | |||||
1947 | /* Copy the elements in SRC to the end of this vector as if by memcpy. | ||||
1948 | SRC and this vector must be allocated with the same mechanism. | ||||
1949 | If there is not enough headroom in this vector, it will be reallocated | ||||
1950 | as needed. */ | ||||
1951 | |||||
1952 | template<typename T> | ||||
1953 | inline void | ||||
1954 | vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src | ||||
1955 | MEM_STAT_DECL) | ||||
1956 | { | ||||
1957 | if (src.length ()) | ||||
1958 | { | ||||
1959 | reserve_exact (src.length ()); | ||||
1960 | splice (src); | ||||
1961 | } | ||||
1962 | } | ||||
1963 | |||||
1964 | |||||
1965 | /* Push OBJ (a new element) onto the end of the vector. There must be | ||||
1966 | sufficient space in the vector. Return a pointer to the slot | ||||
1967 | where OBJ was inserted. */ | ||||
1968 | |||||
1969 | template<typename T> | ||||
1970 | inline T * | ||||
1971 | vec<T, va_heap, vl_ptr>::quick_push (const T &obj) | ||||
1972 | { | ||||
1973 | return m_vec->quick_push (obj); | ||||
1974 | } | ||||
1975 | |||||
1976 | |||||
1977 | /* Push a new element OBJ onto the end of this vector. Reallocates | ||||
1978 | the embedded vector, if needed. Return a pointer to the slot where | ||||
1979 | OBJ was inserted. */ | ||||
1980 | |||||
1981 | template<typename T> | ||||
1982 | inline T * | ||||
1983 | vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL) | ||||
1984 | { | ||||
1985 | reserve (1, false PASS_MEM_STAT); | ||||
1986 | return quick_push (obj); | ||||
1987 | } | ||||
1988 | |||||
1989 | |||||
1990 | /* Pop and return the last element off the end of the vector. */ | ||||
1991 | |||||
1992 | template<typename T> | ||||
1993 | inline T & | ||||
1994 | vec<T, va_heap, vl_ptr>::pop (void) | ||||
1995 | { | ||||
1996 | return m_vec->pop (); | ||||
1997 | } | ||||
1998 | |||||
1999 | |||||
2000 | /* Set the length of the vector to LEN. The new length must be less | ||||
2001 | than or equal to the current length. This is an O(1) operation. */ | ||||
2002 | |||||
2003 | template<typename T> | ||||
2004 | inline void | ||||
2005 | vec<T, va_heap, vl_ptr>::truncate (unsigned size) | ||||
2006 | { | ||||
2007 | if (m_vec) | ||||
2008 | m_vec->truncate (size); | ||||
2009 | else | ||||
2010 | gcc_checking_assert (size == 0)((void)(!(size == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2010, __FUNCTION__), 0 : 0)); | ||||
2011 | } | ||||
2012 | |||||
2013 | |||||
2014 | /* Grow the vector to a specific length. LEN must be as long or | ||||
2015 | longer than the current length. The new elements are | ||||
2016 | uninitialized. Reallocate the internal vector, if needed. */ | ||||
2017 | |||||
2018 | template<typename T> | ||||
2019 | inline void | ||||
2020 | vec<T, va_heap, vl_ptr>::safe_grow (unsigned len, bool exact MEM_STAT_DECL) | ||||
2021 | { | ||||
2022 | unsigned oldlen = length (); | ||||
2023 | gcc_checking_assert (oldlen <= len)((void)(!(oldlen <= len) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2023, __FUNCTION__), 0 : 0)); | ||||
2024 | reserve (len - oldlen, exact PASS_MEM_STAT); | ||||
2025 | if (m_vec) | ||||
2026 | m_vec->quick_grow (len); | ||||
2027 | else | ||||
2028 | gcc_checking_assert (len == 0)((void)(!(len == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2028, __FUNCTION__), 0 : 0)); | ||||
2029 | } | ||||
2030 | |||||
2031 | |||||
2032 | /* Grow the embedded vector to a specific length. LEN must be as | ||||
2033 | long or longer than the current length. The new elements are | ||||
2034 | initialized to zero. Reallocate the internal vector, if needed. */ | ||||
2035 | |||||
2036 | template<typename T> | ||||
2037 | inline void | ||||
2038 | vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len, bool exact | ||||
2039 | MEM_STAT_DECL) | ||||
2040 | { | ||||
2041 | unsigned oldlen = length (); | ||||
2042 | size_t growby = len - oldlen; | ||||
2043 | safe_grow (len, exact PASS_MEM_STAT); | ||||
2044 | if (growby != 0) | ||||
2045 | vec_default_construct (address () + oldlen, growby); | ||||
2046 | } | ||||
2047 | |||||
2048 | |||||
2049 | /* Same as vec::safe_grow but without reallocation of the internal vector. | ||||
2050 | If the vector cannot be extended, a runtime assertion will be triggered. */ | ||||
2051 | |||||
2052 | template<typename T> | ||||
2053 | inline void | ||||
2054 | vec<T, va_heap, vl_ptr>::quick_grow (unsigned len) | ||||
2055 | { | ||||
2056 | gcc_checking_assert (m_vec)((void)(!(m_vec) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2056, __FUNCTION__), 0 : 0)); | ||||
2057 | m_vec->quick_grow (len); | ||||
2058 | } | ||||
2059 | |||||
2060 | |||||
2061 | /* Same as vec::quick_grow_cleared but without reallocation of the | ||||
2062 | internal vector. If the vector cannot be extended, a runtime | ||||
2063 | assertion will be triggered. */ | ||||
2064 | |||||
2065 | template<typename T> | ||||
2066 | inline void | ||||
2067 | vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len) | ||||
2068 | { | ||||
2069 | gcc_checking_assert (m_vec)((void)(!(m_vec) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2069, __FUNCTION__), 0 : 0)); | ||||
2070 | m_vec->quick_grow_cleared (len); | ||||
2071 | } | ||||
2072 | |||||
2073 | |||||
2074 | /* Insert an element, OBJ, at the IXth position of this vector. There | ||||
2075 | must be sufficient space. */ | ||||
2076 | |||||
2077 | template<typename T> | ||||
2078 | inline void | ||||
2079 | vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj) | ||||
2080 | { | ||||
2081 | m_vec->quick_insert (ix, obj); | ||||
2082 | } | ||||
2083 | |||||
2084 | |||||
2085 | /* Insert an element, OBJ, at the IXth position of the vector. | ||||
2086 | Reallocate the embedded vector, if necessary. */ | ||||
2087 | |||||
2088 | template<typename T> | ||||
2089 | inline void | ||||
2090 | vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL) | ||||
2091 | { | ||||
2092 | reserve (1, false PASS_MEM_STAT); | ||||
2093 | quick_insert (ix, obj); | ||||
2094 | } | ||||
2095 | |||||
2096 | |||||
2097 | /* Remove an element from the IXth position of this vector. Ordering of | ||||
2098 | remaining elements is preserved. This is an O(N) operation due to | ||||
2099 | a memmove. */ | ||||
2100 | |||||
2101 | template<typename T> | ||||
2102 | inline void | ||||
2103 | vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix) | ||||
2104 | { | ||||
2105 | m_vec->ordered_remove (ix); | ||||
2106 | } | ||||
2107 | |||||
2108 | |||||
2109 | /* Remove an element from the IXth position of this vector. Ordering | ||||
2110 | of remaining elements is destroyed. This is an O(1) operation. */ | ||||
2111 | |||||
2112 | template<typename T> | ||||
2113 | inline void | ||||
2114 | vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix) | ||||
2115 | { | ||||
2116 | m_vec->unordered_remove (ix); | ||||
2117 | } | ||||
2118 | |||||
2119 | |||||
2120 | /* Remove LEN elements starting at the IXth. Ordering is retained. | ||||
2121 | This is an O(N) operation due to memmove. */ | ||||
2122 | |||||
2123 | template<typename T> | ||||
2124 | inline void | ||||
2125 | vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len) | ||||
2126 | { | ||||
2127 | m_vec->block_remove (ix, len); | ||||
2128 | } | ||||
2129 | |||||
2130 | |||||
2131 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
2132 | function to pass to qsort. */ | ||||
2133 | |||||
2134 | template<typename T> | ||||
2135 | inline void | ||||
2136 | vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *)) | ||||
2137 | { | ||||
2138 | if (m_vec) | ||||
2139 | m_vec->qsort (cmp)qsort (cmp); | ||||
2140 | } | ||||
2141 | |||||
2142 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
2143 | function to pass to qsort. */ | ||||
2144 | |||||
2145 | template<typename T> | ||||
2146 | inline void | ||||
2147 | vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *, | ||||
2148 | void *), void *data) | ||||
2149 | { | ||||
2150 | if (m_vec) | ||||
2151 | m_vec->sort (cmp, data); | ||||
2152 | } | ||||
2153 | |||||
2154 | /* Sort the contents of this vector with gcc_stablesort_r. CMP is the | ||||
2155 | comparison function to pass to qsort. */ | ||||
2156 | |||||
2157 | template<typename T> | ||||
2158 | inline void | ||||
2159 | vec<T, va_heap, vl_ptr>::stablesort (int (*cmp) (const void *, const void *, | ||||
2160 | void *), void *data) | ||||
2161 | { | ||||
2162 | if (m_vec) | ||||
2163 | m_vec->stablesort (cmp, data); | ||||
2164 | } | ||||
2165 | |||||
2166 | /* Search the contents of the sorted vector with a binary search. | ||||
2167 | CMP is the comparison function to pass to bsearch. */ | ||||
2168 | |||||
2169 | template<typename T> | ||||
2170 | inline T * | ||||
2171 | vec<T, va_heap, vl_ptr>::bsearch (const void *key, | ||||
2172 | int (*cmp) (const void *, const void *)) | ||||
2173 | { | ||||
2174 | if (m_vec) | ||||
2175 | return m_vec->bsearch (key, cmp); | ||||
2176 | return NULLnullptr; | ||||
2177 | } | ||||
2178 | |||||
2179 | /* Search the contents of the sorted vector with a binary search. | ||||
2180 | CMP is the comparison function to pass to bsearch. */ | ||||
2181 | |||||
2182 | template<typename T> | ||||
2183 | inline T * | ||||
2184 | vec<T, va_heap, vl_ptr>::bsearch (const void *key, | ||||
2185 | int (*cmp) (const void *, const void *, | ||||
2186 | void *), void *data) | ||||
2187 | { | ||||
2188 | if (m_vec) | ||||
2189 | return m_vec->bsearch (key, cmp, data); | ||||
2190 | return NULLnullptr; | ||||
2191 | } | ||||
2192 | |||||
2193 | |||||
2194 | /* Find and return the first position in which OBJ could be inserted | ||||
2195 | without changing the ordering of this vector. LESSTHAN is a | ||||
2196 | function that returns true if the first argument is strictly less | ||||
2197 | than the second. */ | ||||
2198 | |||||
2199 | template<typename T> | ||||
2200 | inline unsigned | ||||
2201 | vec<T, va_heap, vl_ptr>::lower_bound (T obj, | ||||
2202 | bool (*lessthan)(const T &, const T &)) | ||||
2203 | const | ||||
2204 | { | ||||
2205 | return m_vec ? m_vec->lower_bound (obj, lessthan) : 0; | ||||
2206 | } | ||||
2207 | |||||
2208 | /* Return true if SEARCH is an element of V. Note that this is O(N) in the | ||||
2209 | size of the vector and so should be used with care. */ | ||||
2210 | |||||
2211 | template<typename T> | ||||
2212 | inline bool | ||||
2213 | vec<T, va_heap, vl_ptr>::contains (const T &search) const | ||||
2214 | { | ||||
2215 | return m_vec ? m_vec->contains (search) : false; | ||||
2216 | } | ||||
2217 | |||||
2218 | /* Reverse content of the vector. */ | ||||
2219 | |||||
2220 | template<typename T> | ||||
2221 | inline void | ||||
2222 | vec<T, va_heap, vl_ptr>::reverse (void) | ||||
2223 | { | ||||
2224 | unsigned l = length (); | ||||
2225 | T *ptr = address (); | ||||
2226 | |||||
2227 | for (unsigned i = 0; i < l / 2; i++) | ||||
2228 | std::swap (ptr[i], ptr[l - i - 1]); | ||||
2229 | } | ||||
2230 | |||||
2231 | template<typename T> | ||||
2232 | inline bool | ||||
2233 | vec<T, va_heap, vl_ptr>::using_auto_storage () const | ||||
2234 | { | ||||
2235 | return m_vec ? m_vec->m_vecpfx.m_using_auto_storage : false; | ||||
2236 | } | ||||
2237 | |||||
2238 | /* Release VEC and call release of all element vectors. */ | ||||
2239 | |||||
2240 | template<typename T> | ||||
2241 | inline void | ||||
2242 | release_vec_vec (vec<vec<T> > &vec) | ||||
2243 | { | ||||
2244 | for (unsigned i = 0; i < vec.length (); i++) | ||||
2245 | vec[i].release (); | ||||
2246 | |||||
2247 | vec.release (); | ||||
2248 | } | ||||
2249 | |||||
2250 | // Provide a subset of the std::span functionality. (We can't use std::span | ||||
2251 | // itself because it's a C++20 feature.) | ||||
2252 | // | ||||
2253 | // In addition, provide an invalid value that is distinct from all valid | ||||
2254 | // sequences (including the empty sequence). This can be used to return | ||||
2255 | // failure without having to use std::optional. | ||||
2256 | // | ||||
2257 | // There is no operator bool because it would be ambiguous whether it is | ||||
2258 | // testing for a valid value or an empty sequence. | ||||
2259 | template<typename T> | ||||
2260 | class array_slice | ||||
2261 | { | ||||
2262 | template<typename OtherT> friend class array_slice; | ||||
2263 | |||||
2264 | public: | ||||
2265 | using value_type = T; | ||||
2266 | using iterator = T *; | ||||
2267 | using const_iterator = const T *; | ||||
2268 | |||||
2269 | array_slice () : m_base (nullptr), m_size (0) {} | ||||
2270 | |||||
2271 | template<typename OtherT> | ||||
2272 | array_slice (array_slice<OtherT> other) | ||||
2273 | : m_base (other.m_base), m_size (other.m_size) {} | ||||
2274 | |||||
2275 | array_slice (iterator base, unsigned int size) | ||||
2276 | : m_base (base), m_size (size) {} | ||||
2277 | |||||
2278 | template<size_t N> | ||||
2279 | array_slice (T (&array)[N]) : m_base (array), m_size (N) {} | ||||
2280 | |||||
2281 | template<typename OtherT> | ||||
2282 | array_slice (const vec<OtherT> &v) | ||||
2283 | : m_base (v.address ()), m_size (v.length ()) {} | ||||
2284 | |||||
2285 | template<typename OtherT> | ||||
2286 | array_slice (vec<OtherT> &v) | ||||
2287 | : m_base (v.address ()), m_size (v.length ()) {} | ||||
2288 | |||||
2289 | template<typename OtherT> | ||||
2290 | array_slice (const vec<OtherT, va_gc> *v) | ||||
2291 | : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {} | ||||
2292 | |||||
2293 | template<typename OtherT> | ||||
2294 | array_slice (vec<OtherT, va_gc> *v) | ||||
2295 | : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {} | ||||
2296 | |||||
2297 | iterator begin () { return m_base; } | ||||
2298 | iterator end () { return m_base + m_size; } | ||||
2299 | |||||
2300 | const_iterator begin () const { return m_base; } | ||||
2301 | const_iterator end () const { return m_base + m_size; } | ||||
2302 | |||||
2303 | value_type &front (); | ||||
2304 | value_type &back (); | ||||
2305 | value_type &operator[] (unsigned int i); | ||||
2306 | |||||
2307 | const value_type &front () const; | ||||
2308 | const value_type &back () const; | ||||
2309 | const value_type &operator[] (unsigned int i) const; | ||||
2310 | |||||
2311 | size_t size () const { return m_size; } | ||||
2312 | size_t size_bytes () const { return m_size * sizeof (T); } | ||||
2313 | bool empty () const { return m_size == 0; } | ||||
2314 | |||||
2315 | // An invalid array_slice that represents a failed operation. This is | ||||
2316 | // distinct from an empty slice, which is a valid result in some contexts. | ||||
2317 | static array_slice invalid () { return { nullptr, ~0U }; } | ||||
2318 | |||||
2319 | // True if the array is valid, false if it is an array like INVALID. | ||||
2320 | bool is_valid () const { return m_base || m_size == 0; } | ||||
2321 | |||||
2322 | private: | ||||
2323 | iterator m_base; | ||||
2324 | unsigned int m_size; | ||||
2325 | }; | ||||
2326 | |||||
2327 | template<typename T> | ||||
2328 | inline typename array_slice<T>::value_type & | ||||
2329 | array_slice<T>::front () | ||||
2330 | { | ||||
2331 | gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2331, __FUNCTION__), 0 : 0)); | ||||
2332 | return m_base[0]; | ||||
2333 | } | ||||
2334 | |||||
2335 | template<typename T> | ||||
2336 | inline const typename array_slice<T>::value_type & | ||||
2337 | array_slice<T>::front () const | ||||
2338 | { | ||||
2339 | gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2339, __FUNCTION__), 0 : 0)); | ||||
2340 | return m_base[0]; | ||||
2341 | } | ||||
2342 | |||||
2343 | template<typename T> | ||||
2344 | inline typename array_slice<T>::value_type & | ||||
2345 | array_slice<T>::back () | ||||
2346 | { | ||||
2347 | gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2347, __FUNCTION__), 0 : 0)); | ||||
2348 | return m_base[m_size - 1]; | ||||
2349 | } | ||||
2350 | |||||
2351 | template<typename T> | ||||
2352 | inline const typename array_slice<T>::value_type & | ||||
2353 | array_slice<T>::back () const | ||||
2354 | { | ||||
2355 | gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2355, __FUNCTION__), 0 : 0)); | ||||
2356 | return m_base[m_size - 1]; | ||||
2357 | } | ||||
2358 | |||||
2359 | template<typename T> | ||||
2360 | inline typename array_slice<T>::value_type & | ||||
2361 | array_slice<T>::operator[] (unsigned int i) | ||||
2362 | { | ||||
2363 | gcc_checking_assert (i < m_size)((void)(!(i < m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2363, __FUNCTION__), 0 : 0)); | ||||
2364 | return m_base[i]; | ||||
2365 | } | ||||
2366 | |||||
2367 | template<typename T> | ||||
2368 | inline const typename array_slice<T>::value_type & | ||||
2369 | array_slice<T>::operator[] (unsigned int i) const | ||||
2370 | { | ||||
2371 | gcc_checking_assert (i < m_size)((void)(!(i < m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2371, __FUNCTION__), 0 : 0)); | ||||
2372 | return m_base[i]; | ||||