toolchain.eclass: drop I_PROMISE_TO_SUPPLY_PATCHES_WITH_BUGS guard
[gentoo.git] / eclass / toolchain.eclass
index 2cac026eefa8ab12acad4da3684121a193d0b1ed..46482ad9d7535dc07782ef74a7b9a6a33e5a0dab 100644 (file)
@@ -1,33 +1,39 @@
-# Copyright 1999-2018 Gentoo Foundation
+# Copyright 1999-2020 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 # Maintainer: Toolchain Ninjas <toolchain@gentoo.org>
+# @SUPPORTED_EAPIS: 5 6 7
 
 DESCRIPTION="The GNU Compiler Collection"
 HOMEPAGE="https://gcc.gnu.org/"
-RESTRICT="strip" # cross-compilers need controlled stripping
 
-inherit eutils fixheadtails flag-o-matic gnuconfig libtool multilib pax-utils toolchain-funcs versionator prefix
+inherit eutils fixheadtails flag-o-matic gnuconfig libtool multilib pax-utils toolchain-funcs prefix
 
-if [[ ${PV} == *_pre9999* ]] ; then
+tc_is_live() {
+       [[ ${PV} == *9999* ]]
+}
+
+if tc_is_live ; then
        EGIT_REPO_URI="git://gcc.gnu.org/git/gcc.git"
        # naming style:
-       # gcc-4.7.1_pre9999 -> gcc-4_7-branch
+       # gcc-10.1.0_pre9999 -> gcc-10-branch
        #  Note that the micro version is required or lots of stuff will break.
        #  To checkout master set gcc_LIVE_BRANCH="master" in the ebuild before
        #  inheriting this eclass.
-       EGIT_BRANCH="${PN}-${PV%.?_pre9999}-branch"
+       EGIT_BRANCH="releases/${PN}-${PV%.?.?_pre9999}"
        EGIT_BRANCH=${EGIT_BRANCH//./_}
-       inherit git-2
+       inherit git-r3
 fi
 
 FEATURES=${FEATURES/multilib-strict/}
 
 case ${EAPI:-0} in
        0|1|2|3|4*) die "Need to upgrade to at least EAPI=5" ;;
-       5*)   ;;
-       *)       die "I don't speak EAPI ${EAPI}." ;;
+       5*|6) inherit eapi7-ver ;;
+       7) ;;
+       *) die "I don't speak EAPI ${EAPI}." ;;
 esac
+
 EXPORT_FUNCTIONS pkg_pretend pkg_setup src_unpack src_prepare src_configure \
        src_compile src_test src_install pkg_postinst pkg_postrm
 
