Bug 63810 - gcc sets incorrect macro for OS X deployment targets
Summary: gcc sets incorrect macro for OS X deployment targets
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-11-11 02:00 UTC by Jeremy Huddleston Sequoia
Modified: 2015-05-28 16:10 UTC (History)
7 users (show)

See Also:
Host: *-*-darwin*
Target: *-*-darwin*
Build: *-*-darwin*
Known to work: 6.0
Known to fail: 5.1.0
Last reconfirmed: 2014-11-11 00:00:00


Attachments
patch against trunk for handling deployment targets correctly (3.11 KB, patch)
2014-11-14 09:09 UTC, Lawrence Velázquez
Details | Diff
patch against 4.9 branch for handling deployment targets correctly (3.11 KB, patch)
2014-11-14 09:16 UTC, Lawrence Velázquez
Details | Diff
patch against 4.8 branch for handling deployment targets correctly (4.06 KB, patch)
2014-11-14 09:18 UTC, Lawrence Velázquez
Details | Diff
patch against trunk for handling deployment targets correctly (3.15 KB, patch)
2014-11-14 21:59 UTC, Lawrence Velázquez
Details | Diff
patch against 4.9 branch for handling deployment targets correctly (3.15 KB, patch)
2014-11-14 22:01 UTC, Lawrence Velázquez
Details | Diff
patch against 4.8 branch for handling deployment targets correctly (4.11 KB, patch)
2014-11-14 22:02 UTC, Lawrence Velázquez
Details | Diff
patch against trunk to handle deployment targets correctly (3.55 KB, patch)
2014-11-18 06:40 UTC, Lawrence Velázquez
Details | Diff
patch against 4.9 branch to handle deployment targets correctly (3.21 KB, patch)
2014-11-18 06:40 UTC, Lawrence Velázquez
Details | Diff
patch against 4.8 branch to handle deployment targets correctly (4.15 KB, patch)
2014-11-18 06:41 UTC, Lawrence Velázquez
Details | Diff
patch against trunk to handle deployment targets correctly (3.57 KB, patch)
2014-11-18 07:31 UTC, Lawrence Velázquez
Details | Diff
patch against 4.9 branch to handle deployment targets correctly (3.23 KB, patch)
2014-11-18 07:32 UTC, Lawrence Velázquez
Details | Diff
patch against 4.8 branch to handle deployment targets correctly (4.17 KB, patch)
2014-11-18 07:32 UTC, Lawrence Velázquez
Details | Diff
backport to gcc-5-branch (2.98 KB, patch)
2015-05-28 16:08 UTC, Lawrence Velázquez
Details | Diff
backport to gcc-4_9-branch (2.99 KB, patch)
2015-05-28 16:09 UTC, Lawrence Velázquez
Details | Diff
backport to gcc-4_8-branch (2.99 KB, patch)
2015-05-28 16:10 UTC, Lawrence Velázquez
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jeremy Huddleston Sequoia 2014-11-11 02:00:29 UTC
Even after the change for bug #61407, gcc is not setting up the deployment target macro correctly.  gcc always sets the tiny version to 0 which is not always the case.  For example:

$ echo | clang-mp-3.5 -E -dM - -mmacosx-version-min=10.09.04 | grep __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 1094
Comment 1 Jeremy Huddleston Sequoia 2014-11-11 02:10:15 UTC
Larry said that he's working on a patch to fix this for gcc trunk, and I suspect he's pretty close to having something since that was about a week ago.

The algorithm for determining what the macro should be is quite simple:

Split the string by "."
Use implicit "0" if there are less than three elements.
if (first field is >10) or (first field is 10 and second field >= 10), use "%02d%02d%02d" as the format
else use "%02d%01d%01d" as the format

I had to do this in bash for some unrelated reason, and here it is in case it is helpful to you:

