[v2] C++ : Add the -stdlib= option.

Message ID FE07E514-2D96-467A-A6AC-F1BB11FCF953@sandoe.co.uk
State New
Headers show
Series
  • [v2] C++ : Add the -stdlib= option.
Related show

Commit Message

Iain Sandoe Dec. 22, 2020, 8:39 p.m.
Hi Jason,

Jason Merrill <jason@redhat.com> wrote:

> On 11/11/20 3:58 PM, Iain Sandoe wrote:


>> 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.

>> 


>> +  /* 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.


done - it is also noted that it must track the enum in the opt file.

>> @@ -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.


done (JFTR, it’s because libc++ doesn’t include the abi library for most platforms, so that also has to be
appended to the link line).

>> +#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.


done.

(re-)tested on x86_64-darwin{11,16,17,19, 20} with the installed libc++ and x86_64-linux-gnu with an
LLVM-9 build.  Bootstrapped and smoke-tested for libc++ (regular testing for libstdc++).

OK for master now?
thanks
Iain

-- 
2.24.1

Comments

Andrew Pinski via Gcc-patches Dec. 22, 2020, 8:53 p.m. | #1
On 12/22/20 3:39 PM, Iain Sandoe wrote:
> Hi Jason,

> 

> Jason Merrill <jason@redhat.com> wrote:

> 

>> On 11/11/20 3:58 PM, Iain Sandoe wrote:

> 

>>> 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.

>>>

> 

>>> +  /* 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.

> 

> done - it is also noted that it must track the enum in the opt file.

> 

>>> @@ -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.

> 

> done (JFTR, it’s because libc++ doesn’t include the abi library for most platforms, so that also has to be

> appended to the link line).

> 

>>> +#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.

> 

> done.

> 

> (re-)tested on x86_64-darwin{11,16,17,19, 20} with the installed libc++ and x86_64-linux-gnu with an

> LLVM-9 build.  Bootstrapped and smoke-tested for libc++ (regular testing for libstdc++).

> 

> OK for master now?


OK.

> thanks

> Iain

> 

> ==== revised patch

> 

> 

> This option allows the user to specifiy 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.

> 	* cppdefault.h (struct default_include): Amend comments

> 	to reflect the extended use of the cplusplus field.

> 	* 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.

> 	(enum stdcxxlib_kind): New.

> 	(lang_specific_driver): Allow selection amongst multiple

> 	c++ runtime libraries.

> ---

>   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    | 74 ++++++++++++++++++++++++++++++++++++++++-----

>   gcc/cppdefault.c    |  5 +++

>   gcc/cppdefault.h    |  7 ++++-

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

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

>   10 files changed, 216 insertions(+), 13 deletions(-)

> 

> diff --git a/gcc/Makefile.in b/gcc/Makefile.in

> index 178e4eaa513..6847022f108 100644

> --- a/gcc/Makefile.in

> +++ b/gcc/Makefile.in

> @@ -679,6 +679,9 @@ build_tooldir = $(exec_prefix)/$(target_noncanonical)

>   # Directory in which the compiler finds target-independent g++ includes.

>   gcc_gxx_include_dir = @gcc_gxx_include_dir@

>   gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@

> +# Directory in which the compiler finds libc++ includes.

> +gcc_gxx_libcxx_include_dir = @gcc_gxx_libcxx_include_dir@

> +gcc_gxx_libcxx_include_dir_add_sysroot = @gcc_gxx_libcxx_include_dir_add_sysroot@

>   # Directory to search for site-specific includes.

>   local_includedir = $(local_prefix)/include

>   includedir = $(prefix)/include

> @@ -1185,6 +1188,7 @@ FLAGS_TO_PASS = \

>   	"prefix=$(prefix)" \

>   	"local_prefix=$(local_prefix)" \

>   	"gxx_include_dir=$(gcc_gxx_include_dir)" \

> +	"gxx_libcxx_include_dir=$(gcc_gxx_libcxx_include_dir)" \

>   	"build_tooldir=$(build_tooldir)" \

>   	"gcc_tooldir=$(gcc_tooldir)" \

>   	"bindir=$(bindir)" \

> @@ -3004,6 +3008,8 @@ PREPROCESSOR_DEFINES = \

>     -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \

>     -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \

>     -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \

> +  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"$(gcc_gxx_libcxx_include_dir)\" \

> +  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_libcxx_include_dir_add_sysroot) \

>     -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \

>     -DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \

>     -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \

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

> index 21d8cd03709..e0c322f61ae 100644

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

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

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

>   C ObjC Alias(std=c17)

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

>   

> +stdlib=

> +Driver C++ ObjC++ Common 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/config.in b/gcc/config.in

> index 216505abd2c..10a13cde586 100644

> --- a/gcc/config.in

> +++ b/gcc/config.in

> @@ -240,6 +240,12 @@

>      standards-compatible mode on s390 targets. */

