diff options
author | Martin Liska <mliska@suse.cz> | 2021-12-17 15:04:02 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-12-17 15:04:02 +0100 |
commit | a29aa2eafa30efffed38b14fcbad9513c5dd2590 (patch) | |
tree | 04b7f0deed20e618941225b57f15c30429179cf6 | |
parent | 9d82b7b438bab705ca6da09e997c28c0439e5f72 (diff) | |
parent | 7dca2ad64910ba4aeae8e1f373f4d4796702b42b (diff) | |
download | gcc-a29aa2eafa30efffed38b14fcbad9513c5dd2590.zip gcc-a29aa2eafa30efffed38b14fcbad9513c5dd2590.tar.gz gcc-a29aa2eafa30efffed38b14fcbad9513c5dd2590.tar.bz2 |
Merge branch 'master' into devel/sphinx
114 files changed, 2445 insertions, 641 deletions
@@ -1,3 +1,21 @@ +2021-12-16 Matthias Seidel <mseidel@apache.org> + + * config.sub: Fix typo. + +2021-12-16 H.J. Lu <hjl.tools@gmail.com> + + Revert: + 2021-12-15 H.J. Lu <hjl.tools@gmail.com> + + * Makefile.tpl (AR): Add @AR_PLUGIN_OPTION@ + (RANLIB): Add @RANLIB_PLUGIN_OPTION@. + * configure.ac: Include config/gcc-plugin.m4. + AC_SUBST AR_PLUGIN_OPTION and RANLIB_PLUGIN_OPTION. + * libtool.m4 (_LT_CMD_OLD_ARCHIVE): Pass --plugin to AR and + RANLIB if possible. + * Makefile.in: Regenerated. + * configure: Likewise. + 2021-12-15 H.J. Lu <hjl.tools@gmail.com> * Makefile.tpl (BUILD_CFLAGS): New. diff --git a/config.sub b/config.sub index 63c1f1c..38f3d03 100755..100644 --- a/config.sub +++ b/config.sub @@ -2,7 +2,9 @@ # Configuration validation subroutine script. # Copyright 1992-2021 Free Software Foundation, Inc. -timestamp='2021-01-08' +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2021-10-27' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +52,14 @@ timestamp='2021-01-08' # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. -me=$(echo "$0" | sed -e 's,.*/,,') +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + +me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS @@ -112,9 +121,11 @@ esac # Split fields of configuration type # shellcheck disable=SC2162 +saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <<EOF $1 EOF +IFS=$saved_IFS # Separate into logical components for further validation case $1 in @@ -163,6 +174,10 @@ case $1 in basic_machine=$field1 basic_os=$field2 ;; + zephyr*) + basic_machine=$field1-unknown + basic_os=$field2 + ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ @@ -769,22 +784,22 @@ case $basic_machine in vendor=hp ;; i*86v32) - cpu=$(echo "$1" | sed -e 's/86.*/86/') + cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv32 ;; i*86v4*) - cpu=$(echo "$1" | sed -e 's/86.*/86/') + cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv4 ;; i*86v) - cpu=$(echo "$1" | sed -e 's/86.*/86/') + cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv ;; i*86sol2) - cpu=$(echo "$1" | sed -e 's/86.*/86/') + cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=solaris2 ;; @@ -917,14 +932,16 @@ case $basic_machine in ;; leon-*|leon[3-9]-*) cpu=sparc - vendor=$(echo "$basic_machine" | sed 's/-.*//') + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) # shellcheck disable=SC2162 + saved_IFS=$IFS IFS="-" read cpu vendor <<EOF $basic_machine EOF + IFS=$saved_IFS ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and @@ -1084,7 +1101,7 @@ case $cpu-$vendor in cpu=mipsisa64sb1el ;; sh5e[lb]-*) - cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/') + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` ;; spur-*) cpu=spur @@ -1102,7 +1119,7 @@ case $cpu-$vendor in cpu=x86_64 ;; xscale-* | xscalee[bl]-*) - cpu=$(echo "$cpu" | sed 's/^xscale/arm/') + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` ;; arm64-*) cpu=aarch64 @@ -1165,7 +1182,7 @@ case $cpu-$vendor in | alphapca5[67] | alpha64pca5[67] \ | am33_2.0 \ | amdgcn \ - | arc | arceb \ + | arc | arceb | arc32 | arc64 \ | arm | arm[lb]e | arme[lb] | armv* \ | avr | avr32 \ | asmjs \ @@ -1204,9 +1221,13 @@ case $cpu-$vendor in | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r3 | mipsisa32r3el \ + | mipsisa32r5 | mipsisa32r5el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r3 | mipsisa64r3el \ + | mipsisa64r5 | mipsisa64r5el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ @@ -1283,35 +1304,37 @@ esac if test x$basic_os != x then -# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just +# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux - os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|') + os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` ;; os2-emx) kernel=os2 - os=$(echo $basic_os | sed -e 's|os2-emx|emx|') + os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` ;; nto-qnx*) kernel=nto - os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|') + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ;; *-*) # shellcheck disable=SC2162 + saved_IFS=$IFS IFS="-" read kernel os <<EOF $basic_os EOF + IFS=$saved_IFS ;; # Default OS when just kernel was specified nto*) kernel=nto - os=$(echo $basic_os | sed -e 's|nto|qnx|') + os=`echo "$basic_os" | sed -e 's|nto|qnx|'` ;; linux*) kernel=linux - os=$(echo $basic_os | sed -e 's|linux|gnu|') + os=`echo "$basic_os" | sed -e 's|linux|gnu|'` ;; *) kernel= @@ -1332,7 +1355,7 @@ case $os in os=cnk ;; solaris1 | solaris1.*) - os=$(echo $os | sed -e 's|solaris1|sunos4|') + os=`echo "$os" | sed -e 's|solaris1|sunos4|'` ;; solaris) os=solaris2 @@ -1361,7 +1384,7 @@ case $os in os=sco3.2v4 ;; sco3.2.[4-9]*) - os=$(echo $os | sed -e 's/sco3.2./sco3.2v/') + os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'` ;; sco*v* | scout) # Don't match below @@ -1391,7 +1414,7 @@ case $os in os=lynxos ;; mac[0-9]*) - os=$(echo "$os" | sed -e 's|mac|macos|') + os=`echo "$os" | sed -e 's|mac|macos|'` ;; opened*) os=openedition @@ -1400,10 +1423,10 @@ case $os in os=os400 ;; sunos5*) - os=$(echo "$os" | sed -e 's|sunos5|solaris2|') + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; sunos6*) - os=$(echo "$os" | sed -e 's|sunos6|solaris3|') + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; wince*) os=wince @@ -1437,7 +1460,7 @@ case $os in ;; # Preserve the version number of sinix5. sinix5.*) - os=$(echo $os | sed -e 's|sinix|sysv|') + os=`echo "$os" | sed -e 's|sinix|sysv|'` ;; sinix*) os=sysv4 @@ -1684,7 +1707,7 @@ fi # Now, validate our (potentially fixed-up) OS. case $os in # Sometimes we do "kernel-libc", so those need to count as OSes. - musl* | newlib* | uclibc*) + musl* | newlib* | relibc* | uclibc*) ;; # Likewise for "kernel-abi" eabi* | gnueabi*) @@ -1707,12 +1730,12 @@ case $os in | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ | mirbsd* | netbsd* | dicos* | openedition* | ose* \ - | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ | udi* | lites* | ieee* | go32* | aux* | hcos* \ - | chorusrdb* | cegcc* | glidix* \ + | chorusrdb* | cegcc* | glidix* | serenity* \ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ | midipix* | mingw32* | mingw64* | mint* \ | uxpv* | beos* | mpeix* | udk* | moxiebox* \ @@ -1725,7 +1748,8 @@ case $os in | skyos* | haiku* | rdos* | toppers* | drops* | es* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ - | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*) + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ + | fiwix* ) ;; # This one is extra strict with allowed versions sco3.2v2 | sco3.2v[4-9]* | sco5v6*) @@ -1742,11 +1766,12 @@ esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in - linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ + | linux-musl* | linux-relibc* | linux-uclibc* ) ;; uclinux-uclibc* ) ;; - -dietlibc* | -newlib* | -musl* | -uclibc* ) + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 diff --git a/config/ChangeLog b/config/ChangeLog index 7c2d754..5bc7097 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,3 +1,10 @@ +2021-12-16 H.J. Lu <hjl.tools@gmail.com> + + Revert: + 2021-12-16 H.J. Lu <hjl.tools@gmail.com> + + * gcc-plugin.m4 (GCC_PLUGIN_OPTION): New. + 2021-12-15 H.J. Lu <hjl.tools@gmail.com> * gcc-plugin.m4 (GCC_PLUGIN_OPTION): New. diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 6827325..a027d4b 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,7 @@ +2021-12-16 Xionghu Luo <luoxhu@linux.ibm.com> + + * analyze_brprob_spec.py: Add verbose argument. + 2021-12-06 Martin Liska <mliska@suse.cz> * filter-clang-warnings.py: Filter out one warning. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f2bd21b..02e8f71 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,65 @@ +2021-12-16 Uroš Bizjak <ubizjak@gmail.com> + + PR target/103571 + * config/i386/i386.h (VALID_AVX256_REG_MODE): Add V16HFmode. + (VALID_AVX256_REG_OR_OI_VHF_MODE): Replace with ... + (VALID_AVX256_REG_OR_OI_MODE): ... this. Remove V16HFmode. + (VALID_AVX512F_SCALAR_MODE): Remove HImode and HFmode. + (VALID_AVX512FP16_SCALAR_MODE): New. + (VALID_AVX512F_REG_MODE): Add V32HFmode. + (VALID_SSE2_REG_MODE): Add V8HFmode, V4HFmode and V2HFmode. + (VALID_SSE2_REG_VHF_MODE): Remove. + (VALID_INT_MODE_P): Add V2HFmode. + * config/i386/i386.c (function_arg_advance_64): + Remove explicit mention of V16HFmode and V32HFmode. + (ix86_hard_regno_mode_ok): Remove explicit mention of XImode + and V32HFmode, use VALID_AVX512F_REG_OR_XI_MODE instead. + Use VALID_AVX512FP_SCALAR_MODE for TARGET_aVX512FP16. + Use VALID_AVX256_REG_OR_OI_MODE instead of + VALID_AVX256_REG_OR_OI_VHF_MODE and VALID_SSE2_REG_MODE instead + of VALID_SSE2_REG_VHF_MODE. + (ix86_set_reg_reg_cost): Remove usge of VALID_AVX512FP16_REG_MODE. + (ix86_vector_mode_supported): Ditto. + +2021-12-16 Martin Liska <mliska@suse.cz> + + PR c++/103696 + * attribs.c (decl_attributes): Check if + target_option_current_node is changed. + +2021-12-16 Martin Liska <mliska@suse.cz> + + * doc/invoke.texi: Add missing dash. + +2021-12-16 Bill Schmidt <wschmidt@linux.ibm.com> + + * config/rs6000/rs6000-c.c (resolution): New enum. + (resolve_vec_mul): New function. + (resolve_vec_cmpne): Likewise. + (resolve_vec_adde_sube): Likewise. + (resolve_vec_addec_subec): Likewise. + (resolve_vec_splats): Likewise. + (resolve_vec_extract): Likewise. + (resolve_vec_insert): Likewise. + (resolve_vec_step): Likewise. + (find_instance): Likewise. + (altivec_resolve_overloaded_builtin): Many cleanups. Call factored-out + functions. Move variable declarations closer to uses. Add commentary. + Remove unnecessary levels of braces. Avoid use of gotos. Change + misleading variable names. Use switches over if-else-if chains. + +2021-12-16 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com> + + PR target/103729 + * config/aarch64/aarch64-simd.md (aarch64_movv8di): Allow big endian + targets to move V8DI. + +2021-12-16 Tobias Burnus <tobias@codesourcery.com> + + PR driver/103644 + * gcc.c (check_offload_target_name): Add 'default' and 'disable' + to the candidate list. + 2021-12-15 Iain Sandoe <iain@sandoe.co.uk> * configure: Regenerate. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 4f5ebad..7b090eb 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20211216 +20211217 diff --git a/gcc/attribs.c b/gcc/attribs.c index 01a9ed6..29703e7 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -605,7 +605,8 @@ decl_attributes (tree *node, tree attributes, int flags, } if (TREE_CODE (*node) == FUNCTION_DECL - && optimization_current_node != optimization_default_node + && (optimization_current_node != optimization_default_node + || target_option_current_node != target_option_default_node) && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)) { DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node; diff --git a/gcc/builtins.c b/gcc/builtins.c index cd8947b..00f6c55 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -178,7 +178,7 @@ static rtx expand_builtin_memory_chk (tree, rtx, machine_mode, enum built_in_function); static void maybe_emit_chk_warning (tree, enum built_in_function); static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function); -static tree fold_builtin_object_size (tree, tree); +static tree fold_builtin_object_size (tree, tree, enum built_in_function); unsigned HOST_WIDE_INT target_newline; unsigned HOST_WIDE_INT target_percent; @@ -7909,6 +7909,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, return const0_rtx; case BUILT_IN_OBJECT_SIZE: + case BUILT_IN_DYNAMIC_OBJECT_SIZE: return expand_builtin_object_size (exp); case BUILT_IN_MEMCPY_CHK: @@ -9315,7 +9316,8 @@ fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1) break; case BUILT_IN_OBJECT_SIZE: - return fold_builtin_object_size (arg0, arg1); + case BUILT_IN_DYNAMIC_OBJECT_SIZE: + return fold_builtin_object_size (arg0, arg1, fcode); case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE: return fold_builtin_atomic_always_lock_free (arg0, arg1); @@ -10253,9 +10255,9 @@ maybe_emit_sprintf_chk_warning (tree exp, enum built_in_function fcode) if possible. */ static tree -fold_builtin_object_size (tree ptr, tree ost) +fold_builtin_object_size (tree ptr, tree ost, enum built_in_function fcode) { - unsigned HOST_WIDE_INT bytes; + tree bytes; int object_size_type; if (!validate_arg (ptr, POINTER_TYPE) @@ -10277,11 +10279,14 @@ fold_builtin_object_size (tree ptr, tree ost) if (TREE_SIDE_EFFECTS (ptr)) return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0); + if (fcode == BUILT_IN_DYNAMIC_OBJECT_SIZE) + object_size_type |= OST_DYNAMIC; + if (TREE_CODE (ptr) == ADDR_EXPR) { compute_builtin_object_size (ptr, object_size_type, &bytes); - if (wi::fits_to_tree_p (bytes, size_type_node)) - return build_int_cstu (size_type_node, bytes); + if (int_fits_type_p (bytes, size_type_node)) + return fold_convert (size_type_node, bytes); } else if (TREE_CODE (ptr) == SSA_NAME) { @@ -10289,8 +10294,8 @@ fold_builtin_object_size (tree ptr, tree ost) later. Maybe subsequent passes will help determining it. */ if (compute_builtin_object_size (ptr, object_size_type, &bytes) - && wi::fits_to_tree_p (bytes, size_type_node)) - return build_int_cstu (size_type_node, bytes); + && int_fits_type_p (bytes, size_type_node)) + return fold_convert (size_type_node, bytes); } return NULL_TREE; diff --git a/gcc/builtins.def b/gcc/builtins.def index 45a09b4..a92948de 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -972,6 +972,7 @@ DEF_BUILTIN_STUB (BUILT_IN_STRNCMP_EQ, "__builtin_strncmp_eq") /* Object size checking builtins. */ DEF_GCC_BUILTIN (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_DYNAMIC_OBJECT_SIZE, "dynamic_object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_PURE_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF) diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 605a484..e2dcb93 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2021-12-16 Martin Liska <mliska@suse.cz> + + PR target/103709 + * c-pragma.c (handle_pragma_pop_options): Do not check + global options modification when an error is seen in parsing + of options (pragmas or attributes). + 2021-12-12 Jonathan Wakely <jwakely@redhat.com> * known-headers.cc: Define INCLUDE_MEMORY instead of diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 93845d5..4c20e44 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -975,9 +975,9 @@ c_common_post_options (const char **pfilename) /* Change flag_abi_version to be the actual current ABI level, for the benefit of c_cpp_builtins, and to make comparison simpler. */ - const int latest_abi_version = 16; - /* Generate compatibility aliases for ABI v11 (7.1) by default. */ - const int abi_compat_default = 11; + const int latest_abi_version = 17; + /* Generate compatibility aliases for ABI v13 (8.2) by default. */ + const int abi_compat_default = 13; #define clamp(X) if (X == 0 || X > latest_abi_version) X = latest_abi_version clamp (flag_abi_version); diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index c4ed420..0772c34 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1132,7 +1132,7 @@ handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy)) p->optimize_binary); optimization_current_node = p->optimize_binary; } - if (flag_checking) + if (flag_checking && !seen_error ()) { cl_optimization_compare (p->saved_global_options, &global_options); free (p->saved_global_options); diff --git a/gcc/common.opt b/gcc/common.opt index 8f8fc2f..4af89ce 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -990,6 +990,10 @@ Driver Undocumented ; Adds missing 'on' in mangling of operator names in some cases. ; Default in G++ 11. ; +; 17: Fixes layout of classes that inherit from aggregate classes with default +; member initializers in C++14 and up. +; Default in G++ 12. +; ; Additional positive integers will be assigned as new versions of ; the ABI become the default version of the ABI. fabi-version= diff --git a/gcc/config/darwin-driver.c b/gcc/config/darwin-driver.c index 7fa80ab..688fe8f 100644 --- a/gcc/config/darwin-driver.c +++ b/gcc/config/darwin-driver.c @@ -416,6 +416,10 @@ darwin_driver_init (unsigned int *decoded_options_count, } #endif + /* If there is nothing else on the command line, do not add sysroot etc. */ + if (*decoded_options_count <= 1) + return; + if (appendM32 || appendM64) { ++*decoded_options_count; @@ -426,7 +430,7 @@ darwin_driver_init (unsigned int *decoded_options_count, &(*decoded_options)[*decoded_options_count - 1]); } - if (! seen_sysroot_p) + if (!seen_sysroot_p) { /* We will pick up an SDKROOT if we didn't specify a sysroot and treat it as overriding any configure-time --with-sysroot. */ @@ -445,7 +449,7 @@ darwin_driver_init (unsigned int *decoded_options_count, /* We will need to know the OS X version we're trying to build for here so that we can figure out the mechanism and source for the sysroot to be used. */ - if (! seen_version_min && *decoded_options_count > 1) + if (!seen_version_min) /* Not set by the User, try to figure it out. */ vers_string = darwin_default_min_version (); diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 0ce1320..75b688e 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -268,11 +268,6 @@ extern GTY(()) int darwin_ms_struct; "%{unexported_symbols_list*:\ -Xlinker -unexported_symbols_list -Xlinker %*} \ %<unexported_symbols_list*", \ - "%{!weak_reference_mismatches*:\ - %:version-compare(< 10.5 asm_macosx_version_min= -Xlinker) \ - %:version-compare(< 10.5 asm_macosx_version_min= -weak_reference_mismatches) \ - %:version-compare(< 10.5 asm_macosx_version_min= -Xlinker) \ - %:version-compare(< 10.5 asm_macosx_version_min= non-weak)}", \ "%{weak_reference_mismatches*:\ -Xlinker -weak_reference_mismatches -Xlinker %*} \ %<weak_reference_mismatches*", \ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 9f4ed34..ec15582 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2942,9 +2942,7 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, machine_mode mode, /* Unnamed 512 and 256bit vector mode parameters are passed on stack. */ if (!named && (VALID_AVX512F_REG_MODE (mode) - || VALID_AVX256_REG_MODE (mode) - || mode == V16HFmode - || mode == V32HFmode)) + || VALID_AVX256_REG_MODE (mode))) return 0; if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs) @@ -19915,15 +19913,17 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode) - XI mode - any of 512-bit wide vector mode - any scalar mode. */ - /* For AVX512FP16, vmovw supports movement of HImode - between gpr and sse registser. */ if (TARGET_AVX512F - && (mode == XImode - || mode == V32HFmode - || VALID_AVX512F_REG_MODE (mode) + && (VALID_AVX512F_REG_OR_XI_MODE (mode) || VALID_AVX512F_SCALAR_MODE (mode))) return true; + /* For AVX512FP16, vmovw supports movement of HImode + and HFmode between GPR and SSE registers. */ + if (TARGET_AVX512FP16 + && VALID_AVX512FP16_SCALAR_MODE (mode)) + return true; + /* For AVX-5124FMAPS or AVX-5124VNNIW allow V64SF and V64SI modes for special regnos. */ if ((TARGET_AVX5124FMAPS || TARGET_AVX5124VNNIW) @@ -19934,7 +19934,7 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode) /* TODO check for QI/HI scalars. */ /* AVX512VL allows sse regs16+ for 128/256 bit modes. */ if (TARGET_AVX512VL - && (VALID_AVX256_REG_OR_OI_VHF_MODE (mode) + && (VALID_AVX256_REG_OR_OI_MODE (mode) || VALID_AVX512VL_128_REG_MODE (mode))) return true; @@ -19944,9 +19944,9 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode) /* OImode and AVX modes are available only when AVX is enabled. */ return ((TARGET_AVX - && VALID_AVX256_REG_OR_OI_VHF_MODE (mode)) + && VALID_AVX256_REG_OR_OI_MODE (mode)) || VALID_SSE_REG_MODE (mode) - || VALID_SSE2_REG_VHF_MODE (mode) + || VALID_SSE2_REG_MODE (mode) || VALID_MMX_REG_MODE (mode) || VALID_MMX_REG_MODE_3DNOW (mode)); } @@ -20156,8 +20156,7 @@ ix86_set_reg_reg_cost (machine_mode mode) case MODE_VECTOR_INT: case MODE_VECTOR_FLOAT: - if ((TARGET_AVX512FP16 && VALID_AVX512FP16_REG_MODE (mode)) - || (TARGET_AVX512F && VALID_AVX512F_REG_MODE (mode)) + if ((TARGET_AVX512F && VALID_AVX512F_REG_MODE (mode)) || (TARGET_AVX && VALID_AVX256_REG_MODE (mode)) || (TARGET_SSE2 && VALID_SSE2_REG_MODE (mode)) || (TARGET_SSE && VALID_SSE_REG_MODE (mode)) @@ -22080,8 +22079,6 @@ ix86_vector_mode_supported_p (machine_mode mode) if ((TARGET_MMX || TARGET_MMX_WITH_SSE) && VALID_MMX_REG_MODE (mode)) return true; - if (TARGET_AVX512FP16 && VALID_AVX512FP16_REG_MODE (mode)) - return true; if ((TARGET_3DNOW || TARGET_MMX_WITH_SSE) && VALID_MMX_REG_MODE_3DNOW (mode)) return true; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 46fdd6e..398f751 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1005,20 +1005,22 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define VALID_AVX256_REG_MODE(MODE) \ ((MODE) == V32QImode || (MODE) == V16HImode || (MODE) == V8SImode \ || (MODE) == V4DImode || (MODE) == V2TImode || (MODE) == V8SFmode \ - || (MODE) == V4DFmode) + || (MODE) == V4DFmode || (MODE) == V16HFmode) -#define VALID_AVX256_REG_OR_OI_VHF_MODE(MODE) \ - (VALID_AVX256_REG_MODE (MODE) || (MODE) == OImode || (MODE) == V16HFmode) +#define VALID_AVX256_REG_OR_OI_MODE(MODE) \ + (VALID_AVX256_REG_MODE (MODE) || (MODE) == OImode) #define VALID_AVX512F_SCALAR_MODE(MODE) \ ((MODE) == DImode || (MODE) == DFmode || (MODE) == SImode \ - || (MODE) == SFmode \ - || (TARGET_AVX512FP16 && ((MODE) == HImode || (MODE) == HFmode))) + || (MODE) == SFmode) + +#define VALID_AVX512FP16_SCALAR_MODE(MODE) \ + ((MODE) == HImode || (MODE) == HFmode) #define VALID_AVX512F_REG_MODE(MODE) \ ((MODE) == V8DImode || (MODE) == V8DFmode || (MODE) == V64QImode \ || (MODE) == V16SImode || (MODE) == V16SFmode || (MODE) == V32HImode \ - || (MODE) == V4TImode) + || (MODE) == V4TImode || (MODE) == V32HFmode) #define VALID_AVX512F_REG_OR_XI_MODE(MODE) \ (VALID_AVX512F_REG_MODE (MODE) || (MODE) == XImode) @@ -1035,13 +1037,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define VALID_SSE2_REG_MODE(MODE) \ ((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \ + || (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode \ || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \ || (MODE) == V2DImode || (MODE) == DFmode || (MODE) == HFmode) -#define VALID_SSE2_REG_VHF_MODE(MODE) \ - (VALID_SSE2_REG_MODE (MODE) || (MODE) == V8HFmode \ - || (MODE) == V4HFmode || (MODE) == V2HFmode) - #define VALID_SSE_REG_MODE(MODE) \ ((MODE) == V1TImode || (MODE) == TImode \ || (MODE) == V4SFmode || (MODE) == V4SImode \ @@ -1072,7 +1071,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (MODE) == CSImode || (MODE) == CDImode \ || (MODE) == SDmode || (MODE) == DDmode \ || (MODE) == HFmode || (MODE) == HCmode \ - || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \ + || (MODE) == V2HImode || (MODE) == V2HFmode \ + || (MODE) == V1SImode || (MODE) == V4QImode \ || (TARGET_64BIT \ && ((MODE) == TImode || (MODE) == CTImode \ || (MODE) == TFmode || (MODE) == TCmode \ diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 768a93e..97ce5b3 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -3525,8 +3525,7 @@ UNSPEC_PCMP)))] "TARGET_AVX512VL && ix86_pre_reload_split () /* LT or GE 0 */ - && ((INTVAL (operands[5]) == 1 && !MEM_P (operands[2])) - || (INTVAL (operands[5]) == 5 && !MEM_P (operands[1])))" + && ((INTVAL (operands[5]) == 1) || (INTVAL (operands[5]) == 5))" "#" "&& 1" [(set (match_dup 0) @@ -3540,6 +3539,7 @@ { if (INTVAL (operands[5]) == 5) std::swap (operands[1], operands[2]); + operands[2] = force_reg (<MODE>mode, operands[2]); }) (define_insn_and_split "*avx_cmp<mode>3_ltint" @@ -3554,8 +3554,7 @@ UNSPEC_PCMP)))] "TARGET_AVX512VL && ix86_pre_reload_split () /* LT or GE 0 */ - && ((INTVAL (operands[5]) == 1 && !MEM_P (operands[2])) - || (INTVAL (operands[5]) == 5 && !MEM_P (operands[1])))" + && ((INTVAL (operands[5]) == 1) || (INTVAL (operands[5]) == 5))" "#" "&& 1" [(set (match_dup 0) @@ -3572,7 +3571,44 @@ std::swap (operands[1], operands[2]); operands[0] = gen_lowpart (<ssebytemode>mode, operands[0]); operands[1] = gen_lowpart (<ssebytemode>mode, operands[1]); + operands[2] = force_reg (<ssebytemode>mode, + gen_lowpart (<ssebytemode>mode, operands[2])); +}) + +(define_insn_and_split "*avx_cmp<mode>3_ltint_not" + [(set (match_operand:VI48_AVX 0 "register_operand") + (vec_merge:VI48_AVX + (match_operand:VI48_AVX 1 "vector_operand") + (match_operand:VI48_AVX 2 "vector_operand") + (unspec:<avx512fmaskmode> + [(subreg:VI48_AVX + (not:<ssebytemode> + (match_operand:<ssebytemode> 3 "vector_operand")) 0) + (match_operand:VI48_AVX 4 "const0_operand") + (match_operand:SI 5 "const_0_to_7_operand")] + UNSPEC_PCMP)))] + "TARGET_AVX512VL && ix86_pre_reload_split () + /* not LT or GE 0 */ + && ((INTVAL (operands[5]) == 1) || (INTVAL (operands[5]) == 5))" + "#" + "&& 1" + [(set (match_dup 0) + (unspec:<ssebytemode> + [(match_dup 1) + (match_dup 2) + (subreg:<ssebytemode> + (lt:VI48_AVX + (match_dup 3) + (match_dup 4)) 0)] + UNSPEC_BLENDV))] +{ + if (INTVAL (operands[5]) == 5) + std::swap (operands[1], operands[2]); + operands[0] = gen_lowpart (<ssebytemode>mode, operands[0]); + operands[1] = force_reg (<ssebytemode>mode, + gen_lowpart (<ssebytemode>mode, operands[1])); operands[2] = gen_lowpart (<ssebytemode>mode, operands[2]); + operands[3] = lowpart_subreg (<MODE>mode, operands[3], <ssebytemode>mode); }) (define_insn "avx_vmcmp<mode>3" diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h index 7bc1009..8288003 100644 --- a/gcc/config/rs6000/darwin.h +++ b/gcc/config/rs6000/darwin.h @@ -507,7 +507,7 @@ #define SUBTARGET_INIT_BUILTINS \ do { \ darwin_patch_builtins (); \ - rs6000_builtin_decls_x[(unsigned) (RS6000_BIF_CFSTRING)] \ + rs6000_builtin_decls[(unsigned) (RS6000_BIF_CFSTRING)] \ = darwin_init_cfstring_builtins ((unsigned) (RS6000_BIF_CFSTRING)); \ } while(0) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e427701..b8a0726 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,111 @@ +2021-12-16 Marek Polacek <polacek@redhat.com> + + PR c++/99980 + * parser.c (cp_parser_single_declaration): Maybe pass + CP_PARSER_FLAGS_DELAY_NOEXCEPT down to cp_parser_init_declarator. + +2021-12-16 Martin Sebor <msebor@redhat.com> + + PR c++/103703 + * parser.c (class_decl_loc_t::diag_mismatched_tags): Check for class + type before assuming a type is one. + +2021-12-16 Patrick Palka <ppalka@redhat.com> + + PR c++/51577 + PR c++/83035 + PR c++/100465 + * call.c (add_operator_candidates): Add lookups parameter. + Use it to avoid performing a second unqualified lookup when + instantiating a dependent operator expression. + (build_new_op): Add lookups parameter and pass it appropriately. + * constraint.cc (finish_constraint_binary_op): Use + build_min_nt_loc instead of build_x_binary_op. + * coroutines.cc (build_co_await): Adjust call to build_new_op. + * cp-objcp-common.c (cp_common_init_ts): Mark + DEPENDENT_OPERATOR_TYPE appropriately. + * cp-tree.def (DEPENDENT_OPERATOR_TYPE): Define. + * cp-tree.h (WILDCARD_TYPE_P): Accept DEPENDENT_OPERATOR_TYPE. + (FOLD_EXPR_OP_RAW): New, renamed from ... + (FOLD_EXPR_OP): ... this. Change this to return the tree_code directly. + (DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS): Define. + (templated_operator_saved_lookups): Define. + (build_new_op): Add lookups parameter. + (build_dependent_operator_type): Declare. + (build_x_indirect_ref): Add lookups parameter. + (build_x_binary_op): Likewise. + (build_x_unary_op): Likewise. + (build_x_compound_expr): Likewise. + (build_x_modify_expr): Likewise. + * cxx-pretty-print.c (get_fold_operator): Adjust after + FOLD_EXPR_OP change. + * decl.c (start_preparsed_function): Don't call + push_operator_bindings. + * decl2.c (grok_array_decl): Adjust calls to build_new_op. + * method.c (do_one_comp): Likewise. + (build_comparison_op): Likewise. + * module.cc (trees_out::type_node): Handle DEPENDENT_OPERATOR_TYPE. + (trees_in::tree_node): Likewise. + * name-lookup.c (lookup_name): Revert r11-2876 change. + (op_unqualified_lookup): Remove. + (maybe_save_operator_binding): Remove. + (discard_operator_bindings): Remove. + (push_operator_bindings): Remove. + * name-lookup.h (maybe_save_operator_binding): Remove. + (push_operator_bindings): Remove. + (discard_operator_bindings): Remove. + * parser.c (cp_parser_unary_expression): Adjust calls to build_x_*. + (cp_parser_binary_expression): Likewise. + (cp_parser_assignment_expression): Likewise. + (cp_parser_expression): Likewise. + (do_range_for_auto_deduction): Likewise. + (cp_convert_range_for): Likewise. + (cp_parser_perform_range_for_lookup): Likewise. + (cp_parser_template_argument): Likewise. + (cp_parser_omp_for_cond): Likewise. + (cp_parser_omp_for_incr): Likewise. + (cp_parser_omp_for_loop_init): Likewise. + (cp_convert_omp_range_for): Likewise. + (cp_finish_omp_range_for): Likewise. + * pt.c (fold_expression): Adjust after FOLD_EXPR_OP change. Pass + templated_operator_saved_lookups to build_x_*. + (tsubst_omp_for_iterator): Adjust call to build_x_modify_expr. + (tsubst_expr) <case COMPOUND_EXPR>: Pass + templated_operator_saved_lookups to build_x_*. + (tsubst_copy_and_build) <case INDIRECT_REF>: Likewise. + <case tcc_unary>: Likewise. + <case tcc_binary>: Likewise. + <case MODOP_EXPR>: Likewise. + <case COMPOUND_EXPR>: Likewise. + (dependent_type_p_r): Return true for DEPENDENT_OPERATOR_TYPE. + * ptree.c (cxx_print_type): Handle DEPENDENT_OPERATOR_TYPE. + * semantics.c (finish_increment_expr): Adjust call to + build_x_unary_op. + (finish_unary_op_expr): Likewise. + (handle_omp_for_class_iterator): Adjust calls to build_x_*. + (finish_omp_cancel): Likewise. + (finish_unary_fold_expr): Use build_dependent_operator_type. + (finish_binary_fold_expr): Likewise. + * tree.c (cp_free_lang_data): Don't call discard_operator_bindings. + * typeck.c (rationalize_conditional_expr): Adjust call to + build_x_binary_op. + (op_unqualified_lookup): Define. + (build_dependent_operator_type): Define. + (build_x_indirect_ref): Add lookups parameter and use + build_dependent_operator_type. + (build_x_binary_op): Likewise. + (build_x_array_ref): Likewise. + (build_x_unary_op): Likewise. + (build_x_compound_expr_from_list): Adjust call to + build_x_compound_expr. + (build_x_compound_expr_from_vec): Likewise. + (build_x_compound_expr): Add lookups parameter and use + build_dependent_operator_type. + (cp_build_modify_expr): Adjust call to build_new_op. + (build_x_modify_expr): Add lookups parameter and use + build_dependent_operator_type. + * typeck2.c (build_x_arrow): Adjust call to build_new_op. + 2021-12-15 Marek Polacek <polacek@redhat.com> PR c++/102229 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 347df5d..495dcdd 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6285,12 +6285,17 @@ op_is_ordered (tree_code code) /* Subroutine of build_new_op: Add to CANDIDATES all candidates for the operator indicated by CODE/CODE2. This function calls itself recursively to - handle C++20 rewritten comparison operator candidates. */ + handle C++20 rewritten comparison operator candidates. + + LOOKUPS, if non-NULL, is the set of pertinent namespace-scope operator + overloads to consider. This parameter is used when instantiating a + dependent operator expression and has the same structure as + DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS. */ static tree add_operator_candidates (z_candidate **candidates, tree_code code, tree_code code2, - vec<tree, va_gc> *arglist, + vec<tree, va_gc> *arglist, tree lookups, int flags, tsubst_flags_t complain) { z_candidate *start_candidates = *candidates; @@ -6326,7 +6331,15 @@ add_operator_candidates (z_candidate **candidates, consider. */ if (!memonly) { - tree fns = lookup_name (fnname, LOOK_where::BLOCK_NAMESPACE); + tree fns; + if (!lookups) + fns = lookup_name (fnname, LOOK_where::BLOCK_NAMESPACE); + /* If LOOKUPS is non-NULL, then we're instantiating a dependent operator + expression, and LOOKUPS is the result of stage 1 name lookup. */ + else if (tree found = purpose_member (fnname, lookups)) + fns = TREE_VALUE (found); + else + fns = NULL_TREE; fns = lookup_arg_dependent (fnname, fns, arglist); add_candidates (fns, NULL_TREE, arglist, NULL_TREE, NULL_TREE, false, NULL_TREE, NULL_TREE, @@ -6429,7 +6442,7 @@ add_operator_candidates (z_candidate **candidates, if (rewrite_code != code) /* Add rewritten candidates in same order. */ add_operator_candidates (candidates, rewrite_code, ERROR_MARK, - arglist, flags, complain); + arglist, lookups, flags, complain); z_candidate *save_cand = *candidates; @@ -6439,7 +6452,7 @@ add_operator_candidates (z_candidate **candidates, revlist->quick_push ((*arglist)[1]); revlist->quick_push ((*arglist)[0]); add_operator_candidates (candidates, rewrite_code, ERROR_MARK, - revlist, flags, complain); + revlist, lookups, flags, complain); /* Release the vec if we didn't add a candidate that uses it. */ for (z_candidate *c = *candidates; c != save_cand; c = c->next) @@ -6457,8 +6470,8 @@ add_operator_candidates (z_candidate **candidates, tree build_new_op (const op_location_t &loc, enum tree_code code, int flags, - tree arg1, tree arg2, tree arg3, tree *overload, - tsubst_flags_t complain) + tree arg1, tree arg2, tree arg3, tree lookups, + tree *overload, tsubst_flags_t complain) { struct z_candidate *candidates = 0, *cand; releasing_vec arglist; @@ -6552,7 +6565,7 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags, p = conversion_obstack_alloc (0); result = add_operator_candidates (&candidates, code, code2, arglist, - flags, complain); + lookups, flags, complain); if (result == error_mark_node) goto user_defined_result_ready; @@ -6608,7 +6621,7 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags, else code = PREDECREMENT_EXPR; result = build_new_op (loc, code, flags, arg1, NULL_TREE, - NULL_TREE, overload, complain); + NULL_TREE, lookups, overload, complain); break; /* The caller will deal with these. */ @@ -6765,7 +6778,7 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags, warning_sentinel ws (warn_zero_as_null_pointer_constant); result = build_new_op (loc, code, LOOKUP_NORMAL|LOOKUP_REWRITTEN, - lhs, rhs, NULL_TREE, + lhs, rhs, NULL_TREE, lookups, NULL, complain); } break; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c30a44f..e70c535 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3857,9 +3857,14 @@ check_field_decls (tree t, tree *access_decls, /* Now that we've removed bit-field widths from DECL_INITIAL, anything left in DECL_INITIAL is an NSDMI that makes the class - non-aggregate in C++11. */ - if (DECL_INITIAL (field) && cxx_dialect < cxx14) - CLASSTYPE_NON_AGGREGATE (t) = true; + non-aggregate in C++11, and non-layout-POD always. */ + if (DECL_INITIAL (field)) + { + if (cxx_dialect < cxx14) + CLASSTYPE_NON_AGGREGATE (t) = true; + else + CLASSTYPE_NON_POD_AGGREGATE (t) = true; + } if (CP_TYPE_CONST_P (type)) { @@ -6045,6 +6050,16 @@ check_bases_and_members (tree t) TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_CONTAINS_VPTR_P (t); TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t); + /* Is this class non-layout-POD because it wasn't an aggregate in C++98? */ + if (CLASSTYPE_NON_POD_AGGREGATE (t)) + { + if (CLASSTYPE_NON_LAYOUT_POD_P (t)) + /* It's non-POD for another reason. */ + CLASSTYPE_NON_POD_AGGREGATE (t) = false; + else if (abi_version_at_least (17)) + CLASSTYPE_NON_LAYOUT_POD_P (t) = true; + } + /* If the only explicitly declared default constructor is user-provided, set TYPE_HAS_COMPLEX_DFLT. */ if (!TYPE_HAS_COMPLEX_DFLT (t) @@ -6341,12 +6356,17 @@ end_of_base (tree binfo) return size_binop (PLUS_EXPR, BINFO_OFFSET (binfo), size); } -/* Returns the offset of the byte just past the end of the base class or empty - data member with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, - then only non-virtual bases are included. */ +/* Returns one of three variations of the ending offset of T. If MODE is + eoc_nvsize, the result is the ABI "nvsize" (i.e. sizeof before allocating + vbases). If MODE is eoc_vsize, the result is the sizeof after allocating + vbases but before rounding, which is not named in the ABI. If MODE is + eoc_nv_or_dsize, the result is the greater of "nvsize" and "dsize" (the size + of the actual data in the class, kinda), as used for allocation of + potentially-overlapping fields. */ +enum eoc_mode { eoc_nvsize, eoc_vsize, eoc_nv_or_dsize }; static tree -end_of_class (tree t, bool include_virtuals_p) +end_of_class (tree t, eoc_mode mode) { tree result = size_zero_node; vec<tree, va_gc> *vbases; @@ -6358,8 +6378,7 @@ end_of_class (tree t, bool include_virtuals_p) for (binfo = TYPE_BINFO (t), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) { - if (!include_virtuals_p - && BINFO_VIRTUAL_P (base_binfo) + if (BINFO_VIRTUAL_P (base_binfo) && (!BINFO_PRIMARY_P (base_binfo) || BINFO_INHERITANCE_CHAIN (base_binfo) != TYPE_BINFO (t))) continue; @@ -6369,25 +6388,35 @@ end_of_class (tree t, bool include_virtuals_p) result = offset; } - /* Also consider empty data members. */ for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL - && !DECL_ARTIFICIAL (field) - && field_poverlapping_p (field) - && is_empty_class (TREE_TYPE (field))) + && !DECL_FIELD_IS_BASE (field)) { - /* Update sizeof(C) to max (sizeof(C), offset(D)+sizeof(D)) */ - offset = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (field), - TYPE_SIZE_UNIT (TREE_TYPE (field))); + tree size = DECL_SIZE_UNIT (field); + if (!size) + /* DECL_SIZE_UNIT can be null for a flexible array. */ + continue; + + if (is_empty_field (field)) + /* For empty fields DECL_SIZE_UNIT is 0, but we want the + size of the type (usually 1) for computing nvsize. */ + size = TYPE_SIZE_UNIT (TREE_TYPE (field)); + + offset = size_binop (PLUS_EXPR, byte_position (field), size); if (tree_int_cst_lt (result, offset)) result = offset; } - if (include_virtuals_p) + if (mode != eoc_nvsize) for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0; vec_safe_iterate (vbases, i, &base_binfo); i++) { - offset = end_of_base (base_binfo); + if (mode == eoc_nv_or_dsize) + /* For dsize, don't count trailing empty bases. */ + offset = size_binop (PLUS_EXPR, BINFO_OFFSET (binfo), + CLASSTYPE_SIZE_UNIT (BINFO_TYPE (binfo))); + else + offset = end_of_base (base_binfo); if (tree_int_cst_lt (result, offset)) result = offset; } @@ -6395,6 +6424,45 @@ end_of_class (tree t, bool include_virtuals_p) return result; } +/* Warn as appropriate about the change in whether we pack into the tail + padding of FIELD, a base field which has a C++14 aggregate type with default + member initializers. */ + +static void +check_non_pod_aggregate (tree field) +{ + if (!abi_version_crosses (17) || cxx_dialect < cxx14) + return; + if (TREE_CODE (field) != FIELD_DECL + || (!DECL_FIELD_IS_BASE (field) + && !field_poverlapping_p (field))) + return; + tree next = DECL_CHAIN (field); + while (next && TREE_CODE (next) != FIELD_DECL) next = DECL_CHAIN (next); + if (!next) + return; + tree type = TREE_TYPE (field); + if (TYPE_IDENTIFIER (type) == as_base_identifier) + type = TYPE_CONTEXT (type); + if (!CLASS_TYPE_P (type) || !CLASSTYPE_NON_POD_AGGREGATE (type)) + return; + tree size = end_of_class (type, (DECL_FIELD_IS_BASE (field) + ? eoc_nvsize : eoc_nv_or_dsize)); + tree rounded = round_up_loc (input_location, size, DECL_ALIGN_UNIT (next)); + if (tree_int_cst_lt (rounded, TYPE_SIZE_UNIT (type))) + { + location_t loc = DECL_SOURCE_LOCATION (next); + if (DECL_FIELD_IS_BASE (next)) + warning_at (loc, OPT_Wabi,"offset of %qT base class for " + "%<-std=c++14%> and up changes in " + "%<-fabi-version=17%> (GCC 12)", TREE_TYPE (next)); + else + warning_at (loc, OPT_Wabi, "offset of %qD for " + "%<-std=c++14%> and up changes in " + "%<-fabi-version=17%> (GCC 12)", next); + } +} + /* Warn about bases of T that are inaccessible because they are ambiguous. For example: @@ -6468,7 +6536,7 @@ include_empty_classes (record_layout_info rli) because we are willing to overlay multiple bases at the same offset. However, now we need to make sure that RLI is big enough to reflect the entire class. */ - eoc = end_of_class (rli->t, CLASSTYPE_AS_BASE (rli->t) != NULL_TREE); + eoc = end_of_class (rli->t, eoc_vsize); rli_size = rli_size_unit_so_far (rli); if (TREE_CODE (rli_size) == INTEGER_CST && tree_int_cst_lt (rli_size, eoc)) @@ -6580,21 +6648,13 @@ layout_class_type (tree t, tree *virtuals_p) { /* if D is a potentially-overlapping data member, update sizeof(C) to max (sizeof(C), offset(D)+max (nvsize(D), dsize(D))). */ - tree nvsize = CLASSTYPE_SIZE_UNIT (type); - /* end_of_class doesn't always give dsize, but it does in the case of - a class with virtual bases, which is when dsize > nvsize. */ - tree dsize = end_of_class (type, /*vbases*/true); if (CLASSTYPE_EMPTY_P (type)) DECL_SIZE (field) = DECL_SIZE_UNIT (field) = size_zero_node; - else if (tree_int_cst_le (dsize, nvsize)) - { - DECL_SIZE_UNIT (field) = nvsize; - DECL_SIZE (field) = CLASSTYPE_SIZE (type); - } else { - DECL_SIZE_UNIT (field) = dsize; - DECL_SIZE (field) = bit_from_pos (dsize, bitsize_zero_node); + tree size = end_of_class (type, eoc_nv_or_dsize); + DECL_SIZE_UNIT (field) = size; + DECL_SIZE (field) = bit_from_pos (size, bitsize_zero_node); } } @@ -6760,16 +6820,19 @@ layout_class_type (tree t, tree *virtuals_p) instead, so that the backends can emit -Wpsabi warnings in the cases where the ABI changed. */ for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) - if (TREE_CODE (field) == FIELD_DECL - && DECL_C_BIT_FIELD (field) - /* We should not be confused by the fact that grokbitfield - temporarily sets the width of the bit field into - DECL_BIT_FIELD_REPRESENTATIVE (field). - check_bitfield_decl eventually sets DECL_SIZE (field) - to that width. */ - && (DECL_SIZE (field) == NULL_TREE - || integer_zerop (DECL_SIZE (field)))) - SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field, 1); + { + if (TREE_CODE (field) == FIELD_DECL + && DECL_C_BIT_FIELD (field) + /* We should not be confused by the fact that grokbitfield + temporarily sets the width of the bit field into + DECL_BIT_FIELD_REPRESENTATIVE (field). + check_bitfield_decl eventually sets DECL_SIZE (field) + to that width. */ + && (DECL_SIZE (field) == NULL_TREE + || integer_zerop (DECL_SIZE (field)))) + SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field, 1); + check_non_pod_aggregate (field); + } if (CLASSTYPE_NON_LAYOUT_POD_P (t) || CLASSTYPE_EMPTY_P (t)) { @@ -6792,7 +6855,7 @@ layout_class_type (tree t, tree *virtuals_p) used to compute TYPE_SIZE_UNIT. */ /* Set the size and alignment for the new type. */ - tree eoc = end_of_class (t, /*include_virtuals_p=*/0); + tree eoc = end_of_class (t, eoc_nvsize); TYPE_SIZE_UNIT (base_t) = size_binop (MAX_EXPR, fold_convert (sizetype, diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 566f4e3..8386a7d 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -202,15 +202,8 @@ finish_constraint_binary_op (location_t loc, return error_mark_node; if (!check_constraint_operands (loc, lhs, rhs)) return error_mark_node; - tree overload; - cp_expr expr = build_x_binary_op (loc, code, - lhs, TREE_CODE (lhs), - rhs, TREE_CODE (rhs), - &overload, tf_none); - /* When either operand is dependent, the overload set may be non-empty. */ - if (expr == error_mark_node) - return error_mark_node; - expr.set_location (loc); + cp_expr expr + = build_min_nt_loc (loc, code, lhs.get_value (), rhs.get_value ()); expr.set_range (lhs.get_start (), rhs.get_finish ()); return expr; } @@ -457,8 +450,6 @@ deduce_concept_introduction (tree check) /* Build a constrained placeholder type where SPEC is a type-constraint. SPEC can be anything were concept_definition_p is true. - If DECLTYPE_P is true, then the placeholder is decltype(auto). - Returns a pair whose FIRST is the concept being checked and whose SECOND is the prototype parameter. */ diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 9017902..c00672e 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -912,7 +912,7 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind) if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a))) { o = build_new_op (loc, CO_AWAIT_EXPR, LOOKUP_NORMAL, a, NULL_TREE, - NULL_TREE, NULL, tf_warning_or_error); + NULL_TREE, NULL_TREE, NULL, tf_warning_or_error); /* If no viable functions are found, o is a. */ if (!o || o == error_mark_node) o = a; diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index 38eae88..36e04cd 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -484,6 +484,7 @@ cp_common_init_ts (void) /* New Types. */ MARK_TS_TYPE_COMMON (UNBOUND_CLASS_TEMPLATE); MARK_TS_TYPE_COMMON (TYPE_ARGUMENT_PACK); + MARK_TS_TYPE_COMMON (DEPENDENT_OPERATOR_TYPE); MARK_TS_TYPE_NON_COMMON (DECLTYPE_TYPE); MARK_TS_TYPE_NON_COMMON (TYPENAME_TYPE); diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 725139b..6fb838c 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -476,6 +476,11 @@ DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0) BASES_TYPE is the type in question. */ DEFTREECODE (BASES, "bases", tcc_type, 0) +/* Dependent operator expressions are given this type rather than a NULL_TREE + type so that we have somewhere to stash the result of phase 1 name lookup + (namely into DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS). */ +DEFTREECODE (DEPENDENT_OPERATOR_TYPE, "dependent_operator_type", tcc_type, 0) + /* Used to represent the template information stored by template specializations. The accessors are: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7f32cf5..8b5cfa2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2185,7 +2185,8 @@ enum languages { lang_c, lang_cplusplus }; || TREE_CODE (T) == TYPENAME_TYPE \ || TREE_CODE (T) == TYPEOF_TYPE \ || TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM \ - || TREE_CODE (T) == DECLTYPE_TYPE) + || TREE_CODE (T) == DECLTYPE_TYPE \ + || TREE_CODE (T) == DEPENDENT_OPERATOR_TYPE) /* Nonzero if T is a class (or struct or union) type. Also nonzero for template type parameters, typename types, and instantiated @@ -2343,6 +2344,7 @@ struct GTY(()) lang_type { unsigned unique_obj_representations : 1; unsigned unique_obj_representations_set : 1; bool erroneous : 1; + bool non_pod_aggregate : 1; /* When adding a flag here, consider whether or not it ought to apply to a template instance if it applies to the template. If @@ -2351,7 +2353,7 @@ struct GTY(()) lang_type { /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 4; + unsigned dummy : 3; tree primary_base; vec<tree_pair_s, va_gc> *vcall_indices; @@ -2671,6 +2673,12 @@ struct GTY(()) lang_type { /* True if we saw errors while instantiating this class. */ #define CLASSTYPE_ERRONEOUS(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->erroneous) + +/* True if this class is non-layout-POD only because it was not an aggregate + before C++14. If we run out of bits in lang_type, this could be replaced + with a hash_set only filled in when abi_version_crosses (17). */ +#define CLASSTYPE_NON_POD_AGGREGATE(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_aggregate) /* Additional macros for inheritance information. */ @@ -3978,9 +3986,13 @@ struct GTY(()) lang_decl { TREE_LANG_FLAG_0 (FOLD_EXPR_CHECK (NODE)) /* An INTEGER_CST containing the tree code of the folded operator. */ -#define FOLD_EXPR_OP(NODE) \ +#define FOLD_EXPR_OP_RAW(NODE) \ TREE_OPERAND (FOLD_EXPR_CHECK (NODE), 0) +/* The tree code of the folded operator. */ +#define FOLD_EXPR_OP(NODE) \ + ((enum tree_code) TREE_INT_CST_LOW (FOLD_EXPR_OP_RAW (NODE))) + /* The expression containing an unexpanded parameter pack. */ #define FOLD_EXPR_PACK(NODE) \ TREE_OPERAND (FOLD_EXPR_CHECK (NODE), 1) @@ -4035,6 +4047,26 @@ struct GTY(()) lang_decl { #define CALL_EXPR_OPERATOR_SYNTAX(NODE) \ TREE_LANG_FLAG_6 (CALL_OR_AGGR_INIT_CHECK (NODE)) +/* A TREE_LIST containing the result of phase 1 name lookup of the operator + overloads that are pertinent to the dependent operator expression whose + type is NODE. Each TREE_PURPOSE is an IDENTIFIER_NODE and TREE_VALUE is + the corresponding (possibly empty) lookup result. The TREE_TYPE of the + first TREE_LIST node points back to NODE. */ +#define DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS(NODE) \ + TYPE_VALUES_RAW (DEPENDENT_OPERATOR_TYPE_CHECK (NODE)) + +/* Guarded helper for the above accessor macro that takes a (templated) + operator expression instead of the type thereof. */ +inline tree +templated_operator_saved_lookups (tree t) +{ + tree type = TREE_TYPE (EXPR_CHECK (t)); + if (type && TREE_CODE (type) == DEPENDENT_OPERATOR_TYPE) + return DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS (type); + else + return NULL_TREE; +} + /* Indicates whether a string literal has been parenthesized. Such usages are disallowed in certain circumstances. */ @@ -6464,14 +6496,15 @@ extern tree build_special_member_call (tree, tree, tree, int, tsubst_flags_t); extern tree build_new_op (const op_location_t &, enum tree_code, - int, tree, tree, tree, tree *, - tsubst_flags_t); + int, tree, tree, tree, tree, + tree *, tsubst_flags_t); /* Wrapper that leaves out the usually-null op3 and overload parms. */ inline tree build_new_op (const op_location_t &loc, enum tree_code code, int flags, tree arg1, tree arg2, tsubst_flags_t complain) { - return build_new_op (loc, code, flags, arg1, arg2, NULL_TREE, NULL, complain); + return build_new_op (loc, code, flags, arg1, arg2, NULL_TREE, NULL_TREE, + NULL, complain); } extern tree build_op_call (tree, vec<tree, va_gc> **, tsubst_flags_t); @@ -7875,8 +7908,9 @@ extern tree build_class_member_access_expr (cp_expr, tree, tree, bool, extern tree finish_class_member_access_expr (cp_expr, tree, bool, tsubst_flags_t); extern tree lookup_destructor (tree, tree, tree, tsubst_flags_t); +extern tree build_dependent_operator_type (tree, enum tree_code, bool); extern tree build_x_indirect_ref (location_t, tree, - ref_operator, + ref_operator, tree, tsubst_flags_t); extern tree cp_build_indirect_ref (location_t, tree, ref_operator, @@ -7894,20 +7928,20 @@ extern tree cp_build_function_call_vec (tree, vec<tree, va_gc> **, extern tree build_x_binary_op (const op_location_t &, enum tree_code, tree, enum tree_code, tree, - enum tree_code, tree *, - tsubst_flags_t); + enum tree_code, tree, + tree *, tsubst_flags_t); inline tree build_x_binary_op (const op_location_t &loc, enum tree_code code, tree arg1, tree arg2, tsubst_flags_t complain) { return build_x_binary_op (loc, code, arg1, TREE_CODE (arg1), arg2, - TREE_CODE (arg2), NULL, complain); + TREE_CODE (arg2), NULL_TREE, NULL, complain); } extern tree build_x_array_ref (location_t, tree, tree, tsubst_flags_t); extern tree build_x_unary_op (location_t, enum tree_code, cp_expr, - tsubst_flags_t); + tree, tsubst_flags_t); extern tree cp_build_addressof (location_t, tree, tsubst_flags_t); extern tree cp_build_addr_expr (tree, tsubst_flags_t); @@ -7922,7 +7956,7 @@ extern tree build_x_compound_expr_from_list (tree, expr_list_kind, extern tree build_x_compound_expr_from_vec (vec<tree, va_gc> *, const char *, tsubst_flags_t); extern tree build_x_compound_expr (location_t, tree, tree, - tsubst_flags_t); + tree, tsubst_flags_t); extern tree build_compound_expr (location_t, tree, tree); extern tree cp_build_compound_expr (tree, tree, tsubst_flags_t); extern tree build_static_cast (location_t, tree, tree, @@ -7938,7 +7972,7 @@ extern tree cp_build_c_cast (location_t, tree, tree, tsubst_flags_t); extern cp_expr build_x_modify_expr (location_t, tree, enum tree_code, tree, - tsubst_flags_t); + tree, tsubst_flags_t); extern tree cp_build_modify_expr (location_t, tree, enum tree_code, tree, tsubst_flags_t); diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 3ea357d..6af009c 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -2541,8 +2541,8 @@ pp_cxx_addressof_expression (cxx_pretty_printer *pp, tree t) static char const* get_fold_operator (tree t) { - int op = int_cst_value (FOLD_EXPR_OP (t)); - ovl_op_info_t *info = OVL_OP_INFO (FOLD_EXPR_MODIFY_P (t), op); + ovl_op_info_t *info = OVL_OP_INFO (FOLD_EXPR_MODIFY_P (t), + FOLD_EXPR_OP (t)); return info->name; } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2e03398..7ca8770 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -17118,8 +17118,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags) store_parm_decls (current_function_parms); - push_operator_bindings (); - if (!processing_template_decl && (flag_lifetime_dse > 1) && DECL_CONSTRUCTOR_P (decl1) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 99f5dc7..062c175 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -417,7 +417,8 @@ grok_array_decl (location_t loc, tree array_expr, tree index_exp, { if (index_exp) expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, - index_exp, NULL_TREE, &overload, complain); + index_exp, NULL_TREE, NULL_TREE, + &overload, complain); else if ((*index_exp_list)->is_empty ()) expr = build_op_subscript (loc, array_expr, index_exp_list, &overload, complain); @@ -431,7 +432,7 @@ grok_array_decl (location_t loc, tree array_expr, tree index_exp, tf_none); if (idx != error_mark_node) expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, - idx, NULL_TREE, &overload, + idx, NULL_TREE, NULL_TREE, &overload, complain & tf_decltype); if (expr == error_mark_node) { diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 935946f..44439ba 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1372,7 +1372,7 @@ do_one_comp (location_t loc, const comp_info &info, tree sub, tree lhs, tree rhs to </=, so don't give an error yet if <=> lookup fails. */ bool tentative = retcat != cc_last; tree comp = build_new_op (loc, code, flags, lhs, rhs, - NULL_TREE, &overload, + NULL_TREE, NULL_TREE, &overload, tentative ? tf_none : complain); if (code != SPACESHIP_EXPR) @@ -1684,8 +1684,8 @@ build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain) comp = retval = var; } eq = build_new_op (info.loc, EQ_EXPR, flags, comp, - integer_zero_node, NULL_TREE, NULL, - complain); + integer_zero_node, NULL_TREE, NULL_TREE, + NULL, complain); } tree ceq = contextual_conv_bool (eq, complain); info.check (ceq); @@ -1720,7 +1720,7 @@ build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain) else if (code == NE_EXPR) { tree comp = build_new_op (info.loc, EQ_EXPR, flags, lhs, rhs, - NULL_TREE, NULL, complain); + NULL_TREE, NULL_TREE, NULL, complain); comp = contextual_conv_bool (comp, complain); info.check (comp); if (defining) @@ -1732,9 +1732,9 @@ build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain) else { tree comp = build_new_op (info.loc, SPACESHIP_EXPR, flags, lhs, rhs, - NULL_TREE, NULL, complain); + NULL_TREE, NULL_TREE, NULL, complain); tree comp2 = build_new_op (info.loc, code, flags, comp, integer_zero_node, - NULL_TREE, NULL, complain); + NULL_TREE, NULL_TREE, NULL, complain); info.check (comp2); if (defining) finish_return_stmt (comp2); diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 9266055..f3e7af2 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -8789,6 +8789,7 @@ trees_out::type_node (tree type) case DECLTYPE_TYPE: case TYPEOF_TYPE: case UNDERLYING_TYPE: + case DEPENDENT_OPERATOR_TYPE: tree_node (TYPE_VALUES_RAW (type)); if (TREE_CODE (type) == DECLTYPE_TYPE) /* We stash a whole bunch of things into decltype's @@ -9311,6 +9312,7 @@ trees_in::tree_node (bool is_use) case DECLTYPE_TYPE: case TYPEOF_TYPE: case UNDERLYING_TYPE: + case DEPENDENT_OPERATOR_TYPE: { tree expr = tree_node (); if (!get_overrun ()) diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 6b5e434..3bd7b20 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -7725,20 +7725,14 @@ lookup_name (tree name, LOOK_where where, LOOK_want want) if (binding) { - /* The saved lookups for an operator record 'nothing - found' as error_mark_node. We need to stop the search - here, but not return the error mark node. */ - if (binding == error_mark_node) - binding = NULL_TREE; - val = binding; - goto found; + break; } } } /* Now lookup in namespace scopes. */ - if (bool (where & LOOK_where::NAMESPACE)) + if (!val && bool (where & LOOK_where::NAMESPACE)) { name_lookup lookup (name, want); if (lookup.search_unqualified @@ -7746,8 +7740,6 @@ lookup_name (tree name, LOOK_where where, LOOK_want want) val = lookup.value; } - found:; - /* If we have a known type overload, pull it out. This can happen for both using decls and unhidden functions. */ if (val && TREE_CODE (val) == OVERLOAD && TREE_TYPE (val) != unknown_type_node) @@ -8949,125 +8941,4 @@ cp_emit_debug_info_for_using (tree t, tree context) } } -/* Return the result of unqualified lookup for the overloaded operator - designated by CODE, if we are in a template and the binding we find is - not. */ - -static tree -op_unqualified_lookup (tree fnname) -{ - if (cxx_binding *binding = IDENTIFIER_BINDING (fnname)) - { - cp_binding_level *l = binding->scope; - while (l && !l->this_entity) - l = l->level_chain; - - if (l && uses_template_parms (l->this_entity)) - /* Don't preserve decls from an uninstantiated template, - wait until that template is instantiated. */ - return NULL_TREE; - } - - tree fns = lookup_name (fnname); - if (!fns) - /* Remember we found nothing! */ - return error_mark_node; - - tree d = fns; - if (TREE_CODE (d) == TREE_LIST) - d = TREE_VALUE (d); - if (is_overloaded_fn (d)) - d = get_first_fn (d); - if (DECL_CLASS_SCOPE_P (d)) - /* We don't need to remember class-scope functions or declarations, - normal unqualified lookup will find them again. */ - return NULL_TREE; - - return fns; -} - -/* E is an expression representing an operation with dependent type, so we - don't know yet whether it will use the built-in meaning of the operator or a - function. Remember declarations of that operator in scope. - - We then inject a fake binding of that lookup into the - instantiation's parameter scope. This approach fails if the user - has different using declarations or directives in different local - binding of the current function from whence we need to do lookups - (we'll cache what we see on the first lookup). */ - -static const char *const op_bind_attrname = "operator bindings"; - -void -maybe_save_operator_binding (tree e) -{ - /* This is only useful in a template. */ - if (!processing_template_decl) - return; - - tree cfn = current_function_decl; - if (!cfn) - return; - - tree fnname; - if(TREE_CODE (e) == MODOP_EXPR) - fnname = ovl_op_identifier (true, TREE_CODE (TREE_OPERAND (e, 1))); - else - fnname = ovl_op_identifier (false, TREE_CODE (e)); - if (!fnname || fnname == assign_op_identifier) - return; - - tree attributes = DECL_ATTRIBUTES (cfn); - tree op_attr = lookup_attribute (op_bind_attrname, attributes); - if (!op_attr) - { - tree *ap = &DECL_ATTRIBUTES (cfn); - while (*ap && ATTR_IS_DEPENDENT (*ap)) - ap = &TREE_CHAIN (*ap); - op_attr = tree_cons (get_identifier (op_bind_attrname), - NULL_TREE, *ap); - *ap = op_attr; - } - - tree op_bind = purpose_member (fnname, TREE_VALUE (op_attr)); - if (!op_bind) - { - tree fns = op_unqualified_lookup (fnname); - - /* Always record, so we don't keep looking for this - operator. */ - TREE_VALUE (op_attr) = tree_cons (fnname, fns, TREE_VALUE (op_attr)); - } -} - -/* Called from cp_free_lang_data so we don't put this into LTO. */ - -void -discard_operator_bindings (tree decl) -{ - DECL_ATTRIBUTES (decl) = remove_attribute (op_bind_attrname, - DECL_ATTRIBUTES (decl)); -} - -/* Subroutine of start_preparsed_function: push the bindings we saved away in - maybe_save_op_lookup into the function parameter binding level. */ - -void -push_operator_bindings () -{ - tree decl1 = current_function_decl; - if (tree attr = lookup_attribute (op_bind_attrname, - DECL_ATTRIBUTES (decl1))) - for (tree binds = TREE_VALUE (attr); binds; binds = TREE_CHAIN (binds)) - if (tree val = TREE_VALUE (binds)) - { - tree name = TREE_PURPOSE (binds); - if (TREE_CODE (val) == TREE_LIST) - for (tree v = val; v; v = TREE_CHAIN (v)) - push_local_binding (name, TREE_VALUE (v), /*using*/true); - else - push_local_binding (name, val, /*using*/true); - } -} - #include "gt-cp-name-lookup.h" diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index f63c4f5..db705d2 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -465,10 +465,7 @@ extern void push_nested_namespace (tree); extern void pop_nested_namespace (tree); extern void push_to_top_level (void); extern void pop_from_top_level (void); -extern void maybe_save_operator_binding (tree); -extern void push_operator_bindings (void); extern void push_using_decl_bindings (tree, tree); -extern void discard_operator_bindings (tree); /* Lower level interface for modules. */ extern tree *mergeable_namespace_slots (tree ns, tree name, bool is_global, diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c2564e5..44eed7e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8731,7 +8731,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, return build_x_unary_op (token->location, (keyword == RID_REALPART ? REALPART_EXPR : IMAGPART_EXPR), - expression, + expression, NULL_TREE, tf_warning_or_error); } break; @@ -8908,7 +8908,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, case INDIRECT_REF: non_constant_p = NIC_STAR; expression = build_x_indirect_ref (loc, cast_expression, - RO_UNARY_STAR, + RO_UNARY_STAR, NULL_TREE, complain); /* TODO: build_x_indirect_ref does not always honor the location, so ensure it is set. */ @@ -8921,7 +8921,7 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, case BIT_NOT_EXPR: expression = build_x_unary_op (loc, unary_operator, cast_expression, - complain); + NULL_TREE, complain); /* TODO: build_x_unary_op does not always honor the location, so ensure it is set. */ expression.set_location (loc); @@ -10149,7 +10149,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, op_location_t op_loc (current.loc, combined_loc); current.lhs = build_x_binary_op (op_loc, current.tree_type, current.lhs, current.lhs_type, - rhs, rhs_type, &overload, + rhs, rhs_type, NULL_TREE, &overload, complain_flags (decltype_p)); /* TODO: build_x_binary_op doesn't always honor the location. */ current.lhs.set_location (combined_loc); @@ -10328,7 +10328,7 @@ cp_parser_assignment_expression (cp_parser* parser, cp_id_kind * pidk, rhs.get_finish ()); expr = build_x_modify_expr (loc, expr, assignment_operator, - rhs, + rhs, NULL_TREE, complain_flags (decltype_p)); /* TODO: build_x_modify_expr doesn't honor the location, so we must set it here. */ @@ -10480,7 +10480,7 @@ cp_parser_expression (cp_parser* parser, cp_id_kind * pidk, expression.get_start (), assignment_expression.get_finish ()); expression = build_x_compound_expr (loc, expression, - assignment_expression, + assignment_expression, NULL_TREE, complain_flags (decltype_p)); expression.set_location (loc); } @@ -13617,7 +13617,7 @@ do_range_for_auto_deduction (tree decl, tree range_expr) iter_decl = build_decl (input_location, VAR_DECL, NULL_TREE, iter_type); iter_decl = build_x_indirect_ref (input_location, iter_decl, - RO_UNARY_STAR, + RO_UNARY_STAR, NULL_TREE, tf_warning_or_error); TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), iter_decl, auto_node, @@ -13804,7 +13804,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr, condition = build_x_binary_op (input_location, NE_EXPR, begin, ERROR_MARK, end, ERROR_MARK, - NULL, tf_warning_or_error); + NULL_TREE, NULL, tf_warning_or_error); finish_for_cond (condition, statement, ivdep, unroll); /* The new increment expression. */ @@ -13818,7 +13818,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr, /* The declaration is initialized with *__begin inside the loop body. */ tree deref_begin = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, - tf_warning_or_error); + NULL_TREE, tf_warning_or_error); cp_finish_decl (range_decl, deref_begin, /*is_constant_init*/false, NULL_TREE, LOOKUP_ONLYCONVERTING); @@ -13924,7 +13924,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end) && (build_x_binary_op (input_location, NE_EXPR, *begin, ERROR_MARK, *end, ERROR_MARK, - NULL, tf_none) + NULL_TREE, NULL, tf_none) != error_mark_node)) /* P0184R0 allows __begin and __end to have different types, but make sure they are comparable so we can give a better @@ -18924,7 +18924,7 @@ cp_parser_template_argument (cp_parser* parser) { if (address_p) argument = build_x_unary_op (loc, ADDR_EXPR, argument, - tf_warning_or_error); + NULL_TREE, tf_warning_or_error); else argument = convert_from_reference (argument); return argument; @@ -31673,8 +31673,13 @@ cp_parser_single_declaration (cp_parser* parser, && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON) || decl_specifiers.type != error_mark_node)) { + int flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; + /* We don't delay parsing for friends, though CWG 2510 may change + that. */ + if (member_p && !(friend_p && *friend_p)) + flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT; decl = cp_parser_init_declarator (parser, - CP_PARSER_FLAGS_TYPENAME_OPTIONAL, + flags, &decl_specifiers, checks, /*function_definition_allowed_p=*/true, @@ -33527,7 +33532,7 @@ class_decl_loc_t::diag_mismatched_tags (tree type_decl) class_decl_loc_t *cdlguide = this; tree type = TREE_TYPE (type_decl); - if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)) + if (CLASS_TYPE_P (type) && CLASSTYPE_IMPLICIT_INSTANTIATION (type)) { /* For implicit instantiations of a primary template look up the primary or partial specialization and use it as @@ -41564,7 +41569,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code) TREE_CODE (cond), TREE_OPERAND (cond, 0), ERROR_MARK, TREE_OPERAND (cond, 1), ERROR_MARK, - /*overload=*/NULL, tf_warning_or_error); + NULL_TREE, /*overload=*/NULL, tf_warning_or_error); } /* Helper function, to parse omp for increment expression. */ @@ -41641,11 +41646,13 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl) lhs = rhs; else lhs = build_x_unary_op (input_location, NEGATE_EXPR, rhs, - tf_warning_or_error); + NULL_TREE, tf_warning_or_error); } else - lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs, - ERROR_MARK, NULL, tf_warning_or_error); + lhs = build_x_binary_op (input_location, op, + lhs, ERROR_MARK, + rhs, ERROR_MARK, + NULL_TREE, NULL, tf_warning_or_error); } } while (token->type == CPP_PLUS || token->type == CPP_MINUS); @@ -41873,7 +41880,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser, orig_init = rhs; finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs), decl, NOP_EXPR, - rhs, + rhs, NULL_TREE, tf_warning_or_error)); if (!add_private_clause) add_private_clause = decl; @@ -41995,7 +42002,7 @@ cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block, cond = build_x_binary_op (input_location, NE_EXPR, begin, ERROR_MARK, end, ERROR_MARK, - NULL, tf_warning_or_error); + NULL_TREE, NULL, tf_warning_or_error); /* The new increment expression. */ if (CLASS_TYPE_P (iter_type)) @@ -42033,7 +42040,7 @@ cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block, if (auto_node) { tree t = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, - tf_none); + NULL_TREE, tf_none); if (!error_operand_p (t)) TREE_TYPE (orig_decl) = do_auto_deduction (TREE_TYPE (orig_decl), t, auto_node); @@ -42073,7 +42080,7 @@ cp_finish_omp_range_for (tree orig, tree begin) /* The declaration is initialized with *__begin inside the loop body. */ cp_finish_decl (decl, build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, - tf_warning_or_error), + NULL_TREE, tf_warning_or_error), /*is_constant_init*/false, NULL_TREE, LOOKUP_ONLYCONVERTING); if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 62a058d..18c6f11 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12640,23 +12640,26 @@ expand_empty_fold (tree t, tsubst_flags_t complain) static tree fold_expression (tree t, tree left, tree right, tsubst_flags_t complain) { - tree op = FOLD_EXPR_OP (t); - tree_code code = (tree_code)TREE_INT_CST_LOW (op); + tree_code code = FOLD_EXPR_OP (t); + + tree lookups = templated_operator_saved_lookups (t); // Handle compound assignment operators. if (FOLD_EXPR_MODIFY_P (t)) - return build_x_modify_expr (input_location, left, code, right, complain); + return build_x_modify_expr (input_location, left, code, right, + lookups, complain); warning_sentinel s(warn_parentheses); switch (code) { case COMPOUND_EXPR: - return build_x_compound_expr (input_location, left, right, complain); + return build_x_compound_expr (input_location, left, right, + lookups, complain); default: return build_x_binary_op (input_location, code, left, TREE_CODE (left), right, TREE_CODE (right), - /*overload=*/NULL, + lookups, /*overload=*/NULL, complain); } } @@ -17891,7 +17894,7 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree &orig_declv, tree lhs = RECUR (TREE_OPERAND (incr, 0)); tree rhs = RECUR (TREE_OPERAND (incr, 1)); incr = build_x_modify_expr (EXPR_LOCATION (incr), lhs, - NOP_EXPR, rhs, complain); + NOP_EXPR, rhs, NULL_TREE, complain); } else incr = RECUR (incr); @@ -19204,6 +19207,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, RETURN (RECUR (TREE_OPERAND (t, 1))); RETURN (build_x_compound_expr (EXPR_LOCATION (t), tmp, RECUR (TREE_OPERAND (t, 1)), + templated_operator_saved_lookups (t), complain)); case ANNOTATE_EXPR: @@ -19855,6 +19859,7 @@ tsubst_copy_and_build (tree t, } else r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR, + templated_operator_saved_lookups (t), complain|decltype_flag); if (REF_PARENTHESIZED_P (t)) @@ -19965,6 +19970,7 @@ tsubst_copy_and_build (tree t, op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0), args, complain, in_decl); RETURN (build_x_unary_op (input_location, TREE_CODE (t), op1, + templated_operator_saved_lookups (t), complain|decltype_flag)); case PREDECREMENT_EXPR: @@ -19978,6 +19984,7 @@ tsubst_copy_and_build (tree t, case IMAGPART_EXPR: RETURN (build_x_unary_op (input_location, TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)), + templated_operator_saved_lookups (t), complain|decltype_flag)); case FIX_TRUNC_EXPR: @@ -19996,6 +20003,7 @@ tsubst_copy_and_build (tree t, op1 = tsubst_non_call_postfix_expression (op1, args, complain, in_decl); RETURN (build_x_unary_op (input_location, ADDR_EXPR, op1, + templated_operator_saved_lookups (t), complain|decltype_flag)); case PLUS_EXPR: @@ -20060,6 +20068,7 @@ tsubst_copy_and_build (tree t, (warning_suppressed_p (TREE_OPERAND (t, 1)) ? ERROR_MARK : TREE_CODE (TREE_OPERAND (t, 1))), + templated_operator_saved_lookups (t), /*overload=*/NULL, complain|decltype_flag); if (EXPR_P (r)) @@ -20212,8 +20221,10 @@ tsubst_copy_and_build (tree t, warning_sentinel s(warn_div_by_zero); tree lhs = RECUR (TREE_OPERAND (t, 0)); tree rhs = RECUR (TREE_OPERAND (t, 2)); + tree r = build_x_modify_expr (EXPR_LOCATION (t), lhs, TREE_CODE (TREE_OPERAND (t, 1)), rhs, + templated_operator_saved_lookups (t), complain|decltype_flag); /* TREE_NO_WARNING must be set if either the expression was parenthesized or it uses an operator such as >>= rather @@ -20314,6 +20325,7 @@ tsubst_copy_and_build (tree t, RETURN (build_x_compound_expr (EXPR_LOCATION (t), op0, RECUR (TREE_OPERAND (t, 1)), + templated_operator_saved_lookups (t), complain|decltype_flag)); } @@ -26994,6 +27006,9 @@ dependent_type_p_r (tree type) if (TREE_CODE (type) == TYPE_PACK_EXPANSION) return true; + if (TREE_CODE (type) == DEPENDENT_OPERATOR_TYPE) + return true; + if (any_dependent_type_attributes_p (TYPE_ATTRIBUTES (type))) return true; diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index d514aa2..f7ddae7 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -151,6 +151,12 @@ cxx_print_type (FILE *file, tree node, int indent) print_node (file, "expr", DECLTYPE_TYPE_EXPR (node), indent + 4); return; + case DEPENDENT_OPERATOR_TYPE: + print_node (file, "saved_lookups", + DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS (node), + indent + 4); + return; + case TYPENAME_TYPE: print_node (file, "fullname", TYPENAME_TYPE_FULLNAME (node), indent + 4); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 356fb83..6603066 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2920,7 +2920,7 @@ finish_increment_expr (cp_expr expr, enum tree_code code) expr.get_start (), get_finish (input_location)); cp_expr result = build_x_unary_op (combined_loc, code, expr, - tf_warning_or_error); + NULL_TREE, tf_warning_or_error); /* TODO: build_x_unary_op doesn't honor the location, so set it here. */ result.set_location (combined_loc); return result; @@ -3031,7 +3031,8 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr, of the operator token to the end of EXPR. */ location_t combined_loc = make_location (op_loc, op_loc, expr.get_finish ()); - cp_expr result = build_x_unary_op (combined_loc, code, expr, complain); + cp_expr result = build_x_unary_op (combined_loc, code, expr, + NULL_TREE, complain); /* TODO: build_x_unary_op doesn't always honor the location. */ result.set_location (combined_loc); @@ -9884,7 +9885,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, TREE_CODE (cond), iter, ERROR_MARK, TREE_OPERAND (cond, 1), ERROR_MARK, - NULL, tf_warning_or_error); + NULL_TREE, NULL, tf_warning_or_error); if (error_operand_p (tem)) return true; } @@ -9898,9 +9899,10 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, error_at (elocus, "invalid controlling predicate"); return true; } - diff = build_x_binary_op (elocus, MINUS_EXPR, TREE_OPERAND (cond, 1), - ERROR_MARK, iter, ERROR_MARK, NULL, - tf_warning_or_error); + diff = build_x_binary_op (elocus, MINUS_EXPR, + TREE_OPERAND (cond, 1), ERROR_MARK, + iter, ERROR_MARK, + NULL_TREE, NULL, tf_warning_or_error); diff = cp_fully_fold (diff); if (error_operand_p (diff)) return true; @@ -9928,7 +9930,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, } iter_incr = build_x_unary_op (EXPR_LOCATION (incr), TREE_CODE (incr), iter, - tf_warning_or_error); + NULL_TREE, tf_warning_or_error); if (error_operand_p (iter_incr)) return true; else if (TREE_CODE (incr) == PREINCREMENT_EXPR @@ -9954,6 +9956,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, iter_incr = build_x_modify_expr (EXPR_LOCATION (rhs), iter, TREE_CODE (rhs), TREE_OPERAND (rhs, 1), + NULL_TREE, tf_warning_or_error); if (error_operand_p (iter_incr)) return true; @@ -9983,13 +9986,13 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, PLUS_EXPR, TREE_OPERAND (rhs, 0), ERROR_MARK, iter, - ERROR_MARK, NULL, + ERROR_MARK, NULL_TREE, NULL, tf_warning_or_error); if (error_operand_p (iter_incr)) return true; iter_incr = build_x_modify_expr (EXPR_LOCATION (rhs), iter, NOP_EXPR, - iter_incr, + iter_incr, NULL_TREE, tf_warning_or_error); if (error_operand_p (iter_incr)) return true; @@ -10100,7 +10103,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, if (init != NULL) finish_expr_stmt (build_x_modify_expr (elocus, iter, NOP_EXPR, init, - tf_warning_or_error)); + NULL_TREE, tf_warning_or_error)); init = build_int_cst (TREE_TYPE (diff), 0); if (c && iter_incr == NULL && (!ordered || (i < collapse && collapse > 1))) @@ -10109,23 +10112,24 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, { finish_expr_stmt (build_x_modify_expr (elocus, incr_var, NOP_EXPR, - incr, tf_warning_or_error)); + incr, NULL_TREE, + tf_warning_or_error)); incr = incr_var; } iter_incr = build_x_modify_expr (elocus, iter, PLUS_EXPR, incr, - tf_warning_or_error); + NULL_TREE, tf_warning_or_error); } if (c && ordered && i < collapse && collapse > 1) iter_incr = incr; finish_expr_stmt (build_x_modify_expr (elocus, last, NOP_EXPR, init, - tf_warning_or_error)); + NULL_TREE, tf_warning_or_error)); if (diffvar) { finish_expr_stmt (build_x_modify_expr (elocus, diffvar, NOP_EXPR, - diff, tf_warning_or_error)); + diff, NULL_TREE, tf_warning_or_error)); diff = diffvar; } *pre_body = pop_stmt_list (*pre_body); @@ -10141,13 +10145,13 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), decl, last); iter_init = build_x_modify_expr (elocus, iter, PLUS_EXPR, iter_init, - tf_warning_or_error); + NULL_TREE, tf_warning_or_error); if (iter_init != error_mark_node) iter_init = build1 (NOP_EXPR, void_type_node, iter_init); finish_expr_stmt (iter_init); finish_expr_stmt (build_x_modify_expr (elocus, last, NOP_EXPR, decl, - tf_warning_or_error)); + NULL_TREE, tf_warning_or_error)); add_stmt (orig_body); *body = pop_stmt_list (*body); @@ -10165,7 +10169,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), iter_init, last); iter_init = build_x_modify_expr (elocus, iter, PLUS_EXPR, iter_init, - tf_warning_or_error); + NULL_TREE, tf_warning_or_error); if (iter_init != error_mark_node) iter_init = build1 (NOP_EXPR, void_type_node, iter_init); finish_expr_stmt (iter_init); @@ -10876,7 +10880,7 @@ finish_omp_cancel (tree clauses) ifc = build_x_binary_op (OMP_CLAUSE_LOCATION (ifc), NE_EXPR, OMP_CLAUSE_IF_EXPR (ifc), ERROR_MARK, integer_zero_node, ERROR_MARK, - NULL, tf_warning_or_error); + NULL_TREE, NULL, tf_warning_or_error); } else ifc = boolean_true_node; @@ -12128,6 +12132,9 @@ finish_unary_fold_expr (tree expr, int op, tree_code dir) tree code = build_int_cstu (integer_type_node, abs (op)); tree fold = build_min_nt_loc (UNKNOWN_LOCATION, dir, code, pack); FOLD_EXPR_MODIFY_P (fold) = (op < 0); + TREE_TYPE (fold) = build_dependent_operator_type (NULL_TREE, + FOLD_EXPR_OP (fold), + FOLD_EXPR_MODIFY_P (fold)); return fold; } @@ -12154,6 +12161,9 @@ finish_binary_fold_expr (tree pack, tree init, int op, tree_code dir) tree code = build_int_cstu (integer_type_node, abs (op)); tree fold = build_min_nt_loc (UNKNOWN_LOCATION, dir, code, pack, init); FOLD_EXPR_MODIFY_P (fold) = (op < 0); + TREE_TYPE (fold) = build_dependent_operator_type (NULL_TREE, + FOLD_EXPR_OP (fold), + FOLD_EXPR_MODIFY_P (fold)); return fold; } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 284fb5f..29f3c17 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -5975,8 +5975,6 @@ cp_free_lang_data (tree t) DECL_EXTERNAL (t) = 1; TREE_STATIC (t) = 0; } - if (TREE_CODE (t) == FUNCTION_DECL) - discard_operator_bindings (t); if (TREE_CODE (t) == NAMESPACE_DECL) /* We do not need the leftover chaining of namespaces from the binding level. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 4e60db4..5184b02 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2602,6 +2602,7 @@ rationalize_conditional_expr (enum tree_code code, tree t, ? LE_EXPR : GE_EXPR), op0, TREE_CODE (op0), op1, TREE_CODE (op1), + NULL_TREE, /*overload=*/NULL, complain), cp_build_unary_op (code, op0, false, complain), @@ -3487,6 +3488,67 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) return build_simple_component_ref (ptrmem, member); } +/* Return a TREE_LIST of namespace-scope overloads for the given operator, + and for any other relevant operator. */ + +static tree +op_unqualified_lookup (tree_code code, bool is_assign) +{ + tree lookups = NULL_TREE; + + if (cxx_dialect >= cxx20 && !is_assign) + { + if (code == NE_EXPR) + { + /* != can get rewritten in terms of ==. */ + tree fnname = ovl_op_identifier (false, EQ_EXPR); + if (tree fns = lookup_name (fnname, LOOK_where::BLOCK_NAMESPACE)) + lookups = tree_cons (fnname, fns, lookups); + } + else if (code == GT_EXPR || code == LE_EXPR + || code == LT_EXPR || code == GE_EXPR) + { + /* These can get rewritten in terms of <=>. */ + tree fnname = ovl_op_identifier (false, SPACESHIP_EXPR); + if (tree fns = lookup_name (fnname, LOOK_where::BLOCK_NAMESPACE)) + lookups = tree_cons (fnname, fns, lookups); + } + } + + tree fnname = ovl_op_identifier (is_assign, code); + if (tree fns = lookup_name (fnname, LOOK_where::BLOCK_NAMESPACE)) + lookups = tree_cons (fnname, fns, lookups); + + if (lookups) + return lookups; + else + return build_tree_list (NULL_TREE, NULL_TREE); +} + +/* Create a DEPENDENT_OPERATOR_TYPE for a dependent operator expression of + the given operator. LOOKUPS, if non-NULL, is the result of phase 1 + name lookup for the given operator. */ + +tree +build_dependent_operator_type (tree lookups, tree_code code, bool is_assign) +{ + if (lookups) + /* We're partially instantiating a dependent operator expression, and + LOOKUPS is the result of phase 1 name lookup that we performed + earlier at template definition time, so just reuse the corresponding + DEPENDENT_OPERATOR_TYPE. */ + return TREE_TYPE (lookups); + + /* Otherwise we're processing a dependent operator expression at template + definition time, so perform phase 1 name lookup now. */ + lookups = op_unqualified_lookup (code, is_assign); + + tree type = cxx_make_type (DEPENDENT_OPERATOR_TYPE); + DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS (type) = lookups; + TREE_TYPE (lookups) = type; + return type; +} + /* Given an expression PTR for a pointer, return an expression for the value pointed to. ERRORSTRING is the name of the operator to appear in error messages. @@ -3496,7 +3558,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) tree build_x_indirect_ref (location_t loc, tree expr, ref_operator errorstring, - tsubst_flags_t complain) + tree lookups, tsubst_flags_t complain) { tree orig_expr = expr; tree rval; @@ -3516,12 +3578,18 @@ build_x_indirect_ref (location_t loc, tree expr, ref_operator errorstring, return build_min (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr); } if (type_dependent_expression_p (expr)) - return build_min_nt_loc (loc, INDIRECT_REF, expr); + { + expr = build_min_nt_loc (loc, INDIRECT_REF, expr); + TREE_TYPE (expr) + = build_dependent_operator_type (lookups, INDIRECT_REF, false); + return expr; + } expr = build_non_dependent_expr (expr); } rval = build_new_op (loc, INDIRECT_REF, LOOKUP_NORMAL, expr, - NULL_TREE, NULL_TREE, &overload, complain); + NULL_TREE, NULL_TREE, lookups, + &overload, complain); if (!rval) rval = cp_build_indirect_ref (loc, expr, errorstring, complain); @@ -4458,8 +4526,8 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl, tree build_x_binary_op (const op_location_t &loc, enum tree_code code, tree arg1, enum tree_code arg1_code, tree arg2, - enum tree_code arg2_code, tree *overload_p, - tsubst_flags_t complain) + enum tree_code arg2_code, tree lookups, + tree *overload_p, tsubst_flags_t complain) { tree orig_arg1; tree orig_arg2; @@ -4475,7 +4543,8 @@ build_x_binary_op (const op_location_t &loc, enum tree_code code, tree arg1, || type_dependent_expression_p (arg2)) { expr = build_min_nt_loc (loc, code, arg1, arg2); - maybe_save_operator_binding (expr); + TREE_TYPE (expr) + = build_dependent_operator_type (lookups, code, false); return expr; } arg1 = build_non_dependent_expr (arg1); @@ -4486,7 +4555,7 @@ build_x_binary_op (const op_location_t &loc, enum tree_code code, tree arg1, expr = build_m_component_ref (arg1, arg2, complain); else expr = build_new_op (loc, code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE, - &overload, complain); + lookups, &overload, complain); if (overload_p != NULL) *overload_p = overload; @@ -4538,7 +4607,7 @@ build_x_array_ref (location_t loc, tree arg1, tree arg2, } expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, arg1, arg2, - NULL_TREE, &overload, complain); + NULL_TREE, NULL_TREE, &overload, complain); if (processing_template_decl && expr != error_mark_node) { @@ -6402,7 +6471,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree ptrtype, tree build_x_unary_op (location_t loc, enum tree_code code, cp_expr xarg, - tsubst_flags_t complain) + tree lookups, tsubst_flags_t complain) { tree orig_expr = xarg; tree exp; @@ -6414,7 +6483,7 @@ build_x_unary_op (location_t loc, enum tree_code code, cp_expr xarg, if (type_dependent_expression_p (xarg)) { tree e = build_min_nt_loc (loc, code, xarg.get_value (), NULL_TREE); - maybe_save_operator_binding (e); + TREE_TYPE (e) = build_dependent_operator_type (lookups, code, false); return e; } @@ -6439,7 +6508,7 @@ build_x_unary_op (location_t loc, enum tree_code code, cp_expr xarg, /* Don't look for a function. */; else exp = build_new_op (loc, code, LOOKUP_NORMAL, xarg, NULL_TREE, - NULL_TREE, &overload, complain); + NULL_TREE, lookups, &overload, complain); if (!exp && code == ADDR_EXPR) { @@ -7508,7 +7577,8 @@ build_x_compound_expr_from_list (tree list, expr_list_kind exp, for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list)) expr = build_x_compound_expr (EXPR_LOCATION (TREE_VALUE (list)), - expr, TREE_VALUE (list), complain); + expr, TREE_VALUE (list), NULL_TREE, + complain); } return expr; @@ -7543,7 +7613,7 @@ build_x_compound_expr_from_vec (vec<tree, va_gc> *vec, const char *msg, expr = (*vec)[0]; for (ix = 1; vec->iterate (ix, &t); ++ix) expr = build_x_compound_expr (EXPR_LOCATION (t), expr, - t, complain); + t, NULL_TREE, complain); return expr; } @@ -7553,7 +7623,7 @@ build_x_compound_expr_from_vec (vec<tree, va_gc> *vec, const char *msg, tree build_x_compound_expr (location_t loc, tree op1, tree op2, - tsubst_flags_t complain) + tree lookups, tsubst_flags_t complain) { tree result; tree orig_op1 = op1; @@ -7566,7 +7636,8 @@ build_x_compound_expr (location_t loc, tree op1, tree op2, || type_dependent_expression_p (op2)) { result = build_min_nt_loc (loc, COMPOUND_EXPR, op1, op2); - maybe_save_operator_binding (result); + TREE_TYPE (result) + = build_dependent_operator_type (lookups, COMPOUND_EXPR, false); return result; } op1 = build_non_dependent_expr (op1); @@ -7574,7 +7645,7 @@ build_x_compound_expr (location_t loc, tree op1, tree op2, } result = build_new_op (loc, COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, - NULL_TREE, &overload, complain); + NULL_TREE, lookups, &overload, complain); if (!result) result = cp_build_compound_expr (op1, op2, complain); @@ -9017,8 +9088,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, { result = build_new_op (input_location, MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, - make_node (NOP_EXPR), /*overload=*/NULL, - complain); + make_node (NOP_EXPR), NULL_TREE, + /*overload=*/NULL, complain); if (result == NULL_TREE) return error_mark_node; goto ret; @@ -9233,7 +9304,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, cp_expr build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, - tree rhs, tsubst_flags_t complain) + tree rhs, tree lookups, tsubst_flags_t complain) { tree orig_lhs = lhs; tree orig_rhs = rhs; @@ -9250,7 +9321,9 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, { tree op = build_min_nt_loc (loc, modifycode, NULL_TREE, NULL_TREE); tree rval = build_min_nt_loc (loc, MODOP_EXPR, lhs, op, rhs); - maybe_save_operator_binding (rval); + if (modifycode != NOP_EXPR) + TREE_TYPE (rval) + = build_dependent_operator_type (lookups, modifycode, true); return rval; } @@ -9262,7 +9335,7 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, { tree op = build_nt (modifycode, NULL_TREE, NULL_TREE); tree rval = build_new_op (loc, MODIFY_EXPR, LOOKUP_NORMAL, - lhs, rhs, op, &overload, complain); + lhs, rhs, op, lookups, &overload, complain); if (rval) { if (rval == error_mark_node) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 3fb651a..724684c 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1956,7 +1956,7 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain) while ((expr = build_new_op (loc, COMPONENT_REF, LOOKUP_NORMAL, expr, NULL_TREE, NULL_TREE, - &fn, complain))) + NULL_TREE, &fn, complain))) { if (expr == error_mark_node) return error_mark_node; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 5099fa9..cf508ff 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -12708,6 +12708,7 @@ __atomic_store_n(&lockvar, 0, __ATOMIC_RELEASE|__ATOMIC_HLE_RELEASE); @node Object Size Checking @section Object Size Checking Built-in Functions @findex __builtin_object_size +@findex __builtin_dynamic_object_size @findex __builtin___memcpy_chk @findex __builtin___mempcpy_chk @findex __builtin___memmove_chk @@ -12775,6 +12776,18 @@ assert (__builtin_object_size (q, 1) == sizeof (var.b)); @end smallexample @end deftypefn +@deftypefn {Built-in Function} {size_t} __builtin_dynamic_object_size (const void * @var{ptr}, int @var{type}) +is similar to @code{__builtin_object_size} in that it returns a number of bytes +from @var{ptr} to the end of the object @var{ptr} pointer points to, except +that the size returned may not be a constant. This results in successful +evaluation of object size estimates in a wider range of use cases and can be +more precise than @code{__builtin_object_size}, but it incurs a performance +penalty since it may add a runtime overhead on size computation. Semantics of +@var{type} as well as return values in case it is not possible to determine +which objects @var{ptr} points to at compile time are the same as in the case +of @code{__builtin_object_size}. +@end deftypefn + There are built-in functions added for many common string operation functions, e.g., for @code{memcpy} @code{__builtin___memcpy_chk} built-in is provided. This built-in has an additional last argument, diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 20d172f..03028c2 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -12388,10 +12388,10 @@ The @option{-fstrict-aliasing} option is enabled at levels @item -fipa-strict-aliasing @opindex fipa-strict-aliasing -Constrols whether rules of @option{-fstrict-aliasing} are applied across +Controls whether rules of @option{-fstrict-aliasing} are applied across function boundaries. Note that if multiple functions gets inlined into a -signle function the memory accesses are no longer considred to be crossing a -function bounday. +single function the memory accesses are no longer considered to be crossing a +function boundary. The @option{-fipa-strict-aliasing} option is enabled by default and is effective only in combination with @option{-fstrict-aliasing}. @@ -14147,7 +14147,7 @@ value of a shared integer constant. @item ssp-buffer-size The minimum size of buffers (i.e.@: arrays) that receive stack smashing -protection when @option{-fstack-protection} is used. +protection when @option{-fstack-protector} is used. @item min-size-for-stack-sharing The minimum size of variables taking part in stack slot sharing when not diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 1d8fd74..64515aa 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2493,17 +2493,16 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi) if (!src_len || known_lower (stmt, len, src_len, true)) return false; - unsigned HOST_WIDE_INT dstsize; - bool found_dstsize = compute_builtin_object_size (dst, 1, &dstsize); - /* Warn on constant LEN. */ if (TREE_CODE (len) == INTEGER_CST) { bool nowarn = warning_suppressed_p (stmt, OPT_Wstringop_overflow_); + tree dstsize; - if (!nowarn && found_dstsize) + if (!nowarn && compute_builtin_object_size (dst, 1, &dstsize) + && TREE_CODE (dstsize) == INTEGER_CST) { - int cmpdst = compare_tree_int (len, dstsize); + int cmpdst = tree_int_cst_compare (len, dstsize); if (cmpdst >= 0) { @@ -2519,7 +2518,7 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi) ? G_("%qD specified bound %E equals " "destination size") : G_("%qD specified bound %E exceeds " - "destination size %wu"), + "destination size %E"), fndecl, len, dstsize); if (nowarn) suppress_warning (stmt, OPT_Wstringop_overflow_); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a38eac6..919710f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,57 @@ +2021-12-16 Sandra Loosemore <sandra@codesourcery.com> + + * gcc.dg/20021029-1.c: Build with -G0 for nios2. + +2021-12-16 Marek Polacek <polacek@redhat.com> + + PR c++/99980 + * g++.dg/cpp0x/noexcept71.C: New test. + +2021-12-16 Martin Sebor <msebor@redhat.com> + + PR c++/103703 + * g++.dg/warn/Wmismatched-tags-9.C: New test. + +2021-12-16 Martin Sebor <msebor@redhat.com> + + PR testsuite/103751 + * gcc.dg/Warray-bounds-48.c: Fix member alignment. + +2021-12-16 Patrick Palka <ppalka@redhat.com> + + PR c++/51577 + PR c++/83035 + PR c++/100465 + * g++.dg/lookup/operator-3.C: Split out operator overload + declarations into ... + * g++.dg/lookup/operator-3-ops.h: ... here. + * g++.dg/lookup/operator-3a.C: New test. + * g++.dg/lookup/operator-4.C: New test. + * g++.dg/lookup/operator-4a.C: New test. + * g++.dg/lookup/operator-5.C: New test. + * g++.dg/lookup/operator-5a.C: New test. + * g++.dg/lookup/operator-6.C: New test. + * g++.dg/lookup/operator-7.C: New test. + * g++.dg/lookup/operator-8.C: New test. + +2021-12-16 Uroš Bizjak <ubizjak@gmail.com> + + PR target/103571 + * gcc.target/i386/pr102812.c (dg-final): Do not scan for movdqa. + +2021-12-16 Martin Liska <mliska@suse.cz> + + PR c++/103696 + * g++.target/i386/pr103696.C: New test. + +2021-12-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * gfortran.dg/iostat_5.f90: New file. + +2021-12-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * gfortran.dg/date_and_time_1.f90: New file. + 2021-12-15 Marek Polacek <polacek@redhat.com> PR c++/102229 diff --git a/gcc/testsuite/g++.dg/abi/macro0.C b/gcc/testsuite/g++.dg/abi/macro0.C index f25f291..2d07fcd 100644 --- a/gcc/testsuite/g++.dg/abi/macro0.C +++ b/gcc/testsuite/g++.dg/abi/macro0.C @@ -1,6 +1,6 @@ // This testcase will need to be kept in sync with c_common_post_options. // { dg-options "-fabi-version=0" } -#if __GXX_ABI_VERSION != 1016 +#if __GXX_ABI_VERSION != 1017 #error "Incorrect value of __GXX_ABI_VERSION" #endif diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address6.C b/gcc/testsuite/g++.dg/abi/no_unique_address6.C new file mode 100644 index 0000000..5df6995 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/no_unique_address6.C @@ -0,0 +1,23 @@ +// { dg-do compile { target c++20 } } + +#pragma GCC diagnostic ignored "-Winvalid-offsetof" + +struct E { }; + +struct A: virtual E { + // Deny the vbase offset 0 so it goes at the end. + [[no_unique_address]] E e1; + char c; +}; + +struct B : public A { + char d; +}; + +struct C { + [[no_unique_address]] A a; + char d; +}; + +#define SA(X) static_assert ((X),#X) +SA(__builtin_offsetof (B, d) == __builtin_offsetof (C, d)); diff --git a/gcc/testsuite/g++.dg/abi/nsdmi-aggr1.C b/gcc/testsuite/g++.dg/abi/nsdmi-aggr1.C new file mode 100644 index 0000000..c212c43 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/nsdmi-aggr1.C @@ -0,0 +1,39 @@ +// PR c++/103681 +// { dg-do compile { target c++11 } } +// { dg-additional-options "-fabi-version=16 -Wabi" } + +struct A { + long l; + char c = -1; +}; +struct B : public A { + char d; + // { dg-warning "offset" "" { target c++14 } .-1 } +}; + +#define SA(X) static_assert(X,#X) +SA(sizeof (B) == sizeof (A)); +// { dg-error "static assertion" "" { target c++14 } .-1 } + +struct X { char d; }; +struct B2 : A, X { }; +// { dg-warning "offset" "" { target c++14 } .-1 } +SA(sizeof (B2) == sizeof (A)); +// { dg-error "static assertion" "" { target c++14 } .-1 } + +#if __cplusplus > 201800L + +struct C { + [[no_unique_address]] A a; + char d; + // { dg-warning "offset" "" { target c++20 } .-1 } +}; +SA(sizeof (C) == sizeof (A)); +// { dg-error "static assertion" "" { target c++20 } .-1 } + +struct C2 : A, X { }; +// { dg-warning "offset" "" { target c++20 } .-1 } +SA(sizeof (B2) == sizeof (A)); +// { dg-error "static assertion" "" { target c++20 } .-1 } + +#endif /* C++20 */ diff --git a/gcc/testsuite/g++.dg/abi/nsdmi-aggr1a.C b/gcc/testsuite/g++.dg/abi/nsdmi-aggr1a.C new file mode 100644 index 0000000..e7a509d --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/nsdmi-aggr1a.C @@ -0,0 +1,35 @@ +// PR c++/103681 +// { dg-do compile { target c++11 } } +// { dg-additional-options "-fabi-version=0 -Wabi=16" } + +struct A { + long l; + char c = -1; +}; +struct B : public A { + char d; + // { dg-warning "offset" "" { target c++14 } .-1 } +}; + +#define SA(X) static_assert(X,#X) +SA(sizeof (B) == sizeof (A)); + +struct X { char d; }; +struct B2 : A, X { }; +// { dg-warning "offset" "" { target c++14 } .-1 } +SA(sizeof (B2) == sizeof (A)); + +#if __cplusplus > 201800L + +struct C { + [[no_unique_address]] A a; + char d; + // { dg-warning "offset" "" { target c++20 } .-1 } +}; +SA(sizeof (C) == sizeof (A)); + +struct C2 : A, X { }; +// { dg-warning "offset" "" { target c++20 } .-1 } +SA(sizeof (B2) == sizeof (A)); + +#endif /* C++20 */ diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept71.C b/gcc/testsuite/g++.dg/cpp0x/noexcept71.C new file mode 100644 index 0000000..361d6ad --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept71.C @@ -0,0 +1,31 @@ +// PR c++/99980 +// { dg-do compile { target c++11 } } + +#define SA(X) static_assert(X, #X) + +struct S { + template<typename T> + void f(T) noexcept(B); + + struct N { + template<typename T> + void f2(T) noexcept(B); + }; + + static constexpr bool B = true; +}; + +S s; +SA(noexcept(s.f(10))); +S::N n; +SA(noexcept(n.f2(10))); + +struct Bad { + template<typename T> + using U = void() noexcept(B); // { dg-error "not declared" } + + template<typename T> + friend void friendo() noexcept(B); // { dg-error "not declared" } + + static constexpr bool B = true; +}; diff --git a/gcc/testsuite/g++.dg/ext/builtin-dynamic-object-size1.C b/gcc/testsuite/g++.dg/ext/builtin-dynamic-object-size1.C new file mode 100644 index 0000000..b11ac20 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/builtin-dynamic-object-size1.C @@ -0,0 +1,5 @@ +// { dg-do run } +// { dg-options "-O2" } + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size1.C" diff --git a/gcc/testsuite/g++.dg/ext/builtin-dynamic-object-size2.C b/gcc/testsuite/g++.dg/ext/builtin-dynamic-object-size2.C new file mode 100644 index 0000000..6e52cf3 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/builtin-dynamic-object-size2.C @@ -0,0 +1,5 @@ +// { dg-do run } +// { dg-options "-O2" } + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size2.C" diff --git a/gcc/testsuite/g++.dg/lookup/operator-3-ops.h b/gcc/testsuite/g++.dg/lookup/operator-3-ops.h new file mode 100644 index 0000000..fbd242a --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-3-ops.h @@ -0,0 +1,53 @@ +void operator+(N::A); +void operator-(N::A); +void operator*(N::A); +void operator~(N::A); +#if __cplusplus >= 201103L +void operator&(N::A) = delete; +#else +void operator&(N::A); +#endif +void operator!(N::A); +void operator++(N::A); +void operator--(N::A); +void operator++(N::A, int); +void operator--(N::A, int); + +void operator->*(N::A, N::A); +void operator/(N::A, N::A); +void operator*(N::A, N::A); +void operator+(N::A, N::A); +void operator-(N::A, N::A); +void operator%(N::A, N::A); +void operator&(N::A, N::A); +void operator|(N::A, N::A); +void operator^(N::A, N::A); +void operator<<(N::A, N::A); +void operator>>(N::A, N::A); +void operator&&(N::A, N::A); +void operator||(N::A, N::A); +#if __cplusplus >= 201103L +void operator,(N::A, N::A) = delete; +#else +void operator,(N::A, N::A); +#endif + +void operator==(N::A, N::A); +void operator!=(N::A, N::A); +void operator<(N::A, N::A); +void operator>(N::A, N::A); +void operator<=(N::A, N::A); +void operator>=(N::A, N::A); +#if __cplusplus > 201703L +void operator<=>(N::A, N::A); +#endif + +void operator+=(N::A, N::A); +void operator-=(N::A, N::A); +void operator*=(N::A, N::A); +void operator/=(N::A, N::A); +void operator%=(N::A, N::A); +void operator|=(N::A, N::A); +void operator^=(N::A, N::A); +void operator<<=(N::A, N::A); +void operator>>=(N::A, N::A); diff --git a/gcc/testsuite/g++.dg/lookup/operator-3.C b/gcc/testsuite/g++.dg/lookup/operator-3.C index bc5eb3d..ab0257a 100644 --- a/gcc/testsuite/g++.dg/lookup/operator-3.C +++ b/gcc/testsuite/g++.dg/lookup/operator-3.C @@ -1,4 +1,6 @@ // PR c++/51577 +// Verify we don't consider later-declared namespace-scope operator overloads +// when instantiating a dependent operator expression that occurs at block scope. template <class T> void f (T x) { +x; // { dg-error "no match" } @@ -50,59 +52,7 @@ template <class T> void f (T x) { namespace N { struct A { }; } -void operator+(N::A); -void operator-(N::A); -void operator*(N::A); -void operator~(N::A); -#if __cplusplus >= 201103L -void operator&(N::A) = delete; -#else -void operator&(N::A); -#endif -void operator!(N::A); -void operator++(N::A); -void operator--(N::A); -void operator++(N::A, int); -void operator--(N::A, int); - -void operator->*(N::A, N::A); -void operator/(N::A, N::A); -void operator*(N::A, N::A); -void operator+(N::A, N::A); -void operator-(N::A, N::A); -void operator%(N::A, N::A); -void operator&(N::A, N::A); -void operator|(N::A, N::A); -void operator^(N::A, N::A); -void operator<<(N::A, N::A); -void operator>>(N::A, N::A); -void operator&&(N::A, N::A); -void operator||(N::A, N::A); -#if __cplusplus >= 201103L -void operator,(N::A, N::A) = delete; -#else -void operator,(N::A, N::A); -#endif - -void operator==(N::A, N::A); -void operator!=(N::A, N::A); -void operator<(N::A, N::A); -void operator>(N::A, N::A); -void operator<=(N::A, N::A); -void operator>=(N::A, N::A); -#if __cplusplus > 201703L -void operator<=>(N::A, N::A); -#endif - -void operator+=(N::A, N::A); -void operator-=(N::A, N::A); -void operator*=(N::A, N::A); -void operator/=(N::A, N::A); -void operator%=(N::A, N::A); -void operator|=(N::A, N::A); -void operator^=(N::A, N::A); -void operator<<=(N::A, N::A); -void operator>>=(N::A, N::A); +#include "operator-3-ops.h" int main() { f(N::A()); diff --git a/gcc/testsuite/g++.dg/lookup/operator-3a.C b/gcc/testsuite/g++.dg/lookup/operator-3a.C new file mode 100644 index 0000000..62ae5c3 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-3a.C @@ -0,0 +1,61 @@ +// PR c++/51577 +// { dg-do compile { target c++14 } } +// Like operator-3.C but also containing a partial instantiation step. + +template <class...> auto f () { + return [] (auto x) { + +x; // { dg-error "no match" } + -x; // { dg-error "no match" } + *x; // { dg-error "no match" } + ~x; // { dg-error "no match" } + &x; + !x; // { dg-error "no match" } + ++x; // { dg-error "no match" } + --x; // { dg-error "no match" } + x++; // { dg-error "declared for postfix" } + x--; // { dg-error "declared for postfix" } + + x->*x; // { dg-error "no match" } + x / x; // { dg-error "no match" } + x * x; // { dg-error "no match" } + x + x; // { dg-error "no match" } + x - x; // { dg-error "no match" } + x % x; // { dg-error "no match" } + x & x; // { dg-error "no match" } + x | x; // { dg-error "no match" } + x ^ x; // { dg-error "no match" } + x << x; // { dg-error "no match" } + x >> x; // { dg-error "no match" } + x && x; // { dg-error "no match" } + x || x; // { dg-error "no match" } + x, x; + + x == x; // { dg-error "no match" } + x != x; // { dg-error "no match" } + x < x; // { dg-error "no match" } + x > x; // { dg-error "no match" } + x <= x; // { dg-error "no match" } + x >= x; // { dg-error "no match" } +#if __cplusplus > 201703L + x <=> x; // { dg-error "no match" "" { target c++20 } } +#endif + + x += x; // { dg-error "no match" } + x -= x; // { dg-error "no match" } + x *= x; // { dg-error "no match" } + x /= x; // { dg-error "no match" } + x %= x; // { dg-error "no match" } + x |= x; // { dg-error "no match" } + x ^= x; // { dg-error "no match" } + x <<= x; // { dg-error "no match" } + x >>= x; // { dg-error "no match" } + }; +} + +namespace N { struct A { }; } + +#include "operator-3-ops.h" + +int main() { + f()(N::A()); +} diff --git a/gcc/testsuite/g++.dg/lookup/operator-4.C b/gcc/testsuite/g++.dg/lookup/operator-4.C new file mode 100644 index 0000000..e0b80a1 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-4.C @@ -0,0 +1,74 @@ +// PR c++/51577 +// { dg-do compile { target c++17 } } +// Like operator-3.C but for unary fold expressions. + +template <class... Ts> void f (Ts... xs) { + (xs->*...); // { dg-error "no match" } + (...->*xs); // { dg-error "no match" } + (xs / ...); // { dg-error "no match" } + (... / xs); // { dg-error "no match" } + (xs * ...); // { dg-error "no match" } + (... * xs); // { dg-error "no match" } + (xs + ...); // { dg-error "no match" } + (... + xs); // { dg-error "no match" } + (xs - ...); // { dg-error "no match" } + (... - xs); // { dg-error "no match" } + (xs % ...); // { dg-error "no match" } + (... % xs); // { dg-error "no match" } + (xs & ...); // { dg-error "no match" } + (... & xs); // { dg-error "no match" } + (xs | ...); // { dg-error "no match" } + (... | xs); // { dg-error "no match" } + (xs ^ ...); // { dg-error "no match" } + (... ^ xs); // { dg-error "no match" } + (xs << ...); // { dg-error "no match" } + (... << xs); // { dg-error "no match" } + (xs >> ...); // { dg-error "no match" } + (... >> xs); // { dg-error "no match" } + (xs && ...); // { dg-error "no match" } + (... && xs); // { dg-error "no match" } + (xs || ...); // { dg-error "no match" } + (... || xs); // { dg-error "no match" } + (xs, ...); + (..., xs); + + (xs == ...); // { dg-error "no match" } + (... == xs); // { dg-error "no match" } + (xs != ...); // { dg-error "no match" } + (... != xs); // { dg-error "no match" } + (xs < ...); // { dg-error "no match" } + (... < xs); // { dg-error "no match" } + (xs > ...); // { dg-error "no match" } + (... > xs); // { dg-error "no match" } + (xs <= ...); // { dg-error "no match" } + (... <= xs); // { dg-error "no match" } + (xs >= ...); // { dg-error "no match" } + (... >= xs); // { dg-error "no match" } + + (xs += ...); // { dg-error "no match" } + (... += xs); // { dg-error "no match" } + (xs -= ...); // { dg-error "no match" } + (... -= xs); // { dg-error "no match" } + (xs *= ...); // { dg-error "no match" } + (... *= xs); // { dg-error "no match" } + (xs /= ...); // { dg-error "no match" } + (... /= xs); // { dg-error "no match" } + (xs %= ...); // { dg-error "no match" } + (... %= xs); // { dg-error "no match" } + (xs |= ...); // { dg-error "no match" } + (... |= xs); // { dg-error "no match" } + (xs ^= ...); // { dg-error "no match" } + (... ^= xs); // { dg-error "no match" } + (xs <<= ...); // { dg-error "no match" } + (... <<= xs); // { dg-error "no match" } + (xs >>= ...); // { dg-error "no match" } + (... >>= xs); // { dg-error "no match" } +} + +namespace N { struct A { }; } + +#include "operator-3-ops.h" + +int main() { + f(N::A(), N::A()); +} diff --git a/gcc/testsuite/g++.dg/lookup/operator-4a.C b/gcc/testsuite/g++.dg/lookup/operator-4a.C new file mode 100644 index 0000000..b4a3f94 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-4a.C @@ -0,0 +1,76 @@ +// PR c++/51577 +// { dg-do compile { target c++17 } } +// Like operator-4.C but also containing a partial instantiation step. + +template <class...> auto f () { + return [] (auto... xs) { + (xs->*...); // { dg-error "no match" } + (...->*xs); // { dg-error "no match" } + (xs / ...); // { dg-error "no match" } + (... / xs); // { dg-error "no match" } + (xs * ...); // { dg-error "no match" } + (... * xs); // { dg-error "no match" } + (xs + ...); // { dg-error "no match" } + (... + xs); // { dg-error "no match" } + (xs - ...); // { dg-error "no match" } + (... - xs); // { dg-error "no match" } + (xs % ...); // { dg-error "no match" } + (... % xs); // { dg-error "no match" } + (xs & ...); // { dg-error "no match" } + (... & xs); // { dg-error "no match" } + (xs | ...); // { dg-error "no match" } + (... | xs); // { dg-error "no match" } + (xs ^ ...); // { dg-error "no match" } + (... ^ xs); // { dg-error "no match" } + (xs << ...); // { dg-error "no match" } + (... << xs); // { dg-error "no match" } + (xs >> ...); // { dg-error "no match" } + (... >> xs); // { dg-error "no match" } + (xs && ...); // { dg-error "no match" } + (... && xs); // { dg-error "no match" } + (xs || ...); // { dg-error "no match" } + (... || xs); // { dg-error "no match" } + (xs, ...); + (..., xs); + + (xs == ...); // { dg-error "no match" } + (... == xs); // { dg-error "no match" } + (xs != ...); // { dg-error "no match" } + (... != xs); // { dg-error "no match" } + (xs < ...); // { dg-error "no match" } + (... < xs); // { dg-error "no match" } + (xs > ...); // { dg-error "no match" } + (... > xs); // { dg-error "no match" } + (xs <= ...); // { dg-error "no match" } + (... <= xs); // { dg-error "no match" } + (xs >= ...); // { dg-error "no match" } + (... >= xs); // { dg-error "no match" } + + (xs += ...); // { dg-error "no match" } + (... += xs); // { dg-error "no match" } + (xs -= ...); // { dg-error "no match" } + (... -= xs); // { dg-error "no match" } + (xs *= ...); // { dg-error "no match" } + (... *= xs); // { dg-error "no match" } + (xs /= ...); // { dg-error "no match" } + (... /= xs); // { dg-error "no match" } + (xs %= ...); // { dg-error "no match" } + (... %= xs); // { dg-error "no match" } + (xs |= ...); // { dg-error "no match" } + (... |= xs); // { dg-error "no match" } + (xs ^= ...); // { dg-error "no match" } + (... ^= xs); // { dg-error "no match" } + (xs <<= ...); // { dg-error "no match" } + (... <<= xs); // { dg-error "no match" } + (xs >>= ...); // { dg-error "no match" } + (... >>= xs); // { dg-error "no match" } + }; +} + +namespace N { struct A { }; } + +#include "operator-3-ops.h" + +int main() { + f()(N::A(), N::A()); +} diff --git a/gcc/testsuite/g++.dg/lookup/operator-5.C b/gcc/testsuite/g++.dg/lookup/operator-5.C new file mode 100644 index 0000000..2bbb2c4 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-5.C @@ -0,0 +1,74 @@ +// PR c++/51577 +// { dg-do compile { target c++17 } } +// Like operator-4.C but for binary fold expressions. + +namespace N { struct A { }; } + +template <class... Ts> void f (Ts... xs) { + (xs->*...->*N::A{}); // { dg-error "no match" } + (N::A{}->*...->*xs); // { dg-error "no match" } + (xs / ... / N::A{}); // { dg-error "no match" } + (N::A{} / ... / xs); // { dg-error "no match" } + (xs * ... * N::A{}); // { dg-error "no match" } + (N::A{} * ... * xs); // { dg-error "no match" } + (xs + ... + N::A{}); // { dg-error "no match" } + (N::A{} + ... + xs); // { dg-error "no match" } + (xs - ... - N::A{}); // { dg-error "no match" } + (N::A{} - ... - xs); // { dg-error "no match" } + (xs % ... % N::A{}); // { dg-error "no match" } + (N::A{} % ... % xs); // { dg-error "no match" } + (xs & ... & N::A{}); // { dg-error "no match" } + (N::A{} & ... & xs); // { dg-error "no match" } + (xs | ... | N::A{}); // { dg-error "no match" } + (N::A{} | ... | xs); // { dg-error "no match" } + (xs ^ ... ^ N::A{}); // { dg-error "no match" } + (N::A{} ^ ... ^ xs); // { dg-error "no match" } + (xs << ... << N::A{}); // { dg-error "no match" } + (N::A{} << ... << xs); // { dg-error "no match" } + (xs >> ... >> N::A{}); // { dg-error "no match" } + (N::A{} >> ... >> xs); // { dg-error "no match" } + (xs && ... && N::A{}); // { dg-error "no match" } + (N::A{} && ... && xs); // { dg-error "no match" } + (xs || ... || N::A{}); // { dg-error "no match" } + (N::A{} || ... || xs); // { dg-error "no match" } + (xs , ... , N::A{}); + (N::A{} , ... , xs); + + (xs == ... == N::A{}); // { dg-error "no match" } + (N::A{} == ... == xs); // { dg-error "no match" } + (xs != ... != N::A{}); // { dg-error "no match" } + (N::A{} != ... != xs); // { dg-error "no match" } + (xs < ... < N::A{}); // { dg-error "no match" } + (N::A{} < ... < xs); // { dg-error "no match" } + (xs > ... > N::A{}); // { dg-error "no match" } + (N::A{} > ... > xs); // { dg-error "no match" } + (xs <= ... <= N::A{}); // { dg-error "no match" } + (N::A{} <= ... <= xs); // { dg-error "no match" } + (xs >= ... >= N::A{}); // { dg-error "no match" } + (N::A{} >= ... >= xs); // { dg-error "no match" } + + (xs += ... += N::A{}); // { dg-error "no match" } + (N::A{} += ... += xs); // { dg-error "no match" } + (xs -= ... -= N::A{}); // { dg-error "no match" } + (N::A{} -= ... -= xs); // { dg-error "no match" } + (xs *= ... *= N::A{}); // { dg-error "no match" } + (N::A{} *= ... *= xs); // { dg-error "no match" } + (xs /= ... /= N::A{}); // { dg-error "no match" } + (N::A{} /= ... /= xs); // { dg-error "no match" } + (xs %= ... %= N::A{}); // { dg-error "no match" } + (N::A{} %= ... %= xs); // { dg-error "no match" } + (xs |= ... |= N::A{}); // { dg-error "no match" } + (N::A{} |= ... |= xs); // { dg-error "no match" } + (xs ^= ... ^= N::A{}); // { dg-error "no match" } + (N::A{} ^= ... ^= xs); // { dg-error "no match" } + (xs <<= ... <<= N::A{}); // { dg-error "no match" } + (N::A{} <<= ... <<= xs); // { dg-error "no match" } + (xs >>= ... >>= N::A{}); // { dg-error "no match" } + (N::A{} >>= ... >>= xs); // { dg-error "no match" } +} + +#include "operator-3-ops.h" + +int main() { + f(N::A()); +} diff --git a/gcc/testsuite/g++.dg/lookup/operator-5a.C b/gcc/testsuite/g++.dg/lookup/operator-5a.C new file mode 100644 index 0000000..6f9ecd6 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-5a.C @@ -0,0 +1,76 @@ +// PR c++/51577 +// { dg-do compile { target c++17 } } +// Like operator-5.C but also containing a partial instantiation step. + +namespace N { struct A { }; } + +template <class...> auto f () { + return [] (auto... xs) { + (xs->*...->*N::A{}); // { dg-error "no match" } + (N::A{}->*...->*xs); // { dg-error "no match" } + (xs / ... / N::A{}); // { dg-error "no match" } + (N::A{} / ... / xs); // { dg-error "no match" } + (xs * ... * N::A{}); // { dg-error "no match" } + (N::A{} * ... * xs); // { dg-error "no match" } + (xs + ... + N::A{}); // { dg-error "no match" } + (N::A{} + ... + xs); // { dg-error "no match" } + (xs - ... - N::A{}); // { dg-error "no match" } + (N::A{} - ... - xs); // { dg-error "no match" } + (xs % ... % N::A{}); // { dg-error "no match" } + (N::A{} % ... % xs); // { dg-error "no match" } + (xs & ... & N::A{}); // { dg-error "no match" } + (N::A{} & ... & xs); // { dg-error "no match" } + (xs | ... | N::A{}); // { dg-error "no match" } + (N::A{} | ... | xs); // { dg-error "no match" } + (xs ^ ... ^ N::A{}); // { dg-error "no match" } + (N::A{} ^ ... ^ xs); // { dg-error "no match" } + (xs << ... << N::A{}); // { dg-error "no match" } + (N::A{} << ... << xs); // { dg-error "no match" } + (xs >> ... >> N::A{}); // { dg-error "no match" } + (N::A{} >> ... >> xs); // { dg-error "no match" } + (xs && ... && N::A{}); // { dg-error "no match" } + (N::A{} && ... && xs); // { dg-error "no match" } + (xs || ... || N::A{}); // { dg-error "no match" } + (N::A{} || ... || xs); // { dg-error "no match" } + (xs , ... , N::A{}); + (N::A{} , ... , xs); + + (xs == ... == N::A{}); // { dg-error "no match" } + (N::A{} == ... == xs); // { dg-error "no match" } + (xs != ... != N::A{}); // { dg-error "no match" } + (N::A{} != ... != xs); // { dg-error "no match" } + (xs < ... < N::A{}); // { dg-error "no match" } + (N::A{} < ... < xs); // { dg-error "no match" } + (xs > ... > N::A{}); // { dg-error "no match" } + (N::A{} > ... > xs); // { dg-error "no match" } + (xs <= ... <= N::A{}); // { dg-error "no match" } + (N::A{} <= ... <= xs); // { dg-error "no match" } + (xs >= ... >= N::A{}); // { dg-error "no match" } + (N::A{} >= ... >= xs); // { dg-error "no match" } + + (xs += ... += N::A{}); // { dg-error "no match" } + (N::A{} += ... += xs); // { dg-error "no match" } + (xs -= ... -= N::A{}); // { dg-error "no match" } + (N::A{} -= ... -= xs); // { dg-error "no match" } + (xs *= ... *= N::A{}); // { dg-error "no match" } + (N::A{} *= ... *= xs); // { dg-error "no match" } + (xs /= ... /= N::A{}); // { dg-error "no match" } + (N::A{} /= ... /= xs); // { dg-error "no match" } + (xs %= ... %= N::A{}); // { dg-error "no match" } + (N::A{} %= ... %= xs); // { dg-error "no match" } + (xs |= ... |= N::A{}); // { dg-error "no match" } + (N::A{} |= ... |= xs); // { dg-error "no match" } + (xs ^= ... ^= N::A{}); // { dg-error "no match" } + (N::A{} ^= ... ^= xs); // { dg-error "no match" } + (xs <<= ... <<= N::A{}); // { dg-error "no match" } + (N::A{} <<= ... <<= xs); // { dg-error "no match" } + (xs >>= ... >>= N::A{}); // { dg-error "no match" } + (N::A{} >>= ... >>= xs); // { dg-error "no match" } + }; +} + +#include "operator-3-ops.h" + +int main() { + f()(N::A()); +} diff --git a/gcc/testsuite/g++.dg/lookup/operator-6.C b/gcc/testsuite/g++.dg/lookup/operator-6.C new file mode 100644 index 0000000..b59c137 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-6.C @@ -0,0 +1,59 @@ +// PR c++/83035 +// { dg-do compile { target c++11 } } +// Like operator-3.C but where the lookup occurs at non-block scope. + +template<class T, class = void> struct S { + static constexpr bool is_primary = true; +}; + +template<class T> struct S<T, decltype(+T())> { }; +template<class T> struct S<T, decltype(-T())> { }; +template<class T> struct S<T, decltype(*T())> { }; +template<class T> struct S<T, decltype(~T())> { }; +template<class T> struct S<T, decltype(&T())> { }; +template<class T> struct S<T, decltype(!T())> { }; +template<class T> struct S<T, decltype(++T())> { }; +template<class T> struct S<T, decltype(--T())> { }; +template<class T> struct S<T, decltype(T()++)> { }; +template<class T> struct S<T, decltype(T()--)> { }; + +template<class T> struct S<T, decltype(T()->*T())> { }; +template<class T> struct S<T, decltype(T() / T())> { }; +template<class T> struct S<T, decltype(T() * T())> { }; +template<class T> struct S<T, decltype(T() + T())> { }; +template<class T> struct S<T, decltype(T() - T())> { }; +template<class T> struct S<T, decltype(T() % T())> { }; +template<class T> struct S<T, decltype(T() & T())> { }; +template<class T> struct S<T, decltype(T() | T())> { }; +template<class T> struct S<T, decltype(T() ^ T())> { }; +template<class T> struct S<T, decltype(T() << T())> { }; +template<class T> struct S<T, decltype(T() >> T())> { }; +template<class T> struct S<T, decltype(T() && T())> { }; +template<class T> struct S<T, decltype(T() || T())> { }; +template<class T> struct S<T, decltype(T(), T())> { }; + +template<class T> struct S<T, decltype(T() == T())> { }; +template<class T> struct S<T, decltype(T() != T())> { }; +template<class T> struct S<T, decltype(T() < T())> { }; +template<class T> struct S<T, decltype(T() > T())> { }; +template<class T> struct S<T, decltype(T() <= T())> { }; +template<class T> struct S<T, decltype(T() >= T())> { }; +#if __cplusplus > 201703L +template<class T> struct S<T, decltype(T() <=> T())> { }; +#endif + +template<class T> struct S<T, decltype(T() += T())> { }; +template<class T> struct S<T, decltype(T() -= T())> { }; +template<class T> struct S<T, decltype(T() *= T())> { }; +template<class T> struct S<T, decltype(T() /= T())> { }; +template<class T> struct S<T, decltype(T() %= T())> { }; +template<class T> struct S<T, decltype(T() |= T())> { }; +template<class T> struct S<T, decltype(T() ^= T())> { }; +template<class T> struct S<T, decltype(T() <<= T())> { }; +template<class T> struct S<T, decltype(T() >>= T())> { }; + +namespace N { struct A { }; } + +#include "operator-3-ops.h" + +static_assert(S<N::A>::is_primary, ""); diff --git a/gcc/testsuite/g++.dg/lookup/operator-7.C b/gcc/testsuite/g++.dg/lookup/operator-7.C new file mode 100644 index 0000000..546fcb0 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-7.C @@ -0,0 +1,27 @@ +// PR c++/100465 + +namespace N +{ + struct string + { + template<typename T> + void operator+=(T); + }; + + struct A { + void operator+=(char); // #1 + + template<typename T> + void f() { + string s; + s += T(); + } + + void g() { + f<char>(); + } + }; +} // namespace N + +template<typename T> +void operator+=(N::string, T); diff --git a/gcc/testsuite/g++.dg/lookup/operator-8.C b/gcc/testsuite/g++.dg/lookup/operator-8.C new file mode 100644 index 0000000..64d8a97 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/operator-8.C @@ -0,0 +1,34 @@ +// Verify phase 1 lookup works properly for rewritten non-dependent conditional +// operator expressions. + +// This test currently fails due to build_min_non_dep_op_overload not knowing +// how to handle rewritten operator expressions; see the FIXME in build_new_op. + +// { dg-do compile { target c++20 } } + +#include <compare> + +struct A { + bool operator==(int); + std::strong_ordering operator<=>(int); +}; + +template<class T> +void f() { + A a; + (void)(a != 0, 0 != a); // { dg-bogus "deleted" "" { xfail *-*-* } } + (void)(a < 0, 0 < a); // { dg-bogus "deleted" "" { xfail *-*-* } } + (void)(a <= 0, 0 <= a); // { dg-bogus "deleted" "" { xfail *-*-* } } + (void)(a > 0, 0 > a); // { dg-bogus "deleted" "" { xfail *-*-* } } + (void)(a >= 0, 0 >= a); // { dg-bogus "deleted" "" { xfail *-*-* } } +} + +// These later-declared namespace-scope overloads shouldn't be considered +// when instantiating f<int>. +bool operator!=(A, int) = delete; +bool operator<(A, int) = delete; +bool operator<=(A, int) = delete; +bool operator>(A, int) = delete; +bool operator>=(A, int) = delete; + +template void f<int>(); diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-tags-9.C b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-9.C new file mode 100644 index 0000000..2712c4d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wmismatched-tags-9.C @@ -0,0 +1,32 @@ +/* PR c++/103703 - ICE with -Wmismatched-tags with friends and templates + { dg-do compile } + { dg-options "-Wall -Wmismatched-tags" } */ + +template <typename T> +struct A +{ + struct B { }; +}; + +template <typename T> +struct C +{ + friend class A<C>::B; // { dg-warning "-Wmismatched-tags" "pr102036" { xfail *-*-* } } +}; + +template struct C<int>; + + +template <typename T> +struct D +{ + friend class A<D>::B; // okay, specialized as class below +}; + +template <> +struct A<long> +{ + class B { }; +}; + +template struct D<long>; diff --git a/gcc/testsuite/g++.target/i386/avx512vl-pr100738-1.C b/gcc/testsuite/g++.target/i386/avx512vl-pr100738-1.C new file mode 100755 index 0000000..ac4d62b --- /dev/null +++ b/gcc/testsuite/g++.target/i386/avx512vl-pr100738-1.C @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast -march=cascadelake" } */ +/* { dg-final {scan-assembler-times "vblendvps\[ \\t\]" 2 } } */ +/* { dg-final {scan-assembler-not "vpcmpeqd\[ \\t\]" } } */ +/* { dg-final {scan-assembler-not "vpxor\[ \\t\]" } } */ +/* { dg-final {scan-assembler-not "vpternlogd\[ \\t\]" } } */ + +#include "pr100738-1.C" diff --git a/gcc/testsuite/g++.target/i386/pr103696.C b/gcc/testsuite/g++.target/i386/pr103696.C new file mode 100644 index 0000000..de7d5c6 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr103696.C @@ -0,0 +1,25 @@ +// PR c++/103696 +// { dg-options "-O2 -std=c++14 -fdump-tree-optimized" } + +int global_var; + +void fn() { +} + +#pragma GCC optimize("finite-math-only") +#pragma GCC target("sse3") + +void fn2() { +} + +void fn3() { +} + +int solve() { + auto nested = []() { + return global_var; + }; + return nested(); +} + +/* { dg-final { scan-tree-dump-not "lambda" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/20021029-1.c b/gcc/testsuite/gcc.dg/20021029-1.c index d13f669..f5ddecb 100644 --- a/gcc/testsuite/gcc.dg/20021029-1.c +++ b/gcc/testsuite/gcc.dg/20021029-1.c @@ -2,6 +2,7 @@ variables into writable sections. */ /* { dg-do compile { target fpic } } */ /* { dg-options "-O2 -fpic" } */ +/* { dg-additional-options "-G0" { target nios2-*-* } } */ /* { dg-final { scan-assembler-not ".data.rel.ro.local" } } */ /* { dg-final { scan-assembler-symbol-section {^_?ar} {^\.(const|rodata)|\[RO\]} } } */ /* { dg-require-effective-target label_values } */ diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48.c b/gcc/testsuite/gcc.dg/Warray-bounds-48.c index 29b2086..775b301 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-48.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-48.c @@ -212,6 +212,7 @@ void test_a0 (struct A0 *p, unsigned n) struct A1 { int32_t n; + __attribute__ ((aligned (4))) int16_t a1[1]; // { dg-message "while referencing 'a1'" } }; diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-alloc-size.c b/gcc/testsuite/gcc.dg/builtin-dynamic-alloc-size.c new file mode 100644 index 0000000..9d0eadd --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-alloc-size.c @@ -0,0 +1,7 @@ +/* { dg-do compile } + { dg-require-effective-target alloca } + { dg-additional-options "-O2 -fdump-tree-optimized" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-alloc-size.c" +/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c new file mode 100644 index 0000000..7cc8b1c --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-1.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target alloca } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-1.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-10.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-10.c new file mode 100644 index 0000000..bc880a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-10.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-early_objsz-details" } */ +// { dg-skip-if "packed attribute missing for drone_source_packet" { "epiphany-*-*" } } + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-10.c" + +/* { dg-final { scan-tree-dump "maximum object size 21" "early_objsz" } } */ +/* { dg-final { scan-tree-dump "maximum subobject size 16" "early_objsz" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-11.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-11.c new file mode 100644 index 0000000..65dcec9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-11.c @@ -0,0 +1,7 @@ +/* PR48985 */ +/* { dg-do run } */ +/* { dg-options "-std=gnu89" } */ +/* { dg-skip-if "packed attribute missing for struct s" { "epiphany-*-*" } } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-11.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-12.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-12.c new file mode 100644 index 0000000..f0ce050 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-12.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-12.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-13.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-13.c new file mode 100644 index 0000000..555e235 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-13.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-13.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-14.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-14.c new file mode 100644 index 0000000..2620720 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-14.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-14.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-15.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-15.c new file mode 100644 index 0000000..cd8a941 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-15.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-15.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-16.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-16.c new file mode 100644 index 0000000..cc77508 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-16.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O0" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +char ax2[]; /* { dg-warning "assumed to have one element" } */ +#include "builtin-object-size-16.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-17.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-17.c new file mode 100644 index 0000000..f5c57a8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-17.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -fdump-tree-ssa" } */ + +char ax2[]; /* { dg-warning "assumed to have one element" } */ +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-17.c" +/* { dg-final { scan-tree-dump-not "failure_on_line" "ssa" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-18.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-18.c new file mode 100644 index 0000000..70c1ebc --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-18.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* __stpncpy_chk could return buf up to buf + 64, so + the minimum object size might be far smaller than 64. */ +/* { dg-final { scan-tree-dump-not "return 64;" "optimized" } } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-18.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-19.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-19.c new file mode 100644 index 0000000..44141a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-19.c @@ -0,0 +1,104 @@ +/* PR tree-optimization/88372 - alloc_size attribute is ignored + on function pointers { dg-do compile } + { dg-options "-O2 -fdump-tree-optimized" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-18.c" + +typedef __SIZE_TYPE__ size_t; + +#define ATTR(...) __attribute__ ((__VA_ARGS__)) +#define CONCAT(x, y) x ## y +#define CAT(x, y) CONCAT (x, y) +#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__) + +#define FAIL(name) do { \ + extern void FAILNAME (name) (void); \ + FAILNAME (name)(); \ + } while (0) + +/* Macro to emit a call to function named + call_in_true_branch_not_eliminated_on_line_NNN() + for each call that's expected to be eliminated. The dg-final + scan-tree-dump-time directive at the bottom of the test verifies + that no such call appears in output. */ +#define ELIM(expr) \ + if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0 + +void sink (void*); + +#define T(alloc, n) do { \ + void *p = alloc; \ + sink (p); \ + ELIM (n == __builtin_object_size (p, 0)); \ + ELIM (n == __builtin_object_size (p, 1)); \ + ELIM (n == __builtin_object_size (p, 2)); \ + ELIM (n == __builtin_object_size (p, 3)); \ + } while (0) + + +ATTR (alloc_size (1)) void* (*alloc_1_x)(size_t, size_t); +ATTR (alloc_size (2)) void* (*alloc_x_2)(size_t, size_t); + +/* Verify that things work when attribute alloc_size is applied + to a typedef that is then used to declared a pointer. */ +typedef ATTR (alloc_size (1, 2)) void* (alloc_1_2_t)(size_t, size_t); + +void test_alloc_ptr (alloc_1_2_t *alloc_1_2) +{ + T (alloc_1_x (0, 0), 0); + T (alloc_1_x (1, 0), 1); + T (alloc_1_x (3, 0), 3); + T (alloc_1_x (9, 5), 9); + + T (alloc_x_2 (0, 0), 0); + T (alloc_x_2 (1, 0), 0); + T (alloc_x_2 (0, 1), 1); + T (alloc_x_2 (9, 5), 5); + + T (alloc_1_2 (0, 0), 0); + T (alloc_1_2 (1, 0), 0); + T (alloc_1_2 (0, 1), 0); + T (alloc_1_2 (9, 5), 45); +} + +/* Verify that object size is detected even in indirect calls via + function pointers to built-in allocation functions, even without + explicit use of attribute alloc_size on the pointers. */ + +typedef void *(allocfn_1) (size_t); +typedef void *(allocfn_1_2) (size_t, size_t); + +static inline void * +call_alloc (allocfn_1 *fn1, allocfn_1_2 *fn2, size_t n1, size_t n2) +{ + return fn1 ? fn1 (n1) : fn2 (n1, n2); +} + +static inline void * +call_malloc (size_t n) +{ + return call_alloc (__builtin_malloc, 0, n, 0); +} + +static inline void * +call_calloc (size_t n1, size_t n2) +{ + return call_alloc (0, __builtin_calloc, n1, n2); +} + +void test_builtin_ptr (void) +{ + T (call_malloc (0), 0); + T (call_malloc (1), 1); + T (call_malloc (9), 9); + + T (call_calloc (0, 0), 0); + T (call_calloc (0, 1), 0); + T (call_calloc (1, 0), 0); + T (call_calloc (1, 1), 1); + T (call_calloc (1, 3), 3); + T (call_calloc (2, 3), 6); +} + +/* { dg-final { scan-tree-dump-not "not_eliminated" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c new file mode 100644 index 0000000..267dbf4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-2.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target alloca } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-2.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c new file mode 100644 index 0000000..fb9dc56 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-3.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target alloca } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-3.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c new file mode 100644 index 0000000..870548b --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-4.c @@ -0,0 +1,6 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target alloca } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-4.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-5.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-5.c new file mode 100644 index 0000000..698b03c --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-5.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target i?86-*-linux* i?86-*-gnu* x86_64-*-linux* } } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-5.c" + +/* { dg-final { scan-assembler-not "abort" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-6.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-6.c new file mode 100644 index 0000000..6a275ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-6.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-6.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-7.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-7.c new file mode 100644 index 0000000..e2a6599 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-7.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-7.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-8.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-8.c new file mode 100644 index 0000000..e7af383 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-8.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-8.c" diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-9.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-9.c new file mode 100644 index 0000000..19021bc --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-9.c @@ -0,0 +1,5 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#define __builtin_object_size __builtin_dynamic_object_size +#include "builtin-object-size-9.c" diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-1.c b/gcc/testsuite/gcc.dg/builtin-object-size-1.c index 8cdae49..0154f4e 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-1.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-1.c @@ -424,6 +424,35 @@ test8 (void) abort (); } +void +__attribute__ ((noinline)) +test9 (unsigned cond) +{ + char *buf2 = malloc (10); + char *p; + + if (cond) + p = &buf2[8]; + else + p = &buf2[4]; + + if (__builtin_object_size (&p[-4], 0) != 10) + abort (); + + for (unsigned i = cond; i > 0; i--) + p--; + + if (__builtin_object_size (p, 0) != 10) + abort (); + + p = &y.c[8]; + for (unsigned i = cond; i > 0; i--) + p--; + + if (__builtin_object_size (p, 0) != sizeof (y)) + abort (); +} + int main (void) { @@ -437,5 +466,6 @@ main (void) test6 (4); test7 (); test8 (); + test9 (1); exit (0); } diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-16.c b/gcc/testsuite/gcc.dg/builtin-object-size-16.c index 4822939..f26d5d9 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-16.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-16.c @@ -54,7 +54,9 @@ static int nfails; typedef __SIZE_TYPE__ size_t; extern char ax[]; +#ifndef __builtin_object_size char ax2[]; /* { dg-warning "assumed to have one element" } */ +#endif extern char a0[0]; static char a1[1]; diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-17.c b/gcc/testsuite/gcc.dg/builtin-object-size-17.c index 0497bbf..28f8414 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-17.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-17.c @@ -49,7 +49,9 @@ typedef __SIZE_TYPE__ size_t; extern char ax[]; +#ifndef __builtin_object_size char ax2[]; /* { dg-warning "assumed to have one element" } */ +#endif extern char a0[0]; static char a1[1]; diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-2.c index ad2dd29..5cf2929 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-2.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-2.c @@ -382,6 +382,35 @@ test7 (void) abort (); } +void +__attribute__ ((noinline)) +test8 (unsigned cond) +{ + char *buf2 = malloc (10); + char *p; + + if (cond) + p = &buf2[8]; + else + p = &buf2[4]; + + if (__builtin_object_size (&p[-4], 1) != 10) + abort (); + + for (unsigned i = cond; i > 0; i--) + p--; + + if (__builtin_object_size (p, 1) != 10) + abort (); + + p = &y.c[8]; + for (unsigned i = cond; i > 0; i--) + p--; + + if (__builtin_object_size (p, 1) != sizeof (y.c)) + abort (); +} + int main (void) { @@ -394,5 +423,6 @@ main (void) test5 (4); test6 (); test7 (); + test8 (1); exit (0); } diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-3.c b/gcc/testsuite/gcc.dg/builtin-object-size-3.c index d5ca504..3a692c4 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-3.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-3.c @@ -430,6 +430,36 @@ test8 (void) abort (); } +void +__attribute__ ((noinline)) +test9 (unsigned cond) +{ + char *buf2 = malloc (10); + char *p; + + if (cond) + p = &buf2[8]; + else + p = &buf2[4]; + + if (__builtin_object_size (&p[-4], 2) != 6) + abort (); + + for (unsigned i = cond; i > 0; i--) + p--; + + if (__builtin_object_size (p, 2) != 2) + abort (); + + p = &y.c[8]; + for (unsigned i = cond; i > 0; i--) + p--; + + if (__builtin_object_size (p, 2) + != sizeof (y) - __builtin_offsetof (struct A, c) - 8) + abort (); +} + int main (void) { @@ -443,5 +473,6 @@ main (void) test6 (4); test7 (); test8 (); + test9 (1); exit (0); } diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-4.c index 9f159e3..8738162 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c @@ -395,6 +395,35 @@ test7 (void) abort (); } +void +__attribute__ ((noinline)) +test8 (unsigned cond) +{ + char *buf2 = malloc (10); + char *p; + + if (cond) + p = &buf2[8]; + else + p = &buf2[4]; + + if (__builtin_object_size (&p[-4], 3) != 6) + abort (); + + for (unsigned i = cond; i > 0; i--) + p--; + + if (__builtin_object_size (p, 3) != 2) + abort (); + + p = &y.c[8]; + for (unsigned i = cond; i > 0; i--) + p--; + + if (__builtin_object_size (p, 3) != sizeof (y.c) - 8) + abort (); +} + int main (void) { @@ -407,5 +436,6 @@ main (void) test5 (4); test6 (); test7 (); + test8 (1); exit (0); } diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-5.c b/gcc/testsuite/gcc.dg/builtin-object-size-5.c index 7c274cd..8e63d9c 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-5.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-5.c @@ -53,4 +53,29 @@ test4 (size_t x) abort (); } +void +test5 (void) +{ + char *p = &buf[0x90000004]; + if (__builtin_object_size (p + 2, 0) != 0) + abort (); +} + +void +test6 (void) +{ + char *p = &buf[-4]; + if (__builtin_object_size (p + 2, 0) != 0) + abort (); +} + +void +test7 (void) +{ + char *buf2 = __builtin_malloc (8); + char *p = &buf2[0x90000004]; + if (__builtin_object_size (p + 2, 0) != 0) + abort (); +} + /* { dg-final { scan-assembler-not "abort" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr103741.c b/gcc/testsuite/gcc.target/aarch64/pr103741.c new file mode 100644 index 0000000..ef3ae66 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr103741.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=armv8-a+sve -O1" } */ + +long int m, n; + +int +qux (int z) +{ + return 4 >> z ? z : 0; +} + +int +bar (long int y) +{ + return y ? 3 : 2; +} + +__attribute__ ((simd)) int +foo (int x) +{ + long int a = x & m; + int b = bar (x) / n; + + return qux (b) == a; +} + diff --git a/gcc/testsuite/gcc.target/i386/pr102812.c b/gcc/testsuite/gcc.target/i386/pr102812.c index bad4fa9..51c89a6 100644 --- a/gcc/testsuite/gcc.target/i386/pr102812.c +++ b/gcc/testsuite/gcc.target/i386/pr102812.c @@ -2,7 +2,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -msse4 -mno-avx" } */ /* { dg-final { scan-assembler-not "vmovdqa64\t" } } */ -/* { dg-final { scan-assembler "movdqa\t" } } */ typedef _Float16 v8hf __attribute__((__vector_size__ (16))); diff --git a/gcc/testsuite/gfortran.dg/date_and_time_1.f90 b/gcc/testsuite/gfortran.dg/date_and_time_1.f90 new file mode 100644 index 0000000..9424e50 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/date_and_time_1.f90 @@ -0,0 +1,35 @@ +! PR libfortran/98507 +! { dg-do run } + +program demo_time_and_date + implicit none + character(8) :: date + character(10) :: time + character(5) :: zone + integer :: val(8) + integer :: h, m + + call date_and_time(values=val) + + if (val(1) < 2000 .or. val(1) > 2100) stop 1 + if (val(2) < 1 .or. val(2) > 12) stop 2 + if (val(3) < 1 .or. val(3) > 31) stop 3 + + ! Maximum offset is 14 hours (UTC+14) + if (val(4) < -14*60 .or. val(4) > 14*60) stop 4 + + if (val(5) < 0 .or. val(5) > 23) stop 5 + if (val(6) < 0 .or. val(6) > 59) stop 6 + if (val(7) < 0 .or. val(7) > 60) stop 7 + if (val(8) < 0 .or. val(8) > 999) stop 8 + + call date_and_time(zone=zone) + if (len(zone) /= 0) then + ! If ZONE is present, it should present the same information as + ! given in VALUES(4) + if (len(zone) /= 5) stop 9 + read(zone(1:3),*) h + read(zone(4:5),*) m + if (val(4) /= 60*h+m) stop 10 + endif +end diff --git a/gcc/testsuite/gfortran.dg/iostat_5.f90 b/gcc/testsuite/gfortran.dg/iostat_5.f90 new file mode 100644 index 0000000..1e72dfd --- /dev/null +++ b/gcc/testsuite/gfortran.dg/iostat_5.f90 @@ -0,0 +1,16 @@ +! PR libfortran/101255 +! { dg-do run } + +program test + use ISO_FORTRAN_ENV, only: IOSTAT_EOR, IOSTAT_END + implicit none + character(len=50) :: err + integer :: i + + err = "" + flush(99, iostat=i, iomsg=err) + + if (err == "") stop 1 + if (i >= 0) stop 2 + if (i == IOSTAT_EOR .or. i == IOSTAT_END) stop 3 +end diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index b4881ef..71f6b74 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfg.h" #include "stringpool.h" #include "attribs.h" +#include "builtins.h" struct object_size_info { @@ -45,22 +46,22 @@ struct object_size_info unsigned int *stack, *tos; }; -enum +struct GTY(()) object_size { - OST_SUBOBJECT = 1, - OST_MINIMUM = 2, - OST_END = 4, + /* Estimate of bytes till the end of the object. */ + tree size; + /* Estimate of the size of the whole object. */ + tree wholesize; }; static tree compute_object_offset (const_tree, const_tree); static bool addr_object_size (struct object_size_info *, - const_tree, int, unsigned HOST_WIDE_INT *); -static unsigned HOST_WIDE_INT alloc_object_size (const gcall *, int); + const_tree, int, tree *, tree *t = NULL); +static tree alloc_object_size (const gcall *, int); static tree pass_through_call (const gcall *); static void collect_object_sizes_for (struct object_size_info *, tree); static void expr_object_size (struct object_size_info *, tree, tree); -static bool merge_object_sizes (struct object_size_info *, tree, tree, - unsigned HOST_WIDE_INT); +static bool merge_object_sizes (struct object_size_info *, tree, tree); static bool plus_stmt_object_size (struct object_size_info *, tree, gimple *); static bool cond_expr_object_size (struct object_size_info *, tree, gimple *); static void init_offset_limit (void); @@ -68,13 +69,13 @@ static void check_for_plus_in_loops (struct object_size_info *, tree); static void check_for_plus_in_loops_1 (struct object_size_info *, tree, unsigned int); -/* object_sizes[0] is upper bound for number of bytes till the end of - the object. - object_sizes[1] is upper bound for number of bytes till the end of - the subobject (innermost array or field with address taken). - object_sizes[2] is lower bound for number of bytes till the end of - the object and object_sizes[3] lower bound for subobject. */ -static vec<unsigned HOST_WIDE_INT> object_sizes[OST_END]; +/* object_sizes[0] is upper bound for the object size and number of bytes till + the end of the object. + object_sizes[1] is upper bound for the object size and number of bytes till + the end of the subobject (innermost array or field with address taken). + object_sizes[2] is lower bound for the object size and number of bytes till + the end of the object and object_sizes[3] lower bound for subobject. */ +static vec<object_size> object_sizes[OST_END]; /* Bitmaps what object sizes have been computed already. */ static bitmap computed[OST_END]; @@ -82,10 +83,46 @@ static bitmap computed[OST_END]; /* Maximum value of offset we consider to be addition. */ static unsigned HOST_WIDE_INT offset_limit; +/* Initial value of object sizes; zero for maximum and SIZE_MAX for minimum + object size. */ + +static inline unsigned HOST_WIDE_INT +initval (int object_size_type) +{ + return (object_size_type & OST_MINIMUM) ? HOST_WIDE_INT_M1U : 0; +} + +/* Unknown object size value; it's the opposite of initval. */ + static inline unsigned HOST_WIDE_INT unknown (int object_size_type) { - return ((unsigned HOST_WIDE_INT) -((object_size_type >> 1) ^ 1)); + return ~initval (object_size_type); +} + +/* Return true if VAL is represents an unknown size for OBJECT_SIZE_TYPE. */ + +static inline bool +size_unknown_p (tree val, int object_size_type) +{ + return (tree_fits_uhwi_p (val) + && tree_to_uhwi (val) == unknown (object_size_type)); +} + +/* Return a tree with initial value for OBJECT_SIZE_TYPE. */ + +static inline tree +size_initval (int object_size_type) +{ + return size_int (initval (object_size_type)); +} + +/* Return a tree with unknown value for OBJECT_SIZE_TYPE. */ + +static inline tree +size_unknown (int object_size_type) +{ + return size_int (unknown (object_size_type)); } /* Grow object_sizes[OBJECT_SIZE_TYPE] to num_ssa_names. */ @@ -110,47 +147,57 @@ object_sizes_release (int object_size_type) static inline bool object_sizes_unknown_p (int object_size_type, unsigned varno) { - return (object_sizes[object_size_type][varno] - == unknown (object_size_type)); + return size_unknown_p (object_sizes[object_size_type][varno].size, + object_size_type); } -/* Return size for VARNO corresponding to OSI. */ +/* Return size for VARNO corresponding to OSI. If WHOLE is true, return the + whole object size. */ -static inline unsigned HOST_WIDE_INT -object_sizes_get (struct object_size_info *osi, unsigned varno) +static inline tree +object_sizes_get (struct object_size_info *osi, unsigned varno, + bool whole = false) { - return object_sizes[osi->object_size_type][varno]; + if (whole) + return object_sizes[osi->object_size_type][varno].wholesize; + else + return object_sizes[osi->object_size_type][varno].size; } /* Set size for VARNO corresponding to OSI to VAL. */ -static inline bool -object_sizes_set_force (struct object_size_info *osi, unsigned varno, - unsigned HOST_WIDE_INT val) +static inline void +object_sizes_initialize (struct object_size_info *osi, unsigned varno, + tree val, tree wholeval) { - object_sizes[osi->object_size_type][varno] = val; - return true; + int object_size_type = osi->object_size_type; + + object_sizes[object_size_type][varno].size = val; + object_sizes[object_size_type][varno].wholesize = wholeval; } /* Set size for VARNO corresponding to OSI to VAL if it is the new minimum or maximum. */ static inline bool -object_sizes_set (struct object_size_info *osi, unsigned varno, - unsigned HOST_WIDE_INT val) +object_sizes_set (struct object_size_info *osi, unsigned varno, tree val, + tree wholeval) { int object_size_type = osi->object_size_type; - if ((object_size_type & OST_MINIMUM) == 0) - { - if (object_sizes[object_size_type][varno] < val) - return object_sizes_set_force (osi, varno, val); - } - else - { - if (object_sizes[object_size_type][varno] > val) - return object_sizes_set_force (osi, varno, val); - } - return false; + object_size osize = object_sizes[object_size_type][varno]; + + tree oldval = osize.size; + tree old_wholeval = osize.wholesize; + + enum tree_code code = object_size_type & OST_MINIMUM ? MIN_EXPR : MAX_EXPR; + + val = size_binop (code, val, oldval); + wholeval = size_binop (code, wholeval, old_wholeval); + + object_sizes[object_size_type][varno].size = val; + object_sizes[object_size_type][varno].wholesize = wholeval; + return (tree_int_cst_compare (oldval, val) != 0 + || tree_int_cst_compare (old_wholeval, wholeval) != 0); } /* Initialize OFFSET_LIMIT variable. */ @@ -164,6 +211,48 @@ init_offset_limit (void) offset_limit /= 2; } +/* Bytes at end of the object with SZ from offset OFFSET. If WHOLESIZE is not + NULL_TREE, use it to get the net offset of the pointer, which should always + be positive and hence, be within OFFSET_LIMIT for valid offsets. */ + +static tree +size_for_offset (tree sz, tree offset, tree wholesize = NULL_TREE) +{ + gcc_checking_assert (TREE_CODE (offset) == INTEGER_CST); + gcc_checking_assert (TREE_CODE (sz) == INTEGER_CST); + gcc_checking_assert (types_compatible_p (TREE_TYPE (sz), sizetype)); + + /* For negative offsets, if we have a distinct WHOLESIZE, use it to get a net + offset from the whole object. */ + if (wholesize && tree_int_cst_compare (sz, wholesize)) + { + gcc_checking_assert (TREE_CODE (wholesize) == INTEGER_CST); + gcc_checking_assert (types_compatible_p (TREE_TYPE (wholesize), + sizetype)); + + /* Restructure SZ - OFFSET as + WHOLESIZE - (WHOLESIZE + OFFSET - SZ) so that the offset part, i.e. + WHOLESIZE + OFFSET - SZ is only allowed to be positive. */ + tree tmp = size_binop (MAX_EXPR, wholesize, sz); + offset = fold_build2 (PLUS_EXPR, sizetype, tmp, offset); + offset = fold_build2 (MINUS_EXPR, sizetype, offset, sz); + sz = tmp; + } + + /* Safe to convert now, since a valid net offset should be non-negative. */ + if (!types_compatible_p (TREE_TYPE (offset), sizetype)) + fold_convert (sizetype, offset); + + if (integer_zerop (offset)) + return sz; + + /* Negative or too large offset even after adjustment, cannot be within + bounds of an object. */ + if (compare_tree_int (offset, offset_limit) > 0) + return size_zero_node; + + return size_binop (MINUS_EXPR, size_binop (MAX_EXPR, sz, offset), offset); +} /* Compute offset of EXPR within VAR. Return error_mark_node if unknown. */ @@ -274,19 +363,22 @@ decl_init_size (tree decl, bool min) /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR. OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. - If unknown, return unknown (object_size_type). */ + If unknown, return size_unknown (object_size_type). */ static bool addr_object_size (struct object_size_info *osi, const_tree ptr, - int object_size_type, unsigned HOST_WIDE_INT *psize) + int object_size_type, tree *psize, tree *pwholesize) { - tree pt_var, pt_var_size = NULL_TREE, var_size, bytes; + tree pt_var, pt_var_size = NULL_TREE, pt_var_wholesize = NULL_TREE; + tree var_size, bytes, wholebytes; gcc_assert (TREE_CODE (ptr) == ADDR_EXPR); /* Set to unknown and overwrite just before returning if the size could be determined. */ - *psize = unknown (object_size_type); + *psize = size_unknown (object_size_type); + if (pwholesize) + *pwholesize = size_unknown (object_size_type); pt_var = TREE_OPERAND (ptr, 0); while (handled_component_p (pt_var)) @@ -297,13 +389,14 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, if (TREE_CODE (pt_var) == MEM_REF) { - unsigned HOST_WIDE_INT sz; + tree sz, wholesize; if (!osi || (object_size_type & OST_SUBOBJECT) != 0 || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME) { compute_builtin_object_size (TREE_OPERAND (pt_var, 0), object_size_type & ~OST_SUBOBJECT, &sz); + wholesize = sz; } else { @@ -312,46 +405,47 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, collect_object_sizes_for (osi, var); if (bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (var))) - sz = object_sizes_get (osi, SSA_NAME_VERSION (var)); + { + sz = object_sizes_get (osi, SSA_NAME_VERSION (var)); + wholesize = object_sizes_get (osi, SSA_NAME_VERSION (var), true); + } else - sz = unknown (object_size_type); + sz = wholesize = size_unknown (object_size_type); } - if (sz != unknown (object_size_type)) + if (!size_unknown_p (sz, object_size_type)) { - offset_int mem_offset; - if (mem_ref_offset (pt_var).is_constant (&mem_offset)) - { - offset_int dsz = wi::sub (sz, mem_offset); - if (wi::neg_p (dsz)) - sz = 0; - else if (wi::fits_uhwi_p (dsz)) - sz = dsz.to_uhwi (); - else - sz = unknown (object_size_type); - } + tree offset = TREE_OPERAND (pt_var, 1); + if (TREE_CODE (offset) != INTEGER_CST + || TREE_CODE (sz) != INTEGER_CST) + sz = wholesize = size_unknown (object_size_type); else - sz = unknown (object_size_type); + sz = size_for_offset (sz, offset, wholesize); } - if (sz != unknown (object_size_type) && sz < offset_limit) - pt_var_size = size_int (sz); + if (!size_unknown_p (sz, object_size_type) + && TREE_CODE (sz) == INTEGER_CST + && compare_tree_int (sz, offset_limit) < 0) + { + pt_var_size = sz; + pt_var_wholesize = wholesize; + } } else if (DECL_P (pt_var)) { - pt_var_size = decl_init_size (pt_var, object_size_type & OST_MINIMUM); + pt_var_size = pt_var_wholesize + = decl_init_size (pt_var, object_size_type & OST_MINIMUM); if (!pt_var_size) return false; } else if (TREE_CODE (pt_var) == STRING_CST) - pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var)); + pt_var_size = pt_var_wholesize = TYPE_SIZE_UNIT (TREE_TYPE (pt_var)); else return false; if (pt_var_size) { /* Validate the size determined above. */ - if (!tree_fits_uhwi_p (pt_var_size) - || tree_to_uhwi (pt_var_size) >= offset_limit) + if (compare_tree_int (pt_var_size, offset_limit) >= 0) return false; } @@ -496,28 +590,35 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, bytes = size_binop (MIN_EXPR, bytes, bytes2); } } + + wholebytes + = object_size_type & OST_SUBOBJECT ? var_size : pt_var_wholesize; } else if (!pt_var_size) return false; else - bytes = pt_var_size; - - if (tree_fits_uhwi_p (bytes)) { - *psize = tree_to_uhwi (bytes); - return true; + bytes = pt_var_size; + wholebytes = pt_var_wholesize; } - return false; + if (TREE_CODE (bytes) != INTEGER_CST + || TREE_CODE (wholebytes) != INTEGER_CST) + return false; + + *psize = bytes; + if (pwholesize) + *pwholesize = wholebytes; + return true; } /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL. Handles calls to functions declared with attribute alloc_size. OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. - If unknown, return unknown (object_size_type). */ + If unknown, return size_unknown (object_size_type). */ -static unsigned HOST_WIDE_INT +static tree alloc_object_size (const gcall *call, int object_size_type) { gcc_assert (is_gimple_call (call)); @@ -529,7 +630,7 @@ alloc_object_size (const gcall *call, int object_size_type) calltype = gimple_call_fntype (call); if (!calltype) - return unknown (object_size_type); + return size_unknown (object_size_type); /* Set to positions of alloc_size arguments. */ int arg1 = -1, arg2 = -1; @@ -549,7 +650,7 @@ alloc_object_size (const gcall *call, int object_size_type) || (arg2 >= 0 && (arg2 >= (int)gimple_call_num_args (call) || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST))) - return unknown (object_size_type); + return size_unknown (object_size_type); tree bytes = NULL_TREE; if (arg2 >= 0) @@ -559,10 +660,7 @@ alloc_object_size (const gcall *call, int object_size_type) else if (arg1 >= 0) bytes = fold_convert (sizetype, gimple_call_arg (call, arg1)); - if (bytes && tree_fits_uhwi_p (bytes)) - return tree_to_uhwi (bytes); - - return unknown (object_size_type); + return bytes; } @@ -598,13 +696,13 @@ pass_through_call (const gcall *call) bool compute_builtin_object_size (tree ptr, int object_size_type, - unsigned HOST_WIDE_INT *psize) + tree *psize) { gcc_assert (object_size_type >= 0 && object_size_type < OST_END); /* Set to unknown and overwrite just before returning if the size could be determined. */ - *psize = unknown (object_size_type); + *psize = size_unknown (object_size_type); if (! offset_limit) init_offset_limit (); @@ -638,8 +736,7 @@ compute_builtin_object_size (tree ptr, int object_size_type, psize)) { /* Return zero when the offset is out of bounds. */ - unsigned HOST_WIDE_INT off = tree_to_shwi (offset); - *psize = off < *psize ? *psize - off : 0; + *psize = size_for_offset (*psize, offset); return true; } } @@ -657,8 +754,9 @@ compute_builtin_object_size (tree ptr, int object_size_type, object_sizes_grow (object_size_type); if (dump_file) { - fprintf (dump_file, "Computing %s %sobject size for ", + fprintf (dump_file, "Computing %s %s%sobject size for ", (object_size_type & OST_MINIMUM) ? "minimum" : "maximum", + (object_size_type & OST_DYNAMIC) ? "dynamic " : "", (object_size_type & OST_SUBOBJECT) ? "sub" : ""); print_generic_expr (dump_file, ptr, dump_flags); fprintf (dump_file, ":\n"); @@ -747,12 +845,14 @@ compute_builtin_object_size (tree ptr, int object_size_type, print_generic_expr (dump_file, ssa_name (i), dump_flags); fprintf (dump_file, - ": %s %sobject size " - HOST_WIDE_INT_PRINT_UNSIGNED "\n", + ": %s %s%sobject size ", ((object_size_type & OST_MINIMUM) ? "minimum" : "maximum"), - (object_size_type & OST_SUBOBJECT) ? "sub" : "", - object_sizes_get (&osi, i)); + (object_size_type & OST_DYNAMIC) ? "dynamic " : "", + (object_size_type & OST_SUBOBJECT) ? "sub" : ""); + print_generic_expr (dump_file, object_sizes_get (&osi, i), + dump_flags); + fprintf (dump_file, "\n"); } } @@ -761,7 +861,7 @@ compute_builtin_object_size (tree ptr, int object_size_type, } *psize = object_sizes_get (&osi, SSA_NAME_VERSION (ptr)); - return *psize != unknown (object_size_type); + return !size_unknown_p (*psize, object_size_type); } /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */ @@ -771,7 +871,7 @@ expr_object_size (struct object_size_info *osi, tree ptr, tree value) { int object_size_type = osi->object_size_type; unsigned int varno = SSA_NAME_VERSION (ptr); - unsigned HOST_WIDE_INT bytes; + tree bytes, wholesize; gcc_assert (!object_sizes_unknown_p (object_size_type, varno)); gcc_assert (osi->pass == 0); @@ -784,11 +884,11 @@ expr_object_size (struct object_size_info *osi, tree ptr, tree value) || !POINTER_TYPE_P (TREE_TYPE (value))); if (TREE_CODE (value) == ADDR_EXPR) - addr_object_size (osi, value, object_size_type, &bytes); + addr_object_size (osi, value, object_size_type, &bytes, &wholesize); else - bytes = unknown (object_size_type); + bytes = wholesize = size_unknown (object_size_type); - object_sizes_set (osi, varno, bytes); + object_sizes_set (osi, varno, bytes, wholesize); } @@ -799,16 +899,14 @@ call_object_size (struct object_size_info *osi, tree ptr, gcall *call) { int object_size_type = osi->object_size_type; unsigned int varno = SSA_NAME_VERSION (ptr); - unsigned HOST_WIDE_INT bytes; gcc_assert (is_gimple_call (call)); gcc_assert (!object_sizes_unknown_p (object_size_type, varno)); gcc_assert (osi->pass == 0); + tree bytes = alloc_object_size (call, object_size_type); - bytes = alloc_object_size (call, object_size_type); - - object_sizes_set (osi, varno, bytes); + object_sizes_set (osi, varno, bytes, bytes); } @@ -822,8 +920,9 @@ unknown_object_size (struct object_size_info *osi, tree ptr) gcc_checking_assert (!object_sizes_unknown_p (object_size_type, varno)); gcc_checking_assert (osi->pass == 0); + tree bytes = size_unknown (object_size_type); - object_sizes_set (osi, varno, unknown (object_size_type)); + object_sizes_set (osi, varno, bytes, bytes); } @@ -831,30 +930,22 @@ unknown_object_size (struct object_size_info *osi, tree ptr) the object size might need reexamination later. */ static bool -merge_object_sizes (struct object_size_info *osi, tree dest, tree orig, - unsigned HOST_WIDE_INT offset) +merge_object_sizes (struct object_size_info *osi, tree dest, tree orig) { int object_size_type = osi->object_size_type; unsigned int varno = SSA_NAME_VERSION (dest); - unsigned HOST_WIDE_INT orig_bytes; + tree orig_bytes, wholesize; if (object_sizes_unknown_p (object_size_type, varno)) return false; - if (offset >= offset_limit) - { - object_sizes_set (osi, varno, unknown (object_size_type)); - return false; - } if (osi->pass == 0) collect_object_sizes_for (osi, orig); orig_bytes = object_sizes_get (osi, SSA_NAME_VERSION (orig)); - if (orig_bytes != unknown (object_size_type)) - orig_bytes = (offset > orig_bytes) - ? HOST_WIDE_INT_0U : orig_bytes - offset; + wholesize = object_sizes_get (osi, SSA_NAME_VERSION (orig), true); - if (object_sizes_set (osi, varno, orig_bytes)) + if (object_sizes_set (osi, varno, orig_bytes, wholesize)) osi->changed = true; return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig)); @@ -870,8 +961,9 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) { int object_size_type = osi->object_size_type; unsigned int varno = SSA_NAME_VERSION (var); - unsigned HOST_WIDE_INT bytes; + tree bytes, wholesize; tree op0, op1; + bool reexamine = false; if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) { @@ -896,31 +988,38 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) && (TREE_CODE (op0) == SSA_NAME || TREE_CODE (op0) == ADDR_EXPR)) { - if (! tree_fits_uhwi_p (op1)) - bytes = unknown (object_size_type); - else if (TREE_CODE (op0) == SSA_NAME) - return merge_object_sizes (osi, var, op0, tree_to_uhwi (op1)); + if (TREE_CODE (op0) == SSA_NAME) + { + if (osi->pass == 0) + collect_object_sizes_for (osi, op0); + + bytes = object_sizes_get (osi, SSA_NAME_VERSION (op0)); + wholesize = object_sizes_get (osi, SSA_NAME_VERSION (op0), true); + reexamine = bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (op0)); + } else { - unsigned HOST_WIDE_INT off = tree_to_uhwi (op1); - - /* op0 will be ADDR_EXPR here. */ - addr_object_size (osi, op0, object_size_type, &bytes); - if (bytes == unknown (object_size_type)) - ; - else if (off > offset_limit) - bytes = unknown (object_size_type); - else if (off > bytes) - bytes = 0; - else - bytes -= off; + /* op0 will be ADDR_EXPR here. We should never come here during + reexamination. */ + gcc_checking_assert (osi->pass == 0); + addr_object_size (osi, op0, object_size_type, &bytes, &wholesize); } + + /* In the first pass, do not compute size for offset if either the + maximum size is unknown or the minimum size is not initialized yet; + the latter indicates a dependency loop and will be resolved in + subsequent passes. We attempt to compute offset for 0 minimum size + too because a negative offset could be within bounds of WHOLESIZE, + giving a non-zero result for VAR. */ + if (osi->pass != 0 || !size_unknown_p (bytes, 0)) + bytes = size_for_offset (bytes, op1, wholesize); } else - bytes = unknown (object_size_type); + bytes = wholesize = size_unknown (object_size_type); - object_sizes_set (osi, varno, bytes); - return false; + if (object_sizes_set (osi, varno, bytes, wholesize)) + osi->changed = true; + return reexamine; } @@ -945,7 +1044,7 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) else_ = gimple_assign_rhs3 (stmt); if (TREE_CODE (then_) == SSA_NAME) - reexamine |= merge_object_sizes (osi, var, then_, 0); + reexamine |= merge_object_sizes (osi, var, then_); else expr_object_size (osi, var, then_); @@ -953,7 +1052,7 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) return reexamine; if (TREE_CODE (else_) == SSA_NAME) - reexamine |= merge_object_sizes (osi, var, else_, 0); + reexamine |= merge_object_sizes (osi, var, else_); else expr_object_size (osi, var, else_); @@ -970,11 +1069,11 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) object size is object size of the first operand minus the constant. If the constant is bigger than the number of remaining bytes until the end of the object, object size is 0, but if it is instead a pointer - subtraction, object size is unknown (object_size_type). + subtraction, object size is size_unknown (object_size_type). To differentiate addition from subtraction, ADDR_EXPR returns - unknown (object_size_type) for all objects bigger than half of the address - space, and constants less than half of the address space are considered - addition, while bigger constants subtraction. + size_unknown (object_size_type) for all objects bigger than half of the + address space, and constants less than half of the address space are + considered addition, while bigger constants subtraction. For a memcpy like GIMPLE_CALL that always returns one of its arguments, the object size is object size of that argument. Otherwise, object size is the maximum of object sizes of variables @@ -997,8 +1096,9 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) { /* Initialize to 0 for maximum size and M1U for minimum size so that it gets immediately overridden. */ - object_sizes_set_force (osi, varno, - unknown (object_size_type ^ OST_MINIMUM)); + object_sizes_initialize (osi, varno, + size_initval (object_size_type), + size_initval (object_size_type)); } else { @@ -1041,7 +1141,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) { if (TREE_CODE (rhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (rhs))) - reexamine = merge_object_sizes (osi, var, rhs, 0); + reexamine = merge_object_sizes (osi, var, rhs); else expr_object_size (osi, var, rhs); } @@ -1058,7 +1158,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) { if (TREE_CODE (arg) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (arg))) - reexamine = merge_object_sizes (osi, var, arg, 0); + reexamine = merge_object_sizes (osi, var, arg); else expr_object_size (osi, var, arg); } @@ -1069,7 +1169,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) case GIMPLE_ASM: /* Pointers defined by __asm__ statements can point anywhere. */ - object_sizes_set (osi, varno, unknown (object_size_type)); + unknown_object_size (osi, var); break; case GIMPLE_NOP: @@ -1078,7 +1178,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) expr_object_size (osi, var, SSA_NAME_VAR (var)); else /* Uninitialized SSA names point nowhere. */ - object_sizes_set (osi, varno, unknown (object_size_type)); + unknown_object_size (osi, var); break; case GIMPLE_PHI: @@ -1093,7 +1193,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) break; if (TREE_CODE (rhs) == SSA_NAME) - reexamine |= merge_object_sizes (osi, var, rhs, 0); + reexamine |= merge_object_sizes (osi, var, rhs); else if (osi->pass == 0) expr_object_size (osi, var, rhs); } @@ -1144,7 +1244,8 @@ check_for_plus_in_loops_1 (struct object_size_info *osi, tree var, --sp; bitmap_clear_bit (osi->reexamine, *sp); bitmap_set_bit (computed[osi->object_size_type], *sp); - object_sizes_set_force (osi, *sp, 0); + object_sizes_set (osi, *sp, size_zero_node, + object_sizes_get (osi, *sp, true)); if (*sp == varno) break; } @@ -1244,7 +1345,8 @@ check_for_plus_in_loops (struct object_size_info *osi, tree var) gcc_assert (TREE_CODE (cst) == INTEGER_CST); - if (integer_zerop (cst)) + /* Skip non-positive offsets. */ + if (integer_zerop (cst) || compare_tree_int (cst, offset_limit) > 0) return; osi->depths[SSA_NAME_VERSION (basevar)] = 1; @@ -1298,8 +1400,85 @@ do_valueize (tree t) return t; } +/* Process a __builtin_object_size or __builtin_dynamic_object_size call in + CALL early for subobjects before any object information is lost due to + optimization. Insert a MIN or MAX expression of the result and + __builtin_object_size at I so that it may be processed in the second pass. + __builtin_dynamic_object_size is treated like __builtin_object_size here + since we're only looking for constant bounds. */ + +static void +early_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call) +{ + tree ost = gimple_call_arg (call, 1); + tree lhs = gimple_call_lhs (call); + gcc_assert (lhs != NULL_TREE); + + if (!tree_fits_uhwi_p (ost)) + return; + + unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost); + tree ptr = gimple_call_arg (call, 0); + + if (object_size_type != 1 && object_size_type != 3) + return; + + if (TREE_CODE (ptr) != ADDR_EXPR && TREE_CODE (ptr) != SSA_NAME) + return; + + tree type = TREE_TYPE (lhs); + tree bytes; + if (!compute_builtin_object_size (ptr, object_size_type, &bytes) + || !int_fits_type_p (bytes, type)) + return; + + tree tem = make_ssa_name (type); + gimple_call_set_lhs (call, tem); + enum tree_code code = object_size_type & OST_MINIMUM ? MAX_EXPR : MIN_EXPR; + tree cst = fold_convert (type, bytes); + gimple *g = gimple_build_assign (lhs, code, tem, cst); + gsi_insert_after (i, g, GSI_NEW_STMT); + update_stmt (call); +} + +/* Attempt to fold one __builtin_dynamic_object_size call in CALL into an + expression and insert it at I. Return true if it succeeds. */ + +static bool +dynamic_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call) +{ + gcc_assert (gimple_call_num_args (call) == 2); + + tree args[2]; + args[0] = gimple_call_arg (call, 0); + args[1] = gimple_call_arg (call, 1); + + location_t loc = EXPR_LOC_OR_LOC (args[0], input_location); + tree result_type = gimple_call_return_type (as_a <gcall *> (call)); + tree result = fold_builtin_call_array (loc, result_type, + gimple_call_fn (call), 2, args); + + if (!result) + return false; + + /* fold_builtin_call_array may wrap the result inside a + NOP_EXPR. */ + STRIP_NOPS (result); + gimplify_and_update_call_from_tree (i, result); + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Simplified (dynamic)\n "); + print_gimple_stmt (dump_file, call, 0, dump_flags); + fprintf (dump_file, " to "); + print_generic_expr (dump_file, result); + fprintf (dump_file, "\n"); + } + return true; +} + static unsigned int -object_sizes_execute (function *fun, bool insert_min_max_p) +object_sizes_execute (function *fun, bool early) { basic_block bb; FOR_EACH_BB_FN (bb, fun) @@ -1308,8 +1487,12 @@ object_sizes_execute (function *fun, bool insert_min_max_p) for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) { tree result; + bool dynamic = false; + gimple *call = gsi_stmt (i); - if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE)) + if (gimple_call_builtin_p (call, BUILT_IN_DYNAMIC_OBJECT_SIZE)) + dynamic = true; + else if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE)) continue; tree lhs = gimple_call_lhs (call); @@ -1318,42 +1501,39 @@ object_sizes_execute (function *fun, bool insert_min_max_p) init_object_sizes (); - /* If insert_min_max_p, only attempt to fold + /* If early, only attempt to fold __builtin_object_size (x, 1) and __builtin_object_size (x, 3), and rather than folding the builtin to the constant if any, create a MIN_EXPR or MAX_EXPR of the __builtin_object_size - call result and the computed constant. */ - if (insert_min_max_p) + call result and the computed constant. Do the same for + __builtin_dynamic_object_size too. */ + if (early) { - tree ost = gimple_call_arg (call, 1); - if (tree_fits_uhwi_p (ost)) + early_object_sizes_execute_one (&i, call); + continue; + } + + if (dynamic) + { + if (dynamic_object_sizes_execute_one (&i, call)) + continue; + else { - unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost); - tree ptr = gimple_call_arg (call, 0); - if ((object_size_type & OST_SUBOBJECT) - && (TREE_CODE (ptr) == ADDR_EXPR - || TREE_CODE (ptr) == SSA_NAME)) + /* If we could not find a suitable size expression, lower to + __builtin_object_size so that we may at least get a + constant lower or higher estimate. */ + tree bosfn = builtin_decl_implicit (BUILT_IN_OBJECT_SIZE); + gimple_call_set_fndecl (call, bosfn); + update_stmt (call); + + if (dump_file && (dump_flags & TDF_DETAILS)) { - tree type = TREE_TYPE (lhs); - unsigned HOST_WIDE_INT bytes; - if (compute_builtin_object_size (ptr, object_size_type, - &bytes) - && wi::fits_to_tree_p (bytes, type)) - { - tree tem = make_ssa_name (type); - gimple_call_set_lhs (call, tem); - enum tree_code code - = (object_size_type & OST_MINIMUM - ? MAX_EXPR : MIN_EXPR); - tree cst = build_int_cstu (type, bytes); - gimple *g - = gimple_build_assign (lhs, code, tem, cst); - gsi_insert_after (&i, g, GSI_NEW_STMT); - update_stmt (call); - } + print_generic_expr (dump_file, gimple_call_arg (call, 0), + dump_flags); + fprintf (dump_file, + ": Retrying as __builtin_object_size\n"); } } - continue; } result = gimple_fold_stmt_to_constant (call, do_valueize); diff --git a/gcc/tree-object-size.h b/gcc/tree-object-size.h index ef18aea..f4f438c 100644 --- a/gcc/tree-object-size.h +++ b/gcc/tree-object-size.h @@ -20,9 +20,19 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_OBJECT_SIZE_H #define GCC_TREE_OBJECT_SIZE_H +/* Bits in object_size_type. */ + +enum +{ + OST_SUBOBJECT = 1, + OST_MINIMUM = 2, + OST_DYNAMIC = 4, + OST_END = 8, +}; + extern void init_object_sizes (void); extern void fini_object_sizes (void); -extern bool compute_builtin_object_size (tree, int, unsigned HOST_WIDE_INT *); +extern bool compute_builtin_object_size (tree, int, tree *); extern tree decl_init_size (tree, bool); #endif // GCC_TREE_OBJECT_SIZE_H diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 8c42717..ad90cdb 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -6361,7 +6361,9 @@ vectorizable_operation (vec_info *vinfo, /* When combining two masks check if either of them is elsewhere combined with a loop mask, if that's the case we can mark that the new combined mask doesn't need to be combined with a loop mask. */ - if (masked_loop_p && code == BIT_AND_EXPR) + if (masked_loop_p + && code == BIT_AND_EXPR + && VECTOR_BOOLEAN_TYPE_P (vectype)) { if (loop_vinfo->scalar_cond_masked_set.contains ({ op0, ncopies})) diff --git a/gcc/ubsan.c b/gcc/ubsan.c index ba9adf0..364cf17 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -2160,9 +2160,8 @@ instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs) if (decl_p) base_addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (base)), base); - unsigned HOST_WIDE_INT size; - if (compute_builtin_object_size (base_addr, 0, &size)) - sizet = build_int_cst (sizetype, size); + if (compute_builtin_object_size (base_addr, 0, &sizet)) + ; else if (optimize) { if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION) diff --git a/libcc1/ChangeLog b/libcc1/ChangeLog index ddf2826..c03d89f 100644 --- a/libcc1/ChangeLog +++ b/libcc1/ChangeLog @@ -1,3 +1,12 @@ +2021-12-16 Patrick Palka <ppalka@redhat.com> + + PR c++/51577 + PR c++/83035 + PR c++/100465 + * libcp1plugin.cc (plugin_build_unary_expr): Adjust call to + build_x_unary_op. + (plugin_build_binary_expr): Adjust call to build_x_binary_op. + 2021-12-15 Iain Sandoe <iain@sandoe.co.uk> * configure: Regenerate. diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index ea6ee55..fccdce6 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -2669,7 +2669,7 @@ plugin_build_unary_expr (cc1_plugin::connection *self, break; default: - result = build_x_unary_op (/*loc=*/0, opcode, op0, tf_error); + result = build_x_unary_op (/*loc=*/0, opcode, op0, NULL_TREE, tf_error); break; } @@ -2794,7 +2794,7 @@ plugin_build_binary_expr (cc1_plugin::connection *self, default: result = build_x_binary_op (/*loc=*/0, opcode, op0, ERROR_MARK, - op1, ERROR_MARK, NULL, tf_error); + op1, ERROR_MARK, NULL_TREE, NULL, tf_error); break; } diff --git a/libgcc/config.host b/libgcc/config.host index 1bac57c..ad0cdb2 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1140,10 +1140,14 @@ powerpc-*-darwin*) md_unwind_header=rs6000/darwin-unwind.h ;; esac + # We build the darwin10 EH shim for Rosetta (running on x86 machines). + tm_file="$tm_file i386/darwin-lib.h" tmake_file="$tmake_file rs6000/t-ppc64-fp rs6000/t-ibm-ldouble" extra_parts="$extra_parts crt2.o crt3_2.o libef_ppc.a dw_ppc.o" ;; powerpc64-*-darwin*) + # We build the darwin10 EH shim for Rosetta (running on x86 machines). + tm_file="$tm_file i386/darwin-lib.h" tmake_file="$tmake_file rs6000/t-darwin64 rs6000/t-ibm-ldouble" extra_parts="$extra_parts crt2.o crt3_2.o libef_ppc.a dw_ppc.o" ;; diff --git a/libgcc/config/rs6000/t-darwin-ehs b/libgcc/config/rs6000/t-darwin-ehs index 3047f53..42f5214 100644 --- a/libgcc/config/rs6000/t-darwin-ehs +++ b/libgcc/config/rs6000/t-darwin-ehs @@ -1,5 +1,3 @@ # We need the save_world code for the EH library. -LIBEHSOBJS += darwin-world_s.o - -$(LIBEHSOBJS): libef_ppc.a +LIBEHSOBJS += darwin-world_s.o diff --git a/libgcc/config/t-darwin-ehs b/libgcc/config/t-darwin-ehs index 8481898..9527502 100644 --- a/libgcc/config/t-darwin-ehs +++ b/libgcc/config/t-darwin-ehs @@ -2,3 +2,6 @@ # libgcc_s.1 on systems that used the unwinder in libgcc_s. LIBEHSOBJS = unwind-dw2_s.o unwind-dw2-fde-darwin_s.o unwind-c_s.o + +unwind-dw2_s.o: gthr-default.h md-unwind-support.h +$(LIBEHSOBJS): libgcc_tm.h diff --git a/libgcc/config/t-slibgcc-darwin b/libgcc/config/t-slibgcc-darwin index 7349b87..a8f6966 100644 --- a/libgcc/config/t-slibgcc-darwin +++ b/libgcc/config/t-slibgcc-darwin @@ -59,9 +59,8 @@ ifneq ($(LIBEHSOBJS),) EHS_INSTNAME = libgcc_ehs.$(SHLIB_SOVERSION)$(SHLIB_EXT) # multilib build for a shared EH lib. -$(LIBEHSOBJS): libgcc_tm.h -libgcc_ehs$(SHLIB_EXT): $(LIBEHSOBJS) +libgcc_ehs$(SHLIB_EXT): $(LIBEHSOBJS) $(extra-parts) mkdir -p $(MULTIDIR) $(CC) $(LIBGCC2_CFLAGS) $(LDFLAGS) -dynamiclib -nodefaultlibs \ -install_name $(SHLIB_INSTALL_DIR)/$(EHS_INSTNAME) \ @@ -113,7 +112,8 @@ libgcc_ehs.$(SHLIB_SOVERSION)$(SHLIB_EXT): all-multi libgcc_ehs$(SHLIB_EXT) rm libgcc_ehs.$(SHLIB_SOVERSION)$(SHLIB_EXT)_T* -libgcc_s.1.dylib: libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT) libgcc_ehs.$(SHLIB_SOVERSION)$(SHLIB_EXT) +libgcc_s.1.dylib: all-multi libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT) \ + libgcc_ehs.$(SHLIB_SOVERSION)$(SHLIB_EXT) MLIBS=`$(CC) --print-multi-lib | sed -e 's/;.*$$//'` ; \ for mlib in $$MLIBS ; do \ cp ../$${mlib}/libgcc/$${mlib}/libgcc_s$(SHLIB_EXT) \ @@ -134,7 +134,7 @@ libgcc_s.1.dylib: libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT) libgcc_ehs.$(SHLIB_SOV else -libgcc_s.1.dylib: libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT) +libgcc_s.1.dylib: all-multi libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT) MLIBS=`$(CC) --print-multi-lib | sed -e 's/;.*$$//'` ; \ for mlib in $$MLIBS ; do \ cp ../$${mlib}/libgcc/$${mlib}/libgcc_s$(SHLIB_EXT) \ diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 90d7daf..2f366c8 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,13 @@ +2021-12-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * io/file_pos.c: Fix error code. + +2021-12-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * intrinsics/time_1.h: Prefer clock_gettime() over + gettimeofday(). + * intrinsics/date_and_time.c: Fix timezone wrapping. + 2021-12-14 Harald Anlauf <anlauf@gmx.de> PR libfortran/103634 diff --git a/libgfortran/intrinsics/date_and_time.c b/libgfortran/intrinsics/date_and_time.c index 8213127..de40bbc 100644 --- a/libgfortran/intrinsics/date_and_time.c +++ b/libgfortran/intrinsics/date_and_time.c @@ -113,9 +113,6 @@ gmtime_r (const time_t * timep, struct tm * result) VALUES for INTEGER(kind=4) and INTEGER(kind=8). Based on libU77's date_time_.c. - - TODO : - - Check year boundaries. */ #define DATE_LEN 8 #define TIME_LEN 10 @@ -131,7 +128,7 @@ date_and_time (char *__date, char *__time, char *__zone, gfc_array_i4 *__values, GFC_INTEGER_4 __date_len, GFC_INTEGER_4 __time_len, GFC_INTEGER_4 __zone_len) { - int i; + int i, delta_day; char date[DATE_LEN + 1]; char timec[TIME_LEN + 1]; char zone[ZONE_LEN + 1]; @@ -154,9 +151,22 @@ date_and_time (char *__date, char *__time, char *__zone, values[0] = 1900 + local_time.tm_year; values[1] = 1 + local_time.tm_mon; values[2] = local_time.tm_mday; - values[3] = (local_time.tm_min - UTC_time.tm_min + - 60 * (local_time.tm_hour - UTC_time.tm_hour + - 24 * (local_time.tm_yday - UTC_time.tm_yday))); + + /* Day difference with UTC should always be -1, 0 or +1. + Near year boundaries, we may obtain a large positive (+364, + or +365 on leap years) or negative (-364, or -365 on leap years) + number, which we have to handle. + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98507 + */ + delta_day = local_time.tm_yday - UTC_time.tm_yday; + if (delta_day < -1) + delta_day = 1; + else if (delta_day > 1) + delta_day = -1; + + values[3] = local_time.tm_min - UTC_time.tm_min + + 60 * (local_time.tm_hour - UTC_time.tm_hour + 24 * delta_day); + values[4] = local_time.tm_hour; values[5] = local_time.tm_min; values[6] = local_time.tm_sec; diff --git a/libgfortran/intrinsics/time_1.h b/libgfortran/intrinsics/time_1.h index 2d238fd..b2adca0 100644 --- a/libgfortran/intrinsics/time_1.h +++ b/libgfortran/intrinsics/time_1.h @@ -213,19 +213,19 @@ gf_cputime (long *user_sec, long *user_usec, long *system_sec, long *system_usec static inline int gf_gettime (time_t * secs, long * usecs) { -#ifdef HAVE_GETTIMEOFDAY +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + int err = clock_gettime (CLOCK_REALTIME, &ts); + *secs = ts.tv_sec; + *usecs = ts.tv_nsec / 1000; + return err; +#elif defined(HAVE_GETTIMEOFDAY) struct timeval tv; int err; err = gettimeofday (&tv, NULL); *secs = tv.tv_sec; *usecs = tv.tv_usec; return err; -#elif defined(HAVE_CLOCK_GETTIME) - struct timespec ts; - int err = clock_gettime (CLOCK_REALTIME, &ts); - *secs = ts.tv_sec; - *usecs = ts.tv_nsec / 1000; - return err; #else time_t t = time (NULL); *secs = t; diff --git a/libgfortran/io/file_pos.c b/libgfortran/io/file_pos.c index 7e71ca5..4ed1698 100644 --- a/libgfortran/io/file_pos.c +++ b/libgfortran/io/file_pos.c @@ -527,7 +527,7 @@ st_flush (st_parameter_filepos *fpp) } else /* FLUSH on unconnected unit is illegal: F95 std., 9.3.5. */ - generate_error (&fpp->common, LIBERROR_BAD_OPTION, + generate_error (&fpp->common, -LIBERROR_BAD_UNIT, "Specified UNIT in FLUSH is not connected"); if (needs_unlock) diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index e1102ea..17e6834 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,16 @@ +2021-12-16 H.J. Lu <hjl.tools@gmail.com> + + Revert: + 2021-12-16 H.J. Lu <hjl.tools@gmail.com> + + * Makefile.in (AR): Add @AR_PLUGIN_OPTION@ + (RANLIB): Add @RANLIB_PLUGIN_OPTION@. + (configure_deps): Depend on ../config/gcc-plugin.m4. + * configure.ac: AC_SUBST AR_PLUGIN_OPTION and + RANLIB_PLUGIN_OPTION. + * aclocal.m4: Regenerated. + * configure: Likewise. + 2021-12-15 H.J. Lu <hjl.tools@gmail.com> * Makefile.in (AR): Add @AR_PLUGIN_OPTION@ diff --git a/zlib/ChangeLog b/zlib/ChangeLog index c544842..7d6646b 100644 --- a/zlib/ChangeLog +++ b/zlib/ChangeLog @@ -1,3 +1,10 @@ +2021-12-16 H.J. Lu <hjl.tools@gmail.com> + + Revert: + 2021-12-16 H.J. Lu <hjl.tools@gmail.com> + + * configure: Regenerated. + 2021-12-15 H.J. Lu <hjl.tools@gmail.com> * configure: Regenerated. |