BUILD_MAJOR=$(echo ${PRODUCT_VERSION} | cut -f1 -d.)
BUILD_MINOR=$(echo ${PRODUCT_VERSION} | cut -f2 -d.)
BUILD_TINY=$(echo ${PRODUCT_VERSION} | cut -f3 -d.)

[[ -z "${BUILD_MINOR}" ]] && BUILD_MINOR="0"
[[ -z "${BUILD_TINY}" ]] && BUILD_TINY="0"

if ((BUILD_MAJOR > 10 || (BUILD_MAJOR == 10 && BUILD_MINOR >= 10))) ; then
  VERSION_ENCODED=$(printf "%02d%02d%02d" ${BUILD_MAJOR} ${BUILD_MINOR} ${BUILD_TINY})
else
  VERSION_ENCODED=$(printf "%02d%01d%01d" ${BUILD_MAJOR} ${BUILD_MINOR} ${BUILD_TINY})
fi

For clang, I did this (slightly less clean):

-    char Str[5];
-    Str[0] = '0' + (Maj / 10);
-    Str[1] = '0' + (Maj % 10);
-    Str[2] = '0' + std::min(Min, 9U);
-    Str[3] = '0' + std::min(Rev, 9U);
-    Str[4] = '\0';
+    char Str[7];
+    if (Maj < 10 || Maj == 10 && Min < 10) {
+      Str[0] = '0' + (Maj / 10);
+      Str[1] = '0' + (Maj % 10);
+      Str[2] = '0' + std::min(Min, 9U);
+      Str[3] = '0' + std::min(Rev, 9U);
+      Str[4] = '\0';
+    } else {
+      Str[0] = '0' + (Maj / 10);
+      Str[1] = '0' + (Maj % 10);
+      Str[2] = '0' + (Min / 10);
+      Str[3] = '0' + (Min % 10);
+      Str[4] = '0' + (Rev / 10);
+      Str[5] = '0' + (Rev % 10);
+      Str[6] = '\0';
+    }
Comment 2 Lawrence Velázquez 2014-11-11 19:31:00 UTC
(In reply to Jeremy Huddleston Sequoia from comment #1)
> Larry said that he's working on a patch to fix this for gcc trunk, and I
> suspect he's pretty close to having something since that was about a week
> ago.

I just completed the fix and will attach it as soon as I verify that GCC builds with it and that the tests I added pass.
Comment 3 Lawrence Velázquez 2014-11-14 09:09:48 UTC
Created attachment 33968 [details]
patch against trunk for handling deployment targets correctly

This is more of a rewrite than just a patch. I've divorced parsing of the version string from assembly of legacy macro values from assembly of modern macro values. It should hopefully be easier to make adjustments in the future, since this code is more than a crude DFA implementation.
Comment 4 Lawrence Velázquez 2014-11-14 09:16:14 UTC
Created attachment 33969 [details]
patch against 4.9 branch for handling deployment targets correctly

Patched GCC 4.9.2 matched the behavior of Apple LLVM Compiler 6.0 (clang-600.0.54) over 8,451 out of 8,464 test strings. The 13 mismatches are due to a bug in clang.
Comment 5 Lawrence Velázquez 2014-11-14 09:18:40 UTC
Created attachment 33970 [details]
patch against 4.8 branch for handling deployment targets correctly

This patch incorporates and supersedes attachment 33932 [details] from bug 61407.
Comment 6 Jack Howarth 2014-11-14 21:21:10 UTC
The proposed patch for gcc trunk fails to build here against r217590

/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/./prev-gcc/xg++ -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/./prev-gcc/ -B/sw/lib/gcc5.0/x86_64-apple-darwin14.0.0/bin/ -nostdinc++ -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/prev-x86_64-apple-darwin14.0.0/libstdc++-v3/src/.libs -B/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/prev-x86_64-apple-darwin14.0.0/libstdc++-v3/libsupc++/.libs  -I/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/prev-x86_64-apple-darwin14.0.0/libstdc++-v3/include/x86_64-apple-darwin14.0.0  -I/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/prev-x86_64-apple-darwin14.0.0/libstdc++-v3/include  -I/sw/src/fink.build/gcc50-5.0.0-1000/gcc-5-20141114/libstdc++-v3/libsupc++ -L/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/prev-x86_64-apple-darwin14.0.0/libstdc++-v3/src/.libs -L/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/prev-x86_64-apple-darwin14.0.0/libstdc++-v3/libsupc++/.libs -c  -DIN_GCC_FRONTEND -DIN_GCC_FRONTEND -DIN_GCC_FRONTEND -g -O2  -gtoggle -DIN_GCC    -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Werror -fno-common  -DHAVE_CONFIG_H -I. -I. -I../../gcc-5-20141114/gcc -I../../gcc-5-20141114/gcc/. -I../../gcc-5-20141114/gcc/../include -I../../gcc-5-20141114/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-5-20141114/gcc/../libdecnumber -I../../gcc-5-20141114/gcc/../libdecnumber/dpd -I../libdecnumber -I../../gcc-5-20141114/gcc/../libbacktrace  -DCLOOG_INT_GMP -I/sw/include -I/sw/include -o darwin-c.o -MT darwin-c.o -MMD -MP -MF ./.deps/darwin-c.TPo -DGCC_INCLUDE_DIR=\"/sw/lib/gcc5.0/lib/gcc/x86_64-apple-darwin14.0.0/5.0.0/include\" -DFIXED_INCLUDE_DIR=\"/sw/lib/gcc5.0/lib/gcc/x86_64-apple-darwin14.0.0/5.0.0/include-fixed\" -DGPLUSPLUS_INCLUDE_DIR=\"/sw/lib/gcc5.0/lib/gcc/x86_64-apple-darwin14.0.0/5.0.0/../../../../include/c++/5.0.0\" -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=0 -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"/sw/lib/gcc5.0/lib/gcc/x86_64-apple-darwin14.0.0/5.0.0/../../../../include/c++/5.0.0/x86_64-apple-darwin14.0.0\" -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"/sw/lib/gcc5.0/lib/gcc/x86_64-apple-darwin14.0.0/5.0.0/../../../../include/c++/5.0.0/backward\" -DLOCAL_INCLUDE_DIR=\"/usr/local/include\" -DCROSS_INCLUDE_DIR=\"/sw/lib/gcc5.0/lib/gcc/x86_64-apple-darwin14.0.0/5.0.0/../../../../x86_64-apple-darwin14.0.0/sys-include\" -DTOOL_INCLUDE_DIR=\"/sw/lib/gcc5.0/lib/gcc/x86_64-apple-darwin14.0.0/5.0.0/../../../../x86_64-apple-darwin14.0.0/include\" -DNATIVE_SYSTEM_HEADER_DIR=\"/usr/include\" -DPREFIX=\"/sw/lib/gcc5.0/\" -DSTANDARD_EXEC_PREFIX=\"/sw/lib/gcc5.0/lib/gcc/\"  ../../gcc-5-20141114/gcc/config/darwin-c.c
../../gcc-5-20141114/gcc/config/darwin-c.c: In function ‘const char* version_as_modern_macro(const long unsigned int*)’:
../../gcc-5-20141114/gcc/config/darwin-c.c:711:7: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
       != ((major > 9) ? sizeof "999999" : sizeof "99999") - 1)
       ^