>   #undef ENABLE_S390_EXCESS_FLOAT_PRECISION

>   

> +/* Define if the -stdlib= option should be enabled. */

> +#ifndef USED_FOR_TARGET

> +#undef ENABLE_STDLIB_OPTION

> +#endif

> +

> +

>   /* Define if you want all operations on trees (the basic data structure of the

>      front ends) to be checked for dynamic type safety at runtime. This is

>      moderately expensive. */

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

> index fbe92089640..ee9760354b6 100755

> --- a/gcc/configure

> +++ b/gcc/configure

> @@ -675,6 +675,8 @@ host_xm_defines

>   host_xm_include_list

>   host_xm_file_list

>   host_exeext

> +gcc_gxx_libcxx_include_dir_add_sysroot

> +gcc_gxx_libcxx_include_dir

>   gcc_gxx_include_dir_add_sysroot

>   gcc_gxx_include_dir

>   gcc_config_arguments

> @@ -937,6 +939,7 @@ with_native_system_header_dir

>   with_build_sysroot

>   with_sysroot

>   with_gxx_include_dir

> +with_gxx_libcxx_include_dir

>   with_cpp_install_dir

>   enable_generated_files_in_srcdir

>   with_gnu_ld

> @@ -1801,6 +1804,8 @@ Optional Packages:

>     --with-sysroot[=DIR]    search for usr/lib, usr/include, et al, within DIR

>     --with-gxx-include-dir=DIR

>                             specifies directory to put g++ header files

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

> +                          specifies directory to find libc++ header files

>     --with-cpp-install-dir=DIR

>                             install the user visible C preprocessor in DIR

>                             (relative to PREFIX) as well as PREFIX/bin

> @@ -3731,6 +3736,52 @@ 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

> +

> +# Check whether --with-gxx-libcxx-include-dir was given.

> +if test "${with_gxx_libcxx_include_dir+set}" = set; then :

> +  withval=$with_gxx_libcxx_include_dir; case "${withval}" in

> +yes)	as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;

> +no)	;;

> +*)	gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;

> +esac

> +fi

> +

> +

> +# 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

> +

> +$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h

> +

> +else

> +  $as_echo "#define ENABLE_STDLIB_OPTION 0" >>confdefs.h

> +

> +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

> +

>   

>   # Check whether --with-cpp_install_dir was given.

>   if test "${with_cpp_install_dir+set}" = set; then :

> @@ -19186,7 +19237,7 @@ else

>     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2

>     lt_status=$lt_dlunknown

>     cat > conftest.$ac_ext <<_LT_EOF

> -#line 19189 "configure"

> +#line 19240 "configure"

>   #include "confdefs.h"

>   

>   #if HAVE_DLFCN_H

> @@ -19292,7 +19343,7 @@ else

>     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2

>     lt_status=$lt_dlunknown

>     cat > conftest.$ac_ext <<_LT_EOF

> -#line 19295 "configure"

> +#line 19346 "configure"

