C++ : Add the -stdlib= option.

Message ID ECCBE90A-239F-4073-B54B-E5C0E2639819@sandoe.co.uk
State New
Headers show
Series
  • C++ : Add the -stdlib= option.
Related show

Commit Message

Iain Sandoe Nov. 11, 2020, 8:58 p.m.
resending - the first & second attempt didn’t seem to make it to gcc-patches.

Hi

This option allows the user to specify alternate C++ runtime libraries,
for example when a platform uses libc++ as the installed C++ runtime.

It is the same spelling as a clang option that allows that to use libstdc++.

I have had this patch for some time now (more than a year) on Darwin
branches.

For Darwin [>=11] (and I expect modern FreeBSD) the fact that the installed
C++ runtime is libc++ means conflicts can and do occur when using G++.

I expect that the facility will also be useful for folks who regularly try to
ensure that GCC and clang stay compatible, it is a credit to that effort that
the replacement is pretty much “drop in”.

Testing:

The patch applies without regression on *darwin* and x86_64-linux-gnu.

That doesn’t say much about whether it does what’s intended, of course,
and testing in-tree is not a viable option (it would need a lot of work, not
to mention the fact that it depends on an external source base).  So I’ve
tested this quite extensively on x86 Darwin and Linux.

It’s a lot easier to use an LLVM branch >= 9 for this since there is a
missing __cxa symbol before that (I originally used LLVM-7 for ‘reasons’).
Since coroutines was committed to GCC we have a <coroutine> header
where the libc++ implementation is still using the <experimental/coroutine>
version, so that one needs to  account for this.

Here’s an LLVM-9 tree with an added <coroutine> header (as an example)
https://github.com/iains/llvm-project/tree/9.0.1-gcc-stdlib
(in case someone wants to try this out in the near future; I don’t think that
LLVM-10 will be much different, at least the coroutine header is unchanged
there)

I’ve used this ‘in anger’ on Darwin to build a toolset which includes a  
number
of C++ heavy applications (e.g. LLVM, cmake, etc) and it allowed some of
these to work effectively where it had not been possible before.

One can also do an “installed test” of g++
for that there are (a relatively modest number of) test fails.
AFAICT, there is nothing significant there - some tests fail because the  
output
isn’t expecting to see libc++ __1 inline namespace, some fail because libc++
(as per current branches) doesn’t allow use with GCC + std=c++98, some
are warning diagnostics etc.

[how compatible libc++ is, is somewhat independent of the patch itself; but
it seems “very compatible” is a starting assessment].

phew… description longer than patch, it seems.

OK for master?
thanks
Iain

—— commit message

This option allows the user to specify alternate C++ runtime libraries,
for example when a platform uses libc++ as the installed C++ runtime.

We introduce the command line option: -stdlib= which is the user-facing
mechanism to select the C++ runtime to be used when compiling and linking
code.  This is the same option spelling as that used by clang to allow the
use of libstdc++.

The availability (and thus function) of the option are a configure-time
choice using the configuration control:
--with-gxx-libcxx-include-dir=

Specification of the path for the libc++ headers, enables the -stdlib=
option (using the path as given), default values are set when the path
is unconfigured.

If --with-gxx-libcxx-include-dir is given together with --with-sysroot=,
then we test to see if the include path starts with the sysroot and, if so,
record the sysroot-relative component as the local path.  At runtime, we
prepend the sysroot that is actually active.

At link time, we use the C++ runtime in force and (if that is libc++) also
append the libc++abi ABI library. As for other cases, if a target sets the
name pointer for the ABI library to NULL the G++ driver will omit it from
the link line.

gcc/ChangeLog:

	* configure.ac: Add gxx-libcxx-include-dir handled
	in the same way as the regular cxx header directory.
	* Makefile.in: Regenerated.
	* config.in: Likewise.
	* configure: Likewise.
	* cppdefault.c: Pick up libc++ headers if the option
	is enabled.
	* incpath.c (add_standard_paths): Allow for multiple
	c++ header include path variants.
	* doc/invoke.texi: Document the -stdlib= option.

gcc/c-family/ChangeLog:

	* c.opt: Add -stdlib= option and enumerations for
	libstdc++ and libc++.

gcc/cp/ChangeLog:

	* g++spec.c (LIBCXX, LIBCXX_PROFILE, LIBCXX_STATIC): New.
	(LIBCXXABI, LIBCXXABI_PROFILE, LIBCXXABI_STATIC): New.
	(lang_specific_driver): Allow selection amongst multiple
	c++ libraries to be added to the link command.
---
gcc/Makefile.in     |  6 +++++
gcc/c-family/c.opt  | 14 +++++++++++
gcc/config.in       |  6 +++++
gcc/configure       | 57 +++++++++++++++++++++++++++++++++++++++++++--
gcc/configure.ac    | 44 ++++++++++++++++++++++++++++++++++
gcc/cp/g++spec.c    | 53 ++++++++++++++++++++++++++++++++++++++---
gcc/cppdefault.c    |  5 ++++
gcc/doc/invoke.texi | 11 +++++++++
gcc/incpath.c       |  6 +++--
9 files changed, 195 insertions(+), 7 deletions(-)

		 that iprefix and sysroot are mutually exclusive, for
