diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c index 3803e75..6d49f05 100644 --- a/gcc/config/darwin-c.c +++ b/gcc/config/darwin-c.c @@ -599,42 +599,158 @@ find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp) return 0; } -/* Return the value of darwin_macosx_version_min suitable for the - __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro, so '10.4.2' - becomes 1040 and '10.10.0' becomes 101000. The lowest digit is - always zero, as is the second lowest for '10.10.x' and above. - Print a warning if the version number can't be understood. */ +/* Given an OS X version VERSION_STR, return it as a statically-allocated array + of three integers. If VERSION_STR is invalid, return NULL. + + VERSION_STR must consist of one, two, or three tokens, each separated by + a single period. Each token must contain only the characters '0' through + '9' and is converted to an equivalent non-negative decimal integer. Omitted + tokens become zeros. For example: + + "10" becomes {10,0,0} + "10.10" becomes {10,10,0} + "10.10.1" becomes {10,10,1} + "10.000010.1" becomes {10,10,1} + "10.010.001" becomes {10,10,1} + "000010.10.00001" becomes {10,10,1} + ".9.1" is invalid + "10..9" is invalid + "10.10." is invalid */ + +enum version_components { MAJOR, MINOR, TINY }; + +static const unsigned long * +parse_version (const char *version_str) +{ + size_t version_len; + char *end; + static unsigned long version_array[3]; + + version_len = strlen (version_str); + if (version_len < 1) + return NULL; + + /* Version string must consist of digits and periods only. */ + if (strspn (version_str, "0123456789.") != version_len) + return NULL; + + if (!ISDIGIT (version_str[0]) || !ISDIGIT (version_str[version_len - 1])) + return NULL; + + version_array[MAJOR] = strtoul (version_str, &end, 10); + version_str = end + ((*end == '.') ? 1 : 0); + + /* Version string must not contain adjacent periods. */ + if (*version_str == '.') + return NULL; + + version_array[MINOR] = strtoul (version_str, &end, 10); + version_str = end + ((*end == '.') ? 1 : 0); + + version_array[TINY] = strtoul (version_str, &end, 10); + + /* Version string must contain no more than three tokens. */ + if (*end != '\0') + return NULL; + + return version_array; +} + +/* Given VERSION -- a three-component OS X version represented as an array of + non-negative integers -- return a statically-allocated string suitable for + the legacy __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro. If VERSION + is invalid and cannot be coerced into a valid form, return NULL. + + The legacy format is a four-character string -- two chars for the major + number and one each for the minor and tiny numbers. Minor and tiny numbers + from 10 through 99 are permitted but are clamped to 9 (for example, {10,9,10} + produces "1099"). If VERSION contains numbers greater than 99, it is + rejected. */ + +static const char * +version_as_legacy_macro (const unsigned long *version) +{ + unsigned long major, minor, tiny; + static char result[5]; + + major = version[MAJOR]; + minor = version[MINOR]; + tiny = version[TINY]; + + if (major > 99 || minor > 99 || tiny > 99) + return NULL; + + minor = ((minor > 9) ? 9 : minor); + tiny = ((tiny > 9) ? 9 : tiny); + + if (sprintf (result, "%lu%lu%lu", major, minor, tiny) != 4) + return NULL; + + return result; +} + +/* Given VERSION -- a three-component OS X version represented as an array of + non-negative integers -- return a statically-allocated string suitable for + the modern __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro. If VERSION + is invalid, return NULL. + + The modern format is a six-character string -- two chars for each component, + with zero-padding if necessary (for example, {10,10,1} produces "101001"). If + VERSION contains numbers greater than 99, it is rejected. */ + static const char * -version_as_macro (void) +version_as_modern_macro (const unsigned long *version) { - static char result[7] = "1000"; - int minorDigitIdx; + unsigned long major, minor, tiny; + static char result[7]; + + major = version[MAJOR]; + minor = version[MINOR]; + tiny = version[TINY]; + + if (major > 99 || minor > 99 || tiny > 99) + return NULL; + + if (sprintf (result, "%02lu%02lu%02lu", major, minor, tiny) != 6) + return NULL; + + return result; +} - if (strncmp (darwin_macosx_version_min, "10.", 3) != 0) +/* Return the value of darwin_macosx_version_min, suitably formatted for the + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro. Values representing + OS X 10.9 and earlier are encoded using the legacy four-character format, + while 10.10 and later use a modern six-character format. (For example, + "10.9" produces "1090", and "10.10.1" produces "101001".) If + darwin_macosx_version_min is invalid and cannot be coerced into a valid + form, print a warning and return "1000". */ + +static const char * +macosx_version_as_macro (void) +{ + const unsigned long *version_array; + const char *version_macro; + + version_array = parse_version (darwin_macosx_version_min); + if (!version_array) goto fail; - if (! ISDIGIT (darwin_macosx_version_min[3])) + + if (version_array[MAJOR] != 10) goto fail; - minorDigitIdx = 3; - result[2] = darwin_macosx_version_min[minorDigitIdx++]; - if (ISDIGIT (darwin_macosx_version_min[minorDigitIdx])) - { - /* Starting with OS X 10.10, the macro ends '00' rather than '0', - i.e. 10.10.x becomes 101000 rather than 10100. */ - result[3] = darwin_macosx_version_min[minorDigitIdx++]; - result[4] = '0'; - result[5] = '0'; - result[6] = '\0'; - } - if (darwin_macosx_version_min[minorDigitIdx] != '\0' - && darwin_macosx_version_min[minorDigitIdx] != '.') + if (version_array[MINOR] < 10) + version_macro = version_as_legacy_macro (version_array); + else + version_macro = version_as_modern_macro (version_array); + + if (!version_macro) goto fail; - return result; + return version_macro; fail: error ("unknown value %qs of -mmacosx-version-min", - darwin_macosx_version_min); + darwin_macosx_version_min); return "1000"; } @@ -656,7 +772,7 @@ darwin_cpp_builtins (cpp_reader *pfile) builtin_define ("__CONSTANT_CFSTRINGS__"); builtin_define_with_value ("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", - version_as_macro(), false); + macosx_version_as_macro(), false); /* Since we do not (at 4.6) support ObjC gc for the NeXT runtime, the following will cause a syntax error if one tries to compile gc attributed diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-10.c b/gcc/testsuite/gcc.dg/darwin-minversion-10.c new file mode 100644 index 0000000..bf95d46 --- /dev/null +++ b/gcc/testsuite/gcc.dg/darwin-minversion-10.c @@ -0,0 +1,16 @@ +/* PR target/63810: Test that an OS X minimum version with zero-padded + minor and tiny numbers less than 10 produces the correct + four-character macro. */ +/* Added by Lawrence Velázquez . */ + +/* { dg-options "-mmacosx-version-min=10.07.02" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +int +main () +{ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 1072 + fail me; +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-11.c b/gcc/testsuite/gcc.dg/darwin-minversion-11.c new file mode 100644 index 0000000..a03e707 --- /dev/null +++ b/gcc/testsuite/gcc.dg/darwin-minversion-11.c @@ -0,0 +1,16 @@ +/* PR target/63810: Test that an OS X minimum version with outrageous + zero-padding and a minor number greater than 9 still produces + a six-character macro. */ +/* Added by Lawrence Velázquez . */ + +/* { dg-options "-mmacosx-version-min=00010.010.0000098" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +int +main () +{ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 101098 + fail me; +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-12.c b/gcc/testsuite/gcc.dg/darwin-minversion-12.c new file mode 100644 index 0000000..4c2ce38 --- /dev/null +++ b/gcc/testsuite/gcc.dg/darwin-minversion-12.c @@ -0,0 +1,16 @@ +/* PR target/63810: Test that an OS X minimum version with outrageous + zero-padding and a minor number less than 10 still produces + a four-character macro. */ +/* Added by Lawrence Velázquez . */ + +/* { dg-options "-mmacosx-version-min=010.008.000031" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +int +main () +{ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 1089 + fail me; +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-3.c b/gcc/testsuite/gcc.dg/darwin-minversion-3.c index 4fcb969..d1795e7 100644 --- a/gcc/testsuite/gcc.dg/darwin-minversion-3.c +++ b/gcc/testsuite/gcc.dg/darwin-minversion-3.c @@ -1,11 +1,11 @@ -/* Test that most-minor versions greater than 9 work. */ -/* { dg-options "-mmacosx-version-min=10.4.10" } */ +/* Test that most minor versions less than 10 work. */ +/* { dg-options "-mmacosx-version-min=10.4.1" } */ /* { dg-do compile { target *-*-darwin* } } */ int main () { -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 1040 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 1041 fail me; #endif return 0; diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-4.c b/gcc/testsuite/gcc.dg/darwin-minversion-4.c index 1cb42eb..1481aa5 100644 --- a/gcc/testsuite/gcc.dg/darwin-minversion-4.c +++ b/gcc/testsuite/gcc.dg/darwin-minversion-4.c @@ -1,11 +1,11 @@ -/* Test that major versions greater than 9 work and have the additional 0. */ -/* { dg-options "-mmacosx-version-min=10.10.0" } */ +/* Test that minor versions greater than 9 produce a six-character macro. */ +/* { dg-options "-mmacosx-version-min=10.10.1" } */ /* { dg-do compile { target *-*-darwin* } } */ int main () { -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 101000 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 101001 fail me; #endif return 0; diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-5.c b/gcc/testsuite/gcc.dg/darwin-minversion-5.c new file mode 100644 index 0000000..09a9d72 --- /dev/null +++ b/gcc/testsuite/gcc.dg/darwin-minversion-5.c @@ -0,0 +1,16 @@ +/* PR target/63810: Test that an OS X minimum version with minor number + less than 10 and tiny number greater than 9 produces a four-character + macro with the tiny number clamped to 9. */ +/* Added by Lawrence Velázquez . */ + +/* { dg-options "-mmacosx-version-min=10.9.10" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +int +main () +{ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 1099 + fail me; +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-6.c b/gcc/testsuite/gcc.dg/darwin-minversion-6.c new file mode 100644 index 0000000..e01fa72 --- /dev/null +++ b/gcc/testsuite/gcc.dg/darwin-minversion-6.c @@ -0,0 +1,15 @@ +/* PR target/63810: Test that tiny numbers are preserved in + six-character macros. */ +/* Added by Lawrence Velázquez . */ + +/* { dg-options "-mmacosx-version-min=10.10.11" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +int +main () +{ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 101011 + fail me; +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-7.c b/gcc/testsuite/gcc.dg/darwin-minversion-7.c new file mode 100644 index 0000000..72f495b --- /dev/null +++ b/gcc/testsuite/gcc.dg/darwin-minversion-7.c @@ -0,0 +1,15 @@ +/* PR target/63810: Test that tiny numbers less than 10 are preserved in + four-character macros. */ +/* Added by Lawrence Velázquez . */ + +/* { dg-options "-mmacosx-version-min=10.9.1" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +int +main () +{ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 1091 + fail me; +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-8.c b/gcc/testsuite/gcc.dg/darwin-minversion-8.c new file mode 100644 index 0000000..5982df5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/darwin-minversion-8.c @@ -0,0 +1,16 @@ +/* PR target/63810: Test that an OS X minimum version with minor number + greater than 9 and no tiny number produces a six-character macro + ending in "00". */ +/* Added by Lawrence Velázquez . */ + +/* { dg-options "-mmacosx-version-min=10.11" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +int +main () +{ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 101100 + fail me; +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-9.c b/gcc/testsuite/gcc.dg/darwin-minversion-9.c new file mode 100644 index 0000000..d781783 --- /dev/null +++ b/gcc/testsuite/gcc.dg/darwin-minversion-9.c @@ -0,0 +1,15 @@ +/* PR target/63810: Test that an OS X minimum version with a zero-padded + minor number less than 10 produces a four-character macro. */ +/* Added by Lawrence Velázquez . */ + +/* { dg-options "-mmacosx-version-min=10.08.4" } */ +/* { dg-do compile { target *-*-darwin* } } */ + +int +main () +{ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 1084 + fail me; +#endif + return 0; +}