>   #include "confdefs.h"

>   

>   #if HAVE_DLFCN_H

> @@ -31175,6 +31226,8 @@ fi

>   

>   

>   

> +

> +

>   

>   

>   

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

> index 89b9981e872..6fcf154d987 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

> @@ -7096,6 +7138,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 0f17148ccbd..a8254cd34c9 100644

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

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

> @@ -49,6 +49,34 @@ 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

> +

> +/* The values used here must match those of the stdlib_kind enumeration

> +   in c.opt.  */

> +enum stdcxxlib_kind

> +{

> +  USE_LIBSTDCXX = 1,

> +  USE_LIBCXX = 2

> +};

> +

>   void

>   lang_specific_driver (struct cl_decoded_option **in_decoded_options,

>   		      unsigned int *in_decoded_options_count,

> @@ -59,13 +87,16 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,

>     /* If nonzero, the user gave us the `-p' or `-pg' flag.  */

>     int saw_profile_flag = 0;

>   

> -  /* What do with libstdc++:

> -     -1 means we should not link in libstdc++

> -     0  means we should link in libstdc++ if it is needed

> -     1  means libstdc++ is needed and should be linked in.

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

> +  /* What action to take for the c++ runtime library:

> +    -1  means we should not link it in.

> +     0  means we should link it if it is needed.

> +     1  means it is needed and should be linked in.

> +     2  means it is needed but should be linked statically.  */

>     int library = 0;

>   

> +  /* Which c++ runtime library to link.  */

> +  stdcxxlib_kind which_library = USE_LIBSTDCXX;

> +

>     /* 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.  */

> @@ -194,6 +225,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,

>   	  args[i] |= SKIPOPT;

>   	  break;

>   

> +	case OPT_stdlib_:

> +	  which_library = (stdcxxlib_kind) decoded_options[i].value;

> +	  break;

> +

>   	case OPT_SPECIAL_input_file:

>   	  {

>   	    int len;

> @@ -250,6 +285,13 @@ 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;

> +  /* For libc++, on most platforms, the ABI library (usually called libc++abi)

> +     is provided as a separate DSO, which we must also append.

> +     However, a platform might have the ability to forward the ABI library

> +     from libc++, or combine it in some other way; in that case, LIBCXXABI

> +     should be set to NULL to signal that it need not be appended.  */

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

> +    num_args += 4;

>     new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);

>   

>     i = 0;

> @@ -323,9 +365,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 == USE_LIBCXX)

> +	{

> +	  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/cppdefault.h b/gcc/cppdefault.h

> index a681264f75e..35cf24ec29e 100644

> --- a/gcc/cppdefault.h

> +++ b/gcc/cppdefault.h

> @@ -36,7 +36,12 @@ struct default_include

>     const char *const fname;	/* The name of the directory.  */

>     const char *const component;	/* The component containing the directory

>   				   (see update_path in prefix.c) */

> -  const char cplusplus;		/* Only look here if we're compiling C++.  */

> +  const char cplusplus;		/* When this is non-zero, we should only

> +				   consider this if we're compiling C++.

> +				   When the -stdlib option is configured, this

> +				   may take values greater than 1 to indicate

> +				   which C++ standard library should be

> +				   used.  */

>     const char cxx_aware;		/* Includes in this directory don't need to

>   				   be wrapped in extern "C" when compiling

>   				   C++.  */

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

> index d7d354fc4de..3b8b003c51d 100644

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

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

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

>   -fext-numeric-literals @gol

>   -flang-info-include-translate@r{[}=@var{name}@r{]} @gol

>   -flang-info-include-translate-not @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

> @@ -3368,6 +3369,15 @@ is used when building the C++ library.)

>   @opindex flang-info-include-translate-not

>   Diagnose include translation events.

>   

> +@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;

>   

>
Andrew Pinski via Gcc-patches March 29, 2021, 6:44 p.m. | #2
Hi Iain, could you add a note about this change to the
gcc-11/changes.html page? There are probably some people who would be
interested in this who could use a note about it. Thanks