@@ -168,7 +169,8 @@ add_standard_paths (const char *sysroot, const char  
*iprefix,

  for (p = cpp_include_defaults; p->fname; p++)
    {
-      if (!p->cplusplus || cxx_stdinc)
+      if (p->cplusplus == 0
+	  || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))
	{
	  char *str;

-- 
2.24.1

Comments

Iain Sandoe Nov. 27, 2020, 8:53 p.m. | #1
Hi Folks,

this patch needs C++ review

thanks
Iain

Iain Sandoe <iain@sandoe.co.uk> wrote:

> resending - the first & second attempt didn’t seem to make it to  

> gcc-patches.

>

> Hi

>

> This option allows the user to specify alternate C++ runtime libraries,

> for example when a platform uses libc++ as the installed C++ runtime.

>

> It is the same spelling as a clang option that allows that to use  

> libstdc++.

>

> I have had this patch for some time now (more than a year) on Darwin

> branches.

>

> For Darwin [>=11] (and I expect modern FreeBSD) the fact that the installed

> C++ runtime is libc++ means conflicts can and do occur when using G++.

>

> I expect that the facility will also be useful for folks who regularly  

> try to

> ensure that GCC and clang stay compatible, it is a credit to that effort  

> that

> the replacement is pretty much “drop in”.

>

> Testing:

>

> The patch applies without regression on *darwin* and x86_64-linux-gnu.

>

> That doesn’t say much about whether it does what’s intended, of course,

> and testing in-tree is not a viable option (it would need a lot of work,  

> not

> to mention the fact that it depends on an external source base).  So I’ve

> tested this quite extensively on x86 Darwin and Linux.

>

> It’s a lot easier to use an LLVM branch >= 9 for this since there is a

> missing __cxa symbol before that (I originally used LLVM-7 for ‘reasons’).

> Since coroutines was committed to GCC we have a <coroutine> header

> where the libc++ implementation is still using the <experimental/coroutine>

> version, so that one needs to  account for this.

>

> Here’s an LLVM-9 tree with an added <coroutine> header (as an example)

> https://github.com/iains/llvm-project/tree/9.0.1-gcc-stdlib

> (in case someone wants to try this out in the near future; I don’t think  

> that

> LLVM-10 will be much different, at least the coroutine header is unchanged

> there)

>

> I’ve used this ‘in anger’ on Darwin to build a toolset which includes a  

> number

> of C++ heavy applications (e.g. LLVM, cmake, etc) and it allowed some of

> these to work effectively where it had not been possible before.

>

> One can also do an “installed test” of g++

> for that there are (a relatively modest number of) test fails.

> AFAICT, there is nothing significant there - some tests fail because the  

> output

> isn’t expecting to see libc++ __1 inline namespace, some fail because  

> libc++

> (as per current branches) doesn’t allow use with GCC + std=c++98, some

> are warning diagnostics etc.

>

> [how compatible libc++ is, is somewhat independent of the patch itself; but

> it seems “very compatible” is a starting assessment].

>

> phew… description longer than patch, it seems.

>

> OK for master?

> thanks

> Iain

>

> —— commit message

>

> This option allows the user to specify alternate C++ runtime libraries,

> for example when a platform uses libc++ as the installed C++ runtime.

>

> We introduce the command line option: -stdlib= which is the user-facing

> mechanism to select the C++ runtime to be used when compiling and linking

> code.  This is the same option spelling as that used by clang to allow the

> use of libstdc++.

>

> The availability (and thus function) of the option are a configure-time

> choice using the configuration control:

> --with-gxx-libcxx-include-dir=

>

> Specification of the path for the libc++ headers, enables the -stdlib=

> option (using the path as given), default values are set when the path

> is unconfigured.

>

> If --with-gxx-libcxx-include-dir is given together with --with-sysroot=,

> then we test to see if the include path starts with the sysroot and, if so,

> record the sysroot-relative component as the local path.  At runtime, we

> prepend the sysroot that is actually active.

>

> At link time, we use the C++ runtime in force and (if that is libc++) also

> append the libc++abi ABI library. As for other cases, if a target sets the

> name pointer for the ABI library to NULL the G++ driver will omit it from

> the link line.

>

> gcc/ChangeLog:

>

> 	* configure.ac: Add gxx-libcxx-include-dir handled

> 	in the same way as the regular cxx header directory.

> 	* Makefile.in: Regenerated.

> 	* config.in: Likewise.

> 	* configure: Likewise.

> 	* cppdefault.c: Pick up libc++ headers if the option

> 	is enabled.

> 	* incpath.c (add_standard_paths): Allow for multiple

> 	c++ header include path variants.

> 	* doc/invoke.texi: Document the -stdlib= option.

>

> gcc/c-family/ChangeLog:

>

> 	* c.opt: Add -stdlib= option and enumerations for

> 	libstdc++ and libc++.

>

> gcc/cp/ChangeLog:

>

> 	* g++spec.c (LIBCXX, LIBCXX_PROFILE, LIBCXX_STATIC): New.

> 	(LIBCXXABI, LIBCXXABI_PROFILE, LIBCXXABI_STATIC): New.

> 	(lang_specific_driver): Allow selection amongst multiple

> 	c++ libraries to be added to the link command.

> ---

> gcc/Makefile.in     |  6 +++++

> gcc/c-family/c.opt  | 14 +++++++++++

> gcc/config.in       |  6 +++++

> gcc/configure       | 57 +++++++++++++++++++++++++++++++++++++++++++--

> gcc/configure.ac    | 44 ++++++++++++++++++++++++++++++++++

> gcc/cp/g++spec.c    | 53 ++++++++++++++++++++++++++++++++++++++---

> gcc/cppdefault.c    |  5 ++++

> gcc/doc/invoke.texi | 11 +++++++++

> gcc/incpath.c       |  6 +++--

> 9 files changed, 195 insertions(+), 7 deletions(-)

>

> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt

> index fe16357db85..5fada472db1 100644

> --- a/gcc/c-family/c.opt

> +++ b/gcc/c-family/c.opt

> @@ -2269,6 +2269,20 @@ std=iso9899:2018

> C ObjC Alias(std=c17)

> Conform to the ISO 2017 C standard (published in 2018).

>

> +stdlib=

> +Driver C++ ObjC++ Common Report Condition(ENABLE_STDLIB_OPTION)  

> Var(flag_stdlib_kind) Joined Enum(stdlib_kind) RejectNegative Init(1)

> +-stdlib=[libstdc++|libc++]	The standard library to be used for C++ headers

> +and runtime.

> +

> +Enum

> +Name(stdlib_kind) Type(int)

> +

> +EnumValue

> +Enum(stdlib_kind) String(libstdc++) Value(1)

> +

> +EnumValue

> +Enum(stdlib_kind) String(libc++) Value(2)

> +

> traditional

> Driver

>

> diff --git a/gcc/configure.ac b/gcc/configure.ac

> index 73034bb902b..56b32de4c68 100644

> --- a/gcc/configure.ac

> +++ b/gcc/configure.ac

> @@ -228,6 +228,48 @@ elif test "${with_sysroot+set}" = set; then

> fi

> fi

>

> +# Configuration for an alternate set of C++ headers.

> +gcc_gxx_libcxx_include_dir=

> +# Specify the alternate g++ header file directory

> +AC_ARG_WITH(gxx-libcxx-include-dir,

> +[AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR],

> +                [specifies directory to find libc++ header files])],

> +[case "${withval}" in

> +yes)	AC_MSG_ERROR(bad value ${withval} given for libc++ include  

> directory) ;;

> +no)	;;