cc1plus: all warnings being treated as errors
../../gcc-5-20141114/gcc/config/t-darwin:26: recipe for target 'darwin-c.o' failed
make[3]: *** [darwin-c.o] Error 1
make[3]: Leaving directory '/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir/gcc'
Makefile:4368: recipe for target 'all-stage2-gcc' failed
make[2]: *** [all-stage2-gcc] Error 2
make[2]: Leaving directory '/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir'
Makefile:20616: recipe for target 'stage2-bubble' failed
make[1]: *** [stage2-bubble] Error 2
make[1]: Leaving directory '/sw/src/fink.build/gcc50-5.0.0-1000/darwin_objdir'
Makefile:906: recipe for target 'all' failed
make: *** [all] Error 2
Comment 7 Lawrence Velázquez 2014-11-14 21:24:29 UTC
(In reply to howarth from comment #6)
> ../../gcc-5-20141114/gcc/config/darwin-c.c: In function ‘const char*
> version_as_modern_macro(const long unsigned int*)’:
> ../../gcc-5-20141114/gcc/config/darwin-c.c:711:7: error: comparison between
> signed and unsigned integer expressions [-Werror=sign-compare]
>        != ((major > 9) ? sizeof "999999" : sizeof "99999") - 1)
>        ^

Seriously?
Comment 8 Lawrence Velázquez 2014-11-14 21:59:05 UTC
Created attachment 33975 [details]
patch against trunk for handling deployment targets correctly
Comment 9 Lawrence Velázquez 2014-11-14 21:59:52 UTC
Comment on attachment 33975 [details]
patch against trunk for handling deployment targets correctly

>diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c
>index ffefa37..311cdd4 100644
>--- a/gcc/config/darwin-c.c
>+++ b/gcc/config/darwin-c.c
>@@ -590,42 +590,167 @@ 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 a version string, return the version as a statically-allocated
>+    array of three non-negative integers.  If the version string is
>+    invalid, return null.
>+
>+    Version strings 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
>+    integer.  Omitted tokens are treated as 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}  */
>+
>+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];
>+
>+  if (! version_str)
>+    return NULL;
>+
>+  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 a three-component 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 the 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.  Major
>+    numbers are zero-padded if necessary.  Minor and tiny numbers from
>+    10 through 99 are permitted but are clamped to 9 (for example,
>+    {10,9,10} produces "1099").  Versions containing numbers greater
>+    than 99 are rejected.  */
>+
> static const char *
>-version_as_macro (void)
>+version_as_legacy_macro (const unsigned long *version)
> {
>-  static char result[7] = "1000";
>-  int minorDigitIdx;
>+  unsigned long major = version[MAJOR];
>+  unsigned long minor = version[MINOR];
>+  unsigned long tiny = version[TINY];
>+  static char result[sizeof "9999"];
> 
>-  if (strncmp (darwin_macosx_version_min, "10.", 3) != 0)
>+  if (major > 99 || minor > 99 || tiny > 99)
>+    return NULL;
>+
>+  minor = ((minor > 9) ? 9 : minor);
>+  tiny = ((tiny > 9) ? 9 : tiny);
>+
>+  /* NOTE: Cast result of sizeof so that result of sprintf is not
>+     converted to an unsigned type.  */
>+  if (sprintf (result, "%02lu%lu%lu", major, minor, tiny)
>+      != (int) sizeof "9999" - 1)
>+    return NULL;
>+
>+  return result;
>+}
>+
>+/*  Given a three-component 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
>+    or the __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ macro.  If the
>+    version is invalid, return null.
>+
>+    The modern format is a five- or six-character string -- one or two
>+    chars for the major number and two each for the minor and tiny
>+    numbers, which are zero-padded if necessary (for example, {8,1,0}
>+    produces "80100", and {10,10,1} produces "101001").  Versions
>+    containing numbers greater than 99 are rejected.  */
>+
>+static const char *
>+version_as_modern_macro (const unsigned long *version)
>+{
>+  unsigned long major = version[MAJOR];
>+  unsigned long minor = version[MINOR];
>+  unsigned long tiny = version[TINY];
>+  static char result[sizeof "999999"];
>+
>+  if (major > 99 || minor > 99 || tiny > 99)
>+    return NULL;
>+
>+  /* NOTE: 'sizeof "foo"' returns size of char array, but
>+     'sizeof ((x > y) ? "foo" : "bar")' returns size of char pointer.  */
>+  /* NOTE: Cast result of sizeof so that result of sprintf is not
>+     converted to an unsigned type.  */
>+  if (sprintf (result, "%lu%02lu%02lu", major, minor, tiny)
>+      != (int) ((major > 9) ? sizeof "999999" : sizeof "99999") - 1)
>+    return NULL;
>+
>+  return result;
>+}
>+
>+/*  Return the value of darwin_macosx_version_min, suitably formatted
>+    for the __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro.  (For
>+    example, "10.9" produces "1090", and "10.10.1" produces "101001".)
>+    If its value 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]))
>+
>+  /* Do not assume that the major number will always be exactly 10.  */
>+  if (version_array[MAJOR] < 10 || 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[MAJOR] == 10 && 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";
> }
> 
>@@ -647,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..1f1eafa
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/darwin-minversion-10.c
>@@ -0,0 +1,16 @@
>+/* PR 63810: Test that a version with a zero-padded minor number < 10
>+   and a zero-padded tiny number < 10 produces the correct
>+   four-character macro.  */
>+/* Added by Lawrence Velázquez <larryv@macports.org>.  */
>+
>+/* { 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..39cf0b5
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/darwin-minversion-11.c
>@@ -0,0 +1,15 @@
>+/* PR 63810: Test that a version with outrageous zero-padding and
>+   a minor number > 9 still produces a six-character macro.  */
>+/* Added by Lawrence Velázquez <larryv@macports.org>.  */
>+
>+/* { 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..ea52d30
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/darwin-minversion-12.c
>@@ -0,0 +1,15 @@
>+/* PR 63810: Test that a version with outrageous zero-padding and
>+   a minor number < 10 still produces a four-character macro.  */
>+/* Added by Lawrence Velázquez <larryv@macports.org>.  */
>+
>+/* { 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..4a67f85 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 < 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..ace739e 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 > 9 produce a 6-digit 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..31b5c3d
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/darwin-minversion-5.c
>@@ -0,0 +1,15 @@
>+/* PR 63810: Test that a version with minor number < 10 and tiny number > 9
>+   produces a four-character macro with the tiny number clamped to 9.  */
>+/* Added by Lawrence Velázquez <larryv@macports.org>.  */
>+
>+/* { 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..1455237
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/darwin-minversion-6.c
>@@ -0,0 +1,14 @@
>+/* PR 63810: Test that tiny numbers are preserved in six-character macros.  */
>+/* Added by Lawrence Velázquez <larryv@macports.org>.  */
>+
>+/* { 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..c4d6986
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/darwin-minversion-7.c
>@@ -0,0 +1,15 @@
>+/* PR 63810: Test that tiny numbers < 10 are preserved in four-character
>+   macros.  */
>+/* Added by Lawrence Velázquez <larryv@macports.org>.  */
>+
>+/* { 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..fa3b614
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/darwin-minversion-8.c
>@@ -0,0 +1,16 @@
>+/* PR 63810: Test that a version with minor number > 9 and no tiny
>+   number produces a six-character macro with "00" as the last two
>+   characters.  */
>+/* Added by Lawrence Velázquez <larryv@macports.org>.  */
>+
>+/* { 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..5f8990a
>--- /dev/null
>+++ b/gcc/testsuite/gcc.dg/darwin-minversion-9.c
>@@ -0,0 +1,15 @@
>+/* PR 63810: Test that a version with a zero-padded minor number < 10
>+   produces a four-character macro.  */
>+/* Added by Lawrence Velázquez <larryv@macports.org>.  */
>+
>+/* { 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;
>+}
Comment 10 Lawrence Velázquez 2014-11-14 22:01:36 UTC
Created attachment 33976 [details]
patch against 4.9 branch for handling deployment targets correctly

New 4.9 patch that should satisfy -Werror=sign-compare.
Comment 11 Lawrence Velázquez 2014-11-14 22:02:13 UTC
Created attachment 33977 [details]
patch against 4.8 branch for handling deployment targets correctly

Updated patch that should satisfy -Werror=sign-compare.
Comment 12 Lawrence Velázquez 2014-11-18 06:40:12 UTC
Created attachment 34007 [details]
patch against trunk to handle deployment targets correctly

Added some missing null checks; minor comment editing.
Comment 13 Lawrence Velázquez 2014-11-18 06:40:55 UTC
Created attachment 34008 [details]
patch against 4.9 branch to handle deployment targets correctly

Added some missing null checks; minor comment editing.
Comment 14 Lawrence Velázquez 2014-11-18 06:41:17 UTC
Created attachment 34009 [details]
patch against 4.8 branch to handle deployment targets correctly

Added some missing null checks; minor comment editing.
Comment 15 Lawrence Velázquez 2014-11-18 07:31:33 UTC
Created attachment 34010 [details]
patch against trunk to handle deployment targets correctly

Forgot to fix a comment in the last update.
Comment 16 Lawrence Velázquez 2014-11-18 07:32:01 UTC
Created attachment 34011 [details]
patch against 4.9 branch to handle deployment targets correctly

Forgot to fix a comment in the last update.
Comment 17 Lawrence Velázquez 2014-11-18 07:32:25 UTC
Created attachment 34012 [details]
patch against 4.8 branch to handle deployment targets correctly

Forgot to fix a comment in the last update.
Comment 18 Francois-Xavier Coudert 2014-11-18 09:32:46 UTC
(In reply to Lawrence Velázquez from comment #17)

Hey Lawrence, do you have a copyright assignment in place with the FSF? If so, please submit your trunk patch to gcc-patches@gcc.gnu.org for review. If not, ask on the gcc@gcc.gnu.org list for the paperwork to be sent to you.
Comment 19 Eric Gallager 2014-12-22 22:41:57 UTC
(In reply to Francois-Xavier Coudert from comment #18)
> (In reply to Lawrence Velázquez from comment #17)
> 
> Hey Lawrence, do you have a copyright assignment in place with the FSF? If
> so, please submit your trunk patch to gcc-patches@gcc.gnu.org for review. If
> not, ask on the gcc@gcc.gnu.org list for the paperwork to be sent to you.

He appears to still be waiting on a response to a ping as of http://gcc.gnu.org/ml/gcc/2014-12/msg00047.html
Comment 20 Lawrence Velázquez 2015-05-15 06:54:14 UTC
(In reply to Francois-Xavier Coudert from comment #18)
> (In reply to Lawrence Velázquez from comment #17)
> 
> Hey Lawrence, do you have a copyright assignment in place with the FSF? If
> so, please submit your trunk patch to gcc-patches@gcc.gnu.org for review. If
> not, ask on the gcc@gcc.gnu.org list for the paperwork to be sent to you.

Sorry, it took me a while to obtain the paperwork, and even longer to get around to submitting it.

https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01377.html
Comment 21 Francois-Xavier Coudert 2015-05-15 22:52:52 UTC
(In reply to Lawrence Velázquez from comment #20)
> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01377.html

Quick review of the patch:

 - version_as_modern_macro(): you implement a specific behavior for major <= 9, but it's necessary at all. Having major <= 9 is simply impossible (and Apple's compiler rejects it). I'd say let's make things simpler anduse a format of "%02lu%02lu%02lu" and always be 6 characters long.

 - version_as_legacy_macro(): same issue. Why do we need to handle major <= 9? You have rejected this possibility in macosx_version_as_macro() anyway. Simplify here also.

 - throughout the patch, writing things like "(int) sizeof "9999" - 1" or "char result[sizeof "9999"]" when you could write "4" and "char result[4]" means harder code to read, and no real benefit in terms of security or maintainability (since you're duplicating stuff anyway).

 - in macosx_version_as_macro(), you say "Allow for future major numbers greater than 10", but you actually reject them (and that's OK). Adjust the comment.

 - later, "version_array[MAJOR] == 10" is guaranteed. Remove it.

 - in parse_version(), the string passed is guaranteed to be non-NULL. No need to test it.
Comment 22 mrs@gcc.gnu.org 2015-05-15 23:02:03 UTC
Though I approved it on list, you should feel free to update with the review points others have and post that version if you wish.
Comment 23 Lawrence Velázquez 2015-05-16 02:15:56 UTC
(In reply to Francois-Xavier Coudert from comment #21)
>  - version_as_legacy_macro(): same issue. Why do we need to handle major <=
> 9? You have rejected this possibility in macosx_version_as_macro() anyway.
> Simplify here also.

I don't see anything in version_as_legacy_macro() that specifically deals with major <= 9. Could you point me to the offending code?
Comment 24 Francois-Xavier Coudert 2015-05-16 07:58:04 UTC
(In reply to Lawrence Velázquez from comment #23)
> I don't see anything in version_as_legacy_macro() that specifically deals
> with major <= 9. Could you point me to the offending code?

In the comment above it ("Major numbers are zero-padded if necessary"), and the sprintf format "%02lu%lu%lu" (which can be "%lu%lu%lu").
Comment 25 Lawrence Velázquez 2015-05-20 22:01:31 UTC
(In reply to mrs@gcc.gnu.org from comment #22)
> Though I approved it on list, you should feel free to update with the review
> points others have and post that version if you wish.

Re-roll posted:
https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01888.html
Comment 26 mrs@gcc.gnu.org 2015-05-28 12:27:37 UTC
Author: mrs
Date: Thu May 28 12:27:05 2015
New Revision: 223808

URL: https://gcc.gnu.org/viewcvs?rev=223808&root=gcc&view=rev
Log:
2015-05-28  Lawrence Velázquez  <vq@larryv.me>

	PR target/63810
	* config/darwin-c.c (version_components): New global enum.
	(parse_version, version_as_legacy_macro)
	(version_as_modern_macro, macosx_version_as_macro): New functions.
	(version_as_macro): Remove.
	(darwin_cpp_builtins): Use new function.

testsuite:
	PR target/63810
	* gcc.dg/darwin-minversion-3.c: Update testcase.
	* gcc.dg/darwin-minversion-4.c: Ditto.
	* gcc.dg/darwin-minversion-5.c: New testcase.
	* gcc.dg/darwin-minversion-6.c: Ditto.
	* gcc.dg/darwin-minversion-7.c: Ditto.
	* gcc.dg/darwin-minversion-8.c: Ditto.
	* gcc.dg/darwin-minversion-9.c: Ditto.
	* gcc.dg/darwin-minversion-10.c: Ditto.
	* gcc.dg/darwin-minversion-11.c: Ditto.
	* gcc.dg/darwin-minversion-12.c: Ditto.

Added:
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-10.c
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-11.c
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-12.c
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-5.c
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-6.c
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-7.c
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-8.c
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-9.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/darwin-c.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-3.c
    trunk/gcc/testsuite/gcc.dg/darwin-minversion-4.c
Comment 27 mrs@gcc.gnu.org 2015-05-28 12:33:16 UTC
Fixed in 6.0. Backports pre approved after bake time and testing that includes older darwins and ppc.
Comment 28 Lawrence Velázquez 2015-05-28 16:08:37 UTC
Created attachment 35645 [details]
backport to gcc-5-branch
Comment 29 Lawrence Velázquez 2015-05-28 16:09:45 UTC
Created attachment 35646 [details]
backport to gcc-4_9-branch
Comment 30 Lawrence Velázquez 2015-05-28 16:10:08 UTC
Created attachment 35647 [details]
backport to gcc-4_8-branch
Comment 31 Lawrence Velázquez 2015-05-28 16:10:57 UTC
(In reply to mrs@gcc.gnu.org from comment #27)
> Fixed in 6.0. Backports pre approved after bake time and testing that
> includes older darwins and ppc.

Thanks! I've attached updated patches against 4.8, 4.9, and 5.1, if you need them.