On Tue, Dec 22, 2020 at 3:53 PM Jason Merrill via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>

> On 12/22/20 3:39 PM, Iain Sandoe wrote:

> > Hi Jason,

> >

> > Jason Merrill <jason@redhat.com> wrote:

> >

> >> On 11/11/20 3:58 PM, Iain Sandoe wrote:

> >

> >>> 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.

> >>>

> >

> >>> +  /* 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.

> >

> > done - it is also noted that it must track the enum in the opt file.

> >

> >>> @@ -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.

> >

> > done (JFTR, it’s because libc++ doesn’t include the abi library for most platforms, so that also has to be

> > appended to the link line).

> >

> >>> +#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.

> >

> > done.

> >

> > (re-)tested on x86_64-darwin{11,16,17,19, 20} with the installed libc++ and x86_64-linux-gnu with an

> > LLVM-9 build.  Bootstrapped and smoke-tested for libc++ (regular testing for libstdc++).

> >

> > OK for master now?

>

> OK.

>

> > thanks

> > Iain

> >

> > ==== revised patch

> >

> >

> > This option allows the user to specifiy 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.

> >       * cppdefault.h (struct default_include): Amend comments

> >       to reflect the extended use of the cplusplus field.

> >       * 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.

> >       (enum stdcxxlib_kind): New.

> >       (lang_specific_driver): Allow selection amongst multiple

> >       c++ runtime libraries.

> > ---

> >   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    | 74 ++++++++++++++++++++++++++++++++++++++++-----

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

> >   gcc/cppdefault.h    |  7 ++++-

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

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

> >   10 files changed, 216 insertions(+), 13 deletions(-)

> >

> > diff --git a/gcc/Makefile.in b/gcc/Makefile.in

> > index 178e4eaa513..6847022f108 100644

> > --- a/gcc/Makefile.in

> > +++ b/gcc/Makefile.in

> > @@ -679,6 +679,9 @@ build_tooldir = $(exec_prefix)/$(target_noncanonical)

> >   # Directory in which the compiler finds target-independent g++ includes.

> >   gcc_gxx_include_dir = @gcc_gxx_include_dir@

> >   gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@

> > +# Directory in which the compiler finds libc++ includes.

> > +gcc_gxx_libcxx_include_dir = @gcc_gxx_libcxx_include_dir@

> > +gcc_gxx_libcxx_include_dir_add_sysroot = @gcc_gxx_libcxx_include_dir_add_sysroot@

> >   # Directory to search for site-specific includes.

> >   local_includedir = $(local_prefix)/include

> >   includedir = $(prefix)/include

> > @@ -1185,6 +1188,7 @@ FLAGS_TO_PASS = \

> >       "prefix=$(prefix)" \

> >       "local_prefix=$(local_prefix)" \

> >       "gxx_include_dir=$(gcc_gxx_include_dir)" \

> > +     "gxx_libcxx_include_dir=$(gcc_gxx_libcxx_include_dir)" \

> >       "build_tooldir=$(build_tooldir)" \

> >       "gcc_tooldir=$(gcc_tooldir)" \

> >       "bindir=$(bindir)" \

> > @@ -3004,6 +3008,8 @@ PREPROCESSOR_DEFINES = \

> >     -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \

> >     -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \

> >     -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \

> > +  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"$(gcc_gxx_libcxx_include_dir)\" \

> > +  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_libcxx_include_dir_add_sysroot) \

> >     -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \

> >     -DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \

> >     -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \

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

> > index 21d8cd03709..e0c322f61ae 100644

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

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

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

> >   C ObjC Alias(std=c17)

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

> >

> > +stdlib=

> > +Driver C++ ObjC++ Common 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/config.in b/gcc/config.in

> > index 216505abd2c..10a13cde586 100644

> > --- a/gcc/config.in

> > +++ b/gcc/config.in

> > @@ -240,6 +240,12 @@

> >      standards-compatible mode on s390 targets. */