> +*)	gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;

> +esac])

> +

> +# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we

> +# check to see if the latter starts with the former and, upon success,  

> compute

> +# gcc_gxx_libcxx_include_dir as relative to the sysroot.

> +gcc_gxx_libcxx_include_dir_add_sysroot=0

> +

> +if test x${gcc_gxx_libcxx_include_dir} != x; then

> +  AC_DEFINE(ENABLE_STDLIB_OPTION, 1,

> +            [Define if the -stdlib= option should be enabled.])

> +else

> +  AC_DEFINE(ENABLE_STDLIB_OPTION, 0)

> +fi

> +# ??? This logic must match  

> libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.

> +if test x${gcc_gxx_libcxx_include_dir} = x; then

> +  if test x${enable_version_specific_runtime_libs} = xyes; then

> +    gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1'

> +  else

> +    libcxx_incdir='libc++_include/c++/$(version)/v1'

> +    if test x$host != x$target; then

> +       libcxx_incdir="$target_alias/$libcxx_incdir"

> +    fi

> +     

> gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir"

> +  fi

> +elif test "${with_sysroot+set}" = set; then

> +  gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" :  

> "${with_sysroot}"'\(.*\)'`

> +  if test "${gcc_gxx_libcxx_without_sysroot}"; then

> +    gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}"

> +    gcc_gxx_libcxx_include_dir_add_sysroot=1

> +  fi

> +fi

> +

> AC_ARG_WITH(cpp_install_dir,

> [AC_HELP_STRING([--with-cpp-install-dir=DIR],

>               [install the user visible C preprocessor in DIR

> @@ -6872,6 +6914,8 @@ AC_SUBST(float_h_file)

> AC_SUBST(gcc_config_arguments)

> AC_SUBST(gcc_gxx_include_dir)

> AC_SUBST(gcc_gxx_include_dir_add_sysroot)

> +AC_SUBST(gcc_gxx_libcxx_include_dir)

> +AC_SUBST(gcc_gxx_libcxx_include_dir_add_sysroot)

> AC_SUBST(host_exeext)

> AC_SUBST(host_xm_file_list)

> AC_SUBST(host_xm_include_list)

> diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c

> index 0ab63bcd211..a2f5c7d3cc7 100644

> --- a/gcc/cp/g++spec.c

> +++ b/gcc/cp/g++spec.c

> @@ -55,6 +55,26 @@ along with GCC; see the file COPYING3.  If not see

> #define LIBSTDCXX_STATIC NULL

> #endif

>

> +#ifndef LIBCXX

> +#define LIBCXX "c++"

> +#endif

> +#ifndef LIBCXX_PROFILE

> +#define LIBCXX_PROFILE LIBCXX

> +#endif

> +#ifndef LIBCXX_STATIC

> +#define LIBCXX_STATIC NULL

> +#endif

> +

> +#ifndef LIBCXXABI

> +#define LIBCXXABI "c++abi"

> +#endif

> +#ifndef LIBCXXABI_PROFILE

> +#define LIBCXXABI_PROFILE LIBCXXABI

> +#endif

> +#ifndef LIBCXXABI_STATIC

> +#define LIBCXXABI_STATIC NULL

> +#endif

> +

> void

> lang_specific_driver (struct cl_decoded_option **in_decoded_options,

> 		      unsigned int *in_decoded_options_count,

> @@ -72,6 +92,11 @@ lang_specific_driver (struct cl_decoded_option  

> **in_decoded_options,

>    2  means libstdc++ is needed and should be linked statically.  */

> int library = 0;

>

> +  /* Which standard library to link.

> +     1 = libstdc++

> +     2 = libc++.  */

> +  int which_library = 1;

> +

> /* The number of arguments being added to what's in argv, other than

>    libraries.  We use this to track the number of times we've inserted

>    -xc++/-xnone.  */

> @@ -208,6 +233,10 @@ lang_specific_driver (struct cl_decoded_option  

> **in_decoded_options,

> 	  args[i] |= SKIPOPT;

> 	  break;

>

> +	case OPT_stdlib_:

> +	  which_library = decoded_options[i].value;

> +	  break;

> +

> 	case OPT_SPECIAL_input_file:

> 	  {

> 	    int len;

> @@ -264,6 +293,8 @@ lang_specific_driver (struct cl_decoded_option  

> **in_decoded_options,

>

> /* Add one for shared_libgcc or extra static library.  */

> num_args = argc + added + need_math + (library > 0) * 4 + 1;

> +  if (which_library > 1 && LIBCXXABI != NULL)

> +    num_args += 4;

> new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);

>

> i = 0;

> @@ -343,9 +374,25 @@ lang_specific_driver (struct cl_decoded_option  

> **in_decoded_options,

> 	  j++;

> 	}

> #endif

> -      generate_option (OPT_l,

> -		       saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,

> -		       CL_DRIVER, &new_decoded_options[j]);

> +      if (which_library == 2)

> +	{

> +	  generate_option (OPT_l,

> +			 saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1,

> +			 CL_DRIVER, &new_decoded_options[j]);

> +	  if (LIBCXXABI != NULL)

> +	    {

> +	      j++;

> +	      added_libraries++;

> +	      generate_option (OPT_l,

> +			       saw_profile_flag ? LIBCXXABI_PROFILE

> +						: LIBCXXABI, 1,

> +			       CL_DRIVER, &new_decoded_options[j]);

> +	    }

> +	}

> +      else

> +	generate_option (OPT_l,

> +			 saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,

> +			 CL_DRIVER, &new_decoded_options[j]);

>     added_libraries++;

>     j++;

>     /* Add target-dependent static library, if necessary.  */

> diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c

> index af38cc494ea..eb6f94162cd 100644

> --- a/gcc/cppdefault.c

> +++ b/gcc/cppdefault.c

> @@ -55,6 +55,11 @@ const struct default_include cpp_include_defaults[]

>   { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1,

>     GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },

> #endif

> +#ifdef GPLUSPLUS_LIBCXX_INCLUDE_DIR

> +    /* Pick up libc++ include files, if we have -stdlib=libc++.  */

> +    { GPLUSPLUS_LIBCXX_INCLUDE_DIR, "G++", 2, 1,

> +      GPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT, 0 },

> +#endif

> #ifdef GCC_INCLUDE_DIR

>   /* This is the dir for gcc's private headers.  */

>   { GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 },

> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi

> index 8d0d2136831..a14a25c330f 100644

> --- a/gcc/doc/invoke.texi

> +++ b/gcc/doc/invoke.texi

> @@ -233,6 +233,7 @@ in the following sections.

> -fvisibility-inlines-hidden @gol

> -fvisibility-ms-compat @gol

> -fext-numeric-literals @gol

> +-stdlib=@var{libstdc++,libc++} @gol

> -Wabi-tag  -Wcatch-value  -Wcatch-value=@var{n} @gol

> -Wno-class-conversion  -Wclass-memaccess @gol

> -Wcomma-subscript  -Wconditionally-supported @gol

> @@ -3285,6 +3286,16 @@ for ISO C++11 onwards (@option{-std=c++11}, ...).

> Do not search for header files in the standard directories specific to

> C++, but do still search the other standard directories.  (This option

> is used when building the C++ library.)

> +

> +@item -stdlib=@var{libstdc++,libc++}

> +@opindex stdlib

> +When G++ is configured to support this option, it allows specification of

> +alternate C++ runtime libraries.  Two options are available:  

> @var{libstdc++}

> +(the default, native C++ runtime for G++) and @var{libc++} which is the

> +C++ runtime installed on some operating systems (e.g. Darwin versions from

> +Darwin11 onwards).  The option switches G++ to use the headers from the

> +specified library and to emit @code{-lstdc++} or @code{-lc++}  

> respectively,

> +when a C++ runtime is required for linking.

> @end table

>

> In addition, these warning options have meanings only for C++ programs:

> diff --git a/gcc/incpath.c b/gcc/incpath.c

> index 8437939bf1e..14593a1f4c3 100644

> --- a/gcc/incpath.c

> +++ b/gcc/incpath.c

> @@ -137,7 +137,8 @@ add_standard_paths (const char *sysroot, const char  

> *iprefix,

> 	 IPREFIX and search them first.  */

>     for (p = cpp_include_defaults; p->fname; p++)

> 	{

> -	  if (!p->cplusplus || cxx_stdinc)

> +	  if (p->cplusplus == 0

> +	      || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))

> 	    {

> 	      /* Should we be translating sysrooted dirs too?  Assume

> 		 that iprefix and sysroot are mutually exclusive, for

> @@ -168,7 +169,8 @@ add_standard_paths (const char *sysroot, const char  

> *iprefix,

>

> for (p = cpp_include_defaults; p->fname; p++)

>   {

> -      if (!p->cplusplus || cxx_stdinc)

> +      if (p->cplusplus == 0

> +	  || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))

> 	{

> 	  char *str;

>

> -- 

> 2.24.1
Xionghu Luo via Gcc-patches Dec. 9, 2020, 6:44 p.m. | #2
On 11/11/20 3:58 PM, Iain Sandoe wrote:
> resending - the first & second attempt didn’t seem to make it to 

> gcc-patches.

> 

> Hi

> 

> This option allows the user to specify alternate C++ runtime libraries,

> for example when a platform uses libc++ as the installed C++ runtime.

> 

> It is the same spelling as a clang option that allows that to use 

> libstdc++.

> 

> I have had this patch for some time now (more than a year) on Darwin

> branches.

> 

> For Darwin [>=11] (and I expect modern FreeBSD) the fact that the installed

> C++ runtime is libc++ means conflicts can and do occur when using G++.

> 

> I expect that the facility will also be useful for folks who regularly 

> try to

> ensure that GCC and clang stay compatible, it is a credit to that effort 

> that

> the replacement is pretty much “drop in”.

> 

> Testing:

> 

> The patch applies without regression on *darwin* and x86_64-linux-gnu.

> 

> That doesn’t say much about whether it does what’s intended, of course,

> and testing in-tree is not a viable option (it would need a lot of work, 

> not

> to mention the fact that it depends on an external source base).  So I’ve

> tested this quite extensively on x86 Darwin and Linux.

> 

> It’s a lot easier to use an LLVM branch >= 9 for this since there is a

> missing __cxa symbol before that (I originally used LLVM-7 for ‘reasons’).

> Since coroutines was committed to GCC we have a <coroutine> header

> where the libc++ implementation is still using the <experimental/coroutine>

> version, so that one needs to  account for this.

> 

> Here’s an LLVM-9 tree with an added <coroutine> header (as an example)

> https://github.com/iains/llvm-project/tree/9.0.1-gcc-stdlib

> (in case someone wants to try this out in the near future; I don’t think 

> that

> LLVM-10 will be much different, at least the coroutine header is unchanged

> there)

> 

> I’ve used this ‘in anger’ on Darwin to build a toolset which includes a 

> number

> of C++ heavy applications (e.g. LLVM, cmake, etc) and it allowed some of

> these to work effectively where it had not been possible before.

> 

> One can also do an “installed test” of g++

> for that there are (a relatively modest number of) test fails.

> AFAICT, there is nothing significant there - some tests fail because the 

> output

> isn’t expecting to see libc++ __1 inline namespace, some fail because 

> libc++

> (as per current branches) doesn’t allow use with GCC + std=c++98, some

> are warning diagnostics etc.

> 

> [how compatible libc++ is, is somewhat independent of the patch itself; but

> it seems “very compatible” is a starting assessment].

> 

> phew… description longer than patch, it seems.

> 

> OK for master?

> thanks

> Iain

> 

> —— commit message

> 

> This option allows the user to specify alternate C++ runtime libraries,

> for example when a platform uses libc++ as the installed C++ runtime.

> 

> We introduce the command line option: -stdlib= which is the user-facing

> mechanism to select the C++ runtime to be used when compiling and linking

> code.  This is the same option spelling as that used by clang to allow the

> use of libstdc++.

> 

> The availability (and thus function) of the option are a configure-time

> choice using the configuration control:

> --with-gxx-libcxx-include-dir=

> 

> Specification of the path for the libc++ headers, enables the -stdlib=

> option (using the path as given), default values are set when the path

> is unconfigured.

> 

> If --with-gxx-libcxx-include-dir is given together with --with-sysroot=,

> then we test to see if the include path starts with the sysroot and, if so,

> record the sysroot-relative component as the local path.  At runtime, we

> prepend the sysroot that is actually active.

> 

> At link time, we use the C++ runtime in force and (if that is libc++) also

> append the libc++abi ABI library. As for other cases, if a target sets the

> name pointer for the ABI library to NULL the G++ driver will omit it from

> the link line.

> 

> gcc/ChangeLog:

> 

>      * configure.ac: Add gxx-libcxx-include-dir handled

>      in the same way as the regular cxx header directory.

>      * Makefile.in: Regenerated.

>      * config.in: Likewise.

>      * configure: Likewise.

>      * cppdefault.c: Pick up libc++ headers if the option

>      is enabled.

>      * incpath.c (add_standard_paths): Allow for multiple

>      c++ header include path variants.

>      * doc/invoke.texi: Document the -stdlib= option.

> 

> gcc/c-family/ChangeLog:

> 

>      * c.opt: Add -stdlib= option and enumerations for

>      libstdc++ and libc++.

> 

> gcc/cp/ChangeLog:

> 

>      * g++spec.c (LIBCXX, LIBCXX_PROFILE, LIBCXX_STATIC): New.

>      (LIBCXXABI, LIBCXXABI_PROFILE, LIBCXXABI_STATIC): New.

>      (lang_specific_driver): Allow selection amongst multiple

>      c++ libraries to be added to the link command.

> ---

> gcc/Makefile.in     |  6 +++++

> gcc/c-family/c.opt  | 14 +++++++++++

> gcc/config.in       |  6 +++++

> gcc/configure       | 57 +++++++++++++++++++++++++++++++++++++++++++--

> gcc/configure.ac    | 44 ++++++++++++++++++++++++++++++++++

> gcc/cp/g++spec.c    | 53 ++++++++++++++++++++++++++++++++++++++---

> gcc/cppdefault.c    |  5 ++++

> gcc/doc/invoke.texi | 11 +++++++++

> gcc/incpath.c       |  6 +++--

> 9 files changed, 195 insertions(+), 7 deletions(-)

> 

> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt

> index fe16357db85..5fada472db1 100644

> --- a/gcc/c-family/c.opt

> +++ b/gcc/c-family/c.opt

> @@ -2269,6 +2269,20 @@ std=iso9899:2018

> C ObjC Alias(std=c17)

> Conform to the ISO 2017 C standard (published in 2018).

> 

> +stdlib=

> +Driver C++ ObjC++ Common Report Condition(ENABLE_STDLIB_OPTION) 

> Var(flag_stdlib_kind) Joined Enum(stdlib_kind) RejectNegative Init(1)

> +-stdlib=[libstdc++|libc++]    The standard library to be used for C++ 

> headers

> +and runtime.

> +

> +Enum

> +Name(stdlib_kind) Type(int)

> +

> +EnumValue

> +Enum(stdlib_kind) String(libstdc++) Value(1)

> +

> +EnumValue

> +Enum(stdlib_kind) String(libc++) Value(2)

> +

> traditional

> Driver

> 

> diff --git a/gcc/configure.ac b/gcc/configure.ac

> index 73034bb902b..56b32de4c68 100644

> --- a/gcc/configure.ac

> +++ b/gcc/configure.ac

> @@ -228,6 +228,48 @@ elif test "${with_sysroot+set}" = set; then

>   fi

> fi

> 

> +# Configuration for an alternate set of C++ headers.

> +gcc_gxx_libcxx_include_dir=

> +# Specify the alternate g++ header file directory

> +AC_ARG_WITH(gxx-libcxx-include-dir,

> +[AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR],

> +                [specifies directory to find libc++ header files])],

> +[case "${withval}" in

> +yes)    AC_MSG_ERROR(bad value ${withval} given for libc++ include 

> directory) ;;

> +no)    ;;

> +*)    gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;

> +esac])

> +

> +# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we

> +# check to see if the latter starts with the former and, upon success, 

> compute

> +# gcc_gxx_libcxx_include_dir as relative to the sysroot.

> +gcc_gxx_libcxx_include_dir_add_sysroot=0

> +

> +if test x${gcc_gxx_libcxx_include_dir} != x; then

> +  AC_DEFINE(ENABLE_STDLIB_OPTION, 1,

> +            [Define if the -stdlib= option should be enabled.])

> +else

> +  AC_DEFINE(ENABLE_STDLIB_OPTION, 0)

> +fi

> +# ??? This logic must match 

> libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.

> +if test x${gcc_gxx_libcxx_include_dir} = x; then

> +  if test x${enable_version_specific_runtime_libs} = xyes; then

> +    gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1'

> +  else

> +    libcxx_incdir='libc++_include/c++/$(version)/v1'

> +    if test x$host != x$target; then

> +       libcxx_incdir="$target_alias/$libcxx_incdir"

> +    fi

> +    

> gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir" 

> 

> +  fi

> +elif test "${with_sysroot+set}" = set; then

> +  gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" 

> : "${with_sysroot}"'\(.*\)'`

