]>
Commit | Line | Data |
---|---|---|
0168a849 | 1 | /* Darwin support needed only by C/C++ frontends. |
8d9254fc | 2 | Copyright (C) 2001-2020 Free Software Foundation, Inc. |
0168a849 SS |
3 | Contributed by Apple Computer Inc. |
4 | ||
7ec022b2 | 5 | This file is part of GCC. |
0168a849 | 6 | |
7ec022b2 | 7 | GCC is free software; you can redistribute it and/or modify |
0168a849 | 8 | it under the terms of the GNU General Public License as published by |
2f83c7d6 | 9 | the Free Software Foundation; either version 3, or (at your option) |
0168a849 SS |
10 | any later version. |
11 | ||
7ec022b2 | 12 | GCC is distributed in the hope that it will be useful, |
0168a849 SS |
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 | |
2f83c7d6 NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
0168a849 SS |
20 | |
21 | #include "config.h" | |
22 | #include "system.h" | |
4977bab6 | 23 | #include "coretypes.h" |
70f42967 | 24 | #include "target.h" |
e11c4407 AM |
25 | #include "c-family/c-target.h" |
26 | #include "c-family/c-target-def.h" | |
4d0cdd0c | 27 | #include "memmodel.h" |
e11c4407 AM |
28 | #include "tm_p.h" |
29 | #include "cgraph.h" | |
e8a25ca8 | 30 | #include "incpath.h" |
39dabefd | 31 | #include "c-family/c-pragma.h" |
91ebb981 | 32 | #include "c-family/c-format.h" |
3dd53121 AP |
33 | #include "cppdefault.h" |
34 | #include "prefix.h" | |
833fe7da | 35 | #include "../../libcpp/internal.h" |
0168a849 SS |
36 | |
37 | /* Pragmas. */ | |
38 | ||
76ad5c10 MS |
39 | #define BAD(gmsgid) do { warning (OPT_Wpragmas, gmsgid); return; } while (0) |
40 | #define BAD2(msgid, arg) do { warning (OPT_Wpragmas, msgid, arg); return; } while (0) | |
0168a849 | 41 | |
94d1613b MS |
42 | static bool using_frameworks = false; |
43 | ||
e3c287c9 MS |
44 | static const char *find_subframework_header (cpp_reader *pfile, const char *header, |
45 | cpp_dir **dirp); | |
0168a849 SS |
46 | |
47 | typedef struct align_stack | |
48 | { | |
49 | int alignment; | |
50 | struct align_stack * prev; | |
51 | } align_stack; | |
52 | ||
53 | static struct align_stack * field_align_stack = NULL; | |
54 | ||
1f1d5130 MS |
55 | /* Maintain a small stack of alignments. This is similar to pragma |
56 | pack's stack, but simpler. */ | |
57 | ||
0168a849 | 58 | static void |
9c808aad | 59 | push_field_alignment (int bit_alignment) |
0168a849 | 60 | { |
5ed6ace5 | 61 | align_stack *entry = XNEW (align_stack); |
0168a849 SS |
62 | |
63 | entry->alignment = maximum_field_alignment; | |
64 | entry->prev = field_align_stack; | |
65 | field_align_stack = entry; | |
66 | ||
67 | maximum_field_alignment = bit_alignment; | |
68 | } | |
69 | ||
70 | static void | |
9c808aad | 71 | pop_field_alignment (void) |
0168a849 SS |
72 | { |
73 | if (field_align_stack) | |
74 | { | |
75 | align_stack *entry = field_align_stack; | |
76 | ||
77 | maximum_field_alignment = entry->alignment; | |
78 | field_align_stack = entry->prev; | |
79 | free (entry); | |
80 | } | |
81 | else | |
ccd40a69 | 82 | error ("too many %<#pragma options%> align=reset"); |
0168a849 SS |
83 | } |
84 | ||
85 | /* Handlers for Darwin-specific pragmas. */ | |
86 | ||
87 | void | |
9c808aad | 88 | darwin_pragma_ignore (cpp_reader *pfile ATTRIBUTE_UNUSED) |
0168a849 SS |
89 | { |
90 | /* Do nothing. */ | |
91 | } | |
92 | ||
93 | /* #pragma options align={mac68k|power|reset} */ | |
94 | ||
95 | void | |
9c808aad | 96 | darwin_pragma_options (cpp_reader *pfile ATTRIBUTE_UNUSED) |
0168a849 | 97 | { |
7ae8cf75 | 98 | const char *arg; |
0168a849 SS |
99 | tree t, x; |
100 | ||
75ce3d48 | 101 | if (pragma_lex (&t) != CPP_NAME) |
904f3daa | 102 | BAD ("malformed %<#pragma options%>, ignoring"); |
0168a849 SS |
103 | arg = IDENTIFIER_POINTER (t); |
104 | if (strcmp (arg, "align")) | |
904f3daa | 105 | BAD ("malformed %<#pragma options%>, ignoring"); |
75ce3d48 | 106 | if (pragma_lex (&t) != CPP_EQ) |
904f3daa | 107 | BAD ("malformed %<#pragma options%>, ignoring"); |
75ce3d48 | 108 | if (pragma_lex (&t) != CPP_NAME) |
904f3daa | 109 | BAD ("malformed %<#pragma options%>, ignoring"); |
0168a849 | 110 | |
75ce3d48 | 111 | if (pragma_lex (&x) != CPP_EOF) |
904f3daa | 112 | warning (OPT_Wpragmas, "junk at end of %<#pragma options%>"); |
0168a849 SS |
113 | |
114 | arg = IDENTIFIER_POINTER (t); | |
115 | if (!strcmp (arg, "mac68k")) | |
116 | push_field_alignment (16); | |
117 | else if (!strcmp (arg, "power")) | |
118 | push_field_alignment (0); | |
119 | else if (!strcmp (arg, "reset")) | |
120 | pop_field_alignment (); | |
121 | else | |
904f3daa | 122 | BAD ("malformed %<#pragma options align={mac68k|power|reset}%>, ignoring"); |
0168a849 SS |
123 | } |
124 | ||
125 | /* #pragma unused ([var {, var}*]) */ | |
126 | ||
127 | void | |
9c808aad | 128 | darwin_pragma_unused (cpp_reader *pfile ATTRIBUTE_UNUSED) |
0168a849 SS |
129 | { |
130 | tree decl, x; | |
131 | int tok; | |
132 | ||
75ce3d48 | 133 | if (pragma_lex (&x) != CPP_OPEN_PAREN) |
904f3daa | 134 | BAD ("missing %<(%> after %<#pragma unused%>, ignoring"); |
0168a849 SS |
135 | |
136 | while (1) | |
137 | { | |
75ce3d48 | 138 | tok = pragma_lex (&decl); |
0168a849 SS |
139 | if (tok == CPP_NAME && decl) |
140 | { | |
10e6657a | 141 | tree local = lookup_name (decl); |
0168a849 SS |
142 | if (local && (TREE_CODE (local) == PARM_DECL |
143 | || TREE_CODE (local) == VAR_DECL)) | |
3bd5cdeb IS |
144 | { |
145 | TREE_USED (local) = 1; | |
146 | DECL_READ_P (local) = 1; | |
147 | } | |
75ce3d48 | 148 | tok = pragma_lex (&x); |
0168a849 SS |
149 | if (tok != CPP_COMMA) |
150 | break; | |
151 | } | |
152 | } | |
153 | ||
154 | if (tok != CPP_CLOSE_PAREN) | |
904f3daa | 155 | BAD ("missing %<)%> after %<#pragma unused%>, ignoring"); |
0168a849 | 156 | |
75ce3d48 | 157 | if (pragma_lex (&x) != CPP_EOF) |
904f3daa | 158 | BAD ("junk at end of %<#pragma unused%>"); |
0168a849 | 159 | } |
94d1613b | 160 | |
16d6f994 EC |
161 | /* Parse the ms_struct pragma. */ |
162 | void | |
163 | darwin_pragma_ms_struct (cpp_reader *pfile ATTRIBUTE_UNUSED) | |
164 | { | |
165 | const char *arg; | |
166 | tree t; | |
167 | ||
168 | if (pragma_lex (&t) != CPP_NAME) | |
904f3daa | 169 | BAD ("malformed %<#pragma ms_struct%>, ignoring"); |
16d6f994 EC |
170 | arg = IDENTIFIER_POINTER (t); |
171 | ||
172 | if (!strcmp (arg, "on")) | |
173 | darwin_ms_struct = true; | |
174 | else if (!strcmp (arg, "off") || !strcmp (arg, "reset")) | |
175 | darwin_ms_struct = false; | |
176 | else | |
904f3daa | 177 | BAD ("malformed %<#pragma ms_struct {on|off|reset}%>, ignoring"); |
16d6f994 EC |
178 | |
179 | if (pragma_lex (&t) != CPP_EOF) | |
904f3daa | 180 | BAD ("junk at end of %<#pragma ms_struct%>"); |
16d6f994 EC |
181 | } |
182 | ||
5ead67f6 | 183 | static struct frameworks_in_use { |
94d1613b MS |
184 | size_t len; |
185 | const char *name; | |
186 | cpp_dir* dir; | |
187 | } *frameworks_in_use; | |
188 | static int num_frameworks = 0; | |
189 | static int max_frameworks = 0; | |
190 | ||
191 | ||
192 | /* Remember which frameworks have been seen, so that we can ensure | |
193 | that all uses of that framework come from the same framework. DIR | |
194 | is the place where the named framework NAME, which is of length | |
e3c287c9 MS |
195 | LEN, was found. We copy the directory name from NAME, as it will be |
196 | freed by others. */ | |
94d1613b MS |
197 | |
198 | static void | |
199 | add_framework (const char *name, size_t len, cpp_dir *dir) | |
200 | { | |
e3c287c9 | 201 | char *dir_name; |
94d1613b MS |
202 | int i; |
203 | for (i = 0; i < num_frameworks; ++i) | |
204 | { | |
205 | if (len == frameworks_in_use[i].len | |
206 | && strncmp (name, frameworks_in_use[i].name, len) == 0) | |
207 | { | |
208 | return; | |
209 | } | |
210 | } | |
211 | if (i >= max_frameworks) | |
212 | { | |
213 | max_frameworks = i*2; | |
e3c287c9 | 214 | max_frameworks += i == 0; |
5ead67f6 KG |
215 | frameworks_in_use = XRESIZEVEC (struct frameworks_in_use, |
216 | frameworks_in_use, max_frameworks); | |
94d1613b | 217 | } |
5ed6ace5 | 218 | dir_name = XNEWVEC (char, len + 1); |
e3c287c9 MS |
219 | memcpy (dir_name, name, len); |
220 | dir_name[len] = '\0'; | |
221 | frameworks_in_use[num_frameworks].name = dir_name; | |
94d1613b MS |
222 | frameworks_in_use[num_frameworks].len = len; |
223 | frameworks_in_use[num_frameworks].dir = dir; | |
224 | ++num_frameworks; | |
225 | } | |
226 | ||
227 | /* Recall if we have seen the named framework NAME, before, and where | |
228 | we saw it. NAME is LEN bytes long. The return value is the place | |
229 | where it was seen before. */ | |
230 | ||
231 | static struct cpp_dir* | |
232 | find_framework (const char *name, size_t len) | |
233 | { | |
234 | int i; | |
235 | for (i = 0; i < num_frameworks; ++i) | |
236 | { | |
237 | if (len == frameworks_in_use[i].len | |
238 | && strncmp (name, frameworks_in_use[i].name, len) == 0) | |
239 | { | |
240 | return frameworks_in_use[i].dir; | |
241 | } | |
242 | } | |
243 | return 0; | |
244 | } | |
245 | ||
246 | /* There are two directories in a framework that contain header files, | |
247 | Headers and PrivateHeaders. We search Headers first as it is more | |
248 | common to upgrade a header from PrivateHeaders to Headers and when | |
249 | that is done, the old one might hang around and be out of data, | |
250 | causing grief. */ | |
251 | ||
252 | struct framework_header {const char * dirName; int dirNameLen; }; | |
253 | static struct framework_header framework_header_dirs[] = { | |
254 | { "Headers", 7 }, | |
255 | { "PrivateHeaders", 14 }, | |
256 | { NULL, 0 } | |
257 | }; | |
258 | ||
259 | /* Returns a pointer to a malloced string that contains the real pathname | |
260 | to the file, given the base name and the name. */ | |
261 | ||
262 | static char * | |
263 | framework_construct_pathname (const char *fname, cpp_dir *dir) | |
264 | { | |
b674cffe | 265 | const char *buf; |
94d1613b MS |
266 | size_t fname_len, frname_len; |
267 | cpp_dir *fast_dir; | |
268 | char *frname; | |
269 | struct stat st; | |
270 | int i; | |
271 | ||
272 | /* Framework names must have a / in them. */ | |
273 | buf = strchr (fname, '/'); | |
274 | if (buf) | |
275 | fname_len = buf - fname; | |
276 | else | |
277 | return 0; | |
278 | ||
279 | fast_dir = find_framework (fname, fname_len); | |
280 | ||
281 | /* Framework includes must all come from one framework. */ | |
282 | if (fast_dir && dir != fast_dir) | |
283 | return 0; | |
284 | ||
5ed6ace5 | 285 | frname = XNEWVEC (char, strlen (fname) + dir->len + 2 |
94d1613b | 286 | + strlen(".framework/") + strlen("PrivateHeaders")); |
6e718159 | 287 | memcpy (&frname[0], dir->name, dir->len); |
94d1613b MS |
288 | frname_len = dir->len; |
289 | if (frname_len && frname[frname_len-1] != '/') | |
290 | frname[frname_len++] = '/'; | |
6e718159 | 291 | memcpy (&frname[frname_len], fname, fname_len); |
94d1613b | 292 | frname_len += fname_len; |
6e718159 | 293 | memcpy (&frname[frname_len], ".framework/", strlen (".framework/")); |
94d1613b MS |
294 | frname_len += strlen (".framework/"); |
295 | ||
a68bdb0b MS |
296 | if (fast_dir == 0) |
297 | { | |
298 | frname[frname_len-1] = 0; | |
299 | if (stat (frname, &st) == 0) | |
300 | { | |
301 | /* As soon as we find the first instance of the framework, | |
302 | we stop and never use any later instance of that | |
303 | framework. */ | |
304 | add_framework (fname, fname_len, dir); | |
305 | } | |
306 | else | |
307 | { | |
308 | /* If we can't find the parent directory, no point looking | |
309 | further. */ | |
310 | free (frname); | |
311 | return 0; | |
312 | } | |
313 | frname[frname_len-1] = '/'; | |
314 | } | |
315 | ||
94d1613b MS |
316 | /* Append framework_header_dirs and header file name */ |
317 | for (i = 0; framework_header_dirs[i].dirName; i++) | |
318 | { | |
6e718159 | 319 | memcpy (&frname[frname_len], |
94d1613b MS |
320 | framework_header_dirs[i].dirName, |
321 | framework_header_dirs[i].dirNameLen); | |
322 | strcpy (&frname[frname_len + framework_header_dirs[i].dirNameLen], | |
323 | &fname[fname_len]); | |
324 | ||
325 | if (stat (frname, &st) == 0) | |
a68bdb0b | 326 | return frname; |
94d1613b MS |
327 | } |
328 | ||
329 | free (frname); | |
330 | return 0; | |
331 | } | |
332 | ||
333 | /* Search for FNAME in sub-frameworks. pname is the context that we | |
334 | wish to search in. Return the path the file was found at, | |
335 | otherwise return 0. */ | |
336 | ||
337 | static const char* | |
338 | find_subframework_file (const char *fname, const char *pname) | |
339 | { | |
340 | char *sfrname; | |
341 | const char *dot_framework = ".framework/"; | |
b674cffe | 342 | const char *bufptr; |
16d6f994 | 343 | int sfrname_len, i, fname_len; |
94d1613b MS |
344 | struct cpp_dir *fast_dir; |
345 | static struct cpp_dir subframe_dir; | |
346 | struct stat st; | |
347 | ||
348 | bufptr = strchr (fname, '/'); | |
349 | ||
350 | /* Subframework files must have / in the name. */ | |
351 | if (bufptr == 0) | |
352 | return 0; | |
16d6f994 | 353 | |
94d1613b MS |
354 | fname_len = bufptr - fname; |
355 | fast_dir = find_framework (fname, fname_len); | |
356 | ||
357 | /* Sub framework header filename includes parent framework name and | |
358 | header name in the "CarbonCore/OSUtils.h" form. If it does not | |
359 | include slash it is not a sub framework include. */ | |
360 | bufptr = strstr (pname, dot_framework); | |
361 | ||
362 | /* If the parent header is not of any framework, then this header | |
1e5f1716 | 363 | cannot be part of any subframework. */ |
94d1613b MS |
364 | if (!bufptr) |
365 | return 0; | |
366 | ||
367 | /* Now translate. For example, +- bufptr | |
16d6f994 | 368 | fname = CarbonCore/OSUtils.h | |
94d1613b MS |
369 | pname = /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h |
370 | into | |
371 | sfrname = /System/Library/Frameworks/Foundation.framework/Frameworks/CarbonCore.framework/Headers/OSUtils.h */ | |
372 | ||
5ed6ace5 | 373 | sfrname = XNEWVEC (char, strlen (pname) + strlen (fname) + 2 + |
94d1613b MS |
374 | strlen ("Frameworks/") + strlen (".framework/") |
375 | + strlen ("PrivateHeaders")); | |
16d6f994 | 376 | |
94d1613b MS |
377 | bufptr += strlen (dot_framework); |
378 | ||
16d6f994 | 379 | sfrname_len = bufptr - pname; |
94d1613b | 380 | |
6e718159 | 381 | memcpy (&sfrname[0], pname, sfrname_len); |
94d1613b | 382 | |
6e718159 | 383 | memcpy (&sfrname[sfrname_len], "Frameworks/", strlen ("Frameworks/")); |
94d1613b MS |
384 | sfrname_len += strlen("Frameworks/"); |
385 | ||
6e718159 | 386 | memcpy (&sfrname[sfrname_len], fname, fname_len); |
94d1613b MS |
387 | sfrname_len += fname_len; |
388 | ||
6e718159 | 389 | memcpy (&sfrname[sfrname_len], ".framework/", strlen (".framework/")); |
94d1613b MS |
390 | sfrname_len += strlen (".framework/"); |
391 | ||
392 | /* Append framework_header_dirs and header file name */ | |
393 | for (i = 0; framework_header_dirs[i].dirName; i++) | |
394 | { | |
6e718159 MS |
395 | memcpy (&sfrname[sfrname_len], |
396 | framework_header_dirs[i].dirName, | |
397 | framework_header_dirs[i].dirNameLen); | |
94d1613b MS |
398 | strcpy (&sfrname[sfrname_len + framework_header_dirs[i].dirNameLen], |
399 | &fname[fname_len]); | |
16d6f994 | 400 | |
94d1613b MS |
401 | if (stat (sfrname, &st) == 0) |
402 | { | |
403 | if (fast_dir != &subframe_dir) | |
404 | { | |
405 | if (fast_dir) | |
d4ee4d25 | 406 | warning (0, "subframework include %s conflicts with framework include", |
94d1613b MS |
407 | fname); |
408 | else | |
409 | add_framework (fname, fname_len, &subframe_dir); | |
410 | } | |
411 | ||
412 | return sfrname; | |
413 | } | |
414 | } | |
415 | free (sfrname); | |
416 | ||
417 | return 0; | |
418 | } | |
419 | ||
420 | /* Add PATH to the system includes. PATH must be malloc-ed and | |
421 | NUL-terminated. System framework paths are C++ aware. */ | |
422 | ||
423 | static void | |
424 | add_system_framework_path (char *path) | |
425 | { | |
426 | int cxx_aware = 1; | |
427 | cpp_dir *p; | |
428 | ||
5ed6ace5 | 429 | p = XNEW (cpp_dir); |
94d1613b MS |
430 | p->next = NULL; |
431 | p->name = path; | |
432 | p->sysp = 1 + !cxx_aware; | |
433 | p->construct = framework_construct_pathname; | |
434 | using_frameworks = 1; | |
435 | ||
b90c9338 | 436 | add_cpp_dir_path (p, INC_SYSTEM); |
94d1613b MS |
437 | } |
438 | ||
439 | /* Add PATH to the bracket includes. PATH must be malloc-ed and | |
440 | NUL-terminated. */ | |
441 | ||
442 | void | |
443 | add_framework_path (char *path) | |
444 | { | |
445 | cpp_dir *p; | |
446 | ||
5ed6ace5 | 447 | p = XNEW (cpp_dir); |
94d1613b MS |
448 | p->next = NULL; |
449 | p->name = path; | |
450 | p->sysp = 0; | |
451 | p->construct = framework_construct_pathname; | |
452 | using_frameworks = 1; | |
453 | ||
b90c9338 | 454 | add_cpp_dir_path (p, INC_BRACKET); |
94d1613b MS |
455 | } |
456 | ||
16d6f994 | 457 | static const char *framework_defaults [] = |
94d1613b MS |
458 | { |
459 | "/System/Library/Frameworks", | |
460 | "/Library/Frameworks", | |
94d1613b MS |
461 | }; |
462 | ||
3dd53121 AP |
463 | /* Register the GNU objective-C runtime include path if STDINC. */ |
464 | ||
465 | void | |
7792cf66 IS |
466 | darwin_register_objc_includes (const char *sysroot ATTRIBUTE_UNUSED, |
467 | const char *iprefix, int stdinc) | |
3dd53121 | 468 | { |
7792cf66 IS |
469 | /* If we want standard includes; Register the GNU OBJC runtime include |
470 | path if we are compiling OBJC with GNU-runtime. | |
471 | This path is compiler-relative, we don't want to prepend the sysroot | |
472 | since it's not expected to find the headers there. */ | |
3dd53121 | 473 | |
7792cf66 | 474 | if (stdinc && c_dialect_objc () && !flag_next_runtime) |
3dd53121 | 475 | { |
7792cf66 | 476 | const char *fname = GCC_INCLUDE_DIR "-gnu-runtime"; |
3dd53121 | 477 | char *str; |
7792cf66 IS |
478 | size_t len; |
479 | ||
480 | /* See if our directory starts with the standard prefix. | |
112cdef5 | 481 | "Translate" them, i.e. replace /usr/local/lib/gcc... with |
3dd53121 | 482 | IPREFIX and search them first. */ |
7792cf66 | 483 | if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0 |
3dd53121 AP |
484 | && !strncmp (fname, cpp_GCC_INCLUDE_DIR, len)) |
485 | { | |
486 | str = concat (iprefix, fname + len, NULL); | |
7792cf66 | 487 | add_path (str, INC_SYSTEM, /*c++aware=*/true, false); |
3dd53121 | 488 | } |
16d6f994 | 489 | |
7792cf66 IS |
490 | str = update_path (fname, ""); |
491 | add_path (str, INC_SYSTEM, /*c++aware=*/true, false); | |
3dd53121 AP |
492 | } |
493 | } | |
494 | ||
94d1613b MS |
495 | |
496 | /* Register all the system framework paths if STDINC is true and setup | |
497 | the missing_header callback for subframework searching if any | |
498 | frameworks had been registered. */ | |
499 | ||
500 | void | |
479ec1d1 | 501 | darwin_register_frameworks (const char *sysroot, |
3dd53121 | 502 | const char *iprefix ATTRIBUTE_UNUSED, int stdinc) |
94d1613b MS |
503 | { |
504 | if (stdinc) | |
505 | { | |
506 | size_t i; | |
507 | ||
508 | /* Setup default search path for frameworks. */ | |
509 | for (i=0; i<sizeof (framework_defaults)/sizeof(const char *); ++i) | |
510 | { | |
479ec1d1 DP |
511 | char *str; |
512 | if (sysroot) | |
513 | str = concat (sysroot, xstrdup (framework_defaults [i]), NULL); | |
514 | else | |
515 | str = xstrdup (framework_defaults[i]); | |
94d1613b | 516 | /* System Framework headers are cxx aware. */ |
479ec1d1 | 517 | add_system_framework_path (str); |
94d1613b MS |
518 | } |
519 | } | |
520 | ||
521 | if (using_frameworks) | |
522 | cpp_get_callbacks (parse_in)->missing_header = find_subframework_header; | |
523 | } | |
524 | ||
525 | /* Search for HEADER in context dependent way. The return value is | |
526 | the malloced name of a header to try and open, if any, or NULL | |
527 | otherwise. This is called after normal header lookup processing | |
528 | fails to find a header. We search each file in the include stack, | |
529 | using FUNC, starting from the most deeply nested include and | |
530 | finishing with the main input file. We stop searching when FUNC | |
0e40b5f2 | 531 | returns nonzero. */ |
94d1613b MS |
532 | |
533 | static const char* | |
e3c287c9 | 534 | find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp) |
94d1613b MS |
535 | { |
536 | const char *fname = header; | |
537 | struct cpp_buffer *b; | |
538 | const char *n; | |
539 | ||
540 | for (b = cpp_get_buffer (pfile); | |
541 | b && cpp_get_file (b) && cpp_get_path (cpp_get_file (b)); | |
542 | b = cpp_get_prev (b)) | |
543 | { | |
544 | n = find_subframework_file (fname, cpp_get_path (cpp_get_file (b))); | |
545 | if (n) | |
e3c287c9 MS |
546 | { |
547 | /* Logically, the place where we found the subframework is | |
548 | the place where we found the Framework that contains the | |
549 | subframework. This is useful for tracking wether or not | |
550 | we are in a system header. */ | |
551 | *dirp = cpp_get_dir (cpp_get_file (b)); | |
552 | return n; | |
553 | } | |
94d1613b MS |
554 | } |
555 | ||
556 | return 0; | |
557 | } | |
ed5b9f96 | 558 | |
98fc3d49 LV |
559 | /* Given an OS X version VERSION_STR, return it as a statically-allocated array |
560 | of three integers. If VERSION_STR is invalid, return NULL. | |
561 | ||
562 | VERSION_STR must consist of one, two, or three tokens, each separated by | |
563 | a single period. Each token must contain only the characters '0' through | |
564 | '9' and is converted to an equivalent non-negative decimal integer. Omitted | |
565 | tokens become zeros. For example: | |
566 | ||
567 | "10" becomes {10,0,0} | |
568 | "10.10" becomes {10,10,0} | |
569 | "10.10.1" becomes {10,10,1} | |
570 | "10.000010.1" becomes {10,10,1} | |
571 | "10.010.001" becomes {10,10,1} | |
572 | "000010.10.00001" becomes {10,10,1} | |
573 | ".9.1" is invalid | |
574 | "10..9" is invalid | |
575 | "10.10." is invalid */ | |
576 | ||
577 | enum version_components { MAJOR, MINOR, TINY }; | |
578 | ||
579 | static const unsigned long * | |
580 | parse_version (const char *version_str) | |
581 | { | |
582 | size_t version_len; | |
583 | char *end; | |
584 | static unsigned long version_array[3]; | |
585 | ||
586 | version_len = strlen (version_str); | |
587 | if (version_len < 1) | |
588 | return NULL; | |
589 | ||
590 | /* Version string must consist of digits and periods only. */ | |
591 | if (strspn (version_str, "0123456789.") != version_len) | |
592 | return NULL; | |
593 | ||
594 | if (!ISDIGIT (version_str[0]) || !ISDIGIT (version_str[version_len - 1])) | |
595 | return NULL; | |
596 | ||
597 | version_array[MAJOR] = strtoul (version_str, &end, 10); | |
598 | version_str = end + ((*end == '.') ? 1 : 0); | |
599 | ||
600 | /* Version string must not contain adjacent periods. */ | |
601 | if (*version_str == '.') | |
602 | return NULL; | |
603 | ||
604 | version_array[MINOR] = strtoul (version_str, &end, 10); | |
605 | version_str = end + ((*end == '.') ? 1 : 0); | |
606 | ||
607 | version_array[TINY] = strtoul (version_str, &end, 10); | |
608 | ||
609 | /* Version string must contain no more than three tokens. */ | |
610 | if (*end != '\0') | |
611 | return NULL; | |
612 | ||
613 | return version_array; | |
614 | } | |
615 | ||
616 | /* Given VERSION -- a three-component OS X version represented as an array of | |
617 | non-negative integers -- return a statically-allocated string suitable for | |
618 | the legacy __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro. If VERSION | |
619 | is invalid and cannot be coerced into a valid form, return NULL. | |
620 | ||
621 | The legacy format is a four-character string -- two chars for the major | |
622 | number and one each for the minor and tiny numbers. Minor and tiny numbers | |
623 | from 10 through 99 are permitted but are clamped to 9 (for example, {10,9,10} | |
624 | produces "1099"). If VERSION contains numbers greater than 99, it is | |
625 | rejected. */ | |
626 | ||
ed5b9f96 | 627 | static const char * |
98fc3d49 | 628 | version_as_legacy_macro (const unsigned long *version) |
ed5b9f96 | 629 | { |
98fc3d49 LV |
630 | unsigned long major, minor, tiny; |
631 | static char result[5]; | |
632 | ||
633 | major = version[MAJOR]; | |
634 | minor = version[MINOR]; | |
635 | tiny = version[TINY]; | |
636 | ||
637 | if (major > 99 || minor > 99 || tiny > 99) | |
638 | return NULL; | |
639 | ||
640 | minor = ((minor > 9) ? 9 : minor); | |
641 | tiny = ((tiny > 9) ? 9 : tiny); | |
642 | ||
643 | if (sprintf (result, "%lu%lu%lu", major, minor, tiny) != 4) | |
644 | return NULL; | |
645 | ||
646 | return result; | |
647 | } | |
16d6f994 | 648 | |
98fc3d49 LV |
649 | /* Given VERSION -- a three-component OS X version represented as an array of |
650 | non-negative integers -- return a statically-allocated string suitable for | |
651 | the modern __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro. If VERSION | |
652 | is invalid, return NULL. | |
653 | ||
654 | The modern format is a six-character string -- two chars for each component, | |
655 | with zero-padding if necessary (for example, {10,10,1} produces "101001"). If | |
656 | VERSION contains numbers greater than 99, it is rejected. */ | |
657 | ||
658 | static const char * | |
659 | version_as_modern_macro (const unsigned long *version) | |
660 | { | |
661 | unsigned long major, minor, tiny; | |
662 | static char result[7]; | |
663 | ||
664 | major = version[MAJOR]; | |
665 | minor = version[MINOR]; | |
666 | tiny = version[TINY]; | |
667 | ||
668 | if (major > 99 || minor > 99 || tiny > 99) | |
669 | return NULL; | |
670 | ||
671 | if (sprintf (result, "%02lu%02lu%02lu", major, minor, tiny) != 6) | |
672 | return NULL; | |
673 | ||
674 | return result; | |
675 | } | |
676 | ||
677 | /* Return the value of darwin_macosx_version_min, suitably formatted for the | |
678 | __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro. Values representing | |
679 | OS X 10.9 and earlier are encoded using the legacy four-character format, | |
680 | while 10.10 and later use a modern six-character format. (For example, | |
681 | "10.9" produces "1090", and "10.10.1" produces "101001".) If | |
682 | darwin_macosx_version_min is invalid and cannot be coerced into a valid | |
683 | form, print a warning and return "1000". */ | |
684 | ||
685 | static const char * | |
686 | macosx_version_as_macro (void) | |
687 | { | |
688 | const unsigned long *version_array; | |
689 | const char *version_macro; | |
690 | ||
691 | version_array = parse_version (darwin_macosx_version_min); | |
692 | if (!version_array) | |
ed5b9f96 | 693 | goto fail; |
98fc3d49 LV |
694 | |
695 | if (version_array[MAJOR] != 10) | |
ed5b9f96 | 696 | goto fail; |
9c250803 | 697 | |
98fc3d49 LV |
698 | if (version_array[MINOR] < 10) |
699 | version_macro = version_as_legacy_macro (version_array); | |
700 | else | |
701 | version_macro = version_as_modern_macro (version_array); | |
702 | ||
703 | if (!version_macro) | |
e46b55d0 | 704 | goto fail; |
16d6f994 | 705 | |
98fc3d49 | 706 | return version_macro; |
16d6f994 | 707 | |
ed5b9f96 | 708 | fail: |
a3f9f006 | 709 | error ("unknown value %qs of %<-mmacosx-version-min%>", |
98fc3d49 | 710 | darwin_macosx_version_min); |
ed5b9f96 GK |
711 | return "1000"; |
712 | } | |
713 | ||
714 | /* Define additional CPP flags for Darwin. */ | |
715 | ||
716 | #define builtin_define(TXT) cpp_define (pfile, TXT) | |
717 | ||
718 | void | |
719 | darwin_cpp_builtins (cpp_reader *pfile) | |
720 | { | |
721 | builtin_define ("__MACH__"); | |
722 | builtin_define ("__APPLE__"); | |
723 | ||
724 | /* __APPLE_CC__ is defined as some old Apple include files expect it | |
725 | to be defined and won't work if it isn't. */ | |
726 | builtin_define_with_value ("__APPLE_CC__", "1", false); | |
727 | ||
26705988 IS |
728 | if (darwin_constant_cfstrings) |
729 | builtin_define ("__CONSTANT_CFSTRINGS__"); | |
730 | ||
e4cad568 | 731 | builtin_define_with_value ("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", |
98fc3d49 | 732 | macosx_version_as_macro(), false); |
560d6bd5 IS |
733 | |
734 | /* Since we do not (at 4.6) support ObjC gc for the NeXT runtime, the | |
735 | following will cause a syntax error if one tries to compile gc attributed | |
736 | items. However, without this, NeXT system headers cannot be parsed | |
737 | properly (on systems >= darwin 9). */ | |
738 | if (flag_objc_gc) | |
739 | { | |
740 | builtin_define ("__strong=__attribute__((objc_gc(strong)))"); | |
741 | builtin_define ("__weak=__attribute__((objc_gc(weak)))"); | |
742 | builtin_define ("__OBJC_GC__"); | |
743 | } | |
744 | else | |
745 | { | |
746 | builtin_define ("__strong="); | |
747 | builtin_define ("__weak="); | |
748 | } | |
d764a8e6 | 749 | |
833fe7da | 750 | if (CPP_OPTION (pfile, objc) && flag_objc_abi == 2) |
d764a8e6 | 751 | builtin_define ("__OBJC2__"); |
ed5b9f96 | 752 | } |
1f1d5130 MS |
753 | |
754 | /* Handle C family front-end options. */ | |
755 | ||
756 | static bool | |
757 | handle_c_option (size_t code, | |
758 | const char *arg, | |
759 | int value ATTRIBUTE_UNUSED) | |
760 | { | |
761 | switch (code) | |
762 | { | |
763 | default: | |
764 | /* Unrecognized options that we said we'd handle turn into | |
765 | errors if not listed here. */ | |
766 | return false; | |
767 | ||
768 | case OPT_iframework: | |
769 | add_system_framework_path (xstrdup (arg)); | |
770 | break; | |
c40ce8f3 MS |
771 | |
772 | case OPT_fapple_kext: | |
773 | ; | |
1f1d5130 MS |
774 | } |
775 | ||
776 | /* We recognized the option. */ | |
777 | return true; | |
778 | } | |
779 | ||
26705988 | 780 | /* Allow ObjC* access to CFStrings. */ |
acce4e77 | 781 | static tree |
26705988 IS |
782 | darwin_objc_construct_string (tree str) |
783 | { | |
784 | if (!darwin_constant_cfstrings) | |
785 | { | |
786 | /* Even though we are not using CFStrings, place our literal | |
787 | into the cfstring_htab hash table, so that the | |
788 | darwin_constant_cfstring_p() function will see it. */ | |
789 | darwin_enter_string_into_cfstring_table (str); | |
790 | /* Fall back to NSConstantString. */ | |
791 | return NULL_TREE; | |
792 | } | |
793 | ||
794 | return darwin_build_constant_cfstring (str); | |
795 | } | |
91ebb981 IS |
796 | |
797 | /* The string ref type is created as CFStringRef by <CFBase.h> therefore, we | |
798 | must match for it explicitly, since it's outside the gcc code. */ | |
799 | ||
acce4e77 | 800 | static bool |
91ebb981 IS |
801 | darwin_cfstring_ref_p (const_tree strp) |
802 | { | |
803 | tree tn; | |
804 | if (!strp || TREE_CODE (strp) != POINTER_TYPE) | |
805 | return false; | |
806 | ||
807 | tn = TYPE_NAME (strp); | |
808 | if (tn) | |
809 | tn = DECL_NAME (tn); | |
810 | return (tn | |
811 | && IDENTIFIER_POINTER (tn) | |
812 | && !strncmp (IDENTIFIER_POINTER (tn), "CFStringRef", 8)); | |
813 | } | |
814 | ||
815 | /* At present the behavior of this is undefined and it does nothing. */ | |
acce4e77 | 816 | static void |
91ebb981 IS |
817 | darwin_check_cfstring_format_arg (tree ARG_UNUSED (format_arg), |
818 | tree ARG_UNUSED (args_list)) | |
819 | { | |
820 | } | |
821 | ||
822 | /* The extra format types we recognize. */ | |
3ee44df5 | 823 | EXPORTED_CONST format_kind_info darwin_additional_format_types[] = { |
91ebb981 IS |
824 | { "CFString", NULL, NULL, NULL, NULL, |
825 | NULL, NULL, | |
826 | FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, 0, 0, | |
827 | NULL, NULL | |
828 | } | |
829 | }; | |
acce4e77 | 830 | |
70f42967 SB |
831 | |
832 | /* Support routines to dump the class references for NeXT ABI v1, aka | |
833 | 32-bits ObjC-2.0, as top-level asms. | |
834 | The following two functions should only be called from | |
835 | objc/objc-next-runtime-abi-01.c. */ | |
836 | ||
837 | static void | |
838 | darwin_objc_declare_unresolved_class_reference (const char *name) | |
839 | { | |
840 | const char *lazy_reference = ".lazy_reference\t"; | |
841 | const char *hard_reference = ".reference\t"; | |
842 | const char *reference = MACHOPIC_INDIRECT ? lazy_reference : hard_reference; | |
843 | size_t len = strlen (reference) + strlen(name) + 2; | |
844 | char *buf = (char *) alloca (len); | |
845 | ||
846 | gcc_checking_assert (!strncmp (name, ".objc_class_name_", 17)); | |
847 | ||
848 | snprintf (buf, len, "%s%s", reference, name); | |
3dafb85c | 849 | symtab->finalize_toplevel_asm (build_string (strlen (buf), buf)); |
70f42967 SB |
850 | } |
851 | ||
852 | static void | |
853 | darwin_objc_declare_class_definition (const char *name) | |
854 | { | |
855 | const char *xname = targetm.strip_name_encoding (name); | |
856 | size_t len = strlen (xname) + 7 + 5; | |
857 | char *buf = (char *) alloca (len); | |
858 | ||
859 | gcc_checking_assert (!strncmp (name, ".objc_class_name_", 17) | |
860 | || !strncmp (name, "*.objc_category_name_", 21)); | |
861 | ||
862 | /* Mimic default_globalize_label. */ | |
863 | snprintf (buf, len, ".globl\t%s", xname); | |
3dafb85c | 864 | symtab->finalize_toplevel_asm (build_string (strlen (buf), buf)); |
70f42967 SB |
865 | |
866 | snprintf (buf, len, "%s = 0", xname); | |
3dafb85c | 867 | symtab->finalize_toplevel_asm (build_string (strlen (buf), buf)); |
70f42967 SB |
868 | } |
869 | ||
870 | #undef TARGET_HANDLE_C_OPTION | |
acce4e77 JM |
871 | #define TARGET_HANDLE_C_OPTION handle_c_option |
872 | ||
70f42967 | 873 | #undef TARGET_OBJC_CONSTRUCT_STRING_OBJECT |
acce4e77 JM |
874 | #define TARGET_OBJC_CONSTRUCT_STRING_OBJECT darwin_objc_construct_string |
875 | ||
70f42967 SB |
876 | #undef TARGET_OBJC_DECLARE_UNRESOLVED_CLASS_REFERENCE |
877 | #define TARGET_OBJC_DECLARE_UNRESOLVED_CLASS_REFERENCE \ | |
878 | darwin_objc_declare_unresolved_class_reference | |
879 | ||
880 | #undef TARGET_OBJC_DECLARE_CLASS_DEFINITION | |
881 | #define TARGET_OBJC_DECLARE_CLASS_DEFINITION \ | |
882 | darwin_objc_declare_class_definition | |
883 | ||
884 | #undef TARGET_STRING_OBJECT_REF_TYPE_P | |
acce4e77 JM |
885 | #define TARGET_STRING_OBJECT_REF_TYPE_P darwin_cfstring_ref_p |
886 | ||
887 | #undef TARGET_CHECK_STRING_OBJECT_FORMAT_ARG | |
888 | #define TARGET_CHECK_STRING_OBJECT_FORMAT_ARG darwin_check_cfstring_format_arg | |
889 | ||
890 | struct gcc_targetcm targetcm = TARGETCM_INITIALIZER; |