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