> +  if test "${gcc_gxx_libcxx_without_sysroot}"; then

> +    gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}"

> +    gcc_gxx_libcxx_include_dir_add_sysroot=1

> +  fi

> +fi

> +

> AC_ARG_WITH(cpp_install_dir,

> [AC_HELP_STRING([--with-cpp-install-dir=DIR],

>                 [install the user visible C preprocessor in DIR

> @@ -6872,6 +6914,8 @@ AC_SUBST(float_h_file)

> AC_SUBST(gcc_config_arguments)

> AC_SUBST(gcc_gxx_include_dir)

> AC_SUBST(gcc_gxx_include_dir_add_sysroot)

> +AC_SUBST(gcc_gxx_libcxx_include_dir)

> +AC_SUBST(gcc_gxx_libcxx_include_dir_add_sysroot)

> AC_SUBST(host_exeext)

> AC_SUBST(host_xm_file_list)

> AC_SUBST(host_xm_include_list)

> diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c

> index 0ab63bcd211..a2f5c7d3cc7 100644

> --- a/gcc/cp/g++spec.c

> +++ b/gcc/cp/g++spec.c

> @@ -55,6 +55,26 @@ along with GCC; see the file COPYING3.  If not see

> #define LIBSTDCXX_STATIC NULL

> #endif

> 

> +#ifndef LIBCXX

> +#define LIBCXX "c++"

> +#endif

> +#ifndef LIBCXX_PROFILE

> +#define LIBCXX_PROFILE LIBCXX

> +#endif

> +#ifndef LIBCXX_STATIC

> +#define LIBCXX_STATIC NULL

> +#endif

> +

> +#ifndef LIBCXXABI

> +#define LIBCXXABI "c++abi"

> +#endif

> +#ifndef LIBCXXABI_PROFILE

> +#define LIBCXXABI_PROFILE LIBCXXABI

> +#endif

> +#ifndef LIBCXXABI_STATIC

> +#define LIBCXXABI_STATIC NULL

> +#endif

> +

> void

> lang_specific_driver (struct cl_decoded_option **in_decoded_options,

>                unsigned int *in_decoded_options_count,

> @@ -72,6 +92,11 @@ lang_specific_driver (struct cl_decoded_option 

> **in_decoded_options,

>      2  means libstdc++ is needed and should be linked statically.  */

>   int library = 0;

> 

> +  /* Which standard library to link.

> +     1 = libstdc++

> +     2 = libc++.  */

> +  int which_library = 1;


Even if this variable is an int, let's introduce an enum for comparing 
it to specific values.

> +

>   /* The number of arguments being added to what's in argv, other than

>      libraries.  We use this to track the number of times we've inserted

>      -xc++/-xnone.  */

> @@ -208,6 +233,10 @@ lang_specific_driver (struct cl_decoded_option 

> **in_decoded_options,

>        args[i] |= SKIPOPT;

>        break;

> 

> +    case OPT_stdlib_:

> +      which_library = decoded_options[i].value;

> +      break;

> +

>      case OPT_SPECIAL_input_file:

>        {

>          int len;

> @@ -264,6 +293,8 @@ lang_specific_driver (struct cl_decoded_option 

> **in_decoded_options,

> 

>   /* Add one for shared_libgcc or extra static library.  */

>   num_args = argc + added + need_math + (library > 0) * 4 + 1;

> +  if (which_library > 1 && LIBCXXABI != NULL)

> +    num_args += 4;


Why does libc++ need more args than libstdc++?  Please add a comment.

>   new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);

> 

>   i = 0;

> @@ -343,9 +374,25 @@ lang_specific_driver (struct cl_decoded_option 

> **in_decoded_options,

>        j++;

>      }

> #endif

> -      generate_option (OPT_l,

> -               saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,

> -               CL_DRIVER, &new_decoded_options[j]);

> +      if (which_library == 2)

> +    {

> +      generate_option (OPT_l,

> +             saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1,

> +             CL_DRIVER, &new_decoded_options[j]);

> +      if (LIBCXXABI != NULL)

> +        {

> +          j++;

> +          added_libraries++;

> +          generate_option (OPT_l,

> +                   saw_profile_flag ? LIBCXXABI_PROFILE

> +                        : LIBCXXABI, 1,

> +                   CL_DRIVER, &new_decoded_options[j]);

> +        }

> +    }

> +      else

> +    generate_option (OPT_l,

> +             saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,

> +             CL_DRIVER, &new_decoded_options[j]);

>       added_libraries++;

>       j++;

>       /* Add target-dependent static library, if necessary.  */

> diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c

> index af38cc494ea..eb6f94162cd 100644

> --- a/gcc/cppdefault.c

> +++ b/gcc/cppdefault.c

> @@ -55,6 +55,11 @@ const struct default_include cpp_include_defaults[]

>     { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1,

>       GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },

> #endif

> +#ifdef GPLUSPLUS_LIBCXX_INCLUDE_DIR

> +    /* Pick up libc++ include files, if we have -stdlib=libc++.  */

> +    { GPLUSPLUS_LIBCXX_INCLUDE_DIR, "G++", 2, 1,


If you're going to give cplusplus a non-boolean value, the comment in 
cppdefault.h needs to reflect that.

> +      GPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT, 0 },

> +#endif

> #ifdef GCC_INCLUDE_DIR

>     /* This is the dir for gcc's private headers.  */

>     { GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 },

> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi

> index 8d0d2136831..a14a25c330f 100644

> --- a/gcc/doc/invoke.texi

> +++ b/gcc/doc/invoke.texi

> @@ -233,6 +233,7 @@ in the following sections.

> -fvisibility-inlines-hidden @gol

> -fvisibility-ms-compat @gol

> -fext-numeric-literals @gol

> +-stdlib=@var{libstdc++,libc++} @gol

> -Wabi-tag  -Wcatch-value  -Wcatch-value=@var{n} @gol

> -Wno-class-conversion  -Wclass-memaccess @gol

> -Wcomma-subscript  -Wconditionally-supported @gol

> @@ -3285,6 +3286,16 @@ for ISO C++11 onwards (@option{-std=c++11}, ...).

> Do not search for header files in the standard directories specific to

> C++, but do still search the other standard directories.  (This option

> is used when building the C++ library.)

> +

> +@item -stdlib=@var{libstdc++,libc++}

> +@opindex stdlib

> +When G++ is configured to support this option, it allows specification of

> +alternate C++ runtime libraries.  Two options are available: 

> @var{libstdc++}

> +(the default, native C++ runtime for G++) and @var{libc++} which is the

> +C++ runtime installed on some operating systems (e.g. Darwin versions from

> +Darwin11 onwards).  The option switches G++ to use the headers from the

> +specified library and to emit @code{-lstdc++} or @code{-lc++} 

> respectively,

> +when a C++ runtime is required for linking.

> @end table

> 

> In addition, these warning options have meanings only for C++ programs:

> diff --git a/gcc/incpath.c b/gcc/incpath.c

> index 8437939bf1e..14593a1f4c3 100644

> --- a/gcc/incpath.c

> +++ b/gcc/incpath.c

> @@ -137,7 +137,8 @@ add_standard_paths (const char *sysroot, const char 

> *iprefix,

>       IPREFIX and search them first.  */

>       for (p = cpp_include_defaults; p->fname; p++)

>      {

> -      if (!p->cplusplus || cxx_stdinc)

> +      if (p->cplusplus == 0

> +          || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))

>          {

>            /* Should we be translating sysrooted dirs too?  Assume

>           that iprefix and sysroot are mutually exclusive, for

> @@ -168,7 +169,8 @@ add_standard_paths (const char *sysroot, const char 

> *iprefix,

> 

>   for (p = cpp_include_defaults; p->fname; p++)

>     {

> -      if (!p->cplusplus || cxx_stdinc)

> +      if (p->cplusplus == 0

> +      || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))

>      {

>        char *str;

>

Patch

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index fe16357db85..5fada472db1 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -2269,6 +2269,20 @@  std=iso9899:2018
C ObjC Alias(std=c17)
Conform to the ISO 2017 C standard (published in 2018).

+stdlib=
+Driver C++ ObjC++ Common Report Condition(ENABLE_STDLIB_OPTION)  
Var(flag_stdlib_kind) Joined Enum(stdlib_kind) RejectNegative Init(1)
+-stdlib=[libstdc++|libc++]	The standard library to be used for C++ headers
+and runtime.
+
+Enum
+Name(stdlib_kind) Type(int)
+
+EnumValue
+Enum(stdlib_kind) String(libstdc++) Value(1)
+
+EnumValue
+Enum(stdlib_kind) String(libc++) Value(2)
+
traditional
Driver

diff --git a/gcc/configure.ac b/gcc/configure.ac
index 73034bb902b..56b32de4c68 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -228,6 +228,48 @@  elif test "${with_sysroot+set}" = set; then
  fi
fi

+# Configuration for an alternate set of C++ headers.
+gcc_gxx_libcxx_include_dir=
+# Specify the alternate g++ header file directory
+AC_ARG_WITH(gxx-libcxx-include-dir,
+[AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR],
+                [specifies directory to find libc++ header files])],
+[case "${withval}" in
+yes)	AC_MSG_ERROR(bad value ${withval} given for libc++ include  
directory) ;;
+no)	;;
+*)	gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
+esac])
+
+# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we
+# check to see if the latter starts with the former and, upon success,  
compute
+# gcc_gxx_libcxx_include_dir as relative to the sysroot.
+gcc_gxx_libcxx_include_dir_add_sysroot=0
+
+if test x${gcc_gxx_libcxx_include_dir} != x; then
+  AC_DEFINE(ENABLE_STDLIB_OPTION, 1,
+            [Define if the -stdlib= option should be enabled.])
+else
+  AC_DEFINE(ENABLE_STDLIB_OPTION, 0)
+fi
+# ??? This logic must match  
libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.
+if test x${gcc_gxx_libcxx_include_dir} = x; then
+  if test x${enable_version_specific_runtime_libs} = xyes; then
+    gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1'
+  else
+    libcxx_incdir='libc++_include/c++/$(version)/v1'
+    if test x$host != x$target; then
+       libcxx_incdir="$target_alias/$libcxx_incdir"
+    fi
+     
gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir"
+  fi
+elif test "${with_sysroot+set}" = set; then
+  gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" :  
"${with_sysroot}"'\(.*\)'`
+  if test "${gcc_gxx_libcxx_without_sysroot}"; then
+    gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}"
+    gcc_gxx_libcxx_include_dir_add_sysroot=1
+  fi
+fi
+
AC_ARG_WITH(cpp_install_dir,
[AC_HELP_STRING([--with-cpp-install-dir=DIR],
                [install the user visible C preprocessor in DIR
@@ -6872,6 +6914,8 @@  AC_SUBST(float_h_file)
AC_SUBST(gcc_config_arguments)
AC_SUBST(gcc_gxx_include_dir)
AC_SUBST(gcc_gxx_include_dir_add_sysroot)
+AC_SUBST(gcc_gxx_libcxx_include_dir)
+AC_SUBST(gcc_gxx_libcxx_include_dir_add_sysroot)
AC_SUBST(host_exeext)
AC_SUBST(host_xm_file_list)
AC_SUBST(host_xm_include_list)
diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c
index 0ab63bcd211..a2f5c7d3cc7 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -55,6 +55,26 @@  along with GCC; see the file COPYING3.  If not see
#define LIBSTDCXX_STATIC NULL
#endif

+#ifndef LIBCXX
+#define LIBCXX "c++"
+#endif
+#ifndef LIBCXX_PROFILE
+#define LIBCXX_PROFILE LIBCXX
+#endif
+#ifndef LIBCXX_STATIC
+#define LIBCXX_STATIC NULL
+#endif
+
+#ifndef LIBCXXABI
+#define LIBCXXABI "c++abi"
+#endif
+#ifndef LIBCXXABI_PROFILE
+#define LIBCXXABI_PROFILE LIBCXXABI
+#endif
+#ifndef LIBCXXABI_STATIC
+#define LIBCXXABI_STATIC NULL
+#endif
+
void
lang_specific_driver (struct cl_decoded_option **in_decoded_options,
		      unsigned int *in_decoded_options_count,
@@ -72,6 +92,11 @@  lang_specific_driver (struct cl_decoded_option  
**in_decoded_options,
     2  means libstdc++ is needed and should be linked statically.  */
  int library = 0;

+  /* Which standard library to link.
+     1 = libstdc++
+     2 = libc++.  */
+  int which_library = 1;
+
  /* The number of arguments being added to what's in argv, other than
     libraries.  We use this to track the number of times we've inserted
     -xc++/-xnone.  */
@@ -208,6 +233,10 @@  lang_specific_driver (struct cl_decoded_option  
**in_decoded_options,
	  args[i] |= SKIPOPT;
	  break;

+	case OPT_stdlib_:
+	  which_library = decoded_options[i].value;
+	  break;
+
	case OPT_SPECIAL_input_file:
	  {
	    int len;
@@ -264,6 +293,8 @@  lang_specific_driver (struct cl_decoded_option  
**in_decoded_options,

  /* Add one for shared_libgcc or extra static library.  */
  num_args = argc + added + need_math + (library > 0) * 4 + 1;
+  if (which_library > 1 && LIBCXXABI != NULL)
+    num_args += 4;
  new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);

  i = 0;
@@ -343,9 +374,25 @@  lang_specific_driver (struct cl_decoded_option  
**in_decoded_options,
	  j++;
	}
#endif
-      generate_option (OPT_l,
-		       saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,
-		       CL_DRIVER, &new_decoded_options[j]);
+      if (which_library == 2)
+	{
+	  generate_option (OPT_l,
+			 saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1,
+			 CL_DRIVER, &new_decoded_options[j]);
+	  if (LIBCXXABI != NULL)
+	    {
+	      j++;
+	      added_libraries++;
+	      generate_option (OPT_l,
+			       saw_profile_flag ? LIBCXXABI_PROFILE
+						: LIBCXXABI, 1,
+			       CL_DRIVER, &new_decoded_options[j]);
+	    }
+	}
+      else
+	generate_option (OPT_l,
+			 saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,
+			 CL_DRIVER, &new_decoded_options[j]);
      added_libraries++;
      j++;
      /* Add target-dependent static library, if necessary.  */
diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c
index af38cc494ea..eb6f94162cd 100644
--- a/gcc/cppdefault.c
+++ b/gcc/cppdefault.c
@@ -55,6 +55,11 @@  const struct default_include cpp_include_defaults[]
    { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1,
      GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },
#endif
+#ifdef GPLUSPLUS_LIBCXX_INCLUDE_DIR
+    /* Pick up libc++ include files, if we have -stdlib=libc++.  */
+    { GPLUSPLUS_LIBCXX_INCLUDE_DIR, "G++", 2, 1,
+      GPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT, 0 },
+#endif
#ifdef GCC_INCLUDE_DIR
    /* This is the dir for gcc's private headers.  */
    { GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 },
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8d0d2136831..a14a25c330f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -233,6 +233,7 @@  in the following sections.
-fvisibility-inlines-hidden @gol
-fvisibility-ms-compat @gol
-fext-numeric-literals @gol
+-stdlib=@var{libstdc++,libc++} @gol
-Wabi-tag  -Wcatch-value  -Wcatch-value=@var{n} @gol
-Wno-class-conversion  -Wclass-memaccess @gol
-Wcomma-subscript  -Wconditionally-supported @gol
@@ -3285,6 +3286,16 @@  for ISO C++11 onwards (@option{-std=c++11}, ...).
Do not search for header files in the standard directories specific to
C++, but do still search the other standard directories.  (This option
is used when building the C++ library.)
+
+@item -stdlib=@var{libstdc++,libc++}
+@opindex stdlib
+When G++ is configured to support this option, it allows specification of
+alternate C++ runtime libraries.  Two options are available: @var{libstdc++}
+(the default, native C++ runtime for G++) and @var{libc++} which is the
+C++ runtime installed on some operating systems (e.g. Darwin versions from
+Darwin11 onwards).  The option switches G++ to use the headers from the
+specified library and to emit @code{-lstdc++} or @code{-lc++} respectively,
+when a C++ runtime is required for linking.
@end table

In addition, these warning options have meanings only for C++ programs:
diff --git a/gcc/incpath.c b/gcc/incpath.c
index 8437939bf1e..14593a1f4c3 100644
--- a/gcc/incpath.c
+++ b/gcc/incpath.c
@@ -137,7 +137,8 @@  add_standard_paths (const char *sysroot, const char  
*iprefix,
	 IPREFIX and search them first.  */
      for (p = cpp_include_defaults; p->fname; p++)
	{
-	  if (!p->cplusplus || cxx_stdinc)
+	  if (p->cplusplus == 0
+	      || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))
	    {
	      /* Should we be translating sysrooted dirs too?  Assume