> >   #undef ENABLE_S390_EXCESS_FLOAT_PRECISION

> >

> > +/* Define if the -stdlib= option should be enabled. */

> > +#ifndef USED_FOR_TARGET

> > +#undef ENABLE_STDLIB_OPTION

> > +#endif

> > +

> > +

> >   /* Define if you want all operations on trees (the basic data structure of the

> >      front ends) to be checked for dynamic type safety at runtime. This is

> >      moderately expensive. */

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

> > index fbe92089640..ee9760354b6 100755

> > --- a/gcc/configure

> > +++ b/gcc/configure

> > @@ -675,6 +675,8 @@ host_xm_defines

> >   host_xm_include_list

> >   host_xm_file_list

> >   host_exeext

> > +gcc_gxx_libcxx_include_dir_add_sysroot

> > +gcc_gxx_libcxx_include_dir

> >   gcc_gxx_include_dir_add_sysroot

> >   gcc_gxx_include_dir

> >   gcc_config_arguments

> > @@ -937,6 +939,7 @@ with_native_system_header_dir

> >   with_build_sysroot

> >   with_sysroot

> >   with_gxx_include_dir

> > +with_gxx_libcxx_include_dir

> >   with_cpp_install_dir

> >   enable_generated_files_in_srcdir

> >   with_gnu_ld

> > @@ -1801,6 +1804,8 @@ Optional Packages:

> >     --with-sysroot[=DIR]    search for usr/lib, usr/include, et al, within DIR

> >     --with-gxx-include-dir=DIR

> >                             specifies directory to put g++ header files

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

> > +                          specifies directory to find libc++ header files

> >     --with-cpp-install-dir=DIR

> >                             install the user visible C preprocessor in DIR

> >                             (relative to PREFIX) as well as PREFIX/bin

> > @@ -3731,6 +3736,52 @@ 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

> > +

> > +# Check whether --with-gxx-libcxx-include-dir was given.

> > +if test "${with_gxx_libcxx_include_dir+set}" = set; then :

> > +  withval=$with_gxx_libcxx_include_dir; case "${withval}" in

> > +yes) as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;

> > +no)  ;;

> > +*)   gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;

> > +esac

> > +fi

> > +

> > +

> > +# 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

> > +

> > +$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h

> > +

> > +else

> > +  $as_echo "#define ENABLE_STDLIB_OPTION 0" >>confdefs.h

> > +

> > +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

> > +

> >

> >   # Check whether --with-cpp_install_dir was given.

> >   if test "${with_cpp_install_dir+set}" = set; then :

> > @@ -19186,7 +19237,7 @@ else

> >     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2

> >     lt_status=$lt_dlunknown

> >     cat > conftest.$ac_ext <<_LT_EOF

> > -#line 19189 "configure"

> > +#line 19240 "configure"

> >   #include "confdefs.h"

> >

> >   #if HAVE_DLFCN_H

> > @@ -19292,7 +19343,7 @@ else

> >     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2

> >     lt_status=$lt_dlunknown

> >     cat > conftest.$ac_ext <<_LT_EOF

> > -#line 19295 "configure"

> > +#line 19346 "configure"

> >   #include "confdefs.h"

> >

> >   #if HAVE_DLFCN_H

> > @@ -31175,6 +31226,8 @@ fi

> >

> >

> >

> > +

> > +

> >

> >

> >

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

> > index 89b9981e872..6fcf154d987 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

> > @@ -7096,6 +7138,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 0f17148ccbd..a8254cd34c9 100644

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

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

> > @@ -49,6 +49,34 @@ 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

> > +

> > +/* The values used here must match those of the stdlib_kind enumeration

> > +   in c.opt.  */

> > +enum stdcxxlib_kind

> > +{

> > +  USE_LIBSTDCXX = 1,

> > +  USE_LIBCXX = 2

> > +};

