]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/darwin-c.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / darwin-c.c
CommitLineData
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 5This file is part of GCC.
0168a849 6
7ec022b2 7GCC is free software; you can redistribute it and/or modify
0168a849 8it under the terms of the GNU General Public License as published by
2f83c7d6 9the Free Software Foundation; either version 3, or (at your option)
0168a849
SS
10any later version.
11
7ec022b2 12GCC is distributed in the hope that it will be useful,
0168a849
SS
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
2f83c7d6
NC
18along 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
42static bool using_frameworks = false;
43
e3c287c9
MS
44static const char *find_subframework_header (cpp_reader *pfile, const char *header,
45 cpp_dir **dirp);
0168a849
SS
46
47typedef struct align_stack
48{
49 int alignment;
50 struct align_stack * prev;
51} align_stack;
52
53static 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 58static void
9c808aad 59push_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
70static void
9c808aad 71pop_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
87void
9c808aad 88darwin_pragma_ignore (cpp_reader *pfile ATTRIBUTE_UNUSED)
0168a849
SS
89{
90 /* Do nothing. */
91}
92
93/* #pragma options align={mac68k|power|reset} */
94
95void
9c808aad 96darwin_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
127void
9c808aad 128darwin_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. */
162void
163darwin_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 183static struct frameworks_in_use {
94d1613b
MS
184 size_t len;
185 const char *name;
186 cpp_dir* dir;
187} *frameworks_in_use;
188static int num_frameworks = 0;
189static 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
198static void
199add_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
231static struct cpp_dir*
232find_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
252struct framework_header {const char * dirName; int dirNameLen; };
253static 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
262static char *
263framework_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
337static const char*
338find_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
423static void
424add_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
442void
443add_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 457static 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
465void
7792cf66
IS
466darwin_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
500void
479ec1d1 501darwin_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
533static const char*
e3c287c9 534find_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
577enum version_components { MAJOR, MINOR, TINY };
578
579static const unsigned long *
580parse_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 627static const char *
98fc3d49 628version_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
658static const char *
659version_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
685static const char *
686macosx_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
718void
719darwin_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
756static bool
757handle_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 781static tree
26705988
IS
782darwin_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 800static bool
91ebb981
IS
801darwin_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 816static void
91ebb981
IS
817darwin_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 823EXPORTED_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
837static void
838darwin_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
852static void
853darwin_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
890struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;