@@ -49,7 +55,7 @@ is_crosscompile() {
 
 # General purpose version check.  Without a second arg matches up to minor version (x.x.x)
 tc_version_is_at_least() {
-       version_is_at_least "$1" "${2:-${GCC_RELEASE_VER}}"
+       ver_test "${2:-${GCC_RELEASE_VER}}" -ge "$1"
 }
 
 # General purpose version range check
@@ -61,34 +67,36 @@ tc_version_is_between() {
 GCC_PV=${TOOLCHAIN_GCC_PV:-${PV}}
 GCC_PVR=${GCC_PV}
 [[ ${PR} != "r0" ]] && GCC_PVR=${GCC_PVR}-${PR}
-GCC_RELEASE_VER=$(get_version_component_range 1-3 ${GCC_PV})
-GCC_BRANCH_VER=$(get_version_component_range 1-2 ${GCC_PV})
-GCCMAJOR=$(get_version_component_range 1 ${GCC_PV})
-GCCMINOR=$(get_version_component_range 2 ${GCC_PV})
-GCCMICRO=$(get_version_component_range 3 ${GCC_PV})
-[[ ${BRANCH_UPDATE-notset} == "notset" ]] && \
-       BRANCH_UPDATE=$(get_version_component_range 4 ${GCC_PV})
-
-# According to gcc/c-cppbuiltin.c, GCC_CONFIG_VER MUST match this regex.
-# ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)?
-GCC_CONFIG_VER=${GCC_CONFIG_VER:-$(replace_version_separator 3 '-' ${GCC_PV})}
-
-# Pre-release support
-if [[ ${GCC_PV} == *_pre* ]] ; then
-       PRERELEASE=${GCC_PV/_pre/-}
-elif [[ ${GCC_PV} == *_alpha* ]] ; then
-       SNAPSHOT=${GCC_BRANCH_VER}-${GCC_PV##*_alpha}
-elif [[ ${GCC_PV} == *_beta* ]] ; then
-       SNAPSHOT=${GCC_BRANCH_VER}-${GCC_PV##*_beta}
+
+# GCC_RELEASE_VER must always match 'gcc/BASE-VER' value.
+# It's an internal representation of gcc version used for:
+# - versioned paths on disk
+# - 'gcc -dumpversion' output. Must always match <digit>.<digit>.<digit>.
+GCC_RELEASE_VER=$(ver_cut 1-3 ${GCC_PV})
+
+GCC_BRANCH_VER=$(ver_cut 1-2 ${GCC_PV})
+GCCMAJOR=$(ver_cut 1 ${GCC_PV})
+GCCMINOR=$(ver_cut 2 ${GCC_PV})
+GCCMICRO=$(ver_cut 3 ${GCC_PV})
+
+# Ideally this variable should allow for custom gentoo versioning
+# of binary and gcc-config names not directly tied to upstream
+# versioning. In practive it's hard to untangle from gcc/BASE-VER
+# (GCC_RELEASE_VER) value.
+GCC_CONFIG_VER=${GCC_RELEASE_VER}
+
+# Pre-release support. Versioning schema:
+# 1.0.0_pre9999: live ebuild
+# 1.2.3_alphaYYYYMMDD: weekly snapshots
+# 1.2.3_rcYYYYMMDD: release candidates
+if [[ ${GCC_PV} == *_alpha* ]] ; then
+       # weekly snapshots
+       SNAPSHOT=${GCCMAJOR}-${GCC_PV##*_alpha}
 elif [[ ${GCC_PV} == *_rc* ]] ; then
+       # release candidates
        SNAPSHOT=${GCC_PV%_rc*}-RC-${GCC_PV##*_rc}
 fi
 
-if [[ ${SNAPSHOT} == [56789].0-* ]] ; then
-       # The gcc-5+ releases have dropped the .0 for some reason.
-       SNAPSHOT=${SNAPSHOT/.0}
-fi
-
 PREFIX=${TOOLCHAIN_PREFIX:-${EPREFIX}/usr}
 
 if tc_version_is_at_least 3.4.0 ; then
@@ -127,38 +135,74 @@ else
        LICENSE="GPL-2+ LGPL-2.1+ FDL-1.1+"
 fi
 
-IUSE="regression-test vanilla"
-IUSE_DEF=( nls nptl )
+IUSE="test vanilla +nls"
+RESTRICT="!test? ( test )"
+
+tc_supports_dostrip() {
+       case ${EAPI:-0} in
+               5*|6) return 1 ;;
+               7) return 0 ;;
+               *) die "Update apply_patches() for ${EAPI}." ;;
+       esac
+}
+
+tc_supports_dostrip || RESTRICT+=" strip" # cross-compilers need controlled stripping
+
+TC_FEATURES=()
+
+tc_has_feature() {
+       has "$1" "${TC_FEATURES[@]}"
+}
 
 if [[ ${PN} != "kgcc64" && ${PN} != gcc-* ]] ; then
-       IUSE+=" altivec debug"
-       IUSE_DEF+=( cxx fortran )
+       IUSE+=" altivec debug +cxx +nptl" TC_FEATURES+=(nptl)
        [[ -n ${PIE_VER} ]] && IUSE+=" nopie"
        [[ -n ${HTB_VER} ]] && IUSE+=" boundschecking"
        [[ -n ${D_VER}   ]] && IUSE+=" d"
        [[ -n ${SPECS_VER} ]] && IUSE+=" nossp"
+       # fortran support appeared in 4.1, but 4.1 needs outdated mpfr
+       tc_version_is_at_least 4.2 && IUSE+=" +fortran" TC_FEATURES+=(fortran)
        tc_version_is_at_least 3 && IUSE+=" doc hardened multilib objc"
-       tc_version_is_between 3 7 && IUSE+=" awt gcj"
+       tc_version_is_between 3 7 && IUSE+=" awt gcj" TC_FEATURES+=(gcj)
        tc_version_is_at_least 3.3 && IUSE+=" pgo"
-       tc_version_is_at_least 4.0 && IUSE+=" objc-gc"
+       tc_version_is_at_least 4.0 &&
+               IUSE+=" objc-gc" TC_FEATURES+=(objc-gc)
        tc_version_is_between 4.0 4.9 && IUSE+=" mudflap"
        tc_version_is_at_least 4.1 && IUSE+=" libssp objc++"
-       tc_version_is_at_least 4.2 && IUSE_DEF+=( openmp )
+       tc_version_is_at_least 4.2 && IUSE+=" +openmp"
        tc_version_is_at_least 4.3 && IUSE+=" fixed-point"
        tc_version_is_at_least 4.7 && IUSE+=" go"
-       # Note: while <=gcc-4.7 also supported graphite, it required forked ppl
-       # versions which we dropped.  Since graphite was also experimental in
-       # the older versions, we don't want to bother supporting it.  #448024
-       tc_version_is_at_least 4.8 && IUSE+=" graphite" IUSE_DEF+=( sanitize )
+       # sanitizer support appeared in gcc-4.8, but <gcc-5 does not
+       # support modern glibc.
+       tc_version_is_at_least 5 && IUSE+=" +sanitize"
+       # Note:
+       #   <gcc-4.8 supported graphite, it required forked ppl
+       #     versions which we dropped.  Since graphite was also experimental in
+       #     the older versions, we don't want to bother supporting it.  #448024
+       #   <gcc-5 supported graphite, it required cloog
+       #   <gcc-6.5 supported graphite, it required old incompatible isl
+       tc_version_is_at_least 6.5 &&
+               IUSE+=" graphite" TC_FEATURES+=(graphite)
        tc_version_is_between 4.9 8 && IUSE+=" cilk"
        tc_version_is_at_least 4.9 && IUSE+=" +vtv"
-       tc_version_is_at_least 5.0 && IUSE+=" jit mpx"
+       tc_version_is_at_least 5.0 && IUSE+=" jit"
+       tc_version_is_between 5.0 9 && IUSE+=" mpx"
        tc_version_is_at_least 6.0 && IUSE+=" +pie +ssp +pch"
+       # systemtap is a gentoo-specific switch: bug #654748
+       tc_version_is_at_least 8.0 &&
+               IUSE+=" systemtap" TC_FEATURES+=(systemtap)
+       tc_version_is_at_least 9.0 && IUSE+=" d"
+       tc_version_is_at_least 9.1 && IUSE+=" lto"
+       tc_version_is_at_least 10 && IUSE+=" zstd" TC_FEATURES+=(zstd)
 fi
 
-IUSE+=" ${IUSE_DEF[*]/#/+}"
-
-SLOT="${GCC_CONFIG_VER}"
+if tc_version_is_at_least 10; then
+       # Note: currently we pull in releases, snapshots and
+       # git versions into the same SLOT.
+       SLOT="${GCCMAJOR}"
+else
+       SLOT="${GCC_CONFIG_VER}"
+fi
 
 #---->> DEPEND <<----
 
@@ -171,41 +215,34 @@ if tc_version_is_at_least 4 ; then
        GMP_MPFR_DEPS=">=dev-libs/gmp-4.3.2:0= >=dev-libs/mpfr-2.4.2:0="
        if tc_version_is_at_least 4.3 ; then
                RDEPEND+=" ${GMP_MPFR_DEPS}"
-       elif in_iuse fortran ; then
+       elif tc_has_feature fortran ; then
                RDEPEND+=" fortran? ( ${GMP_MPFR_DEPS} )"
        fi
 fi
 
 tc_version_is_at_least 4.5 && RDEPEND+=" >=dev-libs/mpc-0.8.1:0="
 
-if in_iuse objc-gc ; then
+if tc_has_feature objc-gc ; then
        if tc_version_is_at_least 7 ; then
                RDEPEND+=" objc-gc? ( >=dev-libs/boehm-gc-7.4.2 )"
        fi
 fi
 
-if in_iuse graphite ; then
-       if tc_version_is_at_least 5.0 ; then
-               RDEPEND+=" graphite? ( >=dev-libs/isl-0.14:0= )"
-       elif tc_version_is_at_least 4.8 ; then
-               RDEPEND+="
-                       graphite? (
-                               >=dev-libs/cloog-0.18.0:0=
-                               >=dev-libs/isl-0.11.1:0=
-                       )"
-       fi
+if tc_has_feature graphite ; then
+       RDEPEND+=" graphite? ( >=dev-libs/isl-0.14:0= )"
 fi
 
-DEPEND="${RDEPEND}
+BDEPEND="
        >=sys-devel/bison-1.875
        >=sys-devel/flex-2.5.4
        nls? ( sys-devel/gettext )
-       regression-test? (
+       test? (
                >=dev-util/dejagnu-1.4.4
                >=sys-devel/autogen-5.5.4
        )"
+DEPEND="${RDEPEND}"
 
-if in_iuse gcj ; then
+if tc_has_feature gcj ; then
        GCJ_DEPS=">=media-libs/libart_lgpl-2.1"
        GCJ_GTK_DEPS="
                x11-base/xorg-proto
@@ -220,15 +257,28 @@ if in_iuse gcj ; then
        DEPEND+=" gcj? ( awt? ( ${GCJ_GTK_DEPS} ) ${GCJ_DEPS} )"
 fi
 
+if tc_has_feature systemtap ; then
+       # gcc needs sys/sdt.h headers on target
+       DEPEND+=" systemtap? ( dev-util/systemtap )"
+fi
+
+if tc_has_feature zstd ; then
+       DEPEND+=" zstd? ( app-arch/zstd )"
+fi
+
+case ${EAPI:-0} in
+       5*|6) DEPEND+=" ${BDEPEND}" ;;
+esac
+
 PDEPEND=">=sys-devel/gcc-config-1.7"
 
 #---->> S + SRC_URI essentials <<----
 
 # Set the source directory depending on whether we're using
-# a prerelease, snapshot, or release tarball.
+# a live git tree, snapshot, or release tarball.
 S=$(
-       if [[ -n ${PRERELEASE} ]] ; then
-               echo ${WORKDIR}/gcc-${PRERELEASE}
+       if tc_is_live ; then
+               echo ${EGIT_CHECKOUT_DIR}
        elif [[ -n ${SNAPSHOT} ]] ; then
                echo ${WORKDIR}/gcc-${SNAPSHOT}
        else
@@ -252,20 +302,16 @@ gentoo_urls() {
 # Other than the variables normally set by portage, this function's behavior
 # can be altered by setting the following:
 #
+#      GCC_TARBALL_SRC_URI
+#                      Override link to main tarball into SRC_URI. Used by dev-lang/gnat-gpl
+#                      to provide gcc tarball snapshots. Patches are usually reused as-is.
+#
 #      SNAPSHOT
 #                      If set, this variable signals that we should be using a snapshot of
 #                      gcc. It is expected to be in the format "YYYY-MM-DD". Note that if
 #                      the ebuild has a _pre suffix, this variable is ignored and the
 #                      prerelease tarball is used instead.
 #
-#      BRANCH_UPDATE
-#                      If set, this variable signals that we should be using the main
-#                      release tarball (determined by ebuild version) and applying a
-#                      CVS branch update patch against it. The location of this branch
-#                      update patch is assumed to be in ${GENTOO_TOOLCHAIN_BASE_URI}.
-#                      Just like with SNAPSHOT, this variable is ignored if the ebuild
-#                      has a _pre suffix.
-#
 #      PATCH_VER
 #      PATCH_GCC_VER
 #                      This should be set to the version of the gentoo patch tarball.
@@ -302,6 +348,14 @@ gentoo_urls() {
 #                      ten Brugge's bounds-checking patches. If you want to use a patch
 #                      for an older gcc version with a new gcc, make sure you set
 #                      HTB_GCC_VER to that version of gcc.
+#
+#      CYGWINPORTS_GITREV
+#                      If set, this variable signals that we should apply additional patches
+#                      maintained by upstream Cygwin developers at github/cygwinports/gcc,
+#                      using the specified git commit id there.  The list of patches to
+#                      apply is extracted from gcc.cygport, maintained there as well.
+#                      This is done for compilers running on Cygwin, not for cross compilers
+#                      with a Cygwin target.
 get_gcc_src_uri() {
        export PATCH_GCC_VER=${PATCH_GCC_VER:-${GCC_RELEASE_VER}}
        export UCLIBC_GCC_VER=${UCLIBC_GCC_VER:-${PATCH_GCC_VER}}
@@ -310,27 +364,20 @@ get_gcc_src_uri() {
        export SPECS_GCC_VER=${SPECS_GCC_VER:-${GCC_RELEASE_VER}}
 
        # Set where to download gcc itself depending on whether we're using a
-       # prerelease, snapshot, or release tarball.
-       if [[ ${PV} == *9999* ]] ; then
-               # Nothing to do w/git snapshots.
-               :
-       elif [[ -n ${PRERELEASE} ]] ; then
-               GCC_SRC_URI="ftp://gcc.gnu.org/pub/gcc/prerelease-${PRERELEASE}/gcc-${PRERELEASE}.tar.bz2"
+       # live git tree, snapshot, or release tarball.
+       if tc_is_live ; then
+               # Nothing to do w/git snapshots.
+       elif [[ -n ${GCC_TARBALL_SRC_URI} ]] ; then
+               # pull gcc tarball from another location. Frequently used by gnat-gpl.
+               GCC_SRC_URI="${GCC_TARBALL_SRC_URI}"
        elif [[ -n ${SNAPSHOT} ]] ; then
-               if tc_version_is_between 5.5 6 || tc_version_is_between 6.4 7 || tc_version_is_at_least 7.2 ; then
-                       GCC_SRC_URI="ftp://gcc.gnu.org/pub/gcc/snapshots/${SNAPSHOT}/gcc-${SNAPSHOT}.tar.xz"
-               else
-                       GCC_SRC_URI="ftp://gcc.gnu.org/pub/gcc/snapshots/${SNAPSHOT}/gcc-${SNAPSHOT}.tar.bz2"
-               fi
+               GCC_SRC_URI="ftp://gcc.gnu.org/pub/gcc/snapshots/${SNAPSHOT}/gcc-${SNAPSHOT}.tar.xz"
        else
                if tc_version_is_between 5.5 6 || tc_version_is_between 6.4 7 || tc_version_is_at_least 7.2 ; then
                        GCC_SRC_URI="mirror://gnu/gcc/gcc-${GCC_PV}/gcc-${GCC_RELEASE_VER}.tar.xz"
                else
                        GCC_SRC_URI="mirror://gnu/gcc/gcc-${GCC_PV}/gcc-${GCC_RELEASE_VER}.tar.bz2"
                fi
-               # we want all branch updates to be against the main release
-               [[ -n ${BRANCH_UPDATE} ]] && \
-                       GCC_SRC_URI+=" $(gentoo_urls gcc-${GCC_RELEASE_VER}-branch-update-${BRANCH_UPDATE}.patch.bz2)"
        fi
 
        [[ -n ${UCLIBC_VER} ]] && \
@@ -338,7 +385,6 @@ get_gcc_src_uri() {
        [[ -n ${PATCH_VER} ]] && \
                GCC_SRC_URI+=" $(gentoo_urls gcc-${PATCH_GCC_VER}-patches-${PATCH_VER}.tar.bz2)"
 
-       # strawberry pie, Cappuccino and a Gauloises (it's a good thing)
        [[ -n ${PIE_VER} ]] && \
                PIE_CORE=${PIE_CORE:-gcc-${PIE_GCC_VER}-piepatches-v${PIE_VER}.tar.bz2} && \
                GCC_SRC_URI+=" $(gentoo_urls ${PIE_CORE})"
@@ -360,7 +406,7 @@ get_gcc_src_uri() {
        [[ -n ${D_VER} ]] && \
                GCC_SRC_URI+=" d? ( mirror://sourceforge/dgcc/gdc-${D_VER}-src.tar.bz2 )"
 
-       if in_iuse gcj ; then
+       if tc_has_feature gcj ; then
                if tc_version_is_at_least 4.5 ; then
                        GCC_SRC_URI+=" gcj? ( ftp://sourceware.org/pub/java/ecj-4.5.jar )"
                elif tc_version_is_at_least 4.3 ; then
@@ -368,6 +414,11 @@ get_gcc_src_uri() {
                fi
        fi
 
+       # Cygwin patches from https://github.com/cygwinports/gcc
+       [[ -n ${CYGWINPORTS_GITREV} ]] && \
+               GCC_SRC_URI+=" elibc_Cygwin? ( https://github.com/cygwinports/gcc/archive/${CYGWINPORTS_GITREV}.tar.gz
+                       -> gcc-cygwinports-${CYGWINPORTS_GITREV}.tar.gz )"
+
        echo "${GCC_SRC_URI}"
 }
 
@@ -376,12 +427,6 @@ SRC_URI=$(get_gcc_src_uri)
 #---->> pkg_pretend <<----
 
 toolchain_pkg_pretend() {
-       if [[ -n ${PRERELEASE}${SNAPSHOT} || ${PV} == *9999* ]] &&
-          [[ -z ${I_PROMISE_TO_SUPPLY_PATCHES_WITH_BUGS} ]] ; then
-               die "Please \`export I_PROMISE_TO_SUPPLY_PATCHES_WITH_BUGS=1\` or define it" \
-                       "in your make.conf if you want to use this version."
-       fi
-
        if ! use_if_iuse cxx ; then
                use_if_iuse go && ewarn 'Go requires a C++ compiler, disabled due to USE="-cxx"'
                use_if_iuse objc++ && ewarn 'Obj-C++ requires a C++ compiler, disabled due to USE="-cxx"'
@@ -402,49 +447,37 @@ toolchain_pkg_setup() {
 #---->> src_unpack <<----
 
 toolchain_src_unpack() {
-       if [[ ${PV} == *9999* ]]; then
-               git-2_src_unpack
-       else
-               gcc_quick_unpack
+       if tc_is_live ; then
+               git-r3_src_unpack
        fi
+
+       default_src_unpack
 }
 
-gcc_quick_unpack() {
-       pushd "${WORKDIR}" > /dev/null
-       export PATCH_GCC_VER=${PATCH_GCC_VER:-${GCC_RELEASE_VER}}
-       export UCLIBC_GCC_VER=${UCLIBC_GCC_VER:-${PATCH_GCC_VER}}
-       export PIE_GCC_VER=${PIE_GCC_VER:-${GCC_RELEASE_VER}}
-       export HTB_GCC_VER=${HTB_GCC_VER:-${GCC_RELEASE_VER}}
-       export SPECS_GCC_VER=${SPECS_GCC_VER:-${GCC_RELEASE_VER}}
+#---->> src_prepare <<----
 
-       if [[ -n ${GCC_A_FAKEIT} ]] ; then
-               unpack ${GCC_A_FAKEIT}
-       elif [[ -n ${PRERELEASE} ]] ; then
-               unpack gcc-${PRERELEASE}.tar.bz2
-       elif [[ -n ${SNAPSHOT} ]] ; then
-               if tc_version_is_between 5.5 6 || tc_version_is_between 6.4 7 || tc_version_is_at_least 7.2 ; then
-                       unpack gcc-${SNAPSHOT}.tar.xz
-               else
-                       unpack gcc-${SNAPSHOT}.tar.bz2
-               fi
-       elif [[ ${PV} != *9999* ]] ; then
-               if tc_version_is_between 5.5 6 || tc_version_is_between 6.4 7 || tc_version_is_at_least 7.2 ; then
-                       unpack gcc-${GCC_RELEASE_VER}.tar.xz
-               else
-                       unpack gcc-${GCC_RELEASE_VER}.tar.bz2
-               fi
-               # We want branch updates to be against a release tarball
-               if [[ -n ${BRANCH_UPDATE} ]] ; then
-                       pushd "${S}" > /dev/null
-                       epatch "${DISTDIR}"/gcc-${GCC_RELEASE_VER}-branch-update-${BRANCH_UPDATE}.patch.bz2
-                       popd > /dev/null
-               fi
-       fi
+# 'epatch' is not available in EAPI=7. Abstract away patchset application
+# until we eventually get all gcc ebuilds on EAPI=7 or later.
+tc_apply_patches() {
+       [[ ${#@} -lt 2 ]] && die "usage: tc_apply_patches <message> <patches...>"
+
+       einfo "$1"; shift
+
+       case ${EAPI:-0} in
+               # Note: even for EAPI=6 we used 'epatch' semantics. To avoid
+               # breaking existing ebuilds use 'eapply' only in EAPI=7 or later.
+               5*|6) epatch "$@" ;;
+               7) eapply "$@" ;;
+               *) die "Update apply_patches() for ${EAPI}." ;;
+       esac
+}
+
+toolchain_src_prepare() {
+       export BRANDING_GCC_PKGVERSION="Gentoo ${GCC_PVR}"
+       cd "${S}"
 
        if [[ -n ${D_VER} ]] && use d ; then
-               pushd "${S}"/gcc > /dev/null
-               unpack gdc-${D_VER}-src.tar.bz2
-               cd ..
+               mv "${WORKDIR}"/d gcc/d || die
                ebegin "Adding support for the D language"
                ./gcc/d/setup-gcc.sh >& "${T}"/dgcc.log
                if ! eend $? ; then
@@ -453,52 +486,22 @@ gcc_quick_unpack() {
                        eerror "  ${T}/dgcc.log"
                        die "failed to include the D language"
                fi
-               popd > /dev/null
        fi
 
-       [[ -n ${PATCH_VER} ]] && \
-               unpack gcc-${PATCH_GCC_VER}-patches-${PATCH_VER}.tar.bz2
-
-       [[ -n ${UCLIBC_VER} ]] && \
-               unpack gcc-${UCLIBC_GCC_VER}-uclibc-patches-${UCLIBC_VER}.tar.bz2
+       do_gcc_gentoo_patches
+       do_gcc_HTB_patches
+       do_gcc_PIE_patches
+       do_gcc_CYGWINPORTS_patches
 
-       if want_pie ; then
-               if [[ -n ${PIE_CORE} ]] ; then
-                       unpack ${PIE_CORE}
-               else
-                       unpack gcc-${PIE_GCC_VER}-piepatches-v${PIE_VER}.tar.bz2
-               fi
-               [[ -n ${SPECS_VER} ]] && \
-                       unpack gcc-${SPECS_GCC_VER}-specs-${SPECS_VER}.tar.bz2
+       if tc_is_live ; then
+               BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION}, commit ${EGIT_VERSION}"
        fi
 
-       use_if_iuse boundschecking && unpack "bounds-checking-gcc-${HTB_GCC_VER}-${HTB_VER}.patch.bz2"
-
-       popd > /dev/null
-}
-
-#---->> src_prepare <<----
-
-toolchain_src_prepare() {
-       export BRANDING_GCC_PKGVERSION="Gentoo ${GCC_PVR}"
-       cd "${S}"
-
-       if ! use vanilla ; then
-               if [[ -n ${PATCH_VER} ]] ; then
-                       guess_patch_type_in_dir "${WORKDIR}"/patch
-                       EPATCH_MULTI_MSG="Applying Gentoo patches ..." \
-                       epatch "${WORKDIR}"/patch
-                       BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION} p${PATCH_VER}"
-               fi
-               if [[ -n ${UCLIBC_VER} ]] ; then
-                       guess_patch_type_in_dir "${WORKDIR}"/uclibc
-                       EPATCH_MULTI_MSG="Applying uClibc patches ..." \
-                       epatch "${WORKDIR}"/uclibc
-               fi
-       fi
-       do_gcc_HTB_patches
-       do_gcc_PIE_patches
-       epatch_user
+       case ${EAPI:-0} in
+               5*) epatch_user;;
+               6|7) eapply_user ;;
+               *) die "Update toolchain_src_prepare() for ${EAPI}." ;;
+       esac
 
        if ( tc_version_is_at_least 4.8.2 || use_if_iuse hardened ) && ! use vanilla ; then
                make_gcc_hard
@@ -531,13 +534,10 @@ toolchain_src_prepare() {
        gcc_version_patch
 
        if tc_version_is_at_least 4.1 ; then
-               if [[ -n ${SNAPSHOT} || -n ${PRERELEASE} ]] ; then
-                       # BASE-VER must be a three-digit version number
-                       # followed by an optional -pre string
-                       #   eg. 4.5.1, 4.6.2-pre20120213, 4.7.0-pre9999
-                       # If BASE-VER differs from ${PV/_/-} then libraries get installed in
-                       # the wrong directory.
-                       echo ${PV/_/-} > "${S}"/gcc/BASE-VER
+               local actual_version=$(< "${S}"/gcc/BASE-VER)
+               if [[ "${GCC_RELEASE_VER}" != "${actual_version}" ]] ; then
+                       eerror "'${S}/gcc/BASE-VER' contains '${actual_version}', expected '${GCC_RELEASE_VER}'"
+                       die "Please set 'TOOLCHAIN_GCC_PV' to '${actual_version}'"
                fi
        fi
 
@@ -588,8 +588,11 @@ toolchain_src_prepare() {
        sed -i 's|A-Za-z0-9|[:alnum:]|g' "${S}"/gcc/*.awk #215828
 
        # Prevent new texinfo from breaking old versions (see #198182, #464008)
-       tc_version_is_at_least 4.1 && epatch "${FILESDIR}"/gcc-configure-texinfo.patch
+       if tc_version_is_at_least 4.1; then
+               tc_apply_patches "Remove texinfo (bug #198182, bug #464008)" "${FILESDIR}"/gcc-configure-texinfo.patch
+       fi
 
+       # >=gcc-4
        if [[ -x contrib/gcc_update ]] ; then
                einfo "Touching generated files"
                ./contrib/gcc_update --touch | \
@@ -599,17 +602,23 @@ toolchain_src_prepare() {
        fi
 }
 
-guess_patch_type_in_dir() {
-       [[ -n $(ls "$1"/*.bz2 2>/dev/null) ]] \
-               && EPATCH_SUFFIX="patch.bz2" \
-               || EPATCH_SUFFIX="patch"
+do_gcc_gentoo_patches() {
+       if ! use vanilla ; then
+               if [[ -n ${PATCH_VER} ]] ; then
+                       tc_apply_patches "Applying Gentoo patches ..." "${WORKDIR}"/patch/*.patch
+                       BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION} p${PATCH_VER}"
+               fi
+               if [[ -n ${UCLIBC_VER} ]] ; then
+                       tc_apply_patches "Applying uClibc patches ..." "${WORKDIR}"/uclibc/*.patch
+               fi
+       fi
 }
 
 do_gcc_HTB_patches() {
        use_if_iuse boundschecking || return 0
 
        # modify the bounds checking patch with a regression patch
-       epatch "${WORKDIR}/bounds-checking-gcc-${HTB_GCC_VER}-${HTB_VER}.patch"
+       tc_apply_patches "Bounds checking patch" "${WORKDIR}/bounds-checking-gcc-${HTB_GCC_VER}-${HTB_VER}.patch"
        BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION}, HTB-${HTB_GCC_VER}-${HTB_VER}"
 }
 
@@ -617,34 +626,33 @@ do_gcc_PIE_patches() {
        want_pie || return 0
        use vanilla && return 0
 
-       if tc_version_is_at_least 4.3.2 ; then
-               guess_patch_type_in_dir "${WORKDIR}"/piepatch/
-               EPATCH_MULTI_MSG="Applying pie patches ..." \
-               epatch "${WORKDIR}"/piepatch/
-       else
-               guess_patch_type_in_dir "${WORKDIR}"/piepatch/upstream
-
-               # corrects startfile/endfile selection and shared/static/pie flag usage
-               EPATCH_MULTI_MSG="Applying upstream pie patches ..." \
-               epatch "${WORKDIR}"/piepatch/upstream
-               # adds non-default pie support (rs6000)
-               EPATCH_MULTI_MSG="Applying non-default pie patches ..." \
-               epatch "${WORKDIR}"/piepatch/nondef
-               # adds default pie support (rs6000 too) if DEFAULT_PIE[_SSP] is defined
-               EPATCH_MULTI_MSG="Applying default pie patches ..." \
-               epatch "${WORKDIR}"/piepatch/def
-       fi
+       tc_apply_patches "Applying pie patches ..." "${WORKDIR}"/piepatch/*.patch
 
        BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION}, pie-${PIE_VER}"
 }
 
+do_gcc_CYGWINPORTS_patches() {
+       [[ -n ${CYGWINPORTS_GITREV} ]] || return 0
+       use elibc_Cygwin || return 0
+
+       local p d="${WORKDIR}/gcc-${CYGWINPORTS_GITREV}"
+       # readarray -t is available since bash-4.4 only, #690686
+       local patches=( $(
+               for p in $(
+                       sed -e '1,/PATCH_URI="/d;/"/,$d' < "${d}"/gcc.cygport
+               ); do
+                       echo "${d}/${p}"
+               done
+       ) )
+       tc_apply_patches "Applying cygwin port patches ..." ${patches[*]}
+}
+
 # configure to build with the hardened GCC specs as the default
 make_gcc_hard() {
-
        local gcc_hard_flags=""
 
        # If we use gcc-6 or newer with pie enable to compile older gcc we need to pass -no-pie
-       # to stage1; bug 618908
+       # to stage1; bug #618908
        if ! tc_version_is_at_least 6.0 && [[ $(gcc-major-version) -ge 6 ]] ; then
                einfo "Disabling PIE in stage1 (only) ..."
                sed -i -e "/^STAGE1_LDFLAGS/ s/$/ -no-pie/" "${S}"/Makefile.in || die
@@ -659,7 +667,10 @@ make_gcc_hard() {
                        einfo "Updating gcc to use automatic SSP building ..."
                fi
                if use_if_iuse hardened ; then
-                       # Will add some optimatizion as default.
+                       # Will add some hardened options as default, like:
+                       # -fstack-clash-protection
+                       # -z now
+                       # see *_all_extra-options.patch gcc patches.
                        gcc_hard_flags+=" -DEXTRA_OPTIONS"
                        # rebrand to make bug reports easier
                        BRANDING_GCC_PKGVERSION=${BRANDING_GCC_PKGVERSION/Gentoo/Gentoo Hardened}
@@ -762,8 +773,7 @@ gcc_version_patch() {
        # gcc-4.3+ has configure flags (whoo!)
        tc_version_is_at_least 4.3 && return 0
 
-       local version_string=${GCC_CONFIG_VER}
-       [[ -n ${BRANCH_UPDATE} ]] && version_string+=" ${BRANCH_UPDATE}"
+       local version_string=${GCC_RELEASE_VER}
 
        einfo "patching gcc version: ${version_string} (${BRANDING_GCC_PKGVERSION})"
 
@@ -912,9 +922,9 @@ toolchain_src_configure() {
        tc_version_is_at_least 3.4 || confgcc+=( --disable-libunwind-exceptions )
 
        # Use the default ("release") checking because upstream usually neglects
-       # to test "disabled" so it has a history of breaking. #317217
+       # to test "disabled" so it has a history of breaking. bug #317217
        if tc_version_is_at_least 3.4 && in_iuse debug ; then
-               # The "release" keyword is new to 4.0. #551636
+               # The "release" keyword is new to 4.0. bug #551636
                local off=$(tc_version_is_at_least 4.0 && echo release || echo no)
                confgcc+=( --enable-checking="${GCC_CHECKS_LIST:-$(usex debug yes ${off})}" )
        fi
@@ -932,11 +942,16 @@ toolchain_src_configure() {
 
        # allow gcc to search for clock funcs in the main C lib.
        # if it can't find them, then tough cookies -- we aren't
-       # going to link in -lrt to all C++ apps.  #411681
+       # going to link in -lrt to all C++ apps. bug #411681
        if tc_version_is_at_least 4.4 && is_cxx ; then
                confgcc+=( --enable-libstdcxx-time )
        fi
 
+       # Build compiler itself using LTO
+       if tc_version_is_at_least 9.1 && use_if_iuse lto ; then
+               confgcc+=( --with-build-config=bootstrap-lto )
+       fi
+
        # Support to disable pch when building libstdcxx
        if tc_version_is_at_least 6.0 && ! use_if_iuse pch ; then
                confgcc+=( --disable-libstdcxx-pch )
@@ -945,7 +960,9 @@ toolchain_src_configure() {
        # The jit language requires this.
        is_jit && confgcc+=( --enable-host-shared )
 
-       # # Turn on the -Wl,--build-id flag by default for ELF targets. #525942
+       # build-id was disabled for file collisions: bug #526144
+       #
+       # # Turn on the -Wl,--build-id flag by default for ELF targets. bug #525942
        # # This helps with locating debug files.
        # case ${CTARGET} in
        # *-linux-*|*-elf|*-eabi)
@@ -971,7 +988,7 @@ toolchain_src_configure() {
                # disable a bunch of features or gcc goes boom
                local needed_libc=""
                case ${CTARGET} in
-               *-linux)                 needed_libc=no-fucking-clue;;
+               *-linux)                 needed_libc=error-unknown-libc;;
                *-dietlibc)              needed_libc=dietlibc;;
                *-elf|*-eabi)
                        needed_libc=newlib
@@ -986,18 +1003,19 @@ toolchain_src_configure() {
                *-klibc)                 needed_libc=klibc;;
                *-musl*)                 needed_libc=musl;;
                *-uclibc*)
+                       # Enable shared library support only on targets
+                       # that support it: bug #291870
                        if ! echo '#include <features.h>' | \
                           $(tc-getCPP ${CTARGET}) -E -dD - 2>/dev/null | \
                           grep -q __HAVE_SHARED__
-                       then #291870
+                       then
                                confgcc+=( --disable-shared )
                        fi
-                       needed_libc=uclibc
+                       needed_libc=uclibc-ng
                        ;;
                *-cygwin)                needed_libc=cygwin;;
                x86_64-*-mingw*|\
                *-w64-mingw*)    needed_libc=mingw64-runtime;;
-               mingw*|*-mingw*) needed_libc=mingw-runtime;;
                avr)                     confgcc+=( --enable-shared --disable-threads );;
                esac
                if [[ -n ${needed_libc} ]] ; then
@@ -1027,7 +1045,7 @@ toolchain_src_configure() {
                        confgcc+=( --enable-shared )
                fi
                case ${CHOST} in
-               mingw*|*-mingw*|*-cygwin)
+               mingw*|*-mingw*)
                        confgcc+=( --enable-threads=win32 ) ;;
                *)
                        confgcc+=( --enable-threads=posix ) ;;
@@ -1038,10 +1056,12 @@ toolchain_src_configure() {
        # destructors", but apparently requires glibc.
        case ${CTARGET} in
        *-uclibc*)
-               confgcc+=(
-                       --disable-__cxa_atexit
-                       $(use_enable nptl tls)
-               )
+               if tc_has_feature nptl ; then
+                       confgcc+=(
+                               --disable-__cxa_atexit
+                               $(use_enable nptl tls)
+                       )
+               fi
                tc_version_is_between 3.3 3.4 && confgcc+=( --enable-sjlj-exceptions )
                if tc_version_is_between 3.4 4.3 ; then
                        confgcc+=( --enable-clocale=uclibc )
@@ -1050,6 +1070,9 @@ toolchain_src_configure() {
        *-elf|*-eabi)
                confgcc+=( --with-newlib )
                ;;
+       *-musl*)
+               confgcc+=( --enable-__cxa_atexit )
+               ;;
        *-gnu*)
                confgcc+=(
                        --enable-__cxa_atexit
@@ -1148,6 +1171,19 @@ toolchain_src_configure() {
                is-flagq -mfloat-gprs=double && confgcc+=( --enable-e500-double )
                [[ ${CTARGET//_/-} == *-e500v2-* ]] && confgcc+=( --enable-e500-double )
                ;;
+       ppc64)
+               # On ppc64 big endian target gcc assumes elfv1 by default,
+               # and elfv2 on little endian
+               # but musl does not support elfv1 at all on any endian ppc64
+               # see https://git.musl-libc.org/cgit/musl/tree/INSTALL
+               # https://bugs.gentoo.org/704784
+               # https://gcc.gnu.org/PR93157
+               [[ ${CTARGET} == powerpc64-*-musl ]] && confgcc+=( --with-abi=elfv2 )
+               ;;
+       riscv)
+               # Add --with-abi flags to set default ABI
+               confgcc+=( --with-abi=$(gcc-abi-map ${TARGET_DEFAULT_ABI}) )
+               ;;
        esac
 
        # if the target can do biarch (-m32/-m64), enable it.  overhead should
@@ -1168,10 +1204,13 @@ toolchain_src_configure() {
 
        ### library options
 
-       if ! is_gcj ; then
-               confgcc+=( --disable-libgcj )
-       elif use awt ; then
-               confgcc+=( --enable-java-awt=gtk )
+       if tc_version_is_between 3.0 7.0 ; then
+               if is_gcj ; then
+                       confgcc+=( --disable-gjdoc )
+                       use awt && confgcc+=( --enable-java-awt=gtk )
+               else
+                       confgcc+=( --disable-libgcj )
+               fi
        fi
 
        if tc_version_is_at_least 4.2 ; then
@@ -1207,7 +1246,17 @@ toolchain_src_configure() {
                        if hardened_gcc_is_stable ssp; then
                                export gcc_cv_libc_provides_ssp=yes
                        fi
-                       confgcc+=( --disable-libssp )
+                       if use_if_iuse ssp; then
+                               # On some targets USE="ssp -libssp" is an invalid
+                               # configuration as target libc does not provide
+                               # stack_chk_* functions. Do not disable libssp there.
+                               case ${CTARGET} in
+                                       mingw*|*-mingw*) ewarn "Not disabling libssp" ;;
+                                       *) confgcc+=( --disable-libssp ) ;;
+                               esac
+                       else
+                               confgcc+=( --disable-libssp )
+                       fi
                fi
        fi
 
@@ -1219,13 +1268,22 @@ toolchain_src_configure() {
                confgcc+=( $(use_enable mpx libmpx) )
        fi
 
+       if in_iuse systemtap ; then
+               confgcc+=( $(use_enable systemtap) )
+       fi
+
        if in_iuse vtv ; then
                confgcc+=(
                        $(use_enable vtv vtable-verify)
-                       $(use_enable vtv libvtv)
+                       # See Note [implicitly enabled flags]
+                       $(usex vtv '' --disable-libvtv)
                )
        fi
 
+       if in_iuse zstd ; then
+               confgcc+=( $(use_with zstd) )
+       fi
+
        # newer gcc's come with libquadmath, but only fortran uses
        # it, so auto punt it when we don't care
        if tc_version_is_at_least 4.6 && ! is_fortran ; then
@@ -1238,20 +1296,26 @@ toolchain_src_configure() {
                confgcc+=( --disable-lto )
        fi
 
-       # graphite was added in 4.4 but we only support it in 4.8+ due to external
-       # library issues.  #448024
-       if tc_version_is_at_least 5.0 && in_iuse graphite ; then
+       # graphite was added in 4.4 but we only support it in 6.5+ due to external
+       # library issues.  #448024, #701270
+       if tc_version_is_at_least 6.5 && in_iuse graphite ; then
                confgcc+=( $(use_with graphite isl) )
                use graphite && confgcc+=( --disable-isl-version-check )
-       elif tc_version_is_at_least 4.8 && in_iuse graphite ; then
-               confgcc+=( $(use_with graphite cloog) )
-               use graphite && confgcc+=( --disable-isl-version-check )
+       elif tc_version_is_at_least 5.0 ; then
+               confgcc+=( --without-isl )
+       elif tc_version_is_at_least 4.8 ; then
+               confgcc+=( --without-cloog )
        elif tc_version_is_at_least 4.4 ; then
                confgcc+=( --without-{cloog,ppl} )
        fi
 
-       if tc_version_is_at_least 4.8 && in_iuse sanitize ; then
-               confgcc+=( $(use_enable sanitize libsanitizer) )
+       if tc_version_is_at_least 4.8; then
+               if in_iuse sanitize ; then
+                       # See Note [implicitly enabled flags]
+                       confgcc+=( $(usex sanitize '' --disable-libsanitizer) )
+               else
+                       confgcc+=( --disable-libsanitizer )
+               fi
        fi
 
        if tc_version_is_at_least 6.0 && in_iuse pie ; then
@@ -1298,7 +1362,7 @@ toolchain_src_configure() {
        addwrite /dev/zero
        echo "${S}"/configure "${confgcc[@]}"
        # Older gcc versions did not detect bash and re-exec itself, so force the
-       # use of bash.  Newer ones will auto-detect, but this is not harmeful.
+       # use of bash.  Newer ones will auto-detect, but this is not harmful.
        CONFIG_SHELL="${EPREFIX}/bin/bash" \
        bash "${S}"/configure "${confgcc[@]}" || die "failed to run configure"
 
@@ -1312,7 +1376,8 @@ downgrade_arch_flags() {
        local arch bver i isa myarch mytune rep ver
 
        bver=${1:-${GCC_BRANCH_VER}}
-       [[ $(gcc-version) < ${bver} ]] && return 0
+       # Don't perform downgrade if running gcc is older than ebuild's.
+       tc_version_is_at_least ${bver} $(gcc-version) || return 0
        [[ $(tc-arch) != amd64 && $(tc-arch) != x86 ]] && return 0
 
        myarch=$(get-flag march)
@@ -1320,7 +1385,7 @@ downgrade_arch_flags() {
 
        # If -march=native isn't supported we have to tease out the actual arch
        if [[ ${myarch} == native || ${mytune} == native ]] ; then
-               if [[ ${bver} < 4.2 ]] ; then
+               if ! tc_version_is_at_least 4.2 ${bver}; then
                        arch=$($(tc-getCC) -march=native -v -E -P - </dev/null 2>&1 \
                                | sed -rn "/cc1.*-march/s:.*-march=([^ ']*).*:\1:p")
                        replace-cpu-flags native ${arch}
@@ -1328,10 +1393,10 @@ downgrade_arch_flags() {
        fi
 
        # Handle special -mtune flags
-       [[ ${mytune} == intel && ${bver} < 4.9 ]] && replace-cpu-flags intel generic
-       [[ ${mytune} == generic && ${bver} < 4.2 ]] && filter-flags '-mtune=*'
+       [[ ${mytune} == intel ]] && ! tc_version_is_at_least 4.9 ${bver} && replace-cpu-flags intel generic
+       [[ ${mytune} == generic ]] && ! tc_version_is_at_least 4.2 ${bver} && filter-flags '-mtune=*'
        [[ ${mytune} == x86-64 ]] && filter-flags '-mtune=*'
-       [[ ${bver} < 3.4 ]] && filter-flags '-mtune=*'
+       tc_version_is_at_least 3.4 ${bver} || filter-flags '-mtune=*'
 
        # "added" "arch" "replacement"
        local archlist=(
@@ -1381,8 +1446,8 @@ downgrade_arch_flags() {
 
                [[ ${myarch} != ${arch} && ${mytune} != ${arch} ]] && continue
 
-               if [[ ${ver} > ${bver} ]] ; then
-                       einfo "Replacing ${myarch} (added in gcc ${ver}) with ${rep}..."
+               if ! tc_version_is_at_least ${ver} ${bver}; then
+                       einfo "Downgrading '${myarch}' (added in gcc ${ver}) with '${rep}'..."
                        [[ ${myarch} == ${arch} ]] && replace-cpu-flags ${myarch} ${rep}
                        [[ ${mytune} == ${arch} ]] && replace-cpu-flags ${mytune} ${rep}
                        continue
@@ -1430,13 +1495,17 @@ downgrade_arch_flags() {
        for ((i = 0; i < ${#isalist[@]}; i += 2)) ; do
                ver=${isalist[i]}
                isa=${isalist[i + 1]}
-               [[ ${ver} > ${bver} ]] && filter-flags ${isa} ${isa/-m/-mno-}
+               tc_version_is_at_least ${ver} ${bver} || filter-flags ${isa} ${isa/-m/-mno-}
        done
 }
 
 gcc_do_filter_flags() {
+       # Be conservative here:
+       # - don't allow -O3 and like to over-optimize libgcc # 701786
+       # - don't allow -O0 to generate potentially invalid startup code
        strip-flags
-       replace-flags -O? -O2
+       filter-flags '-O?'
+       append-flags -O2
 
        # dont want to funk ourselves
        filter-flags '-mabi*' -m31 -m32 -m64
@@ -1455,6 +1524,19 @@ gcc_do_filter_flags() {
                filter-flags -f{no-,}unit-at-a-time -f{no-,}web -mno-tls-direct-seg-refs
                filter-flags -f{no-,}stack-protector{,-all}
                filter-flags -fvisibility-inlines-hidden -fvisibility=hidden
+               # and warning options
+               filter-flags -Wextra -Wstack-protector
+       fi
+       if ! tc_version_is_at_least 4.1 ; then
+               filter-flags -fdiagnostics-show-option
+               filter-flags -Wstack-protector
+       fi
+
+       if tc_version_is_between 6 8 ; then
+               # -mstackrealign triggers crashes in exception throwing
+               # at least on ada: bug #688580
+               # The reason is unknown. Drop the flag for now.
+               filter-flags -mstackrealign
        fi
 
        if tc_version_is_at_least 3.4 ; then
@@ -1551,6 +1633,7 @@ gcc-abi-map() {
        local map=()
        case ${CTARGET} in
        mips*)   map=("o32 32" "n32 n32" "n64 64") ;;
+       riscv*)  map=("lp64d lp64d" "lp64 lp64") ;;
        x86_64*) map=("amd64 m64" "x86 m32" "x32 mx32") ;;
        esac
 
@@ -1570,6 +1653,11 @@ toolchain_src_compile() {
        [[ ! -x /usr/bin/perl ]] \
                && find "${WORKDIR}"/build -name '*.[17]' -exec touch {} +
 
+       # Older gcc versions did not detect bash and re-exec itself, so force the
+       # use of bash.  Newer ones will auto-detect, but this is not harmful.
+       # This needs to be set for compile as well, as it's used in libtool
+       # generation, which will break install otherwise (at least in 3.3.6): #664486
+       CONFIG_SHELL="${EPREFIX}/bin/bash" \
        gcc_do_make ${GCC_MAKE_TARGET}
 }
 
@@ -1660,10 +1748,11 @@ gcc_do_make() {
 #---->> src_test <<----
 
 toolchain_src_test() {
-       if use regression-test ; then
-               cd "${WORKDIR}"/build
-               emake -k check
-       fi
+       cd "${WORKDIR}"/build
+       # 'asan' wants to be preloaded first, so does 'sandbox'.
+       # To make asan tests work disable sandbox for all of test suite.
+       # 'backtrace' tests also does not like 'libsandbox.so' presence.
+       SANDBOX_ON=0 LD_PRELOAD= emake -k check
 }
 
 #---->> src_install <<----
@@ -1671,7 +1760,7 @@ toolchain_src_test() {
 toolchain_src_install() {
        cd "${WORKDIR}"/build
 
-       # Do allow symlinks in private gcc include dir as this can break the build
+       # Don't allow symlinks in private gcc include dir as this can break the build
        find gcc/include*/ -type l -delete
 
        # Copy over the info pages.  We disabled their generation earlier, but the
@@ -1699,9 +1788,9 @@ toolchain_src_install() {
        S="${WORKDIR}"/build emake -j1 DESTDIR="${D}" install || die
 
        # Punt some tools which are really only useful while building gcc
-       find "${D}" -name install-tools -prune -type d -exec rm -rf "{}" \;
+       find "${ED}" -name install-tools -prune -type d -exec rm -rf "{}" \;
        # This one comes with binutils
-       find "${D}" -name libiberty.a -delete
+       find "${ED}" -name libiberty.a -delete
 
        # Move the libraries to the proper location
        gcc_movelibs
@@ -1710,11 +1799,12 @@ toolchain_src_install() {
        if ! is_crosscompile ; then
                local EXEEXT
                eval $(grep ^EXEEXT= "${WORKDIR}"/build/gcc/config.log)
-               [[ -r ${D}${BINPATH}/gcc${EXEEXT} ]] || die "gcc not found in ${D}"
+               [[ -r ${D}${BINPATH}/gcc${EXEEXT} ]] || die "gcc not found in ${ED}"
        fi
 
        dodir /etc/env.d/gcc
        create_gcc_env_entry
+       create_revdep_rebuild_entry
 
        # Setup the gcc_env_entry for hardened gcc 4 with minispecs
        want_minispecs && copy_minispecs_gcc_specs
@@ -1727,7 +1817,7 @@ toolchain_src_install() {
        cd "${D}"${BINPATH}
        # Ugh: we really need to auto-detect this list.
        #      It's constantly out of date.
-       for x in cpp gcc g++ c++ gcov g77 gcj gcjh gfortran gccgo ; do
+       for x in cpp gcc g++ c++ gcov g77 gcj gcjh gfortran gccgo gnat* ; do
                # For some reason, g77 gets made instead of ${CTARGET}-g77...
                # this should take care of that
                if [[ -f ${x} ]] ; then
@@ -1740,11 +1830,11 @@ toolchain_src_install() {
                if [[ -f ${CTARGET}-${x} ]] ; then
                        if ! is_crosscompile ; then
                                ln -sf ${CTARGET}-${x} ${x}
-                               dosym ${BINPATH#${EPREFIX}}/${CTARGET}-${x} \
+                               dosym ${BINPATH}/${CTARGET}-${x} \
                                        /usr/bin/${x}-${GCC_CONFIG_VER}
                        fi
                        # Create versioned symlinks
-                       dosym ${BINPATH#${EPREFIX}}/${CTARGET}-${x} \
+                       dosym ${BINPATH}/${CTARGET}-${x} \
                                /usr/bin/${CTARGET}-${x}-${GCC_CONFIG_VER}
                fi
 
@@ -1753,51 +1843,54 @@ toolchain_src_install() {
                        ln -sf ${CTARGET}-${x} ${CTARGET}-${x}-${GCC_CONFIG_VER}
                fi
        done
-       # Rename the main go binaries as we don't want to clobber dev-lang/go
-       # when gcc-config runs. #567806
-       if tc_version_is_at_least 5 && is_go ; then
-               for x in go gofmt; do
-                       mv ${x} ${x}-${GCCMAJOR} || die
-               done
+
+       # When gcc builds a crosscompiler it does not install unprefixed tools.
+       # When cross-building gcc does install native tools.
+       if ! is_crosscompile; then
+               # Rename the main go binaries as we don't want to clobber dev-lang/go
+               # when gcc-config runs. #567806
+               if tc_version_is_at_least 5 && is_go ; then
+                       for x in go gofmt; do
+                               mv ${x} ${x}-${GCCMAJOR} || die
+                       done
+               fi
        fi
 
-       # Now do the fun stripping stuff
-       env RESTRICT="" CHOST=${CHOST} prepstrip "${D}${BINPATH}"
-       is_crosscompile && \
-               env RESTRICT="" CHOST=${CHOST} prepstrip "${D}${HOSTLIBPATH}"
-       env RESTRICT="" CHOST=${CTARGET} prepstrip "${D}${LIBPATH}"
-       # gcc used to install helper binaries in lib/ but then moved to libexec/
-       [[ -d ${D}${PREFIX}/libexec/gcc ]] && \
-               env RESTRICT="" CHOST=${CHOST} prepstrip "${D}${PREFIX}/libexec/gcc/${CTARGET}/${GCC_CONFIG_VER}"
+       # As gcc installs object files built against bost ${CHOST} and ${CTARGET}
+       # ideally we will need to strip them using different tools:
+       # Using ${CHOST} tools:
+       #  - "${D}${BINPATH}"
+       #  - (for is_crosscompile) "${D}${HOSTLIBPATH}"
+       #  - "${D}${PREFIX}/libexec/gcc/${CTARGET}/${GCC_CONFIG_VER}"
+       # Using ${CTARGET} tools:
+       #  - "${D}${LIBPATH}"
+       # As dostrip does not specify host to override ${CHOST} tools just skip
+       # non-native binary stripping.
+       is_crosscompile && tc_supports_dostrip && dostrip -x "${LIBPATH}"
 
        cd "${S}"
        if is_crosscompile; then
-               rm -rf "${ED}"usr/share/{man,info}
+               rm -rf "${ED}"/usr/share/{man,info}
                rm -rf "${D}"${DATAPATH}/{man,info}
        else
                if tc_version_is_at_least 3.0 ; then
                        local cxx_mandir=$(find "${WORKDIR}/build/${CTARGET}/libstdc++-v3" -name man)
                        if [[ -d ${cxx_mandir} ]] ; then
-                               cp -r "${cxx_mandir}"/man? "${D}/${DATAPATH}"/man/
+                               cp -r "${cxx_mandir}"/man? "${D}${DATAPATH}"/man/
                        fi
                fi
-               has noinfo ${FEATURES} \
-                       && rm -r "${D}${DATAPATH}"/info \
-                       || prepinfo "${DATAPATH#${EPREFIX}}"
-               has noman ${FEATURES} \
-                       && rm -r "${D}${DATAPATH}"/man \
-                       || prepman "${DATAPATH#${EPREFIX}}"
        fi
-       # prune empty dirs left behind
-       find "${D}" -depth -type d -delete 2>/dev/null
 
-       # install testsuite results
-       if use regression-test; then
-               docinto testsuite
-               find "${WORKDIR}"/build -type f -name "*.sum" -exec dodoc {} +
-               find "${WORKDIR}"/build -type f -path "*/testsuite/*.log" -exec dodoc {} +
+       # portage regenerates 'dir' files on it's own: bug #672408
+       # Drop 'dir' files to avoid collisions.
+       if [[ -f "${D}${DATAPATH}"/info/dir ]]; then
+               einfo "Deleting '${D}${DATAPATH}/info/dir'"
+               rm "${D}${DATAPATH}"/info/dir || die
        fi
 
+       # prune empty dirs left behind
+       find "${ED}" -depth -type d -delete 2>/dev/null
+
        # Rather install the script, else portage with changing $FILESDIR
        # between binary and source package borks things ....
        if ! is_crosscompile && [[ ${PN} != "kgcc64" ]] ; then
@@ -1829,7 +1922,7 @@ toolchain_src_install() {
        # libvtv.la: gcc itself handles linkage correctly.
        # lib*san.la: Sanitizer linkage is handled internally by gcc, and they
        # do not support static linking. #487550 #546700
-       find "${D}/${LIBPATH}" \
+       find "${D}${LIBPATH}" \
                '(' \
                        -name libstdc++.la -o \
                        -name libstdc++fs.la -o \
@@ -1853,8 +1946,8 @@ toolchain_src_install() {
        # for people who are testing as non-root.
        chown -R root:0 "${D}${LIBPATH}" 2>/dev/null
 
-       # Move pretty-printers to gdb datadir to shut ldconfig up
-       local py gdbdir=/usr/share/gdb/auto-load${LIBPATH/\/lib\//\/$(get_libdir)\/}
+       # Installing gdb pretty-printers into gdb-specific location.
+       local py gdbdir=/usr/share/gdb/auto-load${LIBPATH}
        pushd "${D}${LIBPATH}" >/dev/null
        for py in $(find . -name '*-gdb.py') ; do
                local multidir=${py%/*}
@@ -1895,7 +1988,7 @@ gcc_movelibs() {
        # code to run on the target.
        if tc_version_is_at_least 5 && is_crosscompile ; then
                dodir "${HOSTLIBPATH#${EPREFIX}}"
-               mv "${ED}"usr/$(get_libdir)/libcc1* "${D}${HOSTLIBPATH}" || die
+               mv "${ED}"/usr/$(get_libdir)/libcc1* "${D}${HOSTLIBPATH}" || die
        fi
 
        # For all the libs that are built for CTARGET, move them into the
@@ -1945,7 +2038,7 @@ gcc_movelibs() {
        for FROMDIR in ${removedirs} ; do
                rmdir "${D}"${FROMDIR} >& /dev/null
        done
-       find -depth "${D}" -type d -exec rmdir {} + >& /dev/null
+       find -depth "${ED}" -type d -exec rmdir {} + >& /dev/null
 }
 
 # make sure the libtool archives have libdir set to where they actually
@@ -2014,8 +2107,6 @@ create_gcc_env_entry() {
        fi
 
        cat <<-EOF > ${gcc_envd_file}
-       PATH="${BINPATH}"
-       ROOTPATH="${BINPATH}"
        GCC_PATH="${BINPATH}"
        LDPATH="${ldpaths}"
        MANPATH="${DATAPATH}/man"
@@ -2027,6 +2118,20 @@ create_gcc_env_entry() {
        EOF
 }
 
+create_revdep_rebuild_entry() {
+       local revdep_rebuild_base="/etc/revdep-rebuild/05cross-${CTARGET}-${GCC_CONFIG_VER}"
+       local revdep_rebuild_file="${ED}${revdep_rebuild_base}"
+
+       is_crosscompile || return 0
+
+       dodir /etc/revdep-rebuild
+       cat <<-EOF > "${revdep_rebuild_file}"
+       # Generated by ${CATEGORY}/${PF}
+       # Ignore libraries built for ${CTARGET}, https://bugs.gentoo.org/692844.
+       SEARCH_DIRS_MASK="${LIBPATH}"
+       EOF
+}
+
 copy_minispecs_gcc_specs() {
        # on gcc 6 we don't need minispecs
        if tc_version_is_at_least 6.0 ; then
@@ -2092,7 +2197,7 @@ gcc_slot_java() {
 
 toolchain_pkg_postinst() {
        do_gcc_config
-       if [[ ${ROOT} == / && -f ${EPREFIX}/usr/share/eselect/modules/compiler-shadow.eselect ]] ; then
+       if [[ ! ${ROOT%/} && -f ${EPREFIX}/usr/share/eselect/modules/compiler-shadow.eselect ]] ; then
                eselect compiler-shadow update all
        fi
 
@@ -2107,33 +2212,23 @@ toolchain_pkg_postinst() {
                echo
 
                # Clean up old paths
-               rm -f "${EROOT}"*/rcscripts/awk/fixlafiles.awk "${EROOT}"sbin/fix_libtool_files.sh
-               rmdir "${EROOT}"*/rcscripts{/awk,} 2>/dev/null
+               rm -f "${EROOT%/}"/*/rcscripts/awk/fixlafiles.awk "${EROOT%/}"/sbin/fix_libtool_files.sh
+               rmdir "${EROOT%/}"/*/rcscripts{/awk,} 2>/dev/null
 
-               mkdir -p "${EROOT}"usr/{share/gcc-data,sbin,bin}
+               mkdir -p "${EROOT%/}"/usr/{share/gcc-data,sbin,bin}
                # DATAPATH has EPREFIX already, use ROOT with it
-               cp "${ROOT}${DATAPATH}"/fixlafiles.awk "${EROOT}"usr/share/gcc-data/ || die
-               cp "${ROOT}${DATAPATH}"/fix_libtool_files.sh "${EROOT}"usr/sbin/ || die
+               cp "${ROOT%/}${DATAPATH}"/fixlafiles.awk "${EROOT%/}"/usr/share/gcc-data/ || die
+               cp "${ROOT%/}${DATAPATH}"/fix_libtool_files.sh "${EROOT%/}"/usr/sbin/ || die
 
                # Since these aren't critical files and portage sucks with
                # handling of binpkgs, don't require these to be found
-               cp "${ROOT}${DATAPATH}"/c{89,99} "${EROOT}"usr/bin/ 2>/dev/null
-       fi
-
-       if use regression-test ; then
-               elog "Testsuite results have been installed into /usr/share/doc/${PF}/testsuite"
-               echo
-       fi
-
-       if [[ -n ${PRERELEASE}${SNAPSHOT} ]] ; then
-               einfo "This GCC ebuild is provided for your convenience, and the use"
-               einfo "of this compiler is not supported by the Gentoo Developers."
-               einfo "Please report bugs to upstream at http://gcc.gnu.org/bugzilla/"
+               cp "${ROOT%/}${DATAPATH}"/c{89,99} "${EROOT%/}"/usr/bin/ 2>/dev/null
        fi
 }
 
 toolchain_pkg_postrm() {
-       if [[ ${ROOT} == / && -f ${EPREFIX}/usr/share/eselect/modules/compiler-shadow.eselect ]] ; then
+       do_gcc_config
+       if [[ ! ${ROOT%/} && -f ${EPREFIX}/usr/share/eselect/modules/compiler-shadow.eselect ]] ; then
                eselect compiler-shadow clean all
        fi
 
@@ -2144,27 +2239,21 @@ toolchain_pkg_postrm() {
 
        # clean up the cruft left behind by cross-compilers
        if is_crosscompile ; then
-               if [[ -z $(ls "${EROOT}"etc/env.d/gcc/${CTARGET}* 2>/dev/null) ]] ; then
-                       rm -f "${EROOT}"etc/env.d/gcc/config-${CTARGET}
-                       rm -f "${EROOT}"etc/env.d/??gcc-${CTARGET}
-                       rm -f "${EROOT}"usr/bin/${CTARGET}-{gcc,{g,c}++}{,32,64}
+               if [[ -z $(ls "${EROOT%/}"/etc/env.d/gcc/${CTARGET}* 2>/dev/null) ]] ; then
+                       einfo "Removing last cross-compiler instance. Deleting dangling symlinks."
+                       rm -f "${EROOT%/}"/etc/env.d/gcc/config-${CTARGET}
+                       rm -f "${EROOT%/}"/etc/env.d/??gcc-${CTARGET}
+                       rm -f "${EROOT%/}"/usr/bin/${CTARGET}-{gcc,{g,c}++}{,32,64}
                fi
                return 0
        fi
 
        # ROOT isnt handled by the script
-       [[ ${ROOT} != "/" ]] && return 0
+       [[ ${ROOT%/} ]] && return 0
 
        if [[ ! -e ${LIBPATH}/libstdc++.so ]] ; then
-               # make sure the profile is sane during same-slot upgrade #289403
-               do_gcc_config
-
                einfo "Running 'fix_libtool_files.sh ${GCC_RELEASE_VER}'"
                fix_libtool_files.sh ${GCC_RELEASE_VER}
-               if [[ -n ${BRANCH_UPDATE} ]] ; then
-                       einfo "Running 'fix_libtool_files.sh ${GCC_RELEASE_VER}-${BRANCH_UPDATE}'"
-                       fix_libtool_files.sh ${GCC_RELEASE_VER}-${BRANCH_UPDATE}
-               fi
        fi
 
        return 0
@@ -2186,7 +2275,7 @@ do_gcc_config() {
                [[ -n ${current_specs} ]] && use_specs=-${current_specs}
 
                if [[ -n ${use_specs} ]] && \
-                  [[ ! -e ${ROOT}/etc/env.d/gcc/${CTARGET}-${GCC_CONFIG_VER}${use_specs} ]]
+                  [[ ! -e ${EROOT%/}/etc/env.d/gcc/${CTARGET}-${GCC_CONFIG_VER}${use_specs} ]]
                then
                        ewarn "The currently selected specs-specific gcc config,"
                        ewarn "${current_specs}, doesn't exist anymore. This is usually"
@@ -2219,7 +2308,7 @@ should_we_gcc_config() {
        # for being in the same SLOT, make sure we run gcc-config.
        local curr_config_ver=$(gcc-config -S ${curr_config} | awk '{print $2}')
 
-       local curr_branch_ver=$(get_version_component_range 1-2 ${curr_config_ver})
+       local curr_branch_ver=$(ver_cut 1-2 ${curr_config_ver})
 
        if [[ ${curr_branch_ver} == ${GCC_BRANCH_VER} ]] ; then
                return 0
@@ -2266,7 +2355,6 @@ is_ada() {
 
 is_cxx() {
        gcc-lang-supported 'c++' || return 1
-       ! is_crosscompile && tc_version_is_at_least 4.8 && return 0
        use_if_iuse cxx
 }
 
@@ -2302,6 +2390,10 @@ is_go() {
 
 is_jit() {
        gcc-lang-supported jit || return 1
+       # cross-compiler does not really support jit as it has
+       # to generate code for a target. On target like avr
+       # libgcclit.so can't link at all: bug #594572
+       is_crosscompile && return 1
        use_if_iuse jit
 }
 
@@ -2427,3 +2519,21 @@ toolchain_death_notice() {
                popd >/dev/null
        fi
 }
+
+# Note [implicitly enabled flags]
+# -------------------------------
+# Usually configure-based packages handle explicit feature requests
+# like
+#     ./configure --enable-foo
+# as explicit request to check for support of 'foo' and bail out at
+# configure time.
+#
+# GCC does not follow this pattern and instead overrides autodetection
+# of the feature and enables it unconditionally.
+# See bugs:
+#    https://gcc.gnu.org/PR85663 (libsanitizer on mips)
+#    https://bugs.gentoo.org/661252 (libvtv on powerpc64)
+#
+# Thus safer way to enable/disable the feature is to rely on implicit
+# enabled-by-default state:
+#    econf $(usex foo '' --disable-foo)