> > +

> >   void

> >   lang_specific_driver (struct cl_decoded_option **in_decoded_options,

> >                     unsigned int *in_decoded_options_count,

> > @@ -59,13 +87,16 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,

> >     /* If nonzero, the user gave us the `-p' or `-pg' flag.  */

> >     int saw_profile_flag = 0;

> >

> > -  /* What do with libstdc++:

> > -     -1 means we should not link in libstdc++

> > -     0  means we should link in libstdc++ if it is needed

> > -     1  means libstdc++ is needed and should be linked in.

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

> > +  /* What action to take for the c++ runtime library:

> > +    -1  means we should not link it in.

> > +     0  means we should link it if it is needed.

> > +     1  means it is needed and should be linked in.

> > +     2  means it is needed but should be linked statically.  */

> >     int library = 0;

> >

> > +  /* Which c++ runtime library to link.  */

> > +  stdcxxlib_kind which_library = USE_LIBSTDCXX;

> > +

> >     /* 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.  */

> > @@ -194,6 +225,10 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,

> >         args[i] |= SKIPOPT;

> >         break;

> >

> > +     case OPT_stdlib_:

> > +       which_library = (stdcxxlib_kind) decoded_options[i].value;

> > +       break;

> > +

> >       case OPT_SPECIAL_input_file:

> >         {

> >           int len;

> > @@ -250,6 +285,13 @@ 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;

> > +  /* For libc++, on most platforms, the ABI library (usually called libc++abi)

> > +     is provided as a separate DSO, which we must also append.

> > +     However, a platform might have the ability to forward the ABI library

> > +     from libc++, or combine it in some other way; in that case, LIBCXXABI

> > +     should be set to NULL to signal that it need not be appended.  */

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

> > +    num_args += 4;

> >     new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);

> >

> >     i = 0;

> > @@ -323,9 +365,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 == USE_LIBCXX)

> > +     {

> > +       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/cppdefault.h b/gcc/cppdefault.h

> > index a681264f75e..35cf24ec29e 100644

> > --- a/gcc/cppdefault.h

> > +++ b/gcc/cppdefault.h

> > @@ -36,7 +36,12 @@ struct default_include

> >     const char *const fname;  /* The name of the directory.  */

> >     const char *const component;      /* The component containing the directory

> >                                  (see update_path in prefix.c) */

> > -  const char cplusplus;              /* Only look here if we're compiling C++.  */

> > +  const char cplusplus;              /* When this is non-zero, we should only

> > +                                consider this if we're compiling C++.

> > +                                When the -stdlib option is configured, this

> > +                                may take values greater than 1 to indicate

> > +                                which C++ standard library should be

> > +                                used.  */

> >     const char cxx_aware;             /* Includes in this directory don't need to

> >                                  be wrapped in extern "C" when compiling

> >                                  C++.  */

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

> > index d7d354fc4de..3b8b003c51d 100644

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

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

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

> >   -fext-numeric-literals @gol

> >   -flang-info-include-translate@r{[}=@var{name}@r{]} @gol

> >   -flang-info-include-translate-not @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

> > @@ -3368,6 +3369,15 @@ is used when building the C++ library.)

> >   @opindex flang-info-include-translate-not

> >   Diagnose include translation events.

> >

> > +@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

==== revised patch


This option allows the user to specifiy 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.
	* cppdefault.h (struct default_include): Amend comments
	to reflect the extended use of the cplusplus field.
	* 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.
	(enum stdcxxlib_kind): New.
	(lang_specific_driver): Allow selection amongst multiple
	c++ runtime libraries.
---
 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    | 74 ++++++++++++++++++++++++++++++++++++++++-----
 gcc/cppdefault.c    |  5 +++
 gcc/cppdefault.h    |  7 ++++-
 gcc/doc/invoke.texi | 10 ++++++
 gcc/incpath.c       |  6 ++--
 10 files changed, 216 insertions(+), 13 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 178e4eaa513..6847022f108 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -679,6 +679,9 @@  build_tooldir = $(exec_prefix)/$(target_noncanonical)
 # Directory in which the compiler finds target-independent g++ includes.
 gcc_gxx_include_dir = @gcc_gxx_include_dir@
 gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@
+# Directory in which the compiler finds libc++ includes.
+gcc_gxx_libcxx_include_dir = @gcc_gxx_libcxx_include_dir@
+gcc_gxx_libcxx_include_dir_add_sysroot = @gcc_gxx_libcxx_include_dir_add_sysroot@
 # Directory to search for site-specific includes.
 local_includedir = $(local_prefix)/include
 includedir = $(prefix)/include
@@ -1185,6 +1188,7 @@  FLAGS_TO_PASS = \
 	"prefix=$(prefix)" \
 	"local_prefix=$(local_prefix)" \
 	"gxx_include_dir=$(gcc_gxx_include_dir)" \
+	"gxx_libcxx_include_dir=$(gcc_gxx_libcxx_include_dir)" \
 	"build_tooldir=$(build_tooldir)" \
 	"gcc_tooldir=$(gcc_tooldir)" \
 	"bindir=$(bindir)" \
@@ -3004,6 +3008,8 @@  PREPROCESSOR_DEFINES = \
   -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \
   -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \
   -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \
+  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"$(gcc_gxx_libcxx_include_dir)\" \
+  -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_libcxx_include_dir_add_sysroot) \
   -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
   -DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \
   -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 21d8cd03709..e0c322f61ae 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -2356,6 +2356,20 @@  std=iso9899:2018
 C ObjC Alias(std=c17)
 Conform to the ISO 2017 C standard (published in 2018).
 
+stdlib=
+Driver C++ ObjC++ Common 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/config.in b/gcc/config.in
index 216505abd2c..10a13cde586 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -240,6 +240,12 @@ 
    standards-compatible mode on s390 targets. */
 #undef ENABLE_S390_EXCESS_FLOAT_PRECISION
 
+/* Define if the -stdlib= option should be enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_STDLIB_OPTION
+#endif
+
+
 /* Define if you want all operations on trees (the basic data structure of the
    front ends) to be checked for dynamic type safety at runtime. This is
    moderately expensive. */
diff --git a/gcc/configure b/gcc/configure
index fbe92089640..ee9760354b6 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -675,6 +675,8 @@  host_xm_defines
 host_xm_include_list
 host_xm_file_list
 host_exeext
+gcc_gxx_libcxx_include_dir_add_sysroot
+gcc_gxx_libcxx_include_dir
 gcc_gxx_include_dir_add_sysroot
 gcc_gxx_include_dir
 gcc_config_arguments
@@ -937,6 +939,7 @@  with_native_system_header_dir
 with_build_sysroot
 with_sysroot
 with_gxx_include_dir
+with_gxx_libcxx_include_dir
 with_cpp_install_dir
 enable_generated_files_in_srcdir
 with_gnu_ld
@@ -1801,6 +1804,8 @@  Optional Packages:
   --with-sysroot[=DIR]    search for usr/lib, usr/include, et al, within DIR
   --with-gxx-include-dir=DIR
                           specifies directory to put g++ header files
+  --with-gxx-libcxx-include-dir=DIR
+                          specifies directory to find libc++ header files
   --with-cpp-install-dir=DIR
                           install the user visible C preprocessor in DIR
                           (relative to PREFIX) as well as PREFIX/bin
@@ -3731,6 +3736,52 @@  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
+
+# Check whether --with-gxx-libcxx-include-dir was given.
+if test "${with_gxx_libcxx_include_dir+set}" = set; then :
+  withval=$with_gxx_libcxx_include_dir; case "${withval}" in
+yes)	as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;
+no)	;;
+*)	gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
+esac
+fi
+
+
+# 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
+
+$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h
+
+else
+  $as_echo "#define ENABLE_STDLIB_OPTION 0" >>confdefs.h
+
+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
+
 
 # Check whether --with-cpp_install_dir was given.
 if test "${with_cpp_install_dir+set}" = set; then :
@@ -19186,7 +19237,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19189 "configure"
+#line 19240 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -19292,7 +19343,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19295 "configure"
+#line 19346 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -31175,6 +31226,8 @@  fi
 
 
 
+
+
 
 
 
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 89b9981e872..6fcf154d987 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
@@ -7096,6 +7138,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 0f17148ccbd..a8254cd34c9 100644
--- a/gcc/cp/g++spec.c
+++ b/gcc/cp/g++spec.c
@@ -49,6 +49,34 @@  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
+
+/* The values used here must match those of the stdlib_kind enumeration
+   in c.opt.  */
+enum stdcxxlib_kind
+{
+  USE_LIBSTDCXX = 1,
+  USE_LIBCXX = 2
+};
+
 void
 lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 		      unsigned int *in_decoded_options_count,
@@ -59,13 +87,16 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
   /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
   int saw_profile_flag = 0;
 
-  /* What do with libstdc++:
-     -1 means we should not link in libstdc++
-     0  means we should link in libstdc++ if it is needed
-     1  means libstdc++ is needed and should be linked in.
-     2  means libstdc++ is needed and should be linked statically.  */
+  /* What action to take for the c++ runtime library:
+    -1  means we should not link it in.
+     0  means we should link it if it is needed.
+     1  means it is needed and should be linked in.
+     2  means it is needed but should be linked statically.  */
   int library = 0;
 
+  /* Which c++ runtime library to link.  */
+  stdcxxlib_kind which_library = USE_LIBSTDCXX;
+
   /* 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.  */
@@ -194,6 +225,10 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 	  args[i] |= SKIPOPT;
 	  break;
 
+	case OPT_stdlib_:
+	  which_library = (stdcxxlib_kind) decoded_options[i].value;
+	  break;
+
 	case OPT_SPECIAL_input_file:
 	  {
 	    int len;
@@ -250,6 +285,13 @@  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;
+  /* For libc++, on most platforms, the ABI library (usually called libc++abi)
+     is provided as a separate DSO, which we must also append.
+     However, a platform might have the ability to forward the ABI library
+     from libc++, or combine it in some other way; in that case, LIBCXXABI
+     should be set to NULL to signal that it need not be appended.  */
+  if (which_library == USE_LIBCXX && LIBCXXABI != NULL)
+    num_args += 4;
   new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
 
   i = 0;
@@ -323,9 +365,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 == USE_LIBCXX)
+	{
+	  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/cppdefault.h b/gcc/cppdefault.h
index a681264f75e..35cf24ec29e 100644
--- a/gcc/cppdefault.h
+++ b/gcc/cppdefault.h
@@ -36,7 +36,12 @@  struct default_include
   const char *const fname;	/* The name of the directory.  */
   const char *const component;	/* The component containing the directory
 				   (see update_path in prefix.c) */
-  const char cplusplus;		/* Only look here if we're compiling C++.  */
+  const char cplusplus;		/* When this is non-zero, we should only
+				   consider this if we're compiling C++.
+				   When the -stdlib option is configured, this
+				   may take values greater than 1 to indicate
+				   which C++ standard library should be
+				   used.  */
   const char cxx_aware;		/* Includes in this directory don't need to
 				   be wrapped in extern "C" when compiling
 				   C++.  */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d7d354fc4de..3b8b003c51d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -242,6 +242,7 @@  in the following sections.
 -fext-numeric-literals @gol
 -flang-info-include-translate@r{[}=@var{name}@r{]} @gol
 -flang-info-include-translate-not @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
@@ -3368,6 +3369,15 @@  is used when building the C++ library.)
 @opindex flang-info-include-translate-not
 Diagnose include translation events.
 
+@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;