diff options
357 files changed, 12791 insertions, 2289 deletions
diff --git a/contrib/ChangeLog b/contrib/ChangeLog index c375530..3c016fe 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,16 @@ +2022-10-07 Martin Liska <mliska@suse.cz> + + * gcc-changelog/git_update_version.py: Remove extra fetch. + +2022-10-06 Martin Liska <mliska@suse.cz> + + * gcc-changelog/git_update_version.py: Use logging module + and provide robust debugging output. + +2022-10-05 Martin Liska <mliska@suse.cz> + + * gcc-changelog/git_update_version.py: Do fetch before a push. + 2022-09-20 Martin Liska <mliska@suse.cz> * filter-clang-warnings.py: Skip egrep: warning: egrep is diff --git a/contrib/gcc-changelog/git_update_version.py b/contrib/gcc-changelog/git_update_version.py index 05a9f7e..074e717 100755 --- a/contrib/gcc-changelog/git_update_version.py +++ b/contrib/gcc-changelog/git_update_version.py @@ -18,6 +18,7 @@ import argparse import datetime +import logging import os from git import Repo @@ -34,6 +35,13 @@ IGNORED_COMMITS = ( '3ab5c8cd03d92bf4ec41e351820349d92fbc40c4', '86d8e0c0652ef5236a460b75c25e4f7093cc0651') +FORMAT = '%(asctime)s:%(levelname)s:%(name)s:%(message)s' +logging.basicConfig(level=logging.INFO, format=FORMAT, + handlers=[ + logging.FileHandler('/tmp/git_update_version.txt'), + logging.StreamHandler() + ]) + def read_timestamp(path): with open(path) as f: @@ -43,11 +51,11 @@ def read_timestamp(path): def prepend_to_changelog_files(repo, folder, git_commit, add_to_git): if not git_commit.success: for error in git_commit.errors: - print(error) + logging.info(error) raise AssertionError() for entry, output in git_commit.to_changelog_entries(use_commit_ts=True): full_path = os.path.join(folder, entry, 'ChangeLog') - print('writing to %s' % full_path) + logging.info('writing to %s' % full_path) if os.path.exists(full_path): with open(full_path) as f: content = f.read() @@ -95,7 +103,7 @@ def update_current_branch(ref_name): commit = commit.parents[-1] commit_count += 1 - print('%d revisions since last Daily bump' % commit_count) + logging.info('%d revisions since last Daily bump' % commit_count) datestamp_path = os.path.join(args.git_path, 'gcc/DATESTAMP') if (read_timestamp(datestamp_path) != current_timestamp or args.dry_mode or args.current): @@ -117,25 +125,29 @@ def update_current_branch(ref_name): branch.name.split('/')[-1] + '.patch') with open(patch, 'w+') as f: f.write(diff) - print('branch diff written to %s' % patch) + logging.info('branch diff written to %s' % patch) repo.git.checkout(force=True) else: # update timestamp - print('DATESTAMP will be changed:') + logging.info('DATESTAMP will be changed:') with open(datestamp_path, 'w+') as f: f.write(current_timestamp) repo.git.add(datestamp_path) if not args.current: repo.index.commit('Daily bump.') + logging.info('commit is done') if args.push: - repo.git.push('origin', branch) - print('branch is pushed') + try: + repo.git.push('origin', branch) + logging.info('branch is pushed') + except Exception: + logging.exception('git push failed') else: - print('DATESTAMP unchanged') + logging.info('DATESTAMP unchanged') if args.current: - print('=== Working on the current branch ===', flush=True) + logging.info('=== Working on the current branch ===') update_current_branch() else: for ref in origin.refs: @@ -146,10 +158,11 @@ else: branch = repo.branches[name] else: branch = repo.create_head(name, ref).set_tracking_branch(ref) - print('=== Working on: %s ===' % branch, flush=True) + logging.info('=== Working on: %s ===' % branch) branch.checkout() origin.pull(rebase=True) - print('branch pulled and checked out') + logging.info('branch pulled and checked out') update_current_branch(name) assert not repo.index.diff(None) - print('branch is done\n', flush=True) + logging.info('branch is done') + logging.info('') diff --git a/fixincludes/ChangeLog b/fixincludes/ChangeLog index 0b88d27..c3c398d 100644 --- a/fixincludes/ChangeLog +++ b/fixincludes/ChangeLog @@ -1,3 +1,18 @@ +2022-10-07 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/107059 + * inclhack.def (glibc_cxx_floatn_5): New. + * fixincl.x: Regenerated. + * tests/base/bits/floatn.h: Regenerated. + +2022-10-07 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/107059 + * inclhack.def (glibc_cxx_floatn_2): Handle #elif the same as #if. + (glibc_cxx_floatn_4): New. + * fixincl.x: Regenerated. + * tests/base/bits/floatn.h: Regenerated. + 2022-09-27 Jakub Jelinek <jakub@redhat.com> * inclhack.def (glibc_cxx_floatn_1, glibc_cxx_floatn_2, diff --git a/fixincludes/fixincl.x b/fixincludes/fixincl.x index 6309723..2086754 100644 --- a/fixincludes/fixincl.x +++ b/fixincludes/fixincl.x @@ -2,11 +2,11 @@ * * DO NOT EDIT THIS FILE (fixincl.x) * - * It has been AutoGen-ed September 27, 2022 at 12:21:44 PM by AutoGen 5.18.16 + * It has been AutoGen-ed September 29, 2022 at 10:22:55 PM by AutoGen 5.18.16 * From the definitions inclhack.def * and the template file fixincl */ -/* DO NOT SVN-MERGE THIS FILE, EITHER Tue Sep 27 12:21:44 CEST 2022 +/* DO NOT SVN-MERGE THIS FILE, EITHER Thu Sep 29 22:22:55 CEST 2022 * * You must regenerate it. Use the ./genfixes script. * @@ -15,7 +15,7 @@ * certain ANSI-incompatible system header files which are fixed to work * correctly with ANSI C and placed in a directory that GNU C will search. * - * This file contains 270 fixup descriptions. + * This file contains 272 fixup descriptions. * * See README for more information. * @@ -4167,7 +4167,7 @@ tSCC zGlibc_Cxx_Floatn_2List[] = * content selection pattern - do fix if pattern found */ tSCC zGlibc_Cxx_Floatn_2Select0[] = - "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\ + "^([ \t]*#[ \t]*(el)?if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\ (([ \t]*/\\*[^\n\ ]*\\*/\n\ )?[ \t]*typedef[ \t]+[^\n\ @@ -4183,7 +4183,7 @@ static tTestDesc aGlibc_Cxx_Floatn_2Tests[] = { static const char* apzGlibc_Cxx_Floatn_2Patch[] = { "format", "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n\ -%2", +%3", (char*)NULL }; /* * * * * * * * * * * * * * * * * * * * * * * * * * @@ -4233,6 +4233,83 @@ static const char* apzGlibc_Cxx_Floatn_3Patch[] = { /* * * * * * * * * * * * * * * * * * * * * * * * * * * + * Description of Glibc_Cxx_Floatn_4 fix + */ +tSCC zGlibc_Cxx_Floatn_4Name[] = + "glibc_cxx_floatn_4"; + +/* + * File name selection pattern + */ +tSCC zGlibc_Cxx_Floatn_4List[] = + "bits/floatn.h\0*/bits/floatn.h\0"; +/* + * Machine/OS name selection pattern + */ +#define apzGlibc_Cxx_Floatn_4Machs (const char**)NULL + +/* + * content selection pattern - do fix if pattern found + */ +tSCC zGlibc_Cxx_Floatn_4Select0[] = + "^([ \t]*#[ \t]*if __LDBL_MANT_DIG__ == 113 && )defined __cplusplus\n\ +(([ \t]*/\\*[^\n\ +]*\\*/\n\ +)?[ \t]*typedef[ \t]+[^\n\ +]*[ \t]+_Float128;)"; + +#define GLIBC_CXX_FLOATN_4_TEST_CT 1 +static tTestDesc aGlibc_Cxx_Floatn_4Tests[] = { + { TT_EGREP, zGlibc_Cxx_Floatn_4Select0, (regex_t*)NULL }, }; + +/* + * Fix Command Arguments for Glibc_Cxx_Floatn_4 + */ +static const char* apzGlibc_Cxx_Floatn_4Patch[] = { + "format", + "%1defined __cplusplus && !__GNUC_PREREQ (13, 0)\n\ +%2", + (char*)NULL }; + +/* * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Description of Glibc_Cxx_Floatn_5 fix + */ +tSCC zGlibc_Cxx_Floatn_5Name[] = + "glibc_cxx_floatn_5"; + +/* + * File name selection pattern + */ +tSCC zGlibc_Cxx_Floatn_5List[] = + "bits/floatn.h\0bits/floatn-common.h\0*/bits/floatn.h\0*/bits/floatn-common.h\0"; +/* + * Machine/OS name selection pattern + */ +#define apzGlibc_Cxx_Floatn_5Machs (const char**)NULL + +/* + * content selection pattern - do fix if pattern found + */ +tSCC zGlibc_Cxx_Floatn_5Select0[] = + "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\ +([ \t]*#[ \t]+error \"_Float128[xX] supported but no )"; + +#define GLIBC_CXX_FLOATN_5_TEST_CT 1 +static tTestDesc aGlibc_Cxx_Floatn_5Tests[] = { + { TT_EGREP, zGlibc_Cxx_Floatn_5Select0, (regex_t*)NULL }, }; + +/* + * Fix Command Arguments for Glibc_Cxx_Floatn_5 + */ +static const char* apzGlibc_Cxx_Floatn_5Patch[] = { + "format", + "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n\ +%2", + (char*)NULL }; + +/* * * * * * * * * * * * * * * * * * * * * * * * * * + * * Description of Glibc_Mutex_Init fix */ tSCC zGlibc_Mutex_InitName[] = @@ -10998,9 +11075,9 @@ static const char* apzX11_SprintfPatch[] = { * * List of all fixes */ -#define REGEX_COUNT 308 +#define REGEX_COUNT 310 #define MACH_LIST_SIZE_LIMIT 187 -#define FIX_COUNT 270 +#define FIX_COUNT 272 /* * Enumerate the fixes @@ -11106,6 +11183,8 @@ typedef enum { GLIBC_CXX_FLOATN_1_FIXIDX, GLIBC_CXX_FLOATN_2_FIXIDX, GLIBC_CXX_FLOATN_3_FIXIDX, + GLIBC_CXX_FLOATN_4_FIXIDX, + GLIBC_CXX_FLOATN_5_FIXIDX, GLIBC_MUTEX_INIT_FIXIDX, GLIBC_STDINT_FIXIDX, GLIBC_STRNCPY_FIXIDX, @@ -11779,6 +11858,16 @@ tFixDesc fixDescList[ FIX_COUNT ] = { GLIBC_CXX_FLOATN_3_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, aGlibc_Cxx_Floatn_3Tests, apzGlibc_Cxx_Floatn_3Patch, 0 }, + { zGlibc_Cxx_Floatn_4Name, zGlibc_Cxx_Floatn_4List, + apzGlibc_Cxx_Floatn_4Machs, + GLIBC_CXX_FLOATN_4_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, + aGlibc_Cxx_Floatn_4Tests, apzGlibc_Cxx_Floatn_4Patch, 0 }, + + { zGlibc_Cxx_Floatn_5Name, zGlibc_Cxx_Floatn_5List, + apzGlibc_Cxx_Floatn_5Machs, + GLIBC_CXX_FLOATN_5_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, + aGlibc_Cxx_Floatn_5Tests, apzGlibc_Cxx_Floatn_5Patch, 0 }, + { zGlibc_Mutex_InitName, zGlibc_Mutex_InitList, apzGlibc_Mutex_InitMachs, GLIBC_MUTEX_INIT_TEST_CT, FD_MACH_ONLY, diff --git a/fixincludes/inclhack.def b/fixincludes/inclhack.def index 88bf28f..d463747 100644 --- a/fixincludes/inclhack.def +++ b/fixincludes/inclhack.def @@ -2060,11 +2060,11 @@ fix = { fix = { hackname = glibc_cxx_floatn_2; files = bits/floatn.h, bits/floatn-common.h, "*/bits/floatn.h", "*/bits/floatn-common.h"; - select = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n" + select = "^([ \t]*#[ \t]*(el)?if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n" "(([ \t]*/\\*[^\n]*\\*/\n)?" "[ \t]*typedef[ \t]+[^\n]*[ \t]+_Float(16|32|64|128)x?([ \t]+__attribute__ \\(\\(__mode__ \\(__HF__\\)\\)\\))?;)"; c_fix = format; - c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n%2"; + c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n%3"; test_text = <<-EOT # if !__GNUC_PREREQ (7, 0) || defined __cplusplus typedef float _Float16 __attribute__ ((__mode__ (__HF__))); @@ -2072,6 +2072,10 @@ fix = { # if !__GNUC_PREREQ (7, 0) || defined __cplusplus typedef __float128 _Float128; # endif + # if 0 + # elif !__GNUC_PREREQ (7, 0) || defined __cplusplus + typedef __float128 _Float128; + # endif EOT; }; @@ -2111,6 +2115,39 @@ fix = { EOT; }; +fix = { + hackname = glibc_cxx_floatn_4; + files = bits/floatn.h, "*/bits/floatn.h"; + select = "^([ \t]*#[ \t]*if __LDBL_MANT_DIG__ == 113 && )defined __cplusplus\n" + "(([ \t]*/\\*[^\n]*\\*/\n)?" + "[ \t]*typedef[ \t]+[^\n]*[ \t]+_Float128;)"; + c_fix = format; + c_fix_arg = "%1defined __cplusplus && !__GNUC_PREREQ (13, 0)\n%2"; + test_text = <<-EOT + # if __LDBL_MANT_DIG__ == 113 && defined __cplusplus + typedef long double _Float128; + # define __CFLOAT128 _Complex long double + # endif + EOT; +}; + +fix = { + hackname = glibc_cxx_floatn_5; + files = bits/floatn.h, bits/floatn-common.h, "*/bits/floatn.h", "*/bits/floatn-common.h"; + select = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n" + "([ \t]*#[ \t]+error \"_Float128[xX] supported but no )"; + c_fix = format; + c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 0))\n%2"; + test_text = <<-EOT + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus + # error "_Float128X supported but no constant suffix" + # endif + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus + # error "_Float128x supported but no type" + # endif + EOT; +}; + /* glibc-2.3.5 defines pthread mutex initializers incorrectly, * so we replace them with versions that correspond to the * definition. diff --git a/fixincludes/tests/base/bits/floatn.h b/fixincludes/tests/base/bits/floatn.h index f09528b..9681134 100644 --- a/fixincludes/tests/base/bits/floatn.h +++ b/fixincludes/tests/base/bits/floatn.h @@ -45,6 +45,10 @@ typedef float _Float16 __attribute__ ((__mode__ (__HF__))); # if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0)) typedef __float128 _Float128; # endif +# if 0 +# elif !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0)) +typedef __float128 _Float128; +# endif #endif /* GLIBC_CXX_FLOATN_2_CHECK */ @@ -72,3 +76,21 @@ typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__))); # define __CFLOAT64 _Complex _Float64 # endif #endif /* GLIBC_CXX_FLOATN_3_CHECK */ + + +#if defined( GLIBC_CXX_FLOATN_4_CHECK ) +# if __LDBL_MANT_DIG__ == 113 && defined __cplusplus && !__GNUC_PREREQ (13, 0) +typedef long double _Float128; +# define __CFLOAT128 _Complex long double +# endif +#endif /* GLIBC_CXX_FLOATN_4_CHECK */ + + +#if defined( GLIBC_CXX_FLOATN_5_CHECK ) +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0)) +# error "_Float128X supported but no constant suffix" +# endif +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0)) +# error "_Float128x supported but no type" +# endif +#endif /* GLIBC_CXX_FLOATN_5_CHECK */ diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 48397ff..5086463 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,397 @@ +2022-10-07 Eugene Rozenfeld <erozen@microsoft.com> + + * tree-cfg.cc (assign_discriminators): Set discriminators for call stmts + on the same line within the same basic block. + +2022-10-07 Qing Zhao <qing.zhao@oracle.com> + + PR tree-optimization/101836 + * tree-object-size.cc (addr_object_size): Use array_at_struct_end_p + to determine a flexible array member reference. + +2022-10-07 Qing Zhao <qing.zhao@oracle.com> + + * doc/extend.texi: Document strict_flex_array attribute. + * doc/invoke.texi: Document -fstrict-flex-arrays[=n] option. + * print-tree.cc (print_node): Print new bit decl_not_flexarray. + * tree-core.h (struct tree_decl_common): New bit field + decl_not_flexarray. + * tree-streamer-in.cc (unpack_ts_decl_common_value_fields): Stream + in new bit decl_not_flexarray. + * tree-streamer-out.cc (pack_ts_decl_common_value_fields): Stream + out new bit decl_not_flexarray. + * tree.cc (array_at_struct_end_p): Update it with the new bit field + decl_not_flexarray. + * tree.h (DECL_NOT_FLEXARRAY): New flag. + +2022-10-07 Olivier Hainque <hainque@adacore.com> + + * config/vxworks/_vxworks-versions.h: Use OS specific + paths in #include of version.h. + +2022-10-07 Martin Liska <mliska@suse.cz> + + * opts.cc (finish_options): Print sorry message only + for -flive-patching=inline-only-static. + +2022-10-07 Jason Merrill <jason@redhat.com> + + * gimplify.cc (gimplify_modify_expr_rhs): Don't optimize + x = *(A*)&<expr> to x = <expr> for a TREE_ADDRESSABLE type. + +2022-10-07 Richard Biener <rguenther@suse.de> + + PR tree-optimization/107153 + * tree-cfg.cc (gimple_duplicate_sese_tail): Do not update + SSA form here. + * tree-parloops.cc (gen_parallel_loop): Update SSA form + after to-exit-first transform, no PHI insertion is necessary. + (pass_parallelize_loops::execute): Force re-write of the + virtual operand SSA web. + +2022-10-07 Jonathan Wakely <jwakely@redhat.com> + + * value-range.cc (irange::irange_contains_p): Fix comment typo. + +2022-10-07 Eric Botcazou <ebotcazou@adacore.com> + + * function.cc (thread_prologue_and_epilogue_insns): Update only + entry and exit blocks when not optimizing. Remove dead statement. + +2022-10-07 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (irange::irange_set): Convert nonzero mask to + tree. + (irange::irange_set_anti_range): Same. + (irange::set): Same. + (irange::verify_range): Same. + (irange::contains_p): Same. + (irange::invert): Same. + (irange::set_range_from_nonzero_bits): Same. + (irange::set_nonzero_bits): Same. + (mask_to_wi): Same. + (irange::intersect_nonzero_bits): Same. + (irange::union_nonzero_bits): Same. + * value-range.h (irange::varying_compatible_p): Same. + (gt_ggc_mx): Same. + (gt_pch_nx): Same. + (irange::set_undefined): Same. + (irange::set_varying): Same. + +2022-10-07 Martin Liska <mliska@suse.cz> + + * config/i386/i386-protos.h (ix86_binary_operator_ok): Add array + size to function parameter. + (ix86_unary_operator_ok): Likewise. + +2022-10-07 Martin Liska <mliska@suse.cz> + + * auto-profile.cc (get_inline_stack): Remove unused variable. + +2022-10-07 Jakub Jelinek <jakub@redhat.com> + + * ipa-prop.h (ipa_constant_data): Fix comment typo. + * value-range.cc (irange::irange_contains_p): Likewise. + * value-relation.cc (dom_oracle::set_one_relation): Likewise. + * gimple-predicate-analysis.cc (predicate::simplify_4): Likewise. + * tree-inline.cc (remap_ssa_name): Likewise. + +2022-10-07 Jakub Jelinek <jakub@redhat.com> + + * attribs.h (is_attribute_namespace_p): New inline function. + (lookup_attribute): Document meaning of ATTR_NS equal to "". + * attribs.cc (remove_attribute): Use is_attribute_namespace_p. + (private_lookup_attribute): For ATTR_NS "" match either standard + attribute or "gnu" namespace one. + +2022-10-07 Olivier Hainque <hainque@adacore.com> + + * config/vxworks.h (DWARF_VERSION_DEFAULT): Adjust from + 4 to 3 for VxWorks >= 7. + +2022-10-07 Olivier Hainque <hainque@adacore.com> + + * defaults.h (DWARF_DEFAULT_VERSION): Define if not + defined already. + * common.opt (gdwarf-): Use it. + * doc/tm.texi.in (DWARF_DEFAULT_VERSION): Document. + * doc/tm.texi: Update accordingly. + * config/vxworks.h (DWARF_DEFAULT_VERSION): Redefine. + * config/vxworks.cc: Remove code setting dwarf_version, now + handled by the DWARF_DEFAULT_VERSION redefinition. + +2022-10-07 Olivier Hainque <hainque@adacore.com> + + * ginclude/stddef.h: #undef offsetof before #define. + +2022-10-06 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/107170 + * vr-values.cc (vr_values::range_of_expr): Do not die on + unsupported types. + +2022-10-06 Joseph Myers <joseph@codesourcery.com> + + * doc/invoke.texi (-fno-asm): Update description of effects on + typeof keyword. + +2022-10-06 Eric Botcazou <ebotcazou@adacore.com> + + * gimple-loop-jam.cc (tree_loop_unroll_and_jam): Bail out for a self + dependency that is a write-after-write if the access function is not + affine or constant. + +2022-10-06 Eric Botcazou <ebotcazou@adacore.com> + + * df-scan.cc (df_ref_create_structure): Minor cleanup. + +2022-10-06 Richard Biener <rguenther@suse.de> + + PR middle-end/107115 + * expr.cc (store_expr): Check mems_same_for_tbaa_p before + eliding a seemingly redundant store. + +2022-10-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/aarch64/atomics.md (*atomic_load<ALLX:mode>_zext<SD_HSDI:mode>): + New pattern. + +2022-10-06 Philipp Tomsich <philipp.tomsich@vrull.eu> + + * config/aarch64/aarch64-cores.def (AARCH64_CORE): Update + Ampere-1 core entry. + +2022-10-06 Philipp Tomsich <philipp.tomsich@vrull.eu> + + * config/aarch64/driver-aarch64.cc (readline): Fix off-by-one. + +2022-10-06 Richard Biener <rguenther@suse.de> + + PR tree-optimization/107107 + * tree-ssa-sccvn.cc (visit_reference_op_store): Do not + affect value-numbering when doing the tail merging + MODIFY_EXPR lookup. + +2022-10-06 Claudiu Zissulescu <claziss@synopsys.com> + + * config/arc/linux.h (LINK_SPEC): Remove max-page-size and + common-pave-size. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + PR c++/106654 + * internal-fn.def (ASSUME): New internal function. + * internal-fn.h (expand_ASSUME): Declare. + * internal-fn.cc (expand_ASSUME): Define. + * gimplify.cc (gimplify_call_expr): Gimplify IFN_ASSUME. + * fold-const.h (simple_condition_p): Declare. + * fold-const.cc (simple_operand_p_2): Rename to ... + (simple_condition_p): ... this. Remove forward declaration. + No longer static. Adjust function comment and fix a typo in it. + Adjust recursive call. + (simple_operand_p): Adjust function comment. + (fold_truth_andor): Adjust simple_operand_p_2 callers to call + simple_condition_p. + * doc/extend.texi: Document assume attribute. Move fallthrough + attribute example to its section. + +2022-10-06 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com> + + PR rtl-optimization/107088 + * cselib.cc (new_cselib_val): Skip BImode while keeping track of + subvalue relations. + +2022-10-06 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (frange::set): Call set_nan unconditionally. + (range_tests_nan): Adjust tests. + (range_tests_signed_zeros): Same. + (range_tests_floats): Same. + * value-range.h (frange::update_nan): Guard with HONOR_NANS. + (frange::set_nan): Set undefined if !HONOR_NANS. + +2022-10-06 Aldy Hernandez <aldyh@redhat.com> + + * range-op-float.cc (foperator_lt::fold_range): Remove extra check + to finite_operands_p. + (foperator_le::fold_range): Same. + (foperator_gt::fold_range): Same. + (foperator_ge::fold_range): Same. + +2022-10-06 Aldy Hernandez <aldyh@redhat.com> + + * value-range-pretty-print.cc (vrange_printer::print_real_value): + Avoid printing INF and NAN twice. + +2022-10-05 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/constraints.md (wD): Delete. + * doc/md.texi (Machine Constraints): Adjust. + +2022-10-05 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/vsx.md (vsx_extract_<mode>): Replace define_insn by a + define_expand. Split the contents to... + (*vsx_extract_<mode>_0): ... this. Rewrite. + (*vsx_extract_<mode>_1): ... and this. Rewrite. + +2022-10-05 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/vsx.md (*vsx_extract_<mode>_store): Use "n" instead of + "wD" constraint. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107060 + * doc/analyzer.texi (__analyzer_get_unknown_ptr): Document. + +2022-10-05 Ju-Zhe Zhong <juzhe.zhong@rivai.ai> + + * config.gcc: Add riscv_vector.h. + * config/riscv/riscv-builtins.cc: Add RVV builtin types support. + * config/riscv/riscv-c.cc (riscv_pragma_intrinsic): New function. + (riscv_register_pragmas): Ditto. + * config/riscv/riscv-protos.h (riscv_register_pragmas): Ditto. + (init_builtins): Move declaration from riscv-vector-builtins.h to riscv-protos.h. + (mangle_builtin_type): Ditto. + (verify_type_context): Ditto. + (handle_pragma_vector): New function. + * config/riscv/riscv-vector-builtins.cc (GTY): New variable. + (register_vector_type): New function. + (init_builtins): Add RVV builtin types support. + (handle_pragma_vector): New function. + * config/riscv/riscv-vector-builtins.h (GCC_RISCV_V_BUILTINS_H): Change + name according to file name. + (GCC_RISCV_VECTOR_BUILTINS_H): Ditto. + (init_builtins): Remove declaration in riscv-vector-builtins.h. + (mangle_builtin_type): Ditto. + (verify_type_context): Ditto. + * config/riscv/riscv.cc: Adjust for RVV builtin types support. + * config/riscv/riscv.h (REGISTER_TARGET_PRAGMAS): New macro. + * config/riscv/t-riscv: Remove redundant file including. + * config/riscv/riscv_vector.h: New file. + +2022-10-05 Aldy Hernandez <aldyh@redhat.com> + + * range-op.cc (operator_cast::fold_range): Handle truncating casts + for nonzero masks. + +2022-10-05 Martin Liska <mliska@suse.cz> + + PR c/107156 + * attribs.h (lookup_attribute_by_prefix): Support the attribute + starting with underscore (_Noreturn). + +2022-10-05 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/107052 + * gimple-range-op.cc (cfn_popcount::fold_range): Take into account + nonzero bit mask. + +2022-10-05 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/107052 + * range-op.cc (operator_cast::fold_range): Set nonzero mask. + +2022-10-05 Eric Botcazou <ebotcazou@adacore.com> + + PR tree-optimization/106698 + * pointer-query.cc (handle_array_ref): Fix handling of low bound. + +2022-10-05 Vineet Gupta <vineetg@rivosinc.com> + + * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): + Remove __riscv_cmodel_pic, that deprecated in last version. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107072 + * Makefile.in (ANALYZER_OBJS): Add analyzer/call-summary.o. + +2022-10-04 Jakub Jelinek <jakub@redhat.com> + + * attribs.h (remove_attribute): Declare overload with additional + attr_ns argument. + (private_lookup_attribute): Declare overload with additional + attr_ns and attr_ns_len arguments. + (lookup_attribute): New overload with additional attr_ns argument. + * attribs.cc (remove_attribute): New overload with additional + attr_ns argument. + (private_lookup_attribute): New overload with additional + attr_ns and attr_ns_len arguments. + +2022-10-04 Jakub Jelinek <jakub@redhat.com> + + * attribs.cc (handle_ignored_attributes_option, decl_attributes, + common_function_versions): Use auto_diagnostic_group. + +2022-10-04 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (irange::set_nonzero_bits): Remove assert. + +2022-10-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64.h (AARCH64_ISA_RCPC): New macro. + * config/aarch64/aarch64-arches.def (armv8.3-a): Include RCPC. + * config/aarch64/aarch64-cores.def (thunderx3t110, zeus, neoverse-v1) + (neoverse-512tvb, saphira): Remove RCPC from these Armv8.3-A+ cores. + * config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Define + __ARM_FEATURE_RCPC when appropriate. + +2022-10-04 Tobias Burnus <tobias@codesourcery.com> + + * doc/invoke.texi (-fopenmp): Mention C++ attribut syntax. + (-fopenmp-simd): Likewise; update permitted directives. + +2022-10-04 Tobias Burnus <tobias@codesourcery.com> + + * doc/install.texi (Specific): Add missing items to bullet list. + (amdgcn): Update LLVM requirements, use version not date for newlib. + (nvptx): Use version not git hash for newlib. + +2022-10-04 Aldy Hernandez <aldyh@redhat.com> + + * value-range-storage.cc (irange_storage_slot::set_irange): Remove + special case. + * value-range.cc (irange::irange_set): Adjust for nonzero mask + being a wide int. + (irange::irange_set_anti_range): Same. + (irange::set): Same. + (irange::verify_range): Same. + (irange::legacy_equal_p): Same. + (irange::operator==): Same. + (irange::contains_p): Same. + (irange::legacy_intersect): Same. + (irange::legacy_union): Same. + (irange::irange_single_pair_union): Call union_nonzero_bits. + (irange::irange_union): Same. + (irange::irange_intersect): Call intersect_nonzero_bits. + (irange::intersect): Adjust for nonzero mask being a wide int. + (irange::invert): Same. + (irange::set_nonzero_bits): Same. + (irange::get_nonzero_bits_from_range): New. + (irange::set_range_from_nonzero_bits): New. + (irange::get_nonzero_bits): Adjust for nonzero mask being a wide + int. + (irange::intersect_nonzero_bits): Same. + (irange::union_nonzero_bits): Same. + (range_tests_nonzero_bits): Remove test. + * value-range.h (irange::varying_compatible_p): Adjust for nonzero + mask being a wide int. + (gt_ggc_mx): Same. + (gt_pch_nx): Same. + (irange::set_undefined): Same. + (irange::set_varying): Same. + (irange::normalize_kind): Same. + +2022-10-04 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/107130 + * gimple-range-op.cc (class cfn_popcount): Call op_cfn_ffs. + (class cfn_ffs): New. + (gimple_range_op_handler::maybe_builtin_call): Separate out + CASE_CFN_FFS into its own case. + 2022-10-03 Sergei Trofimovich <siarheit@google.com> * config/i386/t-i386: Add build-time dependencies against diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 59c7fe2..ab0c096 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20221004 +20221008 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index c1d0438..f672e6e 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1255,6 +1255,7 @@ ANALYZER_OBJS = \ analyzer/bar-chart.o \ analyzer/call-info.o \ analyzer/call-string.o \ + analyzer/call-summary.o \ analyzer/checker-path.o \ analyzer/complexity.o \ analyzer/constraint-manager.o \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index be8371d..fc3bc97 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,150 @@ +2022-10-06 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/ada-tree.def (LOAD_EXPR): New expression code. + * gcc-interface/gigi.h (build_storage_model_load): Declare. + (build_storage_model_store): Likewise. + (instantiate_load_in_expr): Likewise. + (INSTANTIATE_LOAD_IN_EXPR): New macro. + (instantiate_load_in_array_ref): Declare. + * gcc-interface/decl.cc (gnat_to_gnu_entity) <E_Record_Type>: Set a + fake discriminant number on the fields of the template type. + (gnat_to_gnu_field): Use integer for DECL_DISCRIMINANT_NUMBER. + * gcc-interface/misc.cc (gnat_init_ts): Mark LOAD_EXPR as typed. + * gcc-interface/trans.cc (fold_constant_decl_in_expr) <ARRAY_REF>: + Also preserve the 4th operand. + (Attribute_to_gnu): Deal with LOAD_EXPR of unconstrained array type. + <Attr_Size>: Call INSTANTIATE_LOAD_IN_EXPR for a storage model. + <Attr_Length>: Likewise. + <Attr_Bit_Position>: Likewise. + (get_storage_model): New function. + (get_storage_model_access): Likewise. + (storage_model_access_required_p): Likewise. + (Call_to_gnu): Add GNAT_STORAGE_MODEL parameter and deal with it. + Also deal with actual parameters that have a storage model. + (gnat_to_gnu) <N_Object_Declaratio>: Adjust call to Call_to_gnu. + <N_Explicit_Dereference>: Deal with a storage model access. + <N_Indexed_Component>: Likewise. + <N_Slice>: Likewise. + <N_Selected_Component>: Likewise. + <N_Assignment_Statement>: Adjust call to Call_to_gnu. Deal with a + storage model access either on the LHS, on the RHS or on both. + <N_Function_Cal>: Adjust call to Call_to_gnu. + <N_Free_Statement>: Deal with a pool that is a storage model. + Replace test for UNCONSTRAINED_ARRAY_REF with test on the type. + (gnat_gimplify_expr) <CALL_EXPR>: Tidy up. + <LOAD_EXPR>: New case. + <UNCONSTRAINED_ARRAY_REF>: Move down. + * gcc-interface/utils.cc (maybe_unconstrained_array): Deal with a + LOAD_EXPR by recursing on its first operand. + * gcc-interface/utils2.cc (build_allocator): Deal with a pool that + is a storage model. + (build_storage_model_copy): New function. + (build_storage_model_load): Likewise. + (build_storage_model_store): Likewise. + (instantiate_load_in_expr): Likewise. + (instantiate_load_in_array_ref): Likewise. + (gnat_rewrite_reference) <ARRAY_REF>: Also preserve the 4th operand. + (get_inner_constant_reference) <ARRAY_REF>: Remove useless test. + (gnat_invariant_expr) <ARRAY_REF>: Rewrite test. + +2022-10-06 Steve Baird <baird@adacore.com> + + * sem_ch6.adb + (Analyze_Procedure_Call): Replace "return;" with "goto Leave;", as + per comment preceding body of Analyze_Procedure_Call. + +2022-10-06 Piotr Trojanek <trojanek@adacore.com> + + * sem_ch9.adb (Allows_Lock_Free_Implementation): Reject + conditional goto statements. + +2022-10-06 Piotr Trojanek <trojanek@adacore.com> + + * doc/gnat_rm/implementation_defined_pragmas.rst + (Lock_Free): Remove inconsistent periods that end item + descriptions. + * sem_ch9.adb + (Allows_Lock_Free_Implementation): Remove unnecessary guard + against an empty list of parameters; replace low-level entity kind + membership test with a high-level query; refill error message. + * gnat_rm.texi: Regenerate. + +2022-10-06 Alexandre Oliva <oliva@adacore.com> + + * doc/gnat_rm/security_hardening_features.rst: Add examples of + codegen changes in hardened conditionals. + * gnat_rm.texi: Regenerate. + +2022-10-06 Alexandre Oliva <oliva@adacore.com> + + * doc/gnat_rm/security_hardening_features.rst: Add examples of + codegen changes in hardened booleans. Mention that C traps where + Ada raises exceptions. + * gnat_rm.texi: Regenerate. + +2022-10-06 Alexandre Oliva <oliva@adacore.com> + + * doc/gnat_rm/security_hardening_features.rst: Add examples of + codegen changes in stack scrubbing. + * gnat_rm.texi: Regenerate. + +2022-10-06 Piotr Trojanek <trojanek@adacore.com> + + * exp_ch9.adb (Build_Lock_Free_Protected_Subprogram_Body): Replace + shallow copy of protected statements with a deep copy. + +2022-10-06 Marc Poulhiès <poulhies@adacore.com> + + * fe.h (Has_Storage_Model_Type_Aspect) + (Has_Designated_Storage_Model_Aspect, Storage_Model_Object) + (Storage_Model_Copy_From, Storage_Model_Copy_To): Add + declarations. + * sem_util.ads: Add WARNING markers for functions for which a new + C declaration has been added in fe.h + +2022-10-06 Steve Baird <baird@adacore.com> + + * exp_util.adb + (Get_Current_Value_Condition): Treat references occurring within + the condition of an if statement, an elsif, or a while loop in the + same way as references that occur before the start of that + enclosing construct. + +2022-10-06 Gary Dismukes <dismukes@adacore.com> + + * sem_ch4.adb (Analyze_Call): Add test of Comes_From_Source on the + enclosing subprogram's Entity_Id for determining whether to + perform the compile-time accessibility check on actuals passed to + aliased formals in a function call occurring within a return + statement. That test excludes cases where the call occurs within + the return statement of a Pre'Class wrapper function. + +2022-10-06 Bob Duff <duff@adacore.com> + + * exp_ch5.adb + (Expand_Assign_Array_Loop_Or_Bitfield): Minor cleanups. + +2022-10-06 Yannick Moy <moy@adacore.com> + + * sem_prag.adb (Analyze_Pragma): Ignore one variant of pragma + Warnings in GNATprove mode. + +2022-10-06 Bob Duff <duff@adacore.com> + + * exp_ch5.adb + (Expand_Assign_Array_Loop_Or_Bitfield): Disable the + Fast_Copy_Bitfield optimization in certain cases. + +2022-10-06 Piotr Trojanek <trojanek@adacore.com> + + * sem_prag.adb + (Sig_Pragma): Change flag for pragma Refined_State to mean "not + significant"; this is primarily for documentation, because the + exact value of the flag is not really taken into account for + Refined_State. + (Is_Non_Significant_Pragma_Reference): Add special handling for + pragma Refined_State. + 2022-09-29 Ronan Desplanques <desplanques@adacore.com> * einfo.ads: remove documentation duplicate diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst index 53836c9..6752d48 100644 --- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst +++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst @@ -3744,10 +3744,10 @@ In addition, each protected subprogram body must satisfy: * May reference only one protected component * May not reference nonconstant entities outside the protected subprogram - scope. + scope * May not contain address representation items, allocators, or quantified - expressions. -* May not contain delay, goto, loop, or procedure-call statements. + expressions +* May not contain delay, goto, loop, or procedure-call statements * May not contain exported and imported entities * May not dereferenced access values * Function calls and attribute references must be static diff --git a/gcc/ada/doc/gnat_rm/security_hardening_features.rst b/gcc/ada/doc/gnat_rm/security_hardening_features.rst index f5fdc8e..d7c02b9 100644 --- a/gcc/ada/doc/gnat_rm/security_hardening_features.rst +++ b/gcc/ada/doc/gnat_rm/security_hardening_features.rst @@ -74,6 +74,58 @@ or a variable.) -- scrubbing of the stack space used by that subprogram. +Given these declarations, Foo has its type and body modified as +follows: + +.. code-block:: ada + + function Foo (<WaterMark> : in out System.Address) returns Integer + is + -- ... + begin + <__strub_update> (<WaterMark>); -- Updates the stack WaterMark. + -- ... + end; + + +whereas its callers are modified from: + +.. code-block:: ada + + X := Foo; + +to: + +.. code-block:: ada + + declare + <WaterMark> : System.Address; + begin + <__strub_enter> (<WaterMark>); -- Initialize <WaterMark>. + X := Foo (<WaterMark>); + <__strub_leave> (<WaterMark>); -- Scrubs stack up to <WaterMark>. + end; + + +As for Bar, because it is strubbed in internal mode, its callers are +not modified. Its definition is modified roughly as follows: + +.. code-block:: ada + + procedure Bar is + <WaterMark> : System.Address; + procedure Strubbed_Bar (<WaterMark> : in out System.Address) is + begin + <__strub_update> (<WaterMark>); -- Updates the stack WaterMark. + -- original Bar body. + end Strubbed_Bar; + begin + <__strub_enter> (<WaterMark>); -- Initialize <WaterMark>. + Strubbed_Bar (<WaterMark>); + <__strub_leave> (<WaterMark>); -- Scrubs stack up to <WaterMark>. + end Bar; + + There are also :switch:`-fstrub={choice}` command-line options to control default settings. For usage and more details on the command-line options, on the ``strub`` attribute, and their use with @@ -151,11 +203,58 @@ activated by a separate command-line option. The option :switch:`-fharden-compares` enables hardening of compares that compute results stored in variables, adding verification that the -reversed compare yields the opposite result. +reversed compare yields the opposite result, turning: + +.. code-block:: ada + + B := X = Y; + + +into: + +.. code-block:: ada + + B := X = Y; + declare + NotB : Boolean := X /= Y; -- Computed independently of B. + begin + if B = NotB then + <__builtin_trap>; + end if; + end; + The option :switch:`-fharden-conditional-branches` enables hardening of compares that guard conditional branches, adding verification of -the reversed compare to both execution paths. +the reversed compare to both execution paths, turning: + +.. code-block:: ada + + if X = Y then + X := Z + 1; + else + Y := Z - 1; + end if; + + +into: + +.. code-block:: ada + + if X = Y then + if X /= Y then -- Computed independently of X = Y. + <__builtin_trap>; + end if; + X := Z + 1; + else + if X /= Y then -- Computed independently of X = Y. + null; + else + <__builtin_trap>; + end if; + Y := Z - 1; + end if; + These transformations are introduced late in the compilation pipeline, long after boolean expressions are decomposed into separate compares, @@ -213,19 +312,40 @@ further remove checks found to be redundant. For additional hardening, the ``hardbool`` :samp:`Machine_Attribute` pragma can be used to annotate boolean types with representation clauses, so that expressions of such types used as conditions are -checked even when compiling with :switch:`-gnatVT`. +checked even when compiling with :switch:`-gnatVT`: .. code-block:: ada pragma Machine_Attribute (HBool, "hardbool"); + function To_Boolean (X : HBool) returns Boolean is (Boolean (X)); + + +is compiled roughly like: + +.. code-block:: ada + + function To_Boolean (X : HBool) returns Boolean is + begin + if X not in True | False then + raise Constraint_Error; + elsif X in True then + return True; + else + return False; + end if; + end To_Boolean; + Note that :switch:`-gnatVn` will disable even ``hardbool`` testing. Analogous behavior is available as a GCC extension to the C and -Objective C programming languages, through the ``hardbool`` attribute. -For usage and more details on that attribute, see :title:`Using the -GNU Compiler Collection (GCC)`. +Objective C programming languages, through the ``hardbool`` attribute, +with the difference that, instead of raising a Constraint_Error +exception, when a hardened boolean variable is found to hold a value +that stands for neither True nor False, the program traps. For usage +and more details on that attribute, see :title:`Using the GNU Compiler +Collection (GCC)`. .. Control Flow Redundancy: diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 209741c..d5d66d9 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -1632,7 +1632,10 @@ package body Exp_Ch5 is end if; if Is_Array_Type (Typ) then - return Volatile_Or_Independent (Empty, Component_Type (Typ)); + if Volatile_Or_Independent (Empty, Component_Type (Typ)) then + return True; + end if; + elsif Is_Record_Type (Typ) then declare Comp : Entity_Id := First_Component (Typ); @@ -1660,6 +1663,15 @@ package body Exp_Ch5 is return False; end Volatile_Or_Independent; + function Slice_Of_Packed_Component (L : Node_Id) return Boolean is + (Nkind (L) = N_Slice + and then Nkind (Prefix (L)) = N_Indexed_Component + and then Is_Bit_Packed_Array (Etype (Prefix (Prefix (L))))); + -- L is the left-hand side Name. Returns True if L is a slice of a + -- component of a bit-packed array. The optimization is disabled in + -- that case, because Expand_Assign_Array_Bitfield_Fast cannot + -- currently handle that case correctly. + L : constant Node_Id := Name (N); R : constant Node_Id := Expression (N); -- Left- and right-hand sides of the assignment statement @@ -1679,8 +1691,8 @@ package body Exp_Ch5 is and then Is_Bit_Packed_Array (R_Type) and then not Reverse_Storage_Order (L_Type) and then not Reverse_Storage_Order (R_Type) - and then Ndim = 1 and then Slices + and then not Slice_Of_Packed_Component (L) and then not Volatile_Or_Independent (L, L_Type) and then not Volatile_Or_Independent (R, R_Type) then diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index 8abff55..decf617 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -2797,7 +2797,7 @@ package body Exp_Ch9 is Expected_Comp : Entity_Id; Stmt : Node_Id; Stmts : List_Id := - New_Copy_List (Statements (Hand_Stmt_Seq)); + New_Copy_List_Tree (Statements (Hand_Stmt_Seq)); Typ_Size : Int; Unsigned : Entity_Id; diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 61395ad..f569d2e 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -6923,6 +6923,11 @@ package body Exp_Util is if Loc < Sloc (CV) then return; + -- In condition of IF statement + + elsif In_Subtree (N => Var, Root => Condition (CV)) then + return; + -- After end of IF statement elsif Loc >= Sloc (CV) + Text_Ptr (UI_To_Int (End_Span (CV))) then @@ -7009,7 +7014,12 @@ package body Exp_Util is if Loc < Sloc (CV) then return; - -- After end of IF statement + -- In condition of ELSIF part + + elsif In_Subtree (N => Var, Root => Condition (CV)) then + return; + + -- After end of IF statement elsif Loc >= Sloc (Stm) + Text_Ptr (UI_To_Int (End_Span (Stm))) @@ -7066,6 +7076,11 @@ package body Exp_Util is if Loc < Sloc (Loop_Stmt) then return; + -- In condition of while loop + + elsif In_Subtree (N => Var, Root => Condition (CV)) then + return; + -- After end of LOOP statement elsif Loc >= Sloc (End_Label (Loop_Stmt)) then diff --git a/gcc/ada/fe.h b/gcc/ada/fe.h index 02cf105..79a1b58 100644 --- a/gcc/ada/fe.h +++ b/gcc/ada/fe.h @@ -304,17 +304,27 @@ extern Boolean Compile_Time_Known_Value (Node_Id); #define Defining_Entity sem_util__defining_entity #define First_Actual sem_util__first_actual +#define Has_Storage_Model_Type_Aspect sem_util__storage_model_support__has_storage_model_type_aspect +#define Has_Designated_Storage_Model_Aspect sem_util__storage_model_support__has_designated_storage_model_aspect #define Is_Expression_Function sem_util__is_expression_function #define Is_Variable_Size_Record sem_util__is_variable_size_record #define Needs_Secondary_Stack sem_util__needs_secondary_stack #define Next_Actual sem_util__next_actual +#define Storage_Model_Object sem_util__storage_model_support__storage_model_object +#define Storage_Model_Copy_From sem_util__storage_model_support__storage_model_copy_from +#define Storage_Model_Copy_To sem_util__storage_model_support__storage_model_copy_to extern Entity_Id Defining_Entity (Node_Id); extern Node_Id First_Actual (Node_Id); +extern Boolean Has_Storage_Model_Type_Aspect (Entity_Id); +extern Boolean Has_Designated_Storage_Model_Aspect (Entity_Id); extern Boolean Is_Expression_Function (Entity_Id); extern Boolean Is_Variable_Size_Record (Entity_Id); extern Boolean Needs_Secondary_Stack (Entity_Id); extern Node_Id Next_Actual (Node_Id); +extern Entity_Id Storage_Model_Object (Entity_Id); +extern Entity_Id Storage_Model_Copy_From (Entity_Id); +extern Entity_Id Storage_Model_Copy_To (Entity_Id); /* sinfo: */ diff --git a/gcc/ada/gcc-interface/ada-tree.def b/gcc/ada/gcc-interface/ada-tree.def index 8eb4688..7fc95cb 100644 --- a/gcc/ada/gcc-interface/ada-tree.def +++ b/gcc/ada/gcc-interface/ada-tree.def @@ -35,6 +35,10 @@ DEFTREECODE (UNCONSTRAINED_ARRAY_TYPE, "unconstrained_array_type", tcc_type, 0) DEFTREECODE (UNCONSTRAINED_ARRAY_REF, "unconstrained_array_ref", tcc_reference, 1) +/* Same as SAVE_EXPR, but operand 1 contains the statement used to initialize + the temporary instead of using the value of operand 0 directly. */ +DEFTREECODE (LOAD_EXPR, "load_expr", tcc_expression, 2) + /* An expression that returns an RTL suitable for its type. Operand 0 is an expression to be evaluated for side effects only. */ DEFTREECODE (NULL_EXPR, "null_expr", tcc_expression, 1) diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc index c5a93fb..f8c7698 100644 --- a/gcc/ada/gcc-interface/decl.cc +++ b/gcc/ada/gcc-interface/decl.cc @@ -2279,6 +2279,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) gnu_index_type, gnu_template_type, NULL_TREE, NULL_TREE, 0, 0); + /* Mark the field specifically for INSTANTIATE_LOAD_IN_EXPR. */ + DECL_DISCRIMINANT_NUMBER (gnu_lb_field) = integer_minus_one_node; Sloc_to_locus (Sloc (gnat_entity), &DECL_SOURCE_LOCATION (gnu_lb_field)); @@ -2287,6 +2289,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) gnu_index_type, gnu_template_type, NULL_TREE, NULL_TREE, 0, 0); + /* Mark the field specifically for INSTANTIATE_LOAD_IN_EXPR. */ + DECL_DISCRIMINANT_NUMBER (gnu_hb_field) = integer_minus_one_node; Sloc_to_locus (Sloc (gnat_entity), &DECL_SOURCE_LOCATION (gnu_hb_field)); @@ -7694,7 +7698,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, if (Ekind (gnat_field) == E_Discriminant) { DECL_DISCRIMINANT_NUMBER (gnu_field) - = UI_To_gnu (Discriminant_Number (gnat_field), sizetype); + = UI_To_gnu (Discriminant_Number (gnat_field), integer_type_node); DECL_INVARIANT_P (gnu_field) = No (Discriminant_Default_Value (gnat_field)); DECL_NONADDRESSABLE_P (gnu_field) = 0; diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index 1c1397a..82e2403 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -912,6 +912,34 @@ extern tree build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc, Entity_Id gnat_pool, Node_Id gnat_node, bool); +/* Build a load of SRC using the storage model of GNAT_SMO. */ +extern tree build_storage_model_load (Entity_Id gnat_smo, tree src); + +/* Build a load of SRC into DEST using the storage model of GNAT_SMO. + If SIZE is specified, use it, otherwise use the size of SRC. */ +extern tree build_storage_model_load (Entity_Id gnat_smo, tree dest, tree src, + tree size = NULL_TREE); + +/* Build a store of SRC into DEST using the storage model of GNAT_SMO. + If SIZE is specified, use it, otherwise use the size of DEST. */ +extern tree build_storage_model_store (Entity_Id gnat_smo, tree dest, tree src, + tree size = NULL_TREE); + +/* Given a tree EXP, instantiate occurrences of LOAD_EXPR in it and associate + them with the storage model of GNAT_SMO. */ +extern tree instantiate_load_in_expr (tree exp, Entity_Id gnat_smo); + +/* This macro calls the above function but short-circuits the common + case of a constant to save time and also checks for NULL. */ + +#define INSTANTIATE_LOAD_IN_EXPR(EXP, GNAT_SMO) \ + ((EXP) == NULL_TREE || TREE_CONSTANT (EXP) ? (EXP) \ + : instantiate_load_in_expr (EXP, GNAT_SMO)) + +/* Given an array or slice reference, instantiate occurrences of LOAD_EXPR in + it and associate them with the storage model of GNAT_SMO. */ +extern void instantiate_load_in_array_ref (tree ref, Entity_Id gnat_smo); + /* Indicate that we need to take the address of T and that it therefore should not be allocated in a register. Returns true if successful. */ extern bool gnat_mark_addressable (tree t); diff --git a/gcc/ada/gcc-interface/misc.cc b/gcc/ada/gcc-interface/misc.cc index f0ca197..e1b5a43 100644 --- a/gcc/ada/gcc-interface/misc.cc +++ b/gcc/ada/gcc-interface/misc.cc @@ -1309,6 +1309,7 @@ gnat_init_ts (void) MARK_TS_COMMON (UNCONSTRAINED_ARRAY_TYPE); MARK_TS_TYPED (UNCONSTRAINED_ARRAY_REF); + MARK_TS_TYPED (LOAD_EXPR); MARK_TS_TYPED (NULL_EXPR); MARK_TS_TYPED (PLUS_NOMOD_EXPR); MARK_TS_TYPED (MINUS_NOMOD_EXPR); diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc index 2d93947..d0ff741 100644 --- a/gcc/ada/gcc-interface/trans.cc +++ b/gcc/ada/gcc-interface/trans.cc @@ -1033,7 +1033,7 @@ fold_constant_decl_in_expr (tree exp) return exp; return fold (build4 (code, TREE_TYPE (exp), op0, TREE_OPERAND (exp, 1), - TREE_OPERAND (exp, 2), NULL_TREE)); + TREE_OPERAND (exp, 2), TREE_OPERAND (exp, 3))); case REALPART_EXPR: case IMAGPART_EXPR: @@ -1671,6 +1671,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) tree gnu_type = TREE_TYPE (gnu_prefix); tree gnu_expr, gnu_result_type, gnu_result = error_mark_node; bool prefix_unused = false; + Entity_Id gnat_smo; /* If the input is a NULL_EXPR, make a new one. */ if (TREE_CODE (gnu_prefix) == NULL_EXPR) @@ -1680,6 +1681,14 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) return build1 (NULL_EXPR, gnu_result_type, TREE_OPERAND (gnu_prefix, 0)); } + /* If the input is a LOAD_EXPR of an unconstrained array type, the second + operand contains the storage model object. */ + if (TREE_CODE (gnu_prefix) == LOAD_EXPR + && TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE) + gnat_smo = tree_to_shwi (TREE_OPERAND (gnu_prefix, 1)); + else + gnat_smo = Empty; + switch (attribute) { case Attr_Pred: @@ -1960,7 +1969,11 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) /* Deal with a self-referential size by qualifying the size with the object or returning the maximum size for a type. */ if (TREE_CODE (gnu_prefix) != TYPE_DECL) - gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result, gnu_prefix); + { + gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result, gnu_prefix); + if (Present (gnat_smo)) + gnu_result = INSTANTIATE_LOAD_IN_EXPR (gnu_result, gnat_smo); + } else if (CONTAINS_PLACEHOLDER_P (gnu_result)) gnu_result = max_size (gnu_result, true); @@ -2191,6 +2204,8 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) handling. Note that these attributes could not have been used on an unconstrained array type. */ gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result, gnu_prefix); + if (Present (gnat_smo)) + gnu_result = INSTANTIATE_LOAD_IN_EXPR (gnu_result, gnat_smo); /* Cache the expression we have just computed. Since we want to do it at run time, we force the use of a SAVE_EXPR and let the gimplifier @@ -2351,6 +2366,8 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) /* If this has a PLACEHOLDER_EXPR, qualify it by the object we are handling. */ gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result, gnu_prefix); + if (Present (gnat_smo)) + gnu_result = INSTANTIATE_LOAD_IN_EXPR (gnu_result, gnat_smo); break; } @@ -4356,6 +4373,49 @@ simple_atomic_access_required_p (Node_Id gnat_node, bool *sync) return type == SIMPLE_ATOMIC; } +/* Return the storage model specified by GNAT_NODE, or else Empty. */ + +static Entity_Id +get_storage_model (Node_Id gnat_node) +{ + if (Nkind (gnat_node) == N_Explicit_Dereference + && Has_Designated_Storage_Model_Aspect (Etype (Prefix (gnat_node)))) + return Storage_Model_Object (Etype (Prefix (gnat_node))); + else + return Empty; +} + +/* Compute whether GNAT_NODE requires storage model access and set GNAT_SMO to + the storage model object to be used for it if it does, or else Empty. */ + +static void +get_storage_model_access (Node_Id gnat_node, Entity_Id *gnat_smo) +{ + const Node_Id gnat_parent = Parent (gnat_node); + + /* If we are the prefix of the parent, then the access is above us. */ + if (node_is_component (gnat_parent) && Prefix (gnat_parent) == gnat_node) + { + *gnat_smo = Empty; + return; + } + + while (node_is_component (gnat_node)) + gnat_node = Prefix (gnat_node); + + *gnat_smo = get_storage_model (gnat_node); +} + +/* Return true if GNAT_NODE requires storage model access and, if so, set + GNAT_SMO to the storage model object to be used for it. */ + +static bool +storage_model_access_required_p (Node_Id gnat_node, Entity_Id *gnat_smo) +{ + get_storage_model_access (gnat_node, gnat_smo); + return Present (*gnat_smo); +} + /* Create a temporary variable with PREFIX and TYPE, and return it. */ static tree @@ -4471,11 +4531,14 @@ elaborate_profile (Entity_Id first_formal, Entity_Id result_type) N_Assignment_Statement and the result is to be placed into that object. ATOMIC_ACCESS is the type of atomic access to be used for the assignment to GNU_TARGET. If, in addition, ATOMIC_SYNC is true, then the assignment - to GNU_TARGET requires atomic synchronization. */ + to GNU_TARGET requires atomic synchronization. GNAT_STORAGE_MODEL is the + storage model object to be used for the assignment to GNU_TARGET or Empty + if there is none. */ static tree Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, - atomic_acces_t atomic_access, bool atomic_sync) + atomic_acces_t atomic_access, bool atomic_sync, + Entity_Id gnat_storage_model) { const bool function_call = (Nkind (gnat_node) == N_Function_Call); const bool returning_value = (function_call && !gnu_target); @@ -4507,6 +4570,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, Node_Id gnat_actual; atomic_acces_t aa_type; bool aa_sync; + Entity_Id gnat_smo; /* The only way we can make a call via an access type is if GNAT_NAME is an explicit dereference. In that case, get the list of formal args from the @@ -4624,7 +4688,9 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, unconstrained record type with default discriminant, because the return may copy more data than the bit-field can contain. - 5. There is no target and we have misaligned In Out or Out parameters + 5. There is a target which needs to be accessed with a storage model. + + 6. There is no target and we have misaligned In Out or Out parameters passed by reference, because we need to preserve the return value before copying back the parameters. However, in this case, we'll defer creating the temporary, see below. @@ -4654,7 +4720,10 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, && DECL_BIT_FIELD (TREE_OPERAND (gnu_target, 1)) && DECL_SIZE (TREE_OPERAND (gnu_target, 1)) != TYPE_SIZE (TREE_TYPE (gnu_target)) - && type_is_padding_self_referential (gnu_result_type)))) + && type_is_padding_self_referential (gnu_result_type)) + || (gnu_target + && Present (gnat_storage_model) + && Present (Storage_Model_Copy_To (gnat_storage_model))))) { gnu_retval = create_temporary ("R", gnu_result_type); DECL_RETURN_VALUE_P (gnu_retval) = 1; @@ -4725,12 +4794,19 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, = build_compound_expr (TREE_TYPE (gnu_name), init, gnu_name); } - /* If we are passing a non-addressable parameter by reference, pass the - address of a copy. In the In Out or Out case, set up to copy back - out after the call. */ + get_storage_model_access (gnat_actual, &gnat_smo); + + /* If we are passing a non-addressable actual parameter by reference, + pass the address of a copy. Likewise if it needs to be accessed with + a storage model. In the In Out or Out case, set up to copy back out + after the call. */ if (is_by_ref_formal_parm && (gnu_name_type = gnat_to_gnu_type (Etype (gnat_name))) - && !addressable_p (gnu_name, gnu_name_type)) + && (!addressable_p (gnu_name, gnu_name_type) + || (Present (gnat_smo) + && (Present (Storage_Model_Copy_From (gnat_smo)) + || (!in_param + && Present (Storage_Model_Copy_To (gnat_smo))))))) { tree gnu_orig = gnu_name, gnu_temp, gnu_stmt; @@ -4801,20 +4877,40 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, } /* Create an explicit temporary holding the copy. */ + tree gnu_temp_type; + if (Nkind (gnat_actual) == N_Explicit_Dereference + && Present (Actual_Designated_Subtype (gnat_actual))) + gnu_temp_type + = gnat_to_gnu_type (Actual_Designated_Subtype (gnat_actual)); + else + gnu_temp_type = TREE_TYPE (gnu_name); + /* Do not initialize it for the _Init parameter of an initialization procedure since no data is meant to be passed in. */ if (Ekind (gnat_formal) == E_Out_Parameter && Is_Entity_Name (gnat_subprog) && Is_Init_Proc (Entity (gnat_subprog))) - gnu_name = gnu_temp = create_temporary ("A", TREE_TYPE (gnu_name)); + gnu_name = gnu_temp = create_temporary ("A", gnu_temp_type); /* Initialize it on the fly like for an implicit temporary in the other cases, as we don't necessarily have a statement list. */ else { - gnu_temp = create_init_temporary ("A", gnu_name, &gnu_stmt, - gnat_actual); - gnu_name = build_compound_expr (TREE_TYPE (gnu_name), gnu_stmt, + if (Present (gnat_smo) + && Present (Storage_Model_Copy_From (gnat_smo))) + { + gnu_temp = create_temporary ("A", gnu_temp_type); + gnu_stmt + = build_storage_model_load (gnat_smo, gnu_temp, + gnu_name, + TYPE_SIZE_UNIT (gnu_temp_type)); + set_expr_location_from_node (gnu_stmt, gnat_actual); + } + else + gnu_temp = create_init_temporary ("A", gnu_name, &gnu_stmt, + gnat_actual); + + gnu_name = build_compound_expr (gnu_temp_type, gnu_stmt, gnu_temp); } @@ -4830,8 +4926,16 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, (TREE_OPERAND (TREE_OPERAND (gnu_orig, 1), 1))) gnu_orig = TREE_OPERAND (gnu_orig, 2); - gnu_stmt - = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_orig, gnu_temp); + if (Present (gnat_smo) + && Present (Storage_Model_Copy_To (gnat_smo))) + gnu_stmt + = build_storage_model_store (gnat_smo, gnu_orig, + gnu_temp, + TYPE_SIZE_UNIT (gnu_temp_type)); + else + gnu_stmt + = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_orig, + gnu_temp); set_expr_location_from_node (gnu_stmt, gnat_node); append_to_statement_list (gnu_stmt, &gnu_after_list); @@ -4842,12 +4946,19 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, tree gnu_actual = gnu_name; /* If atomic access is required for an In or In Out actual parameter, - build the atomic load. */ + build the atomic load. Or else, if storage model access is required, + build the special load. */ if (is_true_formal_parm && !is_by_ref_formal_parm - && Ekind (gnat_formal) != E_Out_Parameter - && simple_atomic_access_required_p (gnat_actual, &aa_sync)) - gnu_actual = build_atomic_load (gnu_actual, aa_sync); + && Ekind (gnat_formal) != E_Out_Parameter) + { + if (simple_atomic_access_required_p (gnat_actual, &aa_sync)) + gnu_actual = build_atomic_load (gnu_actual, aa_sync); + + else if (Present (gnat_smo) + && Present (Storage_Model_Copy_From (gnat_smo))) + gnu_actual = build_storage_model_load (gnat_smo, gnu_actual); + } /* If this was a procedure call, we may not have removed any padding. So do it here for the part we will use as an input, if any. */ @@ -5211,6 +5322,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, } get_atomic_access (gnat_actual, &aa_type, &aa_sync); + get_storage_model_access (gnat_actual, &gnat_smo); /* If an outer atomic access is required for an actual parameter, build the load-modify-store sequence. */ @@ -5224,6 +5336,13 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, gnu_result = build_atomic_store (gnu_actual, gnu_result, aa_sync); + /* Or else, if a storage model access is required, build the special + store. */ + else if (Present (gnat_smo) + && Present (Storage_Model_Copy_To (gnat_smo))) + gnu_result + = build_storage_model_store (gnat_smo, gnu_actual, gnu_result); + /* Otherwise build a regular assignment. */ else gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE, @@ -5298,6 +5417,11 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, = build_load_modify_store (gnu_target, gnu_call, gnat_node); else if (atomic_access == SIMPLE_ATOMIC) gnu_call = build_atomic_store (gnu_target, gnu_call, atomic_sync); + else if (Present (gnat_storage_model) + && Present (Storage_Model_Copy_To (gnat_storage_model))) + gnu_call + = build_storage_model_store (gnat_storage_model, gnu_target, + gnu_call); else gnu_call = build_binary_op (op_code, NULL_TREE, gnu_target, gnu_call); @@ -6104,6 +6228,7 @@ gnat_to_gnu (Node_Id gnat_node) atomic_acces_t aa_type; bool went_into_elab_proc; bool aa_sync; + Entity_Id gnat_smo; /* Save node number for error message and set location information. */ if (Sloc (gnat_node) > No_Location) @@ -6376,7 +6501,7 @@ gnat_to_gnu (Node_Id gnat_node) gnu_result = Call_to_gnu (Prefix (Expression (gnat_node)), &gnu_result_type, gnu_result, - NOT_ATOMIC, false); + NOT_ATOMIC, false, Empty); break; } @@ -6522,15 +6647,25 @@ gnat_to_gnu (Node_Id gnat_node) if (simple_atomic_access_required_p (gnat_node, &aa_sync) && !present_in_lhs_or_actual_p (gnat_node)) gnu_result = build_atomic_load (gnu_result, aa_sync); + + /* If storage model access is required on the RHS, build the load. */ + else if (storage_model_access_required_p (gnat_node, &gnat_smo) + && Present (Storage_Model_Copy_From (gnat_smo)) + && !present_in_lhs_or_actual_p (gnat_node)) + gnu_result = build_storage_model_load (gnat_smo, gnu_result); break; case N_Indexed_Component: { - tree gnu_array_object = gnat_to_gnu ((Prefix (gnat_node))); + const Entity_Id gnat_array_object = Prefix (gnat_node); + tree gnu_array_object = gnat_to_gnu (gnat_array_object); tree gnu_type; int ndim, i; Node_Id *gnat_expr_array; + /* Get the storage model of the array. */ + gnat_smo = get_storage_model (gnat_array_object); + gnu_array_object = maybe_padded_object (gnu_array_object); gnu_array_object = maybe_unconstrained_array (gnu_array_object); @@ -6582,6 +6717,9 @@ gnat_to_gnu (Node_Id gnat_node) gnu_result = build_binary_op (ARRAY_REF, NULL_TREE, gnu_result, gnu_expr); + + if (Present (gnat_smo)) + instantiate_load_in_array_ref (gnu_result, gnat_smo); } gnu_result_type = get_unpadded_type (Etype (gnat_node)); @@ -6590,18 +6728,28 @@ gnat_to_gnu (Node_Id gnat_node) if (simple_atomic_access_required_p (gnat_node, &aa_sync) && !present_in_lhs_or_actual_p (gnat_node)) gnu_result = build_atomic_load (gnu_result, aa_sync); + + /* If storage model access is required on the RHS, build the load. */ + else if (storage_model_access_required_p (gnat_node, &gnat_smo) + && Present (Storage_Model_Copy_From (gnat_smo)) + && !present_in_lhs_or_actual_p (gnat_node)) + gnu_result = build_storage_model_load (gnat_smo, gnu_result); } break; case N_Slice: { - tree gnu_array_object = gnat_to_gnu (Prefix (gnat_node)); + const Entity_Id gnat_array_object = Prefix (gnat_node); + tree gnu_array_object = gnat_to_gnu (gnat_array_object); - gnu_result_type = get_unpadded_type (Etype (gnat_node)); + /* Get the storage model of the array. */ + gnat_smo = get_storage_model (gnat_array_object); gnu_array_object = maybe_padded_object (gnu_array_object); gnu_array_object = maybe_unconstrained_array (gnu_array_object); + gnu_result_type = get_unpadded_type (Etype (gnat_node)); + gnu_expr = TYPE_MIN_VALUE (TYPE_DOMAIN (gnu_result_type)); gnu_expr = maybe_character_value (gnu_expr); @@ -6614,6 +6762,15 @@ gnat_to_gnu (Node_Id gnat_node) gnu_result = build_binary_op (ARRAY_RANGE_REF, gnu_result_type, gnu_array_object, gnu_expr); + + if (Present (gnat_smo)) + instantiate_load_in_array_ref (gnu_result, gnat_smo); + + /* If storage model access is required on the RHS, build the load. */ + if (storage_model_access_required_p (gnat_node, &gnat_smo) + && Present (Storage_Model_Copy_From (gnat_smo)) + && !present_in_lhs_or_actual_p (gnat_node)) + gnu_result = build_storage_model_load (gnat_smo, gnu_result); } break; @@ -6691,6 +6848,12 @@ gnat_to_gnu (Node_Id gnat_node) if (simple_atomic_access_required_p (gnat_node, &aa_sync) && !present_in_lhs_or_actual_p (gnat_node)) gnu_result = build_atomic_load (gnu_result, aa_sync); + + /* If storage model access is required on the RHS, build the load. */ + else if (storage_model_access_required_p (gnat_node, &gnat_smo) + && Present (Storage_Model_Copy_From (gnat_smo)) + && !present_in_lhs_or_actual_p (gnat_node)) + gnu_result = build_storage_model_load (gnat_smo, gnu_result); } break; @@ -7224,9 +7387,10 @@ gnat_to_gnu (Node_Id gnat_node) else if (Nkind (Expression (gnat_node)) == N_Function_Call) { get_atomic_access (Name (gnat_node), &aa_type, &aa_sync); + get_storage_model_access (Name (gnat_node), &gnat_smo); gnu_result = Call_to_gnu (Expression (gnat_node), &gnu_result_type, gnu_lhs, - aa_type, aa_sync); + aa_type, aa_sync, gnat_smo); } /* Otherwise we need to build the assignment statement manually. */ @@ -7264,6 +7428,7 @@ gnat_to_gnu (Node_Id gnat_node) gigi_checking_assert (!Do_Range_Check (gnat_expr)); get_atomic_access (Name (gnat_node), &aa_type, &aa_sync); + get_storage_model_access (Name (gnat_node), &gnat_smo); /* If an outer atomic access is required on the LHS, build the load- modify-store sequence. */ @@ -7275,6 +7440,43 @@ gnat_to_gnu (Node_Id gnat_node) else if (aa_type == SIMPLE_ATOMIC) gnu_result = build_atomic_store (gnu_lhs, gnu_rhs, aa_sync); + /* Or else, if a storage model access is required, build the special + store. */ + else if (Present (gnat_smo) + && Present (Storage_Model_Copy_To (gnat_smo))) + { + tree t = remove_conversions (gnu_rhs, false); + + /* If a storage model load is present on the RHS then instantiate + the temporary associated with it now, lest it be of variable + size and thus could not be instantiated by gimplification. */ + if (TREE_CODE (t) == LOAD_EXPR) + { + t = TREE_OPERAND (t, 1); + gcc_assert (TREE_CODE (t) == CALL_EXPR); + + tree elem + = build_nonstandard_integer_type (BITS_PER_UNIT, 1); + tree size = fold_convert (sizetype, CALL_EXPR_ARG (t, 3)); + tree index = build_index_type (size); + tree temp + = create_temporary ("L", build_array_type (elem, index)); + tree arg = CALL_EXPR_ARG (t, 1); + CALL_EXPR_ARG (t, 1) + = build_unary_op (ADDR_EXPR, TREE_TYPE (arg), temp); + + start_stmt_group (); + add_stmt (t); + t = build_storage_model_store (gnat_smo, gnu_lhs, temp); + add_stmt (t); + gnu_result = end_stmt_group (); + } + + else + gnu_result + = build_storage_model_store (gnat_smo, gnu_lhs, gnu_rhs); + } + /* Or else, use memset when the conditions are met. This has already been validated by Aggr_Assignment_OK_For_Backend in the front-end and the RHS is thus guaranteed to be of the appropriate form. */ @@ -7307,10 +7509,27 @@ gnat_to_gnu (Node_Id gnat_node) gnat_node); } - /* Otherwise build a regular assignment. */ else - gnu_result - = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_lhs, gnu_rhs); + { + tree t = remove_conversions (gnu_rhs, false); + + /* If a storage model load is present on the RHS, then elide the + temporary associated with it. */ + if (TREE_CODE (t) == LOAD_EXPR) + { + gnu_result = TREE_OPERAND (t, 1); + gcc_assert (TREE_CODE (gnu_result) == CALL_EXPR); + + tree arg = CALL_EXPR_ARG (gnu_result, 1); + CALL_EXPR_ARG (gnu_result, 1) + = build_unary_op (ADDR_EXPR, TREE_TYPE (arg), gnu_lhs); + } + + /* Otherwise build a regular assignment. */ + else + gnu_result + = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_lhs, gnu_rhs); + } /* If the assignment type is a regular array and the two sides are not completely disjoint, play safe and use memmove. But don't do @@ -7624,7 +7843,7 @@ gnat_to_gnu (Node_Id gnat_node) case N_Function_Call: case N_Procedure_Call_Statement: gnu_result = Call_to_gnu (gnat_node, &gnu_result_type, NULL_TREE, - NOT_ATOMIC, false); + NOT_ATOMIC, false, Empty); break; /************************/ @@ -8023,10 +8242,14 @@ gnat_to_gnu (Node_Id gnat_node) if (!type_annotate_only) { - tree gnu_ptr, gnu_ptr_type, gnu_obj_type, gnu_actual_obj_type; - const Entity_Id gnat_desig_type = Designated_Type (Underlying_Type (Etype (gnat_temp))); + const Entity_Id gnat_pool = Storage_Pool (gnat_node); + const bool pool_is_storage_model + = Present (gnat_pool) + && Has_Storage_Model_Type_Aspect (Etype (gnat_pool)) + && Present (Storage_Model_Copy_From (gnat_pool)); + tree gnu_ptr, gnu_ptr_type, gnu_obj_type, gnu_actual_obj_type; /* Make sure the designated type is complete before dereferencing, in case it is a Taft Amendment type. */ @@ -8087,12 +8310,13 @@ gnat_to_gnu (Node_Id gnat_node) tree gnu_size = TYPE_SIZE_UNIT (gnu_actual_obj_type); gnu_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_size, gnu_ptr); + if (pool_is_storage_model) + gnu_size = INSTANTIATE_LOAD_IN_EXPR (gnu_size, gnat_pool); gnu_result = build_call_alloc_dealloc (gnu_ptr, gnu_size, gnu_obj_type, Procedure_To_Call (gnat_node), - Storage_Pool (gnat_node), - gnat_node); + gnat_pool, gnat_node); } break; @@ -8300,7 +8524,7 @@ gnat_to_gnu (Node_Id gnat_node) && return_type_with_variable_size_p (TREE_TYPE (gnu_result))) ; - else if (TREE_CODE (gnu_result) == UNCONSTRAINED_ARRAY_REF + else if (TREE_CODE (TREE_TYPE (gnu_result)) == UNCONSTRAINED_ARRAY_TYPE && Present (Parent (gnat_node)) && Nkind (Parent (gnat_node)) == N_Attribute_Reference && lvalue_required_for_attribute_p (Parent (gnat_node))) @@ -8739,7 +8963,7 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, avoid blocking concatenation in the caller when it is inlined. */ for (int i = 0; i < call_expr_nargs (expr); i++) { - tree arg = *(CALL_EXPR_ARGP (expr) + i); + tree arg = CALL_EXPR_ARG (expr, i); if (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg) @@ -8751,7 +8975,7 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, if (TREE_CODE (t) == ADDR_EXPR) t = TREE_OPERAND (t, 0); if (TREE_CODE (t) != STRING_CST) - *(CALL_EXPR_ARGP (expr) + i) = tree_output_constant_def (arg); + CALL_EXPR_ARG (expr, i) = tree_output_constant_def (arg); } } break; @@ -8816,11 +9040,21 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, TREE_NO_WARNING (expr) = TREE_NO_WARNING (op); break; - case UNCONSTRAINED_ARRAY_REF: - /* We should only do this if we are just elaborating for side effects, - but we can't know that yet. */ - *expr_p = TREE_OPERAND (*expr_p, 0); - return GS_OK; + case LOAD_EXPR: + { + tree new_var = create_tmp_var (type, "L"); + TREE_ADDRESSABLE (new_var) = 1; + + tree init = TREE_OPERAND (expr, 1); + gcc_assert (TREE_CODE (init) == CALL_EXPR); + tree arg = CALL_EXPR_ARG (init, 1); + CALL_EXPR_ARG (init, 1) + = build_unary_op (ADDR_EXPR, TREE_TYPE (arg), new_var); + gimplify_and_add (init, pre_p); + + *expr_p = new_var; + return GS_OK; + } case VIEW_CONVERT_EXPR: op = TREE_OPERAND (expr, 0); @@ -8832,10 +9066,10 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, && AGGREGATE_TYPE_P (TREE_TYPE (op)) && !AGGREGATE_TYPE_P (type)) { - tree mod, new_var = create_tmp_var_raw (TREE_TYPE (op), "C"); + tree new_var = create_tmp_var_raw (TREE_TYPE (op), "C"); gimple_add_tmp_var (new_var); - mod = build2 (INIT_EXPR, TREE_TYPE (new_var), new_var, op); + tree mod = build2 (INIT_EXPR, TREE_TYPE (new_var), new_var, op); gimplify_and_add (mod, pre_p); TREE_OPERAND (expr, 0) = new_var; @@ -8843,6 +9077,12 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p, } break; + case UNCONSTRAINED_ARRAY_REF: + /* We should only do this if we are just elaborating for side effects, + but we can't know that yet. */ + *expr_p = TREE_OPERAND (expr, 0); + return GS_OK; + default: break; } diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc index 3d4c1c1..5942de1 100644 --- a/gcc/ada/gcc-interface/utils.cc +++ b/gcc/ada/gcc-interface/utils.cc @@ -5256,6 +5256,13 @@ maybe_unconstrained_array (tree exp) } } + else if (code == LOAD_EXPR) + { + const Entity_Id gnat_smo = tree_to_shwi (TREE_OPERAND (exp, 1)); + tree t = maybe_unconstrained_array (TREE_OPERAND (exp, 0)); + exp = build_storage_model_load (gnat_smo, t); + } + else if (code == NULL_EXPR) exp = build1 (NULL_EXPR, TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type)))), diff --git a/gcc/ada/gcc-interface/utils2.cc b/gcc/ada/gcc-interface/utils2.cc index 4c66a93..ef81f8d 100644 --- a/gcc/ada/gcc-interface/utils2.cc +++ b/gcc/ada/gcc-interface/utils2.cc @@ -2401,6 +2401,10 @@ tree build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc, Entity_Id gnat_pool, Node_Id gnat_node, bool ignore_init_type) { + const bool pool_is_storage_model + = Present (gnat_pool) + && Has_Storage_Model_Type_Aspect (Etype (gnat_pool)) + && Present (Storage_Model_Copy_To (gnat_pool)); tree size, storage, storage_deref, storage_init; /* If the initializer, if present, is a NULL_EXPR, just return a new one. */ @@ -2433,6 +2437,7 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc, get_identifier ("ALLOC"), false); tree template_type = TREE_TYPE (TYPE_FIELDS (storage_type)); tree storage_ptr_type = build_pointer_type (storage_type); + tree lhs, rhs; size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (storage_type), init); @@ -2459,17 +2464,21 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc, build_template (template_type, type, init)); CONSTRUCTOR_APPEND_ELT (v, DECL_CHAIN (TYPE_FIELDS (storage_type)), init); - storage_init - = build_binary_op (INIT_EXPR, NULL_TREE, storage_deref, - gnat_build_constructor (storage_type, v)); + + lhs = storage_deref; + rhs = gnat_build_constructor (storage_type, v); } else - storage_init - = build_binary_op (INIT_EXPR, NULL_TREE, - build_component_ref (storage_deref, - TYPE_FIELDS (storage_type), - false), - build_template (template_type, type, NULL_TREE)); + { + lhs = build_component_ref (storage_deref, TYPE_FIELDS (storage_type), + false); + rhs = build_template (template_type, type, NULL_TREE); + } + + if (pool_is_storage_model) + storage_init = build_storage_model_store (gnat_pool, lhs, rhs); + else + storage_init = build_binary_op (INIT_EXPR, NULL_TREE, lhs, rhs); return build2 (COMPOUND_EXPR, result_type, storage_init, convert (result_type, storage)); @@ -2509,14 +2518,263 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc, storage = gnat_protect_expr (storage); storage_deref = build_unary_op (INDIRECT_REF, NULL_TREE, storage); TREE_THIS_NOTRAP (storage_deref) = 1; - storage_init - = build_binary_op (INIT_EXPR, NULL_TREE, storage_deref, init); + if (pool_is_storage_model) + storage_init + = build_storage_model_store (gnat_pool, storage_deref, init); + else + storage_init + = build_binary_op (INIT_EXPR, NULL_TREE, storage_deref, init); return build2 (COMPOUND_EXPR, result_type, storage_init, storage); } return storage; } +/* Build a call to a copy procedure of a storage model given by an object. + DEST, SRC and SIZE are as for a call to memcpy. GNAT_SMO is the entity + for the storage model object and COPY_TO says which procedure to use. */ + +static tree +build_storage_model_copy (Entity_Id gnat_smo, tree dest, tree src, tree size, + bool copy_to) +{ + const Entity_Id gnat_copy_proc + = copy_to + ? Storage_Model_Copy_To (gnat_smo) + : Storage_Model_Copy_From (gnat_smo); + tree gnu_copy_proc = gnat_to_gnu (gnat_copy_proc); + tree gnu_param_type_list = TYPE_ARG_TYPES (TREE_TYPE (gnu_copy_proc)); + tree t1 = TREE_VALUE (gnu_param_type_list); + tree t2 = TREE_VALUE (TREE_CHAIN (gnu_param_type_list)); + tree t3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (gnu_param_type_list))); + tree t4 + = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (gnu_param_type_list)))); + + return + build_call_n_expr (gnu_copy_proc, + 4, + build_unary_op (ADDR_EXPR, t1, gnat_to_gnu (gnat_smo)), + build_unary_op (ADDR_EXPR, t2, dest), + build_unary_op (ADDR_EXPR, t3, src), + convert (t4, size)); +} + +/* Build a load of SRC using the storage model of GNAT_SMO. */ + +tree +build_storage_model_load (Entity_Id gnat_smo, tree src) +{ + tree ret = build2 (LOAD_EXPR, TREE_TYPE (src), src, NULL_TREE); + + /* Unconstrained array references have no size so we need to store the + storage object model for future processing by the machinery. */ + if (TREE_CODE (src) == UNCONSTRAINED_ARRAY_REF) + TREE_OPERAND (ret, 1) = build_int_cst (integer_type_node, gnat_smo); + else + TREE_OPERAND (ret, 1) = build_storage_model_load (gnat_smo, src, src); + + return ret; +} + +/* Build a load of SRC into DEST using the storage model of GNAT_SMO. + If SIZE is specified, use it, otherwise use the size of SRC. */ + +tree +build_storage_model_load (Entity_Id gnat_smo, tree dest, tree src, tree size) +{ + gcc_assert (TREE_CODE (src) != LOAD_EXPR); + + if (!size) + { + size = TYPE_SIZE_UNIT (TREE_TYPE (src)); + size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, src); + size = INSTANTIATE_LOAD_IN_EXPR (size, gnat_smo); + } + + return build_storage_model_copy (gnat_smo, dest, src, size, false); +} + +/* Build a store of SRC into DEST using the storage model of GNAT_SMO. + If SIZE is specified, use it, otherwise use the size of DEST. */ + +tree +build_storage_model_store (Entity_Id gnat_smo, tree dest, tree src, tree size) +{ + gcc_assert (TREE_CODE (src) != LOAD_EXPR); + + if (!size) + { + size = TYPE_SIZE_UNIT (TREE_TYPE (dest)); + size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, dest); + size = INSTANTIATE_LOAD_IN_EXPR (size, gnat_smo); + } + + return build_storage_model_copy (gnat_smo, dest, src, size, true); +} + +/* Given a tree EXP, instantiate occurrences of LOAD_EXPR in it and associate + them with the storage model of GNAT_SMO. */ + +tree +instantiate_load_in_expr (tree exp, Entity_Id gnat_smo) +{ + const enum tree_code code = TREE_CODE (exp); + tree type = TREE_TYPE (exp); + tree op0, op1, op2, op3; + tree new_tree; + + /* We handle TREE_LIST and COMPONENT_REF separately. */ + if (code == TREE_LIST) + { + op0 = INSTANTIATE_LOAD_IN_EXPR (TREE_CHAIN (exp), gnat_smo); + op1 = INSTANTIATE_LOAD_IN_EXPR (TREE_VALUE (exp), gnat_smo); + if (op0 == TREE_CHAIN (exp) && op1 == TREE_VALUE (exp)) + return exp; + + return tree_cons (TREE_PURPOSE (exp), op1, op0); + } + else if (code == COMPONENT_REF) + { + /* The field. */ + op1 = TREE_OPERAND (exp, 1); + + /* If it is a discriminant or equivalent, a LOAD_EXPR is needed. */ + if (DECL_DISCRIMINANT_NUMBER (op1)) + return build_storage_model_load (gnat_smo, exp); + + op0 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 0), gnat_smo); + if (op0 == TREE_OPERAND (exp, 0)) + return exp; + + new_tree = fold_build3 (COMPONENT_REF, type, op0, op1, NULL_TREE); + } + else + switch (TREE_CODE_CLASS (code)) + { + case tcc_constant: + case tcc_declaration: + return exp; + + case tcc_expression: + if (code == LOAD_EXPR) + return exp; + + /* Fall through. */ + + case tcc_exceptional: + case tcc_unary: + case tcc_binary: + case tcc_comparison: + case tcc_reference: + switch (TREE_CODE_LENGTH (code)) + { + case 0: + return exp; + + case 1: + op0 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 0), gnat_smo); + if (op0 == TREE_OPERAND (exp, 0)) + return exp; + + new_tree = fold_build1 (code, type, op0); + break; + + case 2: + op0 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 0), gnat_smo); + op1 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 1), gnat_smo); + + if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)) + return exp; + + new_tree = fold_build2 (code, type, op0, op1); + break; + + case 3: + op0 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 0), gnat_smo); + op1 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 1), gnat_smo); + op2 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 2), gnat_smo); + + if (op0 == TREE_OPERAND (exp, 0) + && op1 == TREE_OPERAND (exp, 1) + && op2 == TREE_OPERAND (exp, 2)) + return exp; + + new_tree = fold_build3 (code, type, op0, op1, op2); + break; + + case 4: + op0 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 0), gnat_smo); + op1 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 1), gnat_smo); + op2 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 2), gnat_smo); + op3 = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (exp, 3), gnat_smo); + + if (op0 == TREE_OPERAND (exp, 0) + && op1 == TREE_OPERAND (exp, 1) + && op2 == TREE_OPERAND (exp, 2) + && op3 == TREE_OPERAND (exp, 3)) + return exp; + + new_tree = fold (build4 (code, type, op0, op1, op2, op3)); + break; + + default: + gcc_unreachable (); + } + break; + + case tcc_vl_exp: + { + gcc_assert (code == CALL_EXPR); + + const int n = call_expr_nargs (exp); + gcc_assert (n > 0); + tree *argarray = XALLOCAVEC (tree, n); + for (int i = 0; i < n; i++) + argarray[i] + = INSTANTIATE_LOAD_IN_EXPR (CALL_EXPR_ARG (exp, i), gnat_smo); + + for (int i = 0; i < n; i++) + if (argarray[i] != CALL_EXPR_ARG (exp, i)) + return build_call_array (type, CALL_EXPR_FN (exp), n, argarray); + + return exp; + } + + default: + gcc_unreachable (); + } + + TREE_READONLY (new_tree) |= TREE_READONLY (exp); + + if (code == INDIRECT_REF || code == ARRAY_REF || code == ARRAY_RANGE_REF) + TREE_THIS_NOTRAP (new_tree) |= TREE_THIS_NOTRAP (exp); + + return new_tree; +} + +/* Given an array or slice reference, instantiate occurrences of LOAD_EXPR in + it and associate them with the storage model of GNAT_SMO. */ + +void +instantiate_load_in_array_ref (tree ref, Entity_Id gnat_smo) +{ + tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0))); + tree elem_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref, 0))); + + TREE_OPERAND (ref, 2) + = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), ref); + TREE_OPERAND (ref, 2) + = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (ref, 2), gnat_smo); + + TREE_OPERAND (ref, 3) + = size_binop (EXACT_DIV_EXPR, + SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elem_type), + ref), + size_int (TYPE_ALIGN_UNIT (elem_type))); + TREE_OPERAND (ref, 3) + = INSTANTIATE_LOAD_IN_EXPR (TREE_OPERAND (ref, 3), gnat_smo); +} + /* Indicate that we need to take the address of T and that it therefore should not be allocated in a register. Return true if successful. */ @@ -2816,7 +3074,7 @@ gnat_rewrite_reference (tree ref, rewrite_fn func, void *data, tree *init) gnat_rewrite_reference (TREE_OPERAND (ref, 0), func, data, init), func (TREE_OPERAND (ref, 1), data), - TREE_OPERAND (ref, 2), NULL_TREE); + TREE_OPERAND (ref, 2), TREE_OPERAND (ref, 3)); break; case COMPOUND_EXPR: @@ -2901,9 +3159,6 @@ get_inner_constant_reference (tree exp) case ARRAY_REF: case ARRAY_RANGE_REF: { - if (TREE_OPERAND (exp, 2)) - return NULL_TREE; - tree array_type = TREE_TYPE (TREE_OPERAND (exp, 0)); if (!TREE_CONSTANT (TREE_OPERAND (exp, 1)) || !TREE_CONSTANT (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type))) @@ -3044,8 +3299,13 @@ gnat_invariant_expr (tree expr) case ARRAY_REF: case ARRAY_RANGE_REF: - if (!TREE_CONSTANT (TREE_OPERAND (t, 1)) || TREE_OPERAND (t, 2)) - return NULL_TREE; + { + tree array_type = TREE_TYPE (TREE_OPERAND (t, 0)); + if (!TREE_CONSTANT (TREE_OPERAND (t, 1)) + || !TREE_CONSTANT (TYPE_MIN_VALUE (TYPE_DOMAIN (array_type))) + || !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (array_type)))) + return NULL_TREE; + } break; case BIT_FIELD_REF: diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 64f2e79..e79cdee 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -3,7 +3,7 @@ @setfilename gnat_rm.info @documentencoding UTF-8 @ifinfo -@*Generated by Sphinx 5.1.1.@* +@*Generated by Sphinx 5.2.3.@* @end ifinfo @settitle GNAT Reference Manual @defindex ge @@ -19,7 +19,7 @@ @copying @quotation -GNAT Reference Manual , Sep 23, 2022 +GNAT Reference Manual , Oct 04, 2022 AdaCore @@ -5243,14 +5243,14 @@ May reference only one protected component @item May not reference nonconstant entities outside the protected subprogram -scope. +scope @item May not contain address representation items, allocators, or quantified -expressions. +expressions @item -May not contain delay, goto, loop, or procedure-call statements. +May not contain delay, goto, loop, or procedure-call statements @item May not contain exported and imported entities @@ -28734,6 +28734,55 @@ pragma Machine_Attribute (Var, "strub"); -- scrubbing of the stack space used by that subprogram. @end example +Given these declarations, Foo has its type and body modified as +follows: + +@example +function Foo (<WaterMark> : in out System.Address) returns Integer +is + -- ... +begin + <__strub_update> (<WaterMark>); -- Updates the stack WaterMark. + -- ... +end; +@end example + +whereas its callers are modified from: + +@example +X := Foo; +@end example + +to: + +@example +declare + <WaterMark> : System.Address; +begin + <__strub_enter> (<WaterMark>); -- Initialize <WaterMark>. + X := Foo (<WaterMark>); + <__strub_leave> (<WaterMark>); -- Scrubs stack up to <WaterMark>. +end; +@end example + +As for Bar, because it is strubbed in internal mode, its callers are +not modified. Its definition is modified roughly as follows: + +@example +procedure Bar is + <WaterMark> : System.Address; + procedure Strubbed_Bar (<WaterMark> : in out System.Address) is + begin + <__strub_update> (<WaterMark>); -- Updates the stack WaterMark. + -- original Bar body. + end Strubbed_Bar; +begin + <__strub_enter> (<WaterMark>); -- Initialize <WaterMark>. + Strubbed_Bar (<WaterMark>); + <__strub_leave> (<WaterMark>); -- Scrubs stack up to <WaterMark>. +end Bar; +@end example + There are also @code{-fstrub=`choice'} command-line options to control default settings. For usage and more details on the command-line options, on the @code{strub} attribute, and their use with @@ -28809,11 +28858,54 @@ activated by a separate command-line option. The option @code{-fharden-compares} enables hardening of compares that compute results stored in variables, adding verification that the -reversed compare yields the opposite result. +reversed compare yields the opposite result, turning: + +@example +B := X = Y; +@end example + +into: + +@example +B := X = Y; +declare + NotB : Boolean := X /= Y; -- Computed independently of B. +begin + if B = NotB then + <__builtin_trap>; + end if; +end; +@end example The option @code{-fharden-conditional-branches} enables hardening of compares that guard conditional branches, adding verification of -the reversed compare to both execution paths. +the reversed compare to both execution paths, turning: + +@example +if X = Y then + X := Z + 1; +else + Y := Z - 1; +end if; +@end example + +into: + +@example +if X = Y then + if X /= Y then -- Computed independently of X = Y. + <__builtin_trap>; + end if; + X := Z + 1; +else + if X /= Y then -- Computed independently of X = Y. + null; + else + <__builtin_trap>; + end if; + Y := Z - 1; +end if; +@end example These transformations are introduced late in the compilation pipeline, long after boolean expressions are decomposed into separate compares, @@ -28871,17 +28963,37 @@ further remove checks found to be redundant. For additional hardening, the @code{hardbool} @code{Machine_Attribute} pragma can be used to annotate boolean types with representation clauses, so that expressions of such types used as conditions are -checked even when compiling with @code{-gnatVT}. +checked even when compiling with @code{-gnatVT}: @example pragma Machine_Attribute (HBool, "hardbool"); + +function To_Boolean (X : HBool) returns Boolean is (Boolean (X)); +@end example + +is compiled roughly like: + +@example +function To_Boolean (X : HBool) returns Boolean is +begin + if X not in True | False then + raise Constraint_Error; + elsif X in True then + return True; + else + return False; + end if; +end To_Boolean; @end example Note that @code{-gnatVn} will disable even @code{hardbool} testing. Analogous behavior is available as a GCC extension to the C and -Objective C programming languages, through the @code{hardbool} attribute. -For usage and more details on that attribute, see @cite{Using the GNU Compiler Collection (GCC)}. +Objective C programming languages, through the @code{hardbool} attribute, +with the difference that, instead of raising a Constraint_Error +exception, when a hardened boolean variable is found to hold a value +that stands for neither True nor False, the program traps. For usage +and more details on that attribute, see @cite{Using the GNU Compiler Collection (GCC)}. @c Control Flow Redundancy: diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index ceaf66b..6824941 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -1467,12 +1467,17 @@ package body Sem_Ch4 is end if; -- Check the accessibility level for actuals for explicitly aliased - -- formals. + -- formals when a function call appears within a return statement. + -- This is only checked if the enclosing subprogram Comes_From_Source, + -- to avoid issuing errors on calls occurring in wrapper subprograms + -- (for example, where the call is part of an expression of an aspect + -- associated with a wrapper, such as Pre'Class). if Nkind (N) = N_Function_Call and then Comes_From_Source (N) and then Present (Nam_Ent) and then In_Return_Value (N) + and then Comes_From_Source (Current_Subprogram) then declare Form : Node_Id; diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 7db0cb7..7ad6408 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -2398,7 +2398,7 @@ package body Sem_Ch6 is Class_Wide_Type (Etype (First_Formal (Subp))) = Typ) and then Try_Object_Operation (P) then - return; + goto Leave; else Analyze_Call_And_Resolve; diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb index cae0f23..f2a5901 100644 --- a/gcc/ada/sem_ch9.adb +++ b/gcc/ada/sem_ch9.adb @@ -178,8 +178,6 @@ package body Sem_Ch9 is elsif Nkind (Decl) = N_Subprogram_Declaration and then Nkind (Specification (Decl)) = N_Procedure_Specification - and then - Present (Parameter_Specifications (Specification (Decl))) then declare Par_Specs : constant List_Id := @@ -455,7 +453,7 @@ package body Sem_Ch9 is -- Goto statements restricted - elsif Kind = N_Goto_Statement then + elsif Kind in N_Goto_Statement | N_Goto_When_Statement then if Lock_Free_Given then Error_Msg_N ("goto statement not allowed", N); return Skip; @@ -477,7 +475,7 @@ package body Sem_Ch9 is -- Prohibit references to non-constant entities -- outside the protected subprogram scope. - if Ekind (Id) in Assignable_Kind + if Is_Assignable (Id) and then not Scope_Within_Or_Same (Scope (Id), Sub_Id) and then not @@ -487,8 +485,8 @@ package body Sem_Ch9 is then if Lock_Free_Given then Error_Msg_NE - ("reference to global variable& not " & - "allowed", N, Id); + ("reference to global variable& not allowed", + N, Id); return Skip; end if; diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 77ff68e..f85d091 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -25731,6 +25731,13 @@ package body Sem_Prag is ("argument of pragma% must be On/Off or static string " & "expression", Arg1); + -- Use of pragma Warnings to set warning switches is + -- ignored in GNATprove mode, as these switches apply to + -- the compiler only. + + elsif GNATprove_Mode then + null; + -- One argument string expression case else @@ -31608,7 +31615,7 @@ package body Sem_Prag is Pragma_Refined_Depends => -1, Pragma_Refined_Global => -1, Pragma_Refined_Post => -1, - Pragma_Refined_State => -1, + Pragma_Refined_State => 0, Pragma_Relative_Deadline => 0, Pragma_Remote_Access_Type => -1, Pragma_Remote_Call_Interface => -1, @@ -31713,6 +31720,15 @@ package body Sem_Prag is P := Parent (N); if Nkind (P) /= N_Pragma_Argument_Association then + + -- References within pragma Refined_State are not significant. They + -- can't be recognized using pragma argument number, because they + -- appear inside refinement clauses that rely on aggregate syntax. + + if In_Pragma_Expression (N, Name_Refined_State) then + return True; + end if; + return False; else diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index 132c2b8..c23d358 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -3655,10 +3655,14 @@ package Sem_Util is function Has_Storage_Model_Type_Aspect (Typ : Entity_Id) return Boolean; -- Returns True iff Typ specifies aspect Storage_Model_Type + -- WARNING: There is a matching C declaration of this subprogram in fe.h + function Has_Designated_Storage_Model_Aspect (Typ : Entity_Id) return Boolean; -- Returns True iff Typ specifies aspect Designated_Storage_Model + -- WARNING: There is a matching C declaration of this subprogram in fe.h + function Storage_Model_Object (Typ : Entity_Id) return Entity_Id; -- Given an access type Typ with aspect Designated_Storage_Model, -- returns the storage-model object associated with that type. @@ -3666,6 +3670,8 @@ package Sem_Util is -- other functions declared in this interface to retrieve operations -- associated with Storage_Model_Type aspect of the object's type. + -- WARNING: There is a matching C declaration of this subprogram in fe.h + function Storage_Model_Type (Obj : Entity_Id) return Entity_Id; -- Given an object Obj of a type specifying aspect Storage_Model_Type, -- returns that type. @@ -3715,12 +3721,16 @@ package Sem_Util is -- type, returns the procedure specified for the Copy_From choice in -- that aspect; returns Empty if the procedure isn't specified. + -- WARNING: There is a matching C declaration of this subprogram in fe.h + function Storage_Model_Copy_To (SM_Obj_Or_Type : Entity_Id) return Entity_Id; -- Given a type with aspect Storage_Model_Type or an object of such a -- type, returns the procedure specified for the Copy_To choice in that -- aspect; returns Empty if the procedure isn't specified. + -- WARNING: There is a matching C declaration of this subprogram in fe.h + function Storage_Model_Storage_Size (SM_Obj_Or_Type : Entity_Id) return Entity_Id; -- Given a type with aspect Storage_Model_Type or an object of such a diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 3af1a38..33477da 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,205 @@ +2022-10-07 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/105783 + * region-model.cc (selftest::get_bit): New function. + (selftest::test_bits_within_svalue_folding): New. + (selfftest::analyzer_region_model_cc_tests): Call it. + * svalue.cc (constant_svalue::maybe_fold_bits_within): Handle the + case of extracting a single bit. + +2022-10-06 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107158 + * store.cc (store::replay_call_summary_cluster): Eliminate + special-casing of RK_HEAP_ALLOCATED in favor of sharing code with + RK_DECL, avoiding an ICE due to attempting to bind a + compound_svalue into a binding_cluster when an svalue in the + summary cluster converts to a compound_svalue in the caller. + +2022-10-06 David Malcolm <dmalcolm@redhat.com> + + * call-summary.cc (call_summary_replay::dump_to_pp): Bulletproof + against NULL caller regions/svalues. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + * analysis-plan.cc: Simplify includes. + * analyzer-pass.cc: Likewise. + * analyzer-selftests.cc: Likewise. + * analyzer.cc: Likewise. + * analyzer.h: Add includes of "json.h" and "tristate.h". + * call-info.cc: Simplify includes. + * call-string.cc: Likewise. + * call-summary.cc: Likewise. + * checker-path.cc: Likewise. + * complexity.cc: Likewise. + * constraint-manager.cc: Likewise. + * diagnostic-manager.cc: Likewise. + * engine.cc: Likewise. + * feasible-graph.cc: Likewise. + * known-function-manager.cc: Likewise. + * pending-diagnostic.cc: Likewise. + * program-point.cc: Likewise. + * program-state.cc: Likewise. + * region-model-asm.cc: Likewise. + * region-model-impl-calls.cc: Likewise. + * region-model-manager.cc: Likewise. + * region-model-reachability.cc: Likewise. + * region-model.cc: Likewise. + * region-model.h: Include "selftest.h". + * region.cc: Simplify includes. + * sm-fd.cc: Likewise. + * sm-file.cc: Likewise. + * sm-malloc.cc: Likewise. + * sm-pattern-test.cc: Likewise. + * sm-sensitive.cc: Likewise. + * sm-signal.cc: Likewise. + * sm-taint.cc: Likewise. + * sm.cc: Likewise. + * state-purge.cc: Likewise. + * store.cc: Likewise. + * store.h: Likewise. + * supergraph.cc: Likewise. + * svalue.cc: Likewise. + * svalue.h: Likewise. + * trimmed-graph.cc: Likewise. + * varargs.cc: Likewise. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107060 + * call-summary.cc + (call_summary_replay::convert_svalue_from_summary_1): Handle NULL + results from convert_svalue_from_summary in SK_UNARY_OP and + SK_BIN_OP. + * engine.cc (impl_region_model_context::on_unknown_change): Bail + out on svalues that can't have associated state. + * region-model-impl-calls.cc + (region_model::impl_call_analyzer_get_unknown_ptr): New. + * region-model.cc (region_model::on_stmt_pre): Handle + "__analyzer_get_unknown_ptr". + * region-model.h + (region_model::impl_call_analyzer_get_unknown_ptr): New decl. + * store.cc (store::replay_call_summary_cluster): Avoid trying to + create binding clusters for base regions that shouldn't have them. + +2022-10-05 Martin Liska <mliska@suse.cz> + + * call-summary.cc (call_summary_replay::call_summary_replay): + Remove unused variable and arguments. + * call-summary.h: Likewise. + * engine.cc (exploded_node::on_stmt): Likewise. + (exploded_node::replay_call_summaries): Likewise. + (exploded_node::replay_call_summary): Likewise. + * exploded-graph.h (class exploded_node): Likewise. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107072 + * analyzer-logging.h: Include "diagnostic-core.h". + * analyzer.h: Include "function.h". + (class call_summary): New forward decl. + (class call_summary_replay): New forward decl. + (struct per_function_data): New forward decl. + (struct interesting_t): New forward decl. + (custom_edge_info::update_state): New vfunc. + * call-info.cc (custom_edge_info::update_state): New. + * call-summary.cc: New file. + * call-summary.h: New file. + * constraint-manager.cc: Include "analyzer/call-summary.h". + (class replay_fact_visitor): New. + (constraint_manager::replay_call_summary): New. + * constraint-manager.h (constraint_manager::replay_call_summary): + New. + * engine.cc: Include "analyzer/call-summary.h". + (exploded_node::on_stmt): Handle call summaries. + (class call_summary_edge_info): New. + (exploded_node::replay_call_summaries): New. + (exploded_node::replay_call_summary): New. + (per_function_data::~per_function_data): New. + (per_function_data::add_call_summary): Move here from header and + reimplement. + (exploded_graph::process_node): Call update_state rather than + update_model when handling bifurcation + (viz_callgraph_node::dump_dot): Use a regular label rather + than an HTML table; add summaries to dump. + * exploded-graph.h: Include "alloc-pool.h", "fibonacci_heap.h", + "supergraph.h", "sbitmap.h", "shortest-paths.h", "analyzer/sm.h", + "analyzer/program-state.h", and "analyzer/diagnostic-manager.h". + (exploded_node::replay_call_summaries): New decl. + (exploded_node::replay_call_summary): New decl. + (per_function_data::~per_function_data): New decl. + (per_function_data::add_call_summary): Move implemention from + header. + (per_function_data::m_summaries): Update type of element. + * known-function-manager.h: Include "analyzer/analyzer-logging.h". + * program-point.h: Include "pretty-print.h" and + "analyzer/call-string.h". + * program-state.cc: Include "analyzer/call-summary.h". + (sm_state_map::replay_call_summary): New. + (program_state::replay_call_summary): New. + * program-state.h (sm_state_map::replay_call_summary): New decl. + (program_state::replay_call_summary): New decl. + * region-model-manager.cc + (region_model_manager::get_or_create_asm_output_svalue): New + overload. + * region-model-manager.h + (region_model_manager::get_or_create_asm_output_svalue): New + overload decl. + * region-model.cc: Include "analyzer/call-summary.h". + (region_model::maybe_update_for_edge): Remove call to + region_model::update_for_call_summary on + SUPEREDGE_INTRAPROCEDURAL_CALL. + (region_model::update_for_call_summary): Delete. + (region_model::replay_call_summary): New. + * region-model.h (region_model::replay_call_summary): New decl. + (region_model::update_for_call_summary): Delete decl. + * store.cc: Include "analyzer/call-summary.h". + (store::replay_call_summary): New. + (store::replay_call_summary_cluster): New. + * store.h: Include "tristate.h". + (is_a_helper <const ana::concrete_binding *>::test): New. + (store::replay_call_summary): New decl. + (store::replay_call_summary_cluster): New decl. + * supergraph.cc (get_ultimate_function_for_cgraph_edge): Remove + "static" from decl. + (supergraph_call_edge): Make stmt param const. + * supergraph.h: Include "ordered-hash-map.h", "cfg.h", + "basic-block.h", "gimple.h", "gimple-iterator.h", and "digraph.h". + (supergraph_call_edge): Make stmt param const. + (get_ultimate_function_for_cgraph_edge): New decl. + * svalue.cc (compound_svalue::compound_svalue): Assert that we're + not nesting compound_svalues. + * svalue.h: Include "json.h", "analyzer/store.h", and + "analyzer/program-point.h". + (asm_output_svalue::get_num_outputs): New accessor. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + * region-model.h: Include "analyzer/region-model-manager.h" + (class region_model_manager): Move decl to... + * region-model-manager.h: ...this new file. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + * region-model-manager.cc + (region_model_manager::maybe_fold_unaryop): Fold -(-(VAL)) to VAL. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + * region-model-manager.cc + (region_model_manager::get_or_create_widening_svalue): Use a + function_point rather than a program_point. + * region-model.cc (selftest::test_widening_constraints): Likewise. + * region-model.h + (region_model_manager::get_or_create_widening_svalue): Likewise. + (model_merger::get_function_point): New. + * svalue.cc (svalue::can_merge_p): Use a function_point rather + than a program_point. + (svalue::can_merge_p): Likewise. + * svalue.h (widening_svalue::key_t): Likewise. + (widening_svalue::widening_svalue): Likewise. + 2022-09-12 Martin Liska <mliska@suse.cz> * region-model.cc (region_model::maybe_complain_about_infoleak): diff --git a/gcc/analyzer/analysis-plan.cc b/gcc/analyzer/analysis-plan.cc index c488f37..a4a42c5 100644 --- a/gcc/analyzer/analysis-plan.cc +++ b/gcc/analyzer/analysis-plan.cc @@ -27,7 +27,6 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "ipa-utils.h" #include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "diagnostic-core.h" #include "analyzer/analyzer-logging.h" @@ -35,7 +34,6 @@ along with GCC; see the file COPYING3. If not see #include "ordered-hash-map.h" #include "options.h" #include "cgraph.h" -#include "function.h" #include "cfg.h" #include "basic-block.h" #include "gimple.h" diff --git a/gcc/analyzer/analyzer-logging.h b/gcc/analyzer/analyzer-logging.h index ef14b29..71b540c 100644 --- a/gcc/analyzer/analyzer-logging.h +++ b/gcc/analyzer/analyzer-logging.h @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see #ifndef ANALYZER_LOGGING_H #define ANALYZER_LOGGING_H +#include "diagnostic-core.h" + namespace ana { /* A logger encapsulates a logging stream: a way to send diff --git a/gcc/analyzer/analyzer-pass.cc b/gcc/analyzer/analyzer-pass.cc index f6cef58..fc7098d 100644 --- a/gcc/analyzer/analyzer-pass.cc +++ b/gcc/analyzer/analyzer-pass.cc @@ -26,7 +26,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "options.h" #include "tree.h" -#include "function.h" #include "analyzer/analyzer.h" #include "analyzer/engine.h" diff --git a/gcc/analyzer/analyzer-selftests.cc b/gcc/analyzer/analyzer-selftests.cc index 3765e70..278c245 100644 --- a/gcc/analyzer/analyzer-selftests.cc +++ b/gcc/analyzer/analyzer-selftests.cc @@ -23,7 +23,6 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "stringpool.h" -#include "function.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-selftests.h" diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc index c85dbf3..8a2a773 100644 --- a/gcc/analyzer/analyzer.cc +++ b/gcc/analyzer/analyzer.cc @@ -27,7 +27,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "diagnostic.h" #include "intl.h" -#include "function.h" #include "analyzer/analyzer.h" #if ENABLE_ANALYZER diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index b325aee..a2d79e4 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -21,6 +21,10 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_ANALYZER_ANALYZER_H #define GCC_ANALYZER_ANALYZER_H +#include "function.h" +#include "json.h" +#include "tristate.h" + class graphviz_out; namespace ana { @@ -114,6 +118,10 @@ class state_machine; class logger; class visitor; class known_function_manager; +class call_summary; +class call_summary_replay; +struct per_function_data; +struct interesting_t; /* Forward decls of functions. */ @@ -263,6 +271,11 @@ public: /* Hook for making .dot label more readable. */ virtual void print (pretty_printer *pp) const = 0; + /* Hook for updating STATE when handling bifurcation. */ + virtual bool update_state (program_state *state, + const exploded_edge *eedge, + region_model_context *ctxt) const; + /* Hook for updating MODEL within exploded_path::feasible_p and when handling bifurcation. */ virtual bool update_model (region_model *model, diff --git a/gcc/analyzer/call-info.cc b/gcc/analyzer/call-info.cc index efc070b..56059ac 100644 --- a/gcc/analyzer/call-info.cc +++ b/gcc/analyzer/call-info.cc @@ -30,11 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "options.h" #include "cgraph.h" #include "tree-pretty-print.h" -#include "tristate.h" #include "bitmap.h" -#include "selftest.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "ordered-hash-map.h" @@ -56,9 +52,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-path.h" #include "analyzer/checker-path.h" #include "analyzer/diagnostic-manager.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" -#include "shortest-paths.h" #include "analyzer/exploded-graph.h" #include "analyzer/call-info.h" @@ -66,7 +59,17 @@ along with GCC; see the file COPYING3. If not see namespace ana { -/* class call_info : public custom_eedge_info_t. */ +/* class custom_edge_info. */ + +bool +custom_edge_info::update_state (program_state *state, + const exploded_edge *eedge, + region_model_context *ctxt) const +{ + return update_model (state->m_region_model, eedge, ctxt); +} + +/* class call_info : public custom_edge_info. */ /* Implementation of custom_edge_info::print vfunc for call_info: use get_desc to get a label_text, and print it to PP. */ diff --git a/gcc/analyzer/call-string.cc b/gcc/analyzer/call-string.cc index a09f569..f0a30d9 100644 --- a/gcc/analyzer/call-string.cc +++ b/gcc/analyzer/call-string.cc @@ -24,7 +24,6 @@ along with GCC; see the file COPYING3. If not see #include "pretty-print.h" #include "tree.h" #include "options.h" -#include "json.h" #include "ordered-hash-map.h" #include "options.h" #include "cgraph.h" diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc new file mode 100644 index 0000000..12ef82d --- /dev/null +++ b/gcc/analyzer/call-summary.cc @@ -0,0 +1,889 @@ +/* Classes for working with summaries of function calls. + Copyright (C) 2022 David Malcolm <dmalcolm@redhat.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "tree-dfa.h" +#include "diagnostic.h" +#include "tree-diagnostic.h" +#include "analyzer/analyzer.h" +#include "analyzer/region-model.h" +#include "analyzer/call-summary.h" +#include "analyzer/exploded-graph.h" + +#if ENABLE_ANALYZER + +namespace ana { + +/* class call_summary. */ + +const program_state & +call_summary::get_state () const +{ + return m_enode->get_state (); +} + +tree +call_summary::get_fndecl () const +{ + return m_enode->get_point ().get_fndecl (); +} + +label_text +call_summary::get_desc () const +{ + pretty_printer pp; + pp_format_decoder (&pp) = default_tree_printer; + + get_user_facing_desc (&pp); + if (flag_analyzer_verbose_edges) + pp_printf (&pp, " (call summary; EN: %i)", m_enode->m_index); + + return label_text::take (xstrdup (pp_formatted_text (&pp))); +} + +/* Generate a user-facing description of this call summary.c + This has various heuristics for distinguishing between different + summaries. + This will help with debugging, too. */ + +void +call_summary::get_user_facing_desc (pretty_printer *pp) const +{ + tree fndecl = get_fndecl (); + + /* If there are multiple summaries, try to use the return value to + distinguish between them. */ + if (m_per_fn_data->m_summaries.length () > 1) + { + if (tree result = DECL_RESULT (fndecl)) + { + const region *result_reg + = get_state ().m_region_model->get_lvalue (result, NULL); + const svalue *result_sval + = get_state ().m_region_model->get_store_value (result_reg, NULL); + switch (result_sval->get_kind ()) + { + default: + break; + case SK_REGION: + { + const region_svalue *region_sval + = as_a <const region_svalue *> (result_sval); + const region *pointee_reg = region_sval->get_pointee (); + switch (pointee_reg->get_kind ()) + { + default: + break; + case RK_HEAP_ALLOCATED: + pp_printf (pp, + "when %qE returns pointer" + " to heap-allocated buffer", + fndecl); + return; + } + } + break; + case SK_CONSTANT: + { + const constant_svalue *constant_sval + = as_a <const constant_svalue *> (result_sval); + tree cst = constant_sval->get_constant (); + if (POINTER_TYPE_P (TREE_TYPE (result)) + && zerop (cst)) + pp_printf (pp, "when %qE returns NULL", fndecl); + else + pp_printf (pp, "when %qE returns %qE", fndecl, cst); + return; + } + } + } + } + + /* Fallback. */ + pp_printf (pp, "when %qE returns", fndecl); +} + +/* Dump a multiline representation of this object to PP. */ + +void +call_summary::dump_to_pp (const extrinsic_state &ext_state, + pretty_printer *pp, + bool simple) const +{ + label_text desc = get_desc (); + pp_printf (pp, "desc: %qs", desc.get ()); + pp_newline (pp); + + get_state ().dump_to_pp (ext_state, simple, true, pp); +} + +/* Dump a multiline representation of this object to FILE. */ + +void +call_summary::dump (const extrinsic_state &ext_state, + FILE *fp, + bool simple) const +{ + pretty_printer pp; + pp_format_decoder (&pp) = default_tree_printer; + pp_show_color (&pp) = pp_show_color (global_dc->printer); + pp.buffer->stream = fp; + dump_to_pp (ext_state, &pp, simple); + pp_flush (&pp); +} + +/* Dump a multiline representation of this object to stderr. */ + +DEBUG_FUNCTION void +call_summary::dump (const extrinsic_state &ext_state, bool simple) const +{ + dump (ext_state, stderr, simple); +} + +/* class call_summary_replay. */ + +/* call_summary_replay's ctor. + Populate the cache with params for the summary based on + arguments at the caller. */ + +call_summary_replay::call_summary_replay (const call_details &cd, + function *called_fn, + call_summary *summary, + const extrinsic_state &ext_state) +: m_cd (cd), + m_summary (summary), + m_ext_state (ext_state) +{ + region_model_manager *mgr = cd.get_manager (); + + // populate params based on args + tree fndecl = called_fn->decl; + + /* Get a frame_region for use with respect to the summary. + This will be a top-level frame, since that's what's in + the summary. */ + const frame_region *summary_frame + = mgr->get_frame_region (NULL, called_fn); + + unsigned idx = 0; + for (tree iter_parm = DECL_ARGUMENTS (fndecl); iter_parm; + iter_parm = DECL_CHAIN (iter_parm), ++idx) + { + /* If there's a mismatching declaration, the call stmt might + not have enough args. Handle this case by leaving the + rest of the params as uninitialized. */ + if (idx >= cd.num_args ()) + break; + const svalue *caller_arg_sval = cd.get_arg_svalue (idx); + tree parm_lval = iter_parm; + if (tree parm_default_ssa = ssa_default_def (called_fn, iter_parm)) + parm_lval = parm_default_ssa; + const region *summary_parm_reg + = summary_frame->get_region_for_local (mgr, parm_lval, cd.get_ctxt ()); + const svalue *summary_initial_parm_reg + = mgr->get_or_create_initial_value (summary_parm_reg); + add_svalue_mapping (summary_initial_parm_reg, caller_arg_sval); + } + + /* Handle any variadic args. */ + unsigned va_arg_idx = 0; + for (; idx < cd.num_args (); idx++, va_arg_idx++) + { + const svalue *caller_arg_sval = cd.get_arg_svalue (idx); + const region *summary_var_arg_reg + = mgr->get_var_arg_region (summary_frame, va_arg_idx); + const svalue *summary_initial_var_arg_reg + = mgr->get_or_create_initial_value (summary_var_arg_reg); + add_svalue_mapping (summary_initial_var_arg_reg, caller_arg_sval); + } +} + +/* Try to convert SUMMARY_SVAL in the summary to a corresponding svalue + in the caller, caching the result. + + Return NULL if the conversion is not possible. */ + +const svalue * +call_summary_replay::convert_svalue_from_summary (const svalue *summary_sval) +{ + gcc_assert (summary_sval); + + if (const svalue **slot + = m_map_svalue_from_summary_to_caller.get (summary_sval)) + return *slot; + + const svalue *caller_sval = convert_svalue_from_summary_1 (summary_sval); + + /* Add to cache. */ + add_svalue_mapping (summary_sval, caller_sval); + + return caller_sval; +} + +/* Implementation of call_summary_replay::convert_svalue_from_summary. */ + +const svalue * +call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval) +{ + gcc_assert (summary_sval); + + switch (summary_sval->get_kind ()) + { + default: + gcc_unreachable (); + case SK_REGION: + { + const region_svalue *region_summary_sval + = as_a <const region_svalue *> (summary_sval); + const region *summary_reg = region_summary_sval->get_pointee (); + const region *caller_reg = convert_region_from_summary (summary_reg); + if (!caller_reg) + return NULL; + region_model_manager *mgr = get_manager (); + const svalue *caller_ptr + = mgr->get_ptr_svalue (summary_sval->get_type (), + caller_reg); + return caller_ptr; + } + break; + + case SK_CONSTANT: + case SK_PLACEHOLDER: + case SK_POISONED: + case SK_UNKNOWN: + return summary_sval; + + case SK_SETJMP: + return NULL; // TODO + + case SK_INITIAL: + { + const initial_svalue *initial_summary_sval + = as_a <const initial_svalue *> (summary_sval); + /* Params should already be in the cache, courtesy of the ctor. */ + gcc_assert (!initial_summary_sval->initial_value_of_param_p ()); + + /* Initial value of region within the summary is the value of the + region at the point of the call. */ + const region *summary_reg = initial_summary_sval->get_region (); + const region *caller_reg = convert_region_from_summary (summary_reg); + if (!caller_reg) + return NULL; + const svalue *caller_sval + = m_cd.get_model ()->get_store_value (caller_reg, m_cd.get_ctxt ()); + return caller_sval; + } + break; + case SK_UNARYOP: + { + const unaryop_svalue *unaryop_summary_sval + = as_a <const unaryop_svalue *> (summary_sval); + const svalue *summary_arg = unaryop_summary_sval->get_arg (); + const svalue *caller_arg = convert_svalue_from_summary (summary_arg); + if (!caller_arg) + return NULL; + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_unaryop (summary_sval->get_type (), + unaryop_summary_sval->get_op (), + caller_arg); + } + break; + case SK_BINOP: + { + const binop_svalue *binop_summary_sval + = as_a <const binop_svalue *> (summary_sval); + const svalue *summary_arg0 = binop_summary_sval->get_arg0 (); + const svalue *caller_arg0 = convert_svalue_from_summary (summary_arg0); + if (!caller_arg0) + return NULL; + const svalue *summary_arg1 = binop_summary_sval->get_arg1 (); + const svalue *caller_arg1 = convert_svalue_from_summary (summary_arg1); + if (!caller_arg1) + return NULL; + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_binop (summary_sval->get_type (), + binop_summary_sval->get_op (), + caller_arg0, + caller_arg1); + } + break; + case SK_SUB: + { + const sub_svalue *sub_summary_sval + = as_a <const sub_svalue *> (summary_sval); + region_model_manager *mgr = get_manager (); + const svalue *summary_parent_sval = sub_summary_sval->get_parent (); + if (!summary_parent_sval) + return NULL; + const region *summary_subregion = sub_summary_sval->get_subregion (); + if (!summary_subregion) + return NULL; + return mgr->get_or_create_sub_svalue (summary_sval->get_type (), + summary_parent_sval, + summary_subregion); + } + break; + case SK_REPEATED: + { + const repeated_svalue *repeated_summary_sval + = as_a <const repeated_svalue *> (summary_sval); + const svalue *summary_outer_size + = repeated_summary_sval->get_outer_size (); + const svalue *caller_outer_size + = convert_svalue_from_summary (summary_outer_size); + if (!caller_outer_size) + return NULL; + const svalue *summary_inner_sval + = repeated_summary_sval->get_inner_svalue (); + const svalue *caller_inner_sval + = convert_svalue_from_summary (summary_inner_sval); + if (!caller_inner_sval) + return NULL; + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_repeated_svalue (summary_sval->get_type (), + caller_outer_size, + caller_inner_sval); + } + break; + case SK_BITS_WITHIN: + { + const bits_within_svalue *bits_within_summary_sval + = as_a <const bits_within_svalue *> (summary_sval); + const bit_range &bits = bits_within_summary_sval->get_bits (); + const svalue *summary_inner_sval + = bits_within_summary_sval->get_inner_svalue (); + const svalue *caller_inner_sval + = convert_svalue_from_summary (summary_inner_sval); + if (!caller_inner_sval) + return NULL; + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_bits_within (summary_sval->get_type (), + bits, + caller_inner_sval); + } + break; + case SK_UNMERGEABLE: + { + const unmergeable_svalue *unmergeable_summary_sval + = as_a <const unmergeable_svalue *> (summary_sval); + const svalue *summary_arg_sval = unmergeable_summary_sval->get_arg (); + const svalue *caller_arg_sval + = convert_svalue_from_summary (summary_arg_sval); + if (!caller_arg_sval) + return NULL; + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_unmergeable (caller_arg_sval); + } + break; + case SK_WIDENING: + { + const widening_svalue *widening_summary_sval + = as_a <const widening_svalue *> (summary_sval); + const function_point &point = widening_summary_sval->get_point (); + const svalue *summary_base_sval + = widening_summary_sval->get_base_svalue (); + const svalue *caller_base_sval + = convert_svalue_from_summary (summary_base_sval); + if (!(caller_base_sval + && caller_base_sval->can_have_associated_state_p ())) + return NULL; + const svalue *summary_iter_sval + = widening_summary_sval->get_iter_svalue (); + const svalue *caller_iter_sval + = convert_svalue_from_summary (summary_iter_sval); + if (!(caller_iter_sval + && caller_iter_sval->can_have_associated_state_p ())) + return NULL; + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_widening_svalue + (summary_iter_sval->get_type (), + point, + caller_base_sval, + caller_iter_sval); + } + break; + case SK_COMPOUND: + { + const compound_svalue *compound_summary_sval + = as_a <const compound_svalue *> (summary_sval); + region_model_manager *mgr = get_manager (); + store_manager *store_mgr = mgr->get_store_manager (); + binding_map caller_map; + auto_vec <const binding_key *> summary_keys; + for (auto kv : *compound_summary_sval) + summary_keys.safe_push (kv.first); + summary_keys.qsort (binding_key::cmp_ptrs); + for (auto key : summary_keys) + { + gcc_assert (key->concrete_p ()); + /* No remapping is needed for concrete binding keys. */ + + const svalue *bound_summary_sval + = compound_summary_sval->get_map ().get (key); + const svalue *caller_sval + = convert_svalue_from_summary (bound_summary_sval); + if (!caller_sval) + caller_sval = mgr->get_or_create_unknown_svalue (NULL_TREE); + + if (const compound_svalue *inner_compound_sval + = caller_sval->dyn_cast_compound_svalue ()) + { + const concrete_binding *outer_key + = as_a <const concrete_binding *> (key); + for (auto inner_kv : *inner_compound_sval) + { + // These should already be mapped to the caller. + const binding_key *inner_key = inner_kv.first; + const svalue *inner_sval = inner_kv.second; + gcc_assert (inner_key->concrete_p ()); + const concrete_binding *concrete_key + = as_a <const concrete_binding *> (inner_key); + bit_offset_t effective_start + = (concrete_key->get_start_bit_offset () + + outer_key->get_start_bit_offset ()); + const concrete_binding *effective_concrete_key + = store_mgr->get_concrete_binding + (effective_start, + concrete_key->get_size_in_bits ()); + caller_map.put (effective_concrete_key, inner_sval); + } + } + else + caller_map.put (key, caller_sval); + } + return mgr->get_or_create_compound_svalue (summary_sval->get_type (), + caller_map); + } + break; + case SK_CONJURED: + { + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_unknown_svalue (summary_sval->get_type ()); + } + break; + case SK_ASM_OUTPUT: + { + const asm_output_svalue *asm_output_summary_sval + = as_a <const asm_output_svalue *> (summary_sval); + const char *asm_string = asm_output_summary_sval->get_asm_string (); + unsigned output_idx = asm_output_summary_sval->get_output_idx (); + unsigned num_inputs = asm_output_summary_sval->get_num_inputs (); + unsigned num_outputs = asm_output_summary_sval->get_num_outputs (); + auto_vec<const svalue *> inputs (num_inputs); + for (unsigned idx = 0; idx < num_inputs; idx++) + { + const svalue *summary_input + = asm_output_summary_sval->get_input (idx); + const svalue *caller_input + = convert_svalue_from_summary (summary_input); + if (!caller_input) + return NULL; + inputs.safe_push (caller_input); + } + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_asm_output_svalue (summary_sval->get_type (), + asm_string, + output_idx, + num_outputs, + inputs); + } + break; + case SK_CONST_FN_RESULT: + { + const const_fn_result_svalue *const_fn_result_summary_sval + = as_a <const const_fn_result_svalue *> (summary_sval); + tree fndecl = const_fn_result_summary_sval->get_fndecl (); + unsigned num_inputs = const_fn_result_summary_sval->get_num_inputs (); + auto_vec<const svalue *> inputs (num_inputs); + for (unsigned idx = 0; idx < num_inputs; idx++) + { + const svalue *summary_input + = const_fn_result_summary_sval->get_input (idx); + const svalue *caller_input + = convert_svalue_from_summary (summary_input); + if (!caller_input) + return NULL; + inputs.safe_push (caller_input); + } + region_model_manager *mgr = get_manager (); + return mgr->get_or_create_const_fn_result_svalue + (summary_sval->get_type (), + fndecl, + inputs); + } + break; + } +} + +/* Try to convert SUMMARY_REG in the summary to a corresponding region + in the caller, caching the result. + + Return NULL if the conversion is not possible. */ + +const region * +call_summary_replay::convert_region_from_summary (const region *summary_reg) +{ + gcc_assert (summary_reg); + + if (const region **slot + = m_map_region_from_summary_to_caller.get (summary_reg)) + return *slot; + + const region *caller_reg = convert_region_from_summary_1 (summary_reg); + + /* Add to cache. */ + add_region_mapping (summary_reg, caller_reg); + + return caller_reg; +} + +/* Implementation of call_summary_replay::convert_region_from_summary. */ + +const region * +call_summary_replay::convert_region_from_summary_1 (const region *summary_reg) +{ + gcc_assert (summary_reg); + + region_model_manager *mgr = get_manager (); + switch (summary_reg->get_kind ()) + { + default: + gcc_unreachable (); + /* Top-level regions. */ + case RK_FRAME: + case RK_GLOBALS: + case RK_CODE: + case RK_STACK: + case RK_HEAP: + case RK_ROOT: + /* These should never be pointed to by a region_svalue. */ + gcc_unreachable (); + + case RK_FUNCTION: + case RK_LABEL: + case RK_STRING: + case RK_UNKNOWN: + /* We can reuse these regions directly. */ + return summary_reg; + + case RK_SYMBOLIC: + { + const symbolic_region *summary_symbolic_reg + = as_a <const symbolic_region *> (summary_reg); + const svalue *summary_ptr_sval = summary_symbolic_reg->get_pointer (); + const svalue *caller_ptr_sval + = convert_svalue_from_summary (summary_ptr_sval); + if (!caller_ptr_sval) + return NULL; + const region *caller_reg + = get_caller_model ()->deref_rvalue (caller_ptr_sval, + NULL_TREE, + get_ctxt ()); + return caller_reg; + } + break; + + case RK_DECL: + { + const decl_region *summary_decl_reg + = as_a <const decl_region *> (summary_reg); + tree decl = summary_decl_reg->get_decl (); + switch (TREE_CODE (decl)) + { + default: + gcc_unreachable (); + case SSA_NAME: + /* We don't care about writes to locals within + the summary. */ + return NULL; + case VAR_DECL: + /* We don't care about writes to locals within + the summary. */ + if (is_global_var (decl)) + /* If it's a global, we can reuse the region directly. */ + return summary_reg; + else + /* Otherwise, we don't care about locals. */ + return NULL; + case RESULT_DECL: + return m_cd.get_lhs_region (); + case PARM_DECL: + /* Writes (by value) to parms should be visible to the caller. */ + return NULL; + } + } + break; + case RK_FIELD: + { + const field_region *summary_field_reg + = as_a <const field_region *> (summary_reg); + const region *summary_parent_reg = summary_reg->get_parent_region (); + const region *caller_parent_reg + = convert_region_from_summary (summary_parent_reg); + if (!caller_parent_reg) + return NULL; + tree field = summary_field_reg->get_field (); + return mgr->get_field_region (caller_parent_reg, field); + } + break; + case RK_ELEMENT: + { + const element_region *summary_element_reg + = as_a <const element_region *> (summary_reg); + const region *summary_parent_reg = summary_reg->get_parent_region (); + const region *caller_parent_reg + = convert_region_from_summary (summary_parent_reg); + if (!caller_parent_reg) + return NULL; + const svalue *summary_index = summary_element_reg->get_index (); + const svalue *caller_index + = convert_svalue_from_summary (summary_index); + if (!caller_index) + return NULL; + return mgr->get_element_region (caller_parent_reg, + summary_reg->get_type (), + caller_index); + } + break; + case RK_OFFSET: + { + const offset_region *summary_offset_reg + = as_a <const offset_region *> (summary_reg); + const region *summary_parent_reg = summary_reg->get_parent_region (); + const region *caller_parent_reg + = convert_region_from_summary (summary_parent_reg); + if (!caller_parent_reg) + return NULL; + const svalue *summary_byte_offset + = summary_offset_reg->get_byte_offset (); + const svalue *caller_byte_offset + = convert_svalue_from_summary (summary_byte_offset); + if (!caller_byte_offset) + return NULL; + return mgr->get_offset_region (caller_parent_reg, + summary_reg->get_type (), + caller_byte_offset); + } + break; + case RK_SIZED: + { + const sized_region *summary_sized_reg + = as_a <const sized_region *> (summary_reg); + const region *summary_parent_reg = summary_reg->get_parent_region (); + const region *caller_parent_reg + = convert_region_from_summary (summary_parent_reg); + if (!caller_parent_reg) + return NULL; + const svalue *summary_byte_size + = summary_sized_reg->get_byte_size_sval (mgr); + const svalue *caller_byte_size + = convert_svalue_from_summary (summary_byte_size); + if (!caller_byte_size) + return NULL; + return mgr->get_sized_region (caller_parent_reg, + summary_reg->get_type (), + caller_byte_size); + } + break; + case RK_CAST: + { + const cast_region *summary_cast_reg + = as_a <const cast_region *> (summary_reg); + const region *summary_original_reg + = summary_cast_reg->get_original_region (); + const region *caller_original_reg + = convert_region_from_summary (summary_original_reg); + if (!caller_original_reg) + return NULL; + return mgr->get_cast_region (caller_original_reg, + summary_reg->get_type ()); + } + break; + case RK_HEAP_ALLOCATED: + { + /* If we have a heap-allocated region in the summary, then + it was allocated within the callee. + Create a new heap-allocated region to summarize this. */ + return mgr->create_region_for_heap_alloc (); + } + break; + case RK_ALLOCA: + return NULL; + case RK_BIT_RANGE: + { + const bit_range_region *summary_bit_range_reg + = as_a <const bit_range_region *> (summary_reg); + const region *summary_parent_reg = summary_reg->get_parent_region (); + const region *caller_parent_reg + = convert_region_from_summary (summary_parent_reg); + if (!caller_parent_reg) + return NULL; + const bit_range &bits = summary_bit_range_reg->get_bits (); + return mgr->get_bit_range (caller_parent_reg, + summary_reg->get_type (), + bits); + } + break; + case RK_VAR_ARG: + return NULL; + } +} + +/* Try to convert SUMMARY_KEY in the summary to a corresponding binding key + in the caller. + + Return NULL if the conversion is not possible. */ + +const binding_key * +call_summary_replay::convert_key_from_summary (const binding_key *summary_key) +{ + if (summary_key->concrete_p ()) + return summary_key; + + const symbolic_binding *symbolic_key = (const symbolic_binding *)summary_key; + const region *summary_reg = symbolic_key->get_region (); + const region *caller_reg = convert_region_from_summary (summary_reg); + if (!caller_reg) + return NULL; + region_model_manager *mgr = get_manager (); + store_manager *store_mgr = mgr->get_store_manager (); + return store_mgr->get_symbolic_binding (caller_reg); +} + +/* Record that SUMMARY_SVAL maps to CALLER_SVAL for this replay. */ + +void +call_summary_replay::add_svalue_mapping (const svalue *summary_sval, + const svalue *caller_sval) +{ + gcc_assert (summary_sval); + // CALLER_SVAL can be NULL + m_map_svalue_from_summary_to_caller.put (summary_sval, caller_sval); +} + +/* Record that SUMMARY_REG maps to CALLER_REG for this replay. */ + +void +call_summary_replay::add_region_mapping (const region *summary_reg, + const region *caller_reg) +{ + gcc_assert (summary_reg); + // CALLER_REG can be NULL + m_map_region_from_summary_to_caller.put (summary_reg, caller_reg); +} + +/* Dump a multiline representation of this object to PP. */ + +void +call_summary_replay::dump_to_pp (pretty_printer *pp, bool simple) const +{ + pp_newline (pp); + pp_string (pp, "CALL DETAILS:"); + pp_newline (pp); + m_cd.dump_to_pp (pp, simple); + + pp_newline (pp); + pp_string (pp, "CALLEE SUMMARY:"); + pp_newline (pp); + m_summary->dump_to_pp (m_ext_state, pp, simple); + + /* Current state of caller (could be in mid-update). */ + pp_newline (pp); + pp_string (pp, "CALLER:"); + pp_newline (pp); + m_cd.get_model ()->dump_to_pp (pp, simple, true); + + pp_newline (pp); + pp_string (pp, "REPLAY STATE:"); + pp_newline (pp); + pp_string (pp, "svalue mappings from summary to caller:"); + pp_newline (pp); + auto_vec <const svalue *> summary_svals; + for (auto kv : m_map_svalue_from_summary_to_caller) + summary_svals.safe_push (kv.first); + summary_svals.qsort (svalue::cmp_ptr_ptr); + for (auto summary_sval : summary_svals) + { + pp_string (pp, "sval in summary: "); + summary_sval->dump_to_pp (pp, simple); + pp_newline (pp); + + const svalue *caller_sval + = *((const_cast<svalue_map_t &> + (m_map_svalue_from_summary_to_caller)).get (summary_sval)); + pp_string (pp, " sval in caller: "); + caller_sval->dump_to_pp (pp, simple); + pp_newline (pp); + } + + pp_newline (pp); + pp_string (pp, "region mappings from summary to caller:"); + pp_newline (pp); + auto_vec <const region *> summary_regs; + for (auto kv : m_map_region_from_summary_to_caller) + summary_regs.safe_push (kv.first); + summary_regs.qsort (region::cmp_ptr_ptr); + for (auto summary_reg : summary_regs) + { + pp_string (pp, "reg in summary: "); + if (summary_reg) + summary_reg->dump_to_pp (pp, simple); + else + pp_string (pp, "(null)"); + pp_newline (pp); + + const region *caller_reg + = *((const_cast<region_map_t &> + (m_map_region_from_summary_to_caller)).get (summary_reg)); + pp_string (pp, " reg in caller: "); + if (caller_reg) + caller_reg->dump_to_pp (pp, simple); + else + pp_string (pp, "(null)"); + pp_newline (pp); + } +} + +/* Dump a multiline representation of this object to FILE. */ + +void +call_summary_replay::dump (FILE *fp, bool simple) const +{ + pretty_printer pp; + pp_format_decoder (&pp) = default_tree_printer; + pp_show_color (&pp) = pp_show_color (global_dc->printer); + pp.buffer->stream = fp; + dump_to_pp (&pp, simple); + pp_flush (&pp); +} + +/* Dump a multiline representation of this object to stderr. */ + +DEBUG_FUNCTION void +call_summary_replay::dump (bool simple) const +{ + dump (stderr, simple); +} + +} // namespace ana + +#endif /* #if ENABLE_ANALYZER */ diff --git a/gcc/analyzer/call-summary.h b/gcc/analyzer/call-summary.h new file mode 100644 index 0000000..07cd3f5 --- /dev/null +++ b/gcc/analyzer/call-summary.h @@ -0,0 +1,117 @@ +/* Classes for working with summaries of function calls. + Copyright (C) 2022 David Malcolm <dmalcolm@redhat.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_ANALYZER_CALL_SUMMARY_H +#define GCC_ANALYZER_CALL_SUMMARY_H + +namespace ana { + +/* A class summarizing one particular outcome of a function that + we've already analyzed. + This lets us efficiently replay the analysis when we see calls + to the function, providing an approximation of the behavior of + the function without having to execute within the function itself. */ + +class call_summary +{ +public: + call_summary (per_function_data *per_fn_data, + const exploded_node *enode) + : m_per_fn_data (per_fn_data), + m_enode (enode) + {} + const program_state &get_state () const; + tree get_fndecl () const; + + label_text get_desc () const; + + void dump_to_pp (const extrinsic_state &ext_state, + pretty_printer *pp, + bool simple) const; + void dump (const extrinsic_state &ext_state, FILE *fp, bool simple) const; + void dump (const extrinsic_state &ext_state, bool simple) const; + +private: + void get_user_facing_desc (pretty_printer *pp) const; + + per_function_data *const m_per_fn_data; + const exploded_node *const m_enode; +}; + +/* A class for handling replaying a specific call summary at + a specific call site. + + Supports remapping svalues and regions, e.g. remapping + INIT_VAL(param of callee) + to: + whatever that argument is at the call site. */ + +class call_summary_replay +{ +public: + call_summary_replay (const call_details &cd, + function *called_fn, + call_summary *m_summary, + const extrinsic_state &ext_state); + + const call_details &get_call_details () const { return m_cd; } + const gcall *get_call_stmt () const { return m_cd.get_call_stmt (); } + region_model_manager *get_manager () const { return m_cd.get_manager (); } + store_manager *get_store_manager () const + { + return get_manager ()->get_store_manager (); + } + region_model_context *get_ctxt () const { return m_cd.get_ctxt (); } + region_model *get_caller_model () const { return m_cd.get_model (); } + + const svalue *convert_svalue_from_summary (const svalue *); + const region *convert_region_from_summary (const region *); + const binding_key *convert_key_from_summary (const binding_key *); + + void add_svalue_mapping (const svalue *summary_sval, + const svalue *caller_sval); + void add_region_mapping (const region *summary_sval, + const region *caller_sval); + + void dump_to_pp (pretty_printer *pp, bool simple) const; + void dump (FILE *fp, bool simple) const; + void dump (bool simple) const; + +private: + DISABLE_COPY_AND_ASSIGN (call_summary_replay); + + const svalue *convert_svalue_from_summary_1 (const svalue *); + const region *convert_region_from_summary_1 (const region *); + + const call_details &m_cd; + call_summary *m_summary; + const extrinsic_state &m_ext_state; + + // Mapping from svalues in summary to svalues for callsite: + typedef hash_map <const svalue *, const svalue *> svalue_map_t; + svalue_map_t m_map_svalue_from_summary_to_caller; + + // Mapping from regions in summary to regions for callsite: + typedef hash_map <const region *, const region *> region_map_t; + region_map_t m_map_region_from_summary_to_caller; +}; + +} // namespace ana + +#endif /* GCC_ANALYZER_CALL_SUMMARY_H */ diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc index 22bae2f..371111b 100644 --- a/gcc/analyzer/checker-path.cc +++ b/gcc/analyzer/checker-path.cc @@ -28,26 +28,18 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "gimple-pretty-print.h" #include "fold-const.h" -#include "function.h" #include "diagnostic-path.h" #include "options.h" #include "cgraph.h" -#include "function.h" #include "cfg.h" #include "digraph.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" #include "diagnostic-event-id.h" -#include "shortest-paths.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" #include "sbitmap.h" #include "bitmap.h" -#include "tristate.h" #include "ordered-hash-map.h" -#include "selftest.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" diff --git a/gcc/analyzer/complexity.cc b/gcc/analyzer/complexity.cc index 40ae8f7..39fbbc1 100644 --- a/gcc/analyzer/complexity.cc +++ b/gcc/analyzer/complexity.cc @@ -38,11 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "fold-const.h" #include "tree-pretty-print.h" -#include "tristate.h" #include "bitmap.h" -#include "selftest.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "options.h" diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc index 4133a13..96ae073 100644 --- a/gcc/analyzer/constraint-manager.cc +++ b/gcc/analyzer/constraint-manager.cc @@ -30,8 +30,6 @@ along with GCC; see the file COPYING3. If not see #include "selftest.h" #include "diagnostic-core.h" #include "graphviz.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "ordered-hash-map.h" #include "options.h" @@ -41,13 +39,13 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/supergraph.h" #include "sbitmap.h" #include "bitmap.h" -#include "tristate.h" #include "analyzer/analyzer-logging.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/constraint-manager.h" +#include "analyzer/call-summary.h" #include "analyzer/analyzer-selftests.h" #include "tree-pretty-print.h" @@ -3043,6 +3041,60 @@ constraint_manager::for_each_fact (fact_visitor *visitor) const } } +/* Subclass of fact_visitor for use by + constraint_manager::replay_call_summary. */ + +class replay_fact_visitor : public fact_visitor +{ +public: + replay_fact_visitor (call_summary_replay &r, + constraint_manager *out) + : m_r (r), m_out (out), m_feasible (true) + {} + + bool feasible_p () const { return m_feasible; } + + void on_fact (const svalue *lhs, enum tree_code code, const svalue *rhs) + final override + { + const svalue *caller_lhs = m_r.convert_svalue_from_summary (lhs); + if (!caller_lhs) + return; + const svalue *caller_rhs = m_r.convert_svalue_from_summary (rhs); + if (!caller_rhs) + return; + if (!m_out->add_constraint (caller_lhs, code, caller_rhs)) + m_feasible = false; + } + + void on_ranges (const svalue *lhs_sval, + const bounded_ranges *ranges) final override + { + const svalue *caller_lhs = m_r.convert_svalue_from_summary (lhs_sval); + if (!caller_lhs) + return; + if (!m_out->add_bounded_ranges (caller_lhs, ranges)) + m_feasible = false; + } + +private: + call_summary_replay &m_r; + constraint_manager *m_out; + bool m_feasible; +}; + +/* Attempt to use R to replay the constraints from SUMMARY into this object. + Return true if it is feasible. */ + +bool +constraint_manager::replay_call_summary (call_summary_replay &r, + const constraint_manager &summary) +{ + replay_fact_visitor v (r, this); + summary.for_each_fact (&v); + return v.feasible_p (); +} + /* Assert that this object is valid. */ void diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h index 1271f18..daacaa3 100644 --- a/gcc/analyzer/constraint-manager.h +++ b/gcc/analyzer/constraint-manager.h @@ -487,6 +487,9 @@ public: bounded_ranges_manager *get_range_manager () const; + bool replay_call_summary (call_summary_replay &r, + const constraint_manager &summary); + auto_delete_vec<equiv_class> m_equiv_classes; auto_vec<constraint> m_constraints; auto_vec<bounded_ranges_constraint> m_bounded_ranges_constraints; diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 2d185a1..695bde5 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -29,15 +29,8 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "diagnostic-event-id.h" #include "diagnostic-path.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" -#include "shortest-paths.h" -#include "sbitmap.h" #include "bitmap.h" -#include "tristate.h" -#include "selftest.h" #include "ordered-hash-map.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 742ac02..46bcaed 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -25,9 +25,6 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "fold-const.h" #include "gcc-rich-location.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" -#include "shortest-paths.h" #include "diagnostic-core.h" #include "diagnostic-event-id.h" #include "diagnostic-path.h" @@ -35,10 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "pretty-print.h" #include "sbitmap.h" #include "bitmap.h" -#include "tristate.h" #include "ordered-hash-map.h" -#include "selftest.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/call-string.h" @@ -72,6 +66,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "tree-dfa.h" #include "analyzer/known-function-manager.h" +#include "analyzer/call-summary.h" /* For an overview, see gcc/doc/analyzer.texi. */ @@ -171,6 +166,8 @@ void impl_region_model_context::on_unknown_change (const svalue *sval, bool is_mutable) { + if (!sval->can_have_associated_state_p ()) + return; for (sm_state_map *smap : m_new_state->m_checker_states) smap->on_unknown_change (sval, is_mutable, m_ext_state); } @@ -1425,6 +1422,25 @@ exploded_node::on_stmt (exploded_graph &eg, &old_state, state, uncertainty, path_ctxt, stmt); + /* Handle call summaries here. */ + if (cgraph_edge *cgedge + = supergraph_call_edge (snode->get_function (), stmt)) + if (eg.get_analysis_plan ().use_summary_p (cgedge)) + { + function *called_fn = get_ultimate_function_for_cgraph_edge (cgedge); + per_function_data *called_fn_data + = eg.get_per_function_data (called_fn); + if (called_fn_data) + return replay_call_summaries (eg, + snode, + as_a <const gcall *> (stmt), + state, + path_ctxt, + called_fn, + called_fn_data, + &ctxt); + } + bool unknown_side_effects = false; bool terminate_path = false; @@ -1520,6 +1536,140 @@ exploded_node::on_stmt_post (const gimple *stmt, state->m_region_model->on_call_post (call, unknown_side_effects, ctxt); } +/* A concrete call_info subclass representing a replay of a call summary. */ + +class call_summary_edge_info : public call_info +{ +public: + call_summary_edge_info (const call_details &cd, + function *called_fn, + call_summary *summary, + const extrinsic_state &ext_state) + : call_info (cd), + m_called_fn (called_fn), + m_summary (summary), + m_ext_state (ext_state) + {} + + bool update_state (program_state *state, + const exploded_edge *, + region_model_context *ctxt) const final override + { + /* Update STATE based on summary_end_state. */ + call_details cd (get_call_details (state->m_region_model, ctxt)); + call_summary_replay r (cd, m_called_fn, m_summary, m_ext_state); + const program_state &summary_end_state = m_summary->get_state (); + return state->replay_call_summary (r, summary_end_state); + } + + bool update_model (region_model *model, + const exploded_edge *, + region_model_context *ctxt) const final override + { + /* Update STATE based on summary_end_state. */ + call_details cd (get_call_details (model, ctxt)); + call_summary_replay r (cd, m_called_fn, m_summary, m_ext_state); + const program_state &summary_end_state = m_summary->get_state (); + model->replay_call_summary (r, *summary_end_state.m_region_model); + return true; + } + + label_text get_desc (bool /*can_colorize*/) const final override + { + return m_summary->get_desc (); + } + +private: + function *m_called_fn; + call_summary *m_summary; + const extrinsic_state &m_ext_state; +}; + +/* Use PATH_CTXT to bifurcate, which when handled will add custom edges + for a replay of the various feasible summaries in CALLED_FN_DATA. */ + +exploded_node::on_stmt_flags +exploded_node::replay_call_summaries (exploded_graph &eg, + const supernode *snode, + const gcall *call_stmt, + program_state *state, + path_context *path_ctxt, + function *called_fn, + per_function_data *called_fn_data, + region_model_context *ctxt) +{ + logger *logger = eg.get_logger (); + LOG_SCOPE (logger); + + gcc_assert (called_fn); + gcc_assert (called_fn_data); + + /* Each summary will call bifurcate on the PATH_CTXT. */ + for (auto summary : called_fn_data->m_summaries) + replay_call_summary (eg, snode, call_stmt, state, + path_ctxt, called_fn, summary, ctxt); + path_ctxt->terminate_path (); + + return on_stmt_flags (); +} + +/* Use PATH_CTXT to bifurcate, which when handled will add a + custom edge for a replay of SUMMARY, if the summary's + conditions are feasible based on the current state. */ + +void +exploded_node::replay_call_summary (exploded_graph &eg, + const supernode *snode, + const gcall *call_stmt, + program_state *old_state, + path_context *path_ctxt, + function *called_fn, + call_summary *summary, + region_model_context *ctxt) +{ + logger *logger = eg.get_logger (); + LOG_SCOPE (logger); + gcc_assert (snode); + gcc_assert (call_stmt); + gcc_assert (old_state); + gcc_assert (called_fn); + gcc_assert (summary); + + if (logger) + logger->log ("using %s as summary for call to %qE from %qE", + summary->get_desc ().get (), + called_fn->decl, + snode->get_function ()->decl); + const extrinsic_state &ext_state = eg.get_ext_state (); + const program_state &summary_end_state = summary->get_state (); + if (logger) + { + pretty_printer *pp = logger->get_printer (); + + logger->start_log_line (); + pp_string (pp, "callsite state: "); + old_state->dump_to_pp (ext_state, true, false, pp); + logger->end_log_line (); + + logger->start_log_line (); + pp_string (pp, "summary end state: "); + summary_end_state.dump_to_pp (ext_state, true, false, pp); + logger->end_log_line (); + } + + program_state new_state (*old_state); + + call_details cd (call_stmt, new_state.m_region_model, ctxt); + call_summary_replay r (cd, called_fn, summary, ext_state); + + if (path_ctxt) + path_ctxt->bifurcate (new call_summary_edge_info (cd, + called_fn, + summary, + ext_state)); +} + + /* Consider the effect of following superedge SUCC from this node. Return true if it's feasible to follow the edge, or false @@ -2115,6 +2265,20 @@ stats::get_total_enodes () const return result; } +/* struct per_function_data. */ + +per_function_data::~per_function_data () +{ + for (auto iter : m_summaries) + delete iter; +} + +void +per_function_data::add_call_summary (exploded_node *node) +{ + m_summaries.safe_push (new call_summary (this, node)); +} + /* strongly_connected_components's ctor. Tarjan's SCC algorithm. */ strongly_connected_components:: @@ -3980,7 +4144,7 @@ exploded_graph::process_node (exploded_node *node) NULL, // uncertainty_t *uncertainty NULL, // path_context *path_ctxt stmt); - if (edge_info->update_model (bifurcated_new_state.m_region_model, + if (edge_info->update_state (&bifurcated_new_state, NULL, /* no exploded_edge yet. */ &bifurcation_ctxt)) { @@ -5350,24 +5514,17 @@ public: pretty_printer *pp = gv->get_pp (); dump_dot_id (pp); - pp_printf (pp, " [shape=none,margin=0,style=filled,fillcolor=%s,label=<", + pp_printf (pp, " [shape=none,margin=0,style=filled,fillcolor=%s,label=\"", "lightgrey"); - pp_string (pp, "<TABLE BORDER=\"0\">"); pp_write_text_to_stream (pp); - gv->begin_trtd (); pp_printf (pp, "VCG: %i: %s", m_index, function_name (m_fun)); - gv->end_tdtr (); pp_newline (pp); - gv->begin_trtd (); pp_printf (pp, "supernodes: %i\n", m_num_supernodes); - gv->end_tdtr (); pp_newline (pp); - gv->begin_trtd (); pp_printf (pp, "superedges: %i\n", m_num_superedges); - gv->end_tdtr (); pp_newline (pp); if (args.m_eg) @@ -5380,9 +5537,7 @@ public: if (enode->get_point ().get_function () == m_fun) num_enodes++; } - gv->begin_trtd (); pp_printf (pp, "enodes: %i\n", num_enodes); - gv->end_tdtr (); pp_newline (pp); // TODO: also show the per-callstring breakdown @@ -5404,11 +5559,8 @@ public: } if (num_enodes > 0) { - gv->begin_trtd (); cs->print (pp); pp_printf (pp, ": %i\n", num_enodes); - pp_write_text_as_html_like_dot_to_stream (pp); - gv->end_tdtr (); } } @@ -5417,14 +5569,20 @@ public: if (data) { pp_newline (pp); - gv->begin_trtd (); pp_printf (pp, "summaries: %i\n", data->m_summaries.length ()); - pp_write_text_as_html_like_dot_to_stream (pp); - gv->end_tdtr (); + for (auto summary : data->m_summaries) + { + pp_printf (pp, "\nsummary: %s:\n", summary->get_desc ().get ()); + const extrinsic_state &ext_state = args.m_eg->get_ext_state (); + const program_state &state = summary->get_state (); + state.dump_to_pp (ext_state, false, true, pp); + pp_newline (pp); + } } } - pp_string (pp, "</TABLE>>];\n\n"); + pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true); + pp_string (pp, "\"];\n\n"); pp_flush (pp); } diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index f957568..11e46ca 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -21,6 +21,15 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_ANALYZER_EXPLODED_GRAPH_H #define GCC_ANALYZER_EXPLODED_GRAPH_H +#include "alloc-pool.h" +#include "fibonacci_heap.h" +#include "supergraph.h" +#include "sbitmap.h" +#include "shortest-paths.h" +#include "analyzer/sm.h" +#include "analyzer/program-state.h" +#include "analyzer/diagnostic-manager.h" + namespace ana { /* Concrete implementation of region_model_context, wiring it up to the @@ -258,6 +267,23 @@ class exploded_node : public dnode<eg_traits> bool unknown_side_effects, region_model_context *ctxt); + on_stmt_flags replay_call_summaries (exploded_graph &eg, + const supernode *snode, + const gcall *call_stmt, + program_state *state, + path_context *path_ctxt, + function *called_fn, + per_function_data *called_fn_data, + region_model_context *ctxt); + void replay_call_summary (exploded_graph &eg, + const supernode *snode, + const gcall *call_stmt, + program_state *state, + path_context *path_ctxt, + function *called_fn, + call_summary *summary, + region_model_context *ctxt); + bool on_edge (exploded_graph &eg, const superedge *succ, program_point *next_point, @@ -611,13 +637,11 @@ struct per_call_string_data struct per_function_data { per_function_data () {} + ~per_function_data (); - void add_call_summary (exploded_node *node) - { - m_summaries.safe_push (node); - } + void add_call_summary (exploded_node *node); - auto_vec<exploded_node *> m_summaries; + auto_vec<call_summary *> m_summaries; }; diff --git a/gcc/analyzer/feasible-graph.cc b/gcc/analyzer/feasible-graph.cc index fe7e79f..a946e4c 100644 --- a/gcc/analyzer/feasible-graph.cc +++ b/gcc/analyzer/feasible-graph.cc @@ -29,15 +29,8 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "diagnostic-event-id.h" #include "diagnostic-path.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" -#include "shortest-paths.h" -#include "sbitmap.h" #include "bitmap.h" -#include "tristate.h" -#include "selftest.h" #include "ordered-hash-map.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" diff --git a/gcc/analyzer/known-function-manager.cc b/gcc/analyzer/known-function-manager.cc index f0fd4fc..48fb005 100644 --- a/gcc/analyzer/known-function-manager.cc +++ b/gcc/analyzer/known-function-manager.cc @@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" -#include "function.h" #include "analyzer/analyzer.h" #include "diagnostic-core.h" #include "analyzer/analyzer-logging.h" diff --git a/gcc/analyzer/known-function-manager.h b/gcc/analyzer/known-function-manager.h index fbde853..2b95b7e 100644 --- a/gcc/analyzer/known-function-manager.h +++ b/gcc/analyzer/known-function-manager.h @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_ANALYZER_KNOWN_FUNCTION_MANAGER_H #define GCC_ANALYZER_KNOWN_FUNCTION_MANAGER_H +#include "analyzer/analyzer-logging.h" + namespace ana { class known_function_manager : public log_user diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc index eff050f..50a8afc 100644 --- a/gcc/analyzer/pending-diagnostic.cc +++ b/gcc/analyzer/pending-diagnostic.cc @@ -24,8 +24,6 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "intl.h" #include "diagnostic.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -34,8 +32,6 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" #include "analyzer/diagnostic-manager.h" -#include "selftest.h" -#include "tristate.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" @@ -50,10 +46,6 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "analyzer/supergraph.h" #include "analyzer/program-state.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" -#include "shortest-paths.h" -#include "sbitmap.h" #include "analyzer/exploded-graph.h" #include "diagnostic-path.h" #include "analyzer/checker-path.h" diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc index 6c296d5..cfa4dda 100644 --- a/gcc/analyzer/program-point.cc +++ b/gcc/analyzer/program-point.cc @@ -24,7 +24,6 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "gimple-pretty-print.h" #include "gcc-rich-location.h" -#include "json.h" #include "ordered-hash-map.h" #include "options.h" #include "cgraph.h" @@ -41,14 +40,11 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/program-point.h" #include "sbitmap.h" #include "bitmap.h" -#include "tristate.h" #include "selftest.h" #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/sm.h" #include "analyzer/program-state.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" #include "diagnostic-event-id.h" #include "analyzer/pending-diagnostic.h" #include "analyzer/diagnostic-manager.h" diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h index 63f7224..f72b86d 100644 --- a/gcc/analyzer/program-point.h +++ b/gcc/analyzer/program-point.h @@ -21,6 +21,9 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_ANALYZER_PROGRAM_POINT_H #define GCC_ANALYZER_PROGRAM_POINT_H +#include "pretty-print.h" +#include "analyzer/call-string.h" + namespace ana { class exploded_graph; diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index f0f4046..7537dc0 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -24,14 +24,11 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "diagnostic-core.h" #include "diagnostic.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" #include "sbitmap.h" #include "bitmap.h" -#include "tristate.h" #include "ordered-hash-map.h" #include "selftest.h" #include "analyzer/call-string.h" @@ -40,9 +37,6 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/region-model.h" #include "analyzer/program-state.h" #include "analyzer/constraint-manager.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" -#include "shortest-paths.h" #include "diagnostic-event-id.h" #include "analyzer/pending-diagnostic.h" #include "analyzer/diagnostic-manager.h" @@ -56,6 +50,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/program-state.h" #include "analyzer/exploded-graph.h" #include "analyzer/state-purge.h" +#include "analyzer/call-summary.h" #include "analyzer/analyzer-selftests.h" #if ENABLE_ANALYZER @@ -743,6 +738,31 @@ program_state::program_state (const extrinsic_state &ext_state) } } +/* Attempt to to use R to replay SUMMARY into this object. + Return true if it is possible. */ + +bool +sm_state_map::replay_call_summary (call_summary_replay &r, + const sm_state_map &summary) +{ + for (auto kv : summary.m_map) + { + const svalue *summary_sval = kv.first; + const svalue *caller_sval = r.convert_svalue_from_summary (summary_sval); + if (!caller_sval) + continue; + const svalue *summary_origin = kv.second.m_origin; + const svalue *caller_origin + = (summary_origin + ? r.convert_svalue_from_summary (summary_origin) + : NULL); + // caller_origin can be NULL. + m_map.put (caller_sval, entry_t (kv.second.m_state, caller_origin)); + } + m_global_state = summary.m_global_state; + return true; +} + /* program_state's copy ctor. */ program_state::program_state (const program_state &other) @@ -1437,6 +1457,28 @@ program_state::detect_leaks (const program_state &src_state, dest_state.m_region_model->unset_dynamic_extents (reg); } +/* Attempt to to use R to replay SUMMARY into this object. + Return true if it is possible. */ + +bool +program_state::replay_call_summary (call_summary_replay &r, + const program_state &summary) +{ + if (!m_region_model->replay_call_summary (r, *summary.m_region_model)) + return false; + + for (unsigned sm_idx = 0; sm_idx < m_checker_states.length (); sm_idx++) + { + const sm_state_map *summary_sm_map = summary.m_checker_states[sm_idx]; + m_checker_states[sm_idx]->replay_call_summary (r, *summary_sm_map); + } + + if (!summary.m_valid) + m_valid = false; + + return true; +} + /* Handle calls to "__analyzer_dump_state". */ void diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h index baab787..ad40578 100644 --- a/gcc/analyzer/program-state.h +++ b/gcc/analyzer/program-state.h @@ -171,6 +171,9 @@ public: static const svalue * canonicalize_svalue (const svalue *sval, const extrinsic_state &ext_state); + bool replay_call_summary (call_summary_replay &r, + const sm_state_map &summary); + private: const state_machine &m_sm; map_t m_map; @@ -273,6 +276,9 @@ public: const extrinsic_state &ext_state, region_model_context *ctxt); + bool replay_call_summary (call_summary_replay &r, + const program_state &summary); + void impl_call_analyzer_dump_state (const gcall *call, const extrinsic_state &ext_state, region_model_context *ctxt); diff --git a/gcc/analyzer/region-model-asm.cc b/gcc/analyzer/region-model-asm.cc index bb73e6e..b4c1f91 100644 --- a/gcc/analyzer/region-model-asm.cc +++ b/gcc/analyzer/region-model-asm.cc @@ -28,9 +28,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple-iterator.h" #include "diagnostic-core.h" #include "pretty-print.h" -#include "tristate.h" -#include "selftest.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "options.h" diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc index 71fb277..8f4940a 100644 --- a/gcc/analyzer/region-model-impl-calls.cc +++ b/gcc/analyzer/region-model-impl-calls.cc @@ -38,18 +38,11 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "diagnostic-color.h" #include "diagnostic-metadata.h" -#include "tristate.h" #include "bitmap.h" -#include "selftest.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "ordered-hash-map.h" #include "options.h" -#include "cgraph.h" -#include "cfg.h" -#include "digraph.h" #include "analyzer/supergraph.h" #include "sbitmap.h" #include "analyzer/call-string.h" @@ -374,6 +367,16 @@ region_model::impl_call_analyzer_eval (const gcall *call, warning_at (call->location, 0, "%s", t.as_string ()); } +/* Handle the on_call_pre part of "__analyzer_get_unknown_ptr". */ + +void +region_model::impl_call_analyzer_get_unknown_ptr (const call_details &cd) +{ + const svalue *ptr_sval + = m_mgr->get_or_create_unknown_svalue (cd.get_lhs_type ()); + cd.maybe_set_lhs (ptr_sval); +} + /* Handle the on_call_pre part of "__builtin_expect" etc. */ void diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index cbda77f..f5999e6 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -38,18 +38,11 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "fold-const.h" #include "tree-pretty-print.h" -#include "tristate.h" #include "bitmap.h" -#include "selftest.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "ordered-hash-map.h" #include "options.h" -#include "cgraph.h" -#include "cfg.h" -#include "digraph.h" #include "analyzer/supergraph.h" #include "sbitmap.h" #include "analyzer/call-string.h" @@ -432,6 +425,17 @@ region_model_manager::maybe_fold_unaryop (tree type, enum tree_code op, } } break; + case NEGATE_EXPR: + { + /* -(-(VAL)) is VAL, for integer types. */ + if (const unaryop_svalue *unaryop = arg->dyn_cast_unaryop_svalue ()) + if (unaryop->get_op () == NEGATE_EXPR + && type == unaryop->get_type () + && type + && INTEGRAL_TYPE_P (type)) + return unaryop->get_arg (); + } + break; } /* Constants. */ @@ -1143,10 +1147,11 @@ region_model_manager::get_or_create_unmergeable (const svalue *arg) and ITER_SVAL at POINT, creating it if necessary. */ const svalue * -region_model_manager::get_or_create_widening_svalue (tree type, - const program_point &point, - const svalue *base_sval, - const svalue *iter_sval) +region_model_manager:: +get_or_create_widening_svalue (tree type, + const function_point &point, + const svalue *base_sval, + const svalue *iter_sval) { gcc_assert (base_sval->get_kind () != SK_WIDENING); gcc_assert (iter_sval->get_kind () != SK_WIDENING); @@ -1263,6 +1268,33 @@ get_or_create_asm_output_svalue (tree type, return asm_output_sval; } +/* Return the svalue * of type TYPE for OUTPUT_IDX of a deterministic + asm stmt with string ASM_STRING with NUM_OUTPUTS outputs, given + INPUTS as inputs. */ + +const svalue * +region_model_manager:: +get_or_create_asm_output_svalue (tree type, + const char *asm_string, + unsigned output_idx, + unsigned num_outputs, + const vec<const svalue *> &inputs) +{ + gcc_assert (inputs.length () <= asm_output_svalue::MAX_INPUTS); + + if (const svalue *folded + = maybe_fold_asm_output_svalue (type, inputs)) + return folded; + + asm_output_svalue::key_t key (type, asm_string, output_idx, inputs); + if (asm_output_svalue **slot = m_asm_output_values_map.get (key)) + return *slot; + asm_output_svalue *asm_output_sval + = new asm_output_svalue (type, asm_string, output_idx, num_outputs, inputs); + RETURN_UNKNOWN_IF_TOO_COMPLEX (asm_output_sval); + m_asm_output_values_map.put (key, asm_output_sval); + return asm_output_sval; +} /* Return the svalue * of type TYPE for the result of a call to FNDECL with __attribute__((const)), given INPUTS as inputs. */ diff --git a/gcc/analyzer/region-model-manager.h b/gcc/analyzer/region-model-manager.h new file mode 100644 index 0000000..3d8f76e --- /dev/null +++ b/gcc/analyzer/region-model-manager.h @@ -0,0 +1,318 @@ +/* Consolidation of svalues and regions. + Copyright (C) 2020-2022 Free Software Foundation, Inc. + Contributed by David Malcolm <dmalcolm@redhat.com>. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_ANALYZER_REGION_MODEL_MANAGER_H +#define GCC_ANALYZER_REGION_MODEL_MANAGER_H + +namespace ana { + +/* A class responsible for owning and consolidating region and svalue + instances. + region and svalue instances are immutable as far as clients are + concerned, so they are provided as "const" ptrs. */ + +class region_model_manager +{ +public: + region_model_manager (logger *logger = NULL); + ~region_model_manager (); + + /* call_string consolidation. */ + const call_string &get_empty_call_string () const + { + return m_empty_call_string; + } + + /* svalue consolidation. */ + const svalue *get_or_create_constant_svalue (tree cst_expr); + const svalue *get_or_create_int_cst (tree type, poly_int64); + const svalue *get_or_create_unknown_svalue (tree type); + const svalue *get_or_create_setjmp_svalue (const setjmp_record &r, + tree type); + const svalue *get_or_create_poisoned_svalue (enum poison_kind kind, + tree type); + const svalue *get_or_create_initial_value (const region *reg); + const svalue *get_ptr_svalue (tree ptr_type, const region *pointee); + const svalue *get_or_create_unaryop (tree type, enum tree_code op, + const svalue *arg); + const svalue *get_or_create_cast (tree type, const svalue *arg); + const svalue *get_or_create_binop (tree type, + enum tree_code op, + const svalue *arg0, const svalue *arg1); + const svalue *get_or_create_sub_svalue (tree type, + const svalue *parent_svalue, + const region *subregion); + const svalue *get_or_create_repeated_svalue (tree type, + const svalue *outer_size, + const svalue *inner_svalue); + const svalue *get_or_create_bits_within (tree type, + const bit_range &bits, + const svalue *inner_svalue); + const svalue *get_or_create_unmergeable (const svalue *arg); + const svalue *get_or_create_widening_svalue (tree type, + const function_point &point, + const svalue *base_svalue, + const svalue *iter_svalue); + const svalue *get_or_create_compound_svalue (tree type, + const binding_map &map); + const svalue *get_or_create_conjured_svalue (tree type, const gimple *stmt, + const region *id_reg, + const conjured_purge &p); + const svalue * + get_or_create_asm_output_svalue (tree type, + const gasm *asm_stmt, + unsigned output_idx, + const vec<const svalue *> &inputs); + const svalue * + get_or_create_asm_output_svalue (tree type, + const char *asm_string, + unsigned output_idx, + unsigned num_outputs, + const vec<const svalue *> &inputs); + const svalue * + get_or_create_const_fn_result_svalue (tree type, + tree fndecl, + const vec<const svalue *> &inputs); + + const svalue *maybe_get_char_from_string_cst (tree string_cst, + tree byte_offset_cst); + + /* Dynamically-allocated svalue instances. + The number of these within the analysis can grow arbitrarily. + They are still owned by the manager. */ + const svalue *create_unique_svalue (tree type); + + /* region consolidation. */ + const stack_region * get_stack_region () const { return &m_stack_region; } + const heap_region *get_heap_region () const { return &m_heap_region; } + const code_region *get_code_region () const { return &m_code_region; } + const globals_region *get_globals_region () const + { + return &m_globals_region; + } + const function_region *get_region_for_fndecl (tree fndecl); + const label_region *get_region_for_label (tree label); + const decl_region *get_region_for_global (tree expr); + const region *get_field_region (const region *parent, tree field); + const region *get_element_region (const region *parent, + tree element_type, + const svalue *index); + const region *get_offset_region (const region *parent, + tree type, + const svalue *byte_offset); + const region *get_sized_region (const region *parent, + tree type, + const svalue *byte_size_sval); + const region *get_cast_region (const region *original_region, + tree type); + const frame_region *get_frame_region (const frame_region *calling_frame, + function *fun); + const region *get_symbolic_region (const svalue *sval); + const string_region *get_region_for_string (tree string_cst); + const region *get_bit_range (const region *parent, tree type, + const bit_range &bits); + const var_arg_region *get_var_arg_region (const frame_region *parent, + unsigned idx); + + const region *get_unknown_symbolic_region (tree region_type); + + const region * + get_region_for_unexpected_tree_code (region_model_context *ctxt, + tree t, + const dump_location_t &loc); + + unsigned alloc_region_id () { return m_next_region_id++; } + + store_manager *get_store_manager () { return &m_store_mgr; } + bounded_ranges_manager *get_range_manager () const { return m_range_mgr; } + + known_function_manager *get_known_function_manager () + { + return &m_known_fn_mgr; + } + + /* Dynamically-allocated region instances. + The number of these within the analysis can grow arbitrarily. + They are still owned by the manager. */ + const region *create_region_for_heap_alloc (); + const region *create_region_for_alloca (const frame_region *frame); + + void log_stats (logger *logger, bool show_objs) const; + + void begin_checking_feasibility (void) { m_checking_feasibility = true; } + void end_checking_feasibility (void) { m_checking_feasibility = false; } + + logger *get_logger () const { return m_logger; } + + void dump_untracked_regions () const; + +private: + bool too_complex_p (const complexity &c) const; + bool reject_if_too_complex (svalue *sval); + + const svalue *maybe_fold_unaryop (tree type, enum tree_code op, + const svalue *arg); + const svalue *maybe_fold_binop (tree type, enum tree_code op, + const svalue *arg0, const svalue *arg1); + const svalue *maybe_fold_sub_svalue (tree type, + const svalue *parent_svalue, + const region *subregion); + const svalue *maybe_fold_repeated_svalue (tree type, + const svalue *outer_size, + const svalue *inner_svalue); + const svalue *maybe_fold_bits_within_svalue (tree type, + const bit_range &bits, + const svalue *inner_svalue); + const svalue *maybe_undo_optimize_bit_field_compare (tree type, + const compound_svalue *compound_sval, + tree cst, const svalue *arg1); + const svalue *maybe_fold_asm_output_svalue (tree type, + const vec<const svalue *> &inputs); + + logger *m_logger; + + const call_string m_empty_call_string; + + unsigned m_next_region_id; + root_region m_root_region; + stack_region m_stack_region; + heap_region m_heap_region; + + /* svalue consolidation. */ + typedef hash_map<tree, constant_svalue *> constants_map_t; + constants_map_t m_constants_map; + + typedef hash_map<tree, unknown_svalue *> unknowns_map_t; + unknowns_map_t m_unknowns_map; + const unknown_svalue *m_unknown_NULL; + + typedef hash_map<poisoned_svalue::key_t, + poisoned_svalue *> poisoned_values_map_t; + poisoned_values_map_t m_poisoned_values_map; + + typedef hash_map<setjmp_svalue::key_t, + setjmp_svalue *> setjmp_values_map_t; + setjmp_values_map_t m_setjmp_values_map; + + typedef hash_map<const region *, initial_svalue *> initial_values_map_t; + initial_values_map_t m_initial_values_map; + + typedef hash_map<region_svalue::key_t, region_svalue *> pointer_values_map_t; + pointer_values_map_t m_pointer_values_map; + + typedef hash_map<unaryop_svalue::key_t, + unaryop_svalue *> unaryop_values_map_t; + unaryop_values_map_t m_unaryop_values_map; + + typedef hash_map<binop_svalue::key_t, binop_svalue *> binop_values_map_t; + binop_values_map_t m_binop_values_map; + + typedef hash_map<sub_svalue::key_t, sub_svalue *> sub_values_map_t; + sub_values_map_t m_sub_values_map; + + typedef hash_map<repeated_svalue::key_t, + repeated_svalue *> repeated_values_map_t; + repeated_values_map_t m_repeated_values_map; + + typedef hash_map<bits_within_svalue::key_t, + bits_within_svalue *> bits_within_values_map_t; + bits_within_values_map_t m_bits_within_values_map; + + typedef hash_map<const svalue *, + unmergeable_svalue *> unmergeable_values_map_t; + unmergeable_values_map_t m_unmergeable_values_map; + + typedef hash_map<widening_svalue::key_t, + widening_svalue */*, + widening_svalue::key_t::hash_map_traits*/> + widening_values_map_t; + widening_values_map_t m_widening_values_map; + + typedef hash_map<compound_svalue::key_t, + compound_svalue *> compound_values_map_t; + compound_values_map_t m_compound_values_map; + + typedef hash_map<conjured_svalue::key_t, + conjured_svalue *> conjured_values_map_t; + conjured_values_map_t m_conjured_values_map; + + typedef hash_map<asm_output_svalue::key_t, + asm_output_svalue *> asm_output_values_map_t; + asm_output_values_map_t m_asm_output_values_map; + + typedef hash_map<const_fn_result_svalue::key_t, + const_fn_result_svalue *> const_fn_result_values_map_t; + const_fn_result_values_map_t m_const_fn_result_values_map; + + bool m_checking_feasibility; + + /* "Dynamically-allocated" svalue instances. + The number of these within the analysis can grow arbitrarily. + They are still owned by the manager. */ + auto_delete_vec<svalue> m_managed_dynamic_svalues; + + /* Maximum complexity of svalues that weren't rejected. */ + complexity m_max_complexity; + + /* region consolidation. */ + + code_region m_code_region; + typedef hash_map<tree, function_region *> fndecls_map_t; + typedef fndecls_map_t::iterator fndecls_iterator_t; + fndecls_map_t m_fndecls_map; + + typedef hash_map<tree, label_region *> labels_map_t; + typedef labels_map_t::iterator labels_iterator_t; + labels_map_t m_labels_map; + + globals_region m_globals_region; + typedef hash_map<tree, decl_region *> globals_map_t; + typedef globals_map_t::iterator globals_iterator_t; + globals_map_t m_globals_map; + + consolidation_map<field_region> m_field_regions; + consolidation_map<element_region> m_element_regions; + consolidation_map<offset_region> m_offset_regions; + consolidation_map<sized_region> m_sized_regions; + consolidation_map<cast_region> m_cast_regions; + consolidation_map<frame_region> m_frame_regions; + consolidation_map<symbolic_region> m_symbolic_regions; + + typedef hash_map<tree, string_region *> string_map_t; + string_map_t m_string_map; + + consolidation_map<bit_range_region> m_bit_range_regions; + consolidation_map<var_arg_region> m_var_arg_regions; + + store_manager m_store_mgr; + + bounded_ranges_manager *m_range_mgr; + + known_function_manager m_known_fn_mgr; + + /* "Dynamically-allocated" region instances. + The number of these within the analysis can grow arbitrarily. + They are still owned by the manager. */ + auto_delete_vec<region> m_managed_dynamic_regions; +}; + +} // namespace ana + +#endif /* GCC_ANALYZER_REGION_MODEL_MANAGER_H */ diff --git a/gcc/analyzer/region-model-reachability.cc b/gcc/analyzer/region-model-reachability.cc index 12d09c3..be1372c 100644 --- a/gcc/analyzer/region-model-reachability.cc +++ b/gcc/analyzer/region-model-reachability.cc @@ -36,23 +36,18 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "fold-const.h" #include "tree-pretty-print.h" -#include "tristate.h" #include "bitmap.h" -#include "selftest.h" -#include "function.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "ordered-hash-map.h" #include "options.h" -#include "cgraph.h" -#include "cfg.h" -#include "digraph.h" -#include "json.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/region-model-reachability.h" +#include "diagnostic.h" +#include "tree-diagnostic.h" #if ENABLE_ANALYZER diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 22c5287..81ef41e 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -39,18 +39,14 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "diagnostic-color.h" #include "diagnostic-metadata.h" -#include "tristate.h" #include "bitmap.h" #include "selftest.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "ordered-hash-map.h" #include "options.h" #include "cgraph.h" #include "cfg.h" -#include "digraph.h" #include "analyzer/supergraph.h" #include "sbitmap.h" #include "analyzer/call-string.h" @@ -66,6 +62,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/region-model-reachability.h" #include "analyzer/analyzer-selftests.h" #include "analyzer/program-state.h" +#include "analyzer/call-summary.h" #include "stor-layout.h" #include "attribs.h" #include "tree-object-size.h" @@ -1255,6 +1252,12 @@ region_model::on_stmt_pre (const gimple *stmt, { /* This is handled elsewhere. */ } + else if (is_special_named_call_p (call, "__analyzer_get_unknown_ptr", + 0)) + { + call_details cd (call, this, ctxt); + impl_call_analyzer_get_unknown_ptr (cd); + } else *out_unknown_side_effects = on_call_pre (call, ctxt, out_terminate_path); @@ -5038,11 +5041,8 @@ region_model::maybe_update_for_edge (const superedge &edge, break; case SUPEREDGE_INTRAPROCEDURAL_CALL: - { - const callgraph_superedge *cg_sedge - = as_a <const callgraph_superedge *> (&edge); - update_for_call_summary (*cg_sedge, ctxt); - } + /* This is a no-op for call summaries; we should already + have handled the effect of the call summary at the call stmt. */ break; } @@ -5140,25 +5140,34 @@ region_model::update_for_return_superedge (const return_superedge &return_edge, update_for_return_gcall (call_stmt, ctxt); } -/* Update this region_model with a summary of the effect of calling - and returning from CG_SEDGE. +/* Attempt to to use R to replay SUMMARY into this object. + Return true if it is possible. */ - TODO: Currently this is extremely simplistic: we merely set the - return value to "unknown". A proper implementation would e.g. update - sm-state, and presumably be reworked to support multiple outcomes. */ - -void -region_model::update_for_call_summary (const callgraph_superedge &cg_sedge, - region_model_context *ctxt) +bool +region_model::replay_call_summary (call_summary_replay &r, + const region_model &summary) { - /* For now, set any return value to "unknown". */ - const gcall *call_stmt = cg_sedge.get_call_stmt (); - tree lhs = gimple_call_lhs (call_stmt); - if (lhs) - mark_region_as_unknown (get_lvalue (lhs, ctxt), - ctxt ? ctxt->get_uncertainty () : NULL); + gcc_assert (summary.get_stack_depth () == 1); + + m_store.replay_call_summary (r, summary.m_store); - // TODO: actually implement some kind of summary here + if (!m_constraints->replay_call_summary (r, *summary.m_constraints)) + return false; + + for (auto kv : summary.m_dynamic_extents) + { + const region *summary_reg = kv.first; + const region *caller_reg = r.convert_region_from_summary (summary_reg); + if (!caller_reg) + continue; + const svalue *summary_sval = kv.second; + const svalue *caller_sval = r.convert_svalue_from_summary (summary_sval); + if (!caller_sval) + continue; + m_dynamic_extents.put (caller_reg, caller_sval); + } + + return true; } /* Given a true or false edge guarded by conditional statement COND_STMT, @@ -7123,6 +7132,57 @@ test_sub_svalue_folding () ASSERT_EQ (sub->get_type (), TREE_TYPE (ct.m_x_field)); } +/* Get BIT within VAL as a symbolic value within MGR. */ + +static const svalue * +get_bit (region_model_manager *mgr, + bit_offset_t bit, + unsigned HOST_WIDE_INT val) +{ + const svalue *inner_svalue + = mgr->get_or_create_int_cst (unsigned_type_node, val); + return mgr->get_or_create_bits_within (boolean_type_node, + bit_range (bit, 1), + inner_svalue); +} + +/* Verify that bits_within_svalues are folded as expected. */ + +static void +test_bits_within_svalue_folding () +{ + region_model_manager mgr; + + const svalue *zero = mgr.get_or_create_int_cst (boolean_type_node, 0); + const svalue *one = mgr.get_or_create_int_cst (boolean_type_node, 1); + + { + const unsigned val = 0x0000; + for (unsigned bit = 0; bit < 16; bit++) + ASSERT_EQ (get_bit (&mgr, bit, val), zero); + } + + { + const unsigned val = 0x0001; + ASSERT_EQ (get_bit (&mgr, 0, val), one); + for (unsigned bit = 1; bit < 16; bit++) + ASSERT_EQ (get_bit (&mgr, bit, val), zero); + } + + { + const unsigned val = 0x8000; + for (unsigned bit = 0; bit < 15; bit++) + ASSERT_EQ (get_bit (&mgr, bit, val), zero); + ASSERT_EQ (get_bit (&mgr, 15, val), one); + } + + { + const unsigned val = 0xFFFF; + for (unsigned bit = 0; bit < 16; bit++) + ASSERT_EQ (get_bit (&mgr, bit, val), one); + } +} + /* Test that region::descendent_of_p works as expected. */ static void @@ -7956,7 +8016,7 @@ static void test_widening_constraints () { region_model_manager mgr; - program_point point (program_point::origin (mgr)); + function_point point (program_point::origin (mgr).get_function_point ()); tree int_0 = build_int_cst (integer_type_node, 0); tree int_m1 = build_int_cst (integer_type_node, -1); tree int_1 = build_int_cst (integer_type_node, 1); @@ -8479,6 +8539,7 @@ analyzer_region_model_cc_tests () test_unaryop_svalue_folding (); test_binop_svalue_folding (); test_sub_svalue_folding (); + test_bits_within_svalue_folding (); test_descendent_of_p (); test_bit_range_regions (); test_assignment (); diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index e86720a..635a0c2 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -26,9 +26,11 @@ along with GCC; see the file COPYING3. If not see (Zhongxing Xu, Ted Kremenek, and Jian Zhang) http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf */ +#include "selftest.h" #include "analyzer/svalue.h" #include "analyzer/region.h" #include "analyzer/known-function-manager.h" +#include "analyzer/region-model-manager.h" using namespace ana; @@ -230,294 +232,6 @@ public: virtual void visit_region (const region *) {} }; -} // namespace ana - -namespace ana { - -/* A class responsible for owning and consolidating region and svalue - instances. - region and svalue instances are immutable as far as clients are - concerned, so they are provided as "const" ptrs. */ - -class region_model_manager -{ -public: - region_model_manager (logger *logger = NULL); - ~region_model_manager (); - - /* call_string consolidation. */ - const call_string &get_empty_call_string () const - { - return m_empty_call_string; - } - - /* svalue consolidation. */ - const svalue *get_or_create_constant_svalue (tree cst_expr); - const svalue *get_or_create_int_cst (tree type, poly_int64); - const svalue *get_or_create_unknown_svalue (tree type); - const svalue *get_or_create_setjmp_svalue (const setjmp_record &r, - tree type); - const svalue *get_or_create_poisoned_svalue (enum poison_kind kind, - tree type); - const svalue *get_or_create_initial_value (const region *reg); - const svalue *get_ptr_svalue (tree ptr_type, const region *pointee); - const svalue *get_or_create_unaryop (tree type, enum tree_code op, - const svalue *arg); - const svalue *get_or_create_cast (tree type, const svalue *arg); - const svalue *get_or_create_binop (tree type, - enum tree_code op, - const svalue *arg0, const svalue *arg1); - const svalue *get_or_create_sub_svalue (tree type, - const svalue *parent_svalue, - const region *subregion); - const svalue *get_or_create_repeated_svalue (tree type, - const svalue *outer_size, - const svalue *inner_svalue); - const svalue *get_or_create_bits_within (tree type, - const bit_range &bits, - const svalue *inner_svalue); - const svalue *get_or_create_unmergeable (const svalue *arg); - const svalue *get_or_create_widening_svalue (tree type, - const program_point &point, - const svalue *base_svalue, - const svalue *iter_svalue); - const svalue *get_or_create_compound_svalue (tree type, - const binding_map &map); - const svalue *get_or_create_conjured_svalue (tree type, const gimple *stmt, - const region *id_reg, - const conjured_purge &p); - const svalue * - get_or_create_asm_output_svalue (tree type, - const gasm *asm_stmt, - unsigned output_idx, - const vec<const svalue *> &inputs); - const svalue * - get_or_create_const_fn_result_svalue (tree type, - tree fndecl, - const vec<const svalue *> &inputs); - - const svalue *maybe_get_char_from_string_cst (tree string_cst, - tree byte_offset_cst); - - /* Dynamically-allocated svalue instances. - The number of these within the analysis can grow arbitrarily. - They are still owned by the manager. */ - const svalue *create_unique_svalue (tree type); - - /* region consolidation. */ - const stack_region * get_stack_region () const { return &m_stack_region; } - const heap_region *get_heap_region () const { return &m_heap_region; } - const code_region *get_code_region () const { return &m_code_region; } - const globals_region *get_globals_region () const - { - return &m_globals_region; - } - const function_region *get_region_for_fndecl (tree fndecl); - const label_region *get_region_for_label (tree label); - const decl_region *get_region_for_global (tree expr); - const region *get_field_region (const region *parent, tree field); - const region *get_element_region (const region *parent, - tree element_type, - const svalue *index); - const region *get_offset_region (const region *parent, - tree type, - const svalue *byte_offset); - const region *get_sized_region (const region *parent, - tree type, - const svalue *byte_size_sval); - const region *get_cast_region (const region *original_region, - tree type); - const frame_region *get_frame_region (const frame_region *calling_frame, - function *fun); - const region *get_symbolic_region (const svalue *sval); - const string_region *get_region_for_string (tree string_cst); - const region *get_bit_range (const region *parent, tree type, - const bit_range &bits); - const var_arg_region *get_var_arg_region (const frame_region *parent, - unsigned idx); - - const region *get_unknown_symbolic_region (tree region_type); - - const region * - get_region_for_unexpected_tree_code (region_model_context *ctxt, - tree t, - const dump_location_t &loc); - - unsigned alloc_region_id () { return m_next_region_id++; } - - store_manager *get_store_manager () { return &m_store_mgr; } - bounded_ranges_manager *get_range_manager () const { return m_range_mgr; } - - known_function_manager *get_known_function_manager () - { - return &m_known_fn_mgr; - } - - /* Dynamically-allocated region instances. - The number of these within the analysis can grow arbitrarily. - They are still owned by the manager. */ - const region *create_region_for_heap_alloc (); - const region *create_region_for_alloca (const frame_region *frame); - - void log_stats (logger *logger, bool show_objs) const; - - void begin_checking_feasibility (void) { m_checking_feasibility = true; } - void end_checking_feasibility (void) { m_checking_feasibility = false; } - - logger *get_logger () const { return m_logger; } - - void dump_untracked_regions () const; - -private: - bool too_complex_p (const complexity &c) const; - bool reject_if_too_complex (svalue *sval); - - const svalue *maybe_fold_unaryop (tree type, enum tree_code op, - const svalue *arg); - const svalue *maybe_fold_binop (tree type, enum tree_code op, - const svalue *arg0, const svalue *arg1); - const svalue *maybe_fold_sub_svalue (tree type, - const svalue *parent_svalue, - const region *subregion); - const svalue *maybe_fold_repeated_svalue (tree type, - const svalue *outer_size, - const svalue *inner_svalue); - const svalue *maybe_fold_bits_within_svalue (tree type, - const bit_range &bits, - const svalue *inner_svalue); - const svalue *maybe_undo_optimize_bit_field_compare (tree type, - const compound_svalue *compound_sval, - tree cst, const svalue *arg1); - const svalue *maybe_fold_asm_output_svalue (tree type, - const vec<const svalue *> &inputs); - - logger *m_logger; - - const call_string m_empty_call_string; - - unsigned m_next_region_id; - root_region m_root_region; - stack_region m_stack_region; - heap_region m_heap_region; - - /* svalue consolidation. */ - typedef hash_map<tree, constant_svalue *> constants_map_t; - constants_map_t m_constants_map; - - typedef hash_map<tree, unknown_svalue *> unknowns_map_t; - unknowns_map_t m_unknowns_map; - const unknown_svalue *m_unknown_NULL; - - typedef hash_map<poisoned_svalue::key_t, - poisoned_svalue *> poisoned_values_map_t; - poisoned_values_map_t m_poisoned_values_map; - - typedef hash_map<setjmp_svalue::key_t, - setjmp_svalue *> setjmp_values_map_t; - setjmp_values_map_t m_setjmp_values_map; - - typedef hash_map<const region *, initial_svalue *> initial_values_map_t; - initial_values_map_t m_initial_values_map; - - typedef hash_map<region_svalue::key_t, region_svalue *> pointer_values_map_t; - pointer_values_map_t m_pointer_values_map; - - typedef hash_map<unaryop_svalue::key_t, - unaryop_svalue *> unaryop_values_map_t; - unaryop_values_map_t m_unaryop_values_map; - - typedef hash_map<binop_svalue::key_t, binop_svalue *> binop_values_map_t; - binop_values_map_t m_binop_values_map; - - typedef hash_map<sub_svalue::key_t, sub_svalue *> sub_values_map_t; - sub_values_map_t m_sub_values_map; - - typedef hash_map<repeated_svalue::key_t, - repeated_svalue *> repeated_values_map_t; - repeated_values_map_t m_repeated_values_map; - - typedef hash_map<bits_within_svalue::key_t, - bits_within_svalue *> bits_within_values_map_t; - bits_within_values_map_t m_bits_within_values_map; - - typedef hash_map<const svalue *, - unmergeable_svalue *> unmergeable_values_map_t; - unmergeable_values_map_t m_unmergeable_values_map; - - typedef hash_map<widening_svalue::key_t, - widening_svalue */*, - widening_svalue::key_t::hash_map_traits*/> - widening_values_map_t; - widening_values_map_t m_widening_values_map; - - typedef hash_map<compound_svalue::key_t, - compound_svalue *> compound_values_map_t; - compound_values_map_t m_compound_values_map; - - typedef hash_map<conjured_svalue::key_t, - conjured_svalue *> conjured_values_map_t; - conjured_values_map_t m_conjured_values_map; - - typedef hash_map<asm_output_svalue::key_t, - asm_output_svalue *> asm_output_values_map_t; - asm_output_values_map_t m_asm_output_values_map; - - typedef hash_map<const_fn_result_svalue::key_t, - const_fn_result_svalue *> const_fn_result_values_map_t; - const_fn_result_values_map_t m_const_fn_result_values_map; - - bool m_checking_feasibility; - - /* "Dynamically-allocated" svalue instances. - The number of these within the analysis can grow arbitrarily. - They are still owned by the manager. */ - auto_delete_vec<svalue> m_managed_dynamic_svalues; - - /* Maximum complexity of svalues that weren't rejected. */ - complexity m_max_complexity; - - /* region consolidation. */ - - code_region m_code_region; - typedef hash_map<tree, function_region *> fndecls_map_t; - typedef fndecls_map_t::iterator fndecls_iterator_t; - fndecls_map_t m_fndecls_map; - - typedef hash_map<tree, label_region *> labels_map_t; - typedef labels_map_t::iterator labels_iterator_t; - labels_map_t m_labels_map; - - globals_region m_globals_region; - typedef hash_map<tree, decl_region *> globals_map_t; - typedef globals_map_t::iterator globals_iterator_t; - globals_map_t m_globals_map; - - consolidation_map<field_region> m_field_regions; - consolidation_map<element_region> m_element_regions; - consolidation_map<offset_region> m_offset_regions; - consolidation_map<sized_region> m_sized_regions; - consolidation_map<cast_region> m_cast_regions; - consolidation_map<frame_region> m_frame_regions; - consolidation_map<symbolic_region> m_symbolic_regions; - - typedef hash_map<tree, string_region *> string_map_t; - string_map_t m_string_map; - - consolidation_map<bit_range_region> m_bit_range_regions; - consolidation_map<var_arg_region> m_var_arg_regions; - - store_manager m_store_mgr; - - bounded_ranges_manager *m_range_mgr; - - known_function_manager m_known_fn_mgr; - - /* "Dynamically-allocated" region instances. - The number of these within the analysis can grow arbitrarily. - They are still owned by the manager. */ - auto_delete_vec<region> m_managed_dynamic_regions; -}; - struct append_regions_cb_data; /* Helper class for handling calls to functions with known behavior. @@ -631,6 +345,7 @@ class region_model void impl_call_analyzer_dump_escaped (const gcall *call); void impl_call_analyzer_eval (const gcall *call, region_model_context *ctxt); + void impl_call_analyzer_get_unknown_ptr (const call_details &cd); void impl_call_builtin_expect (const call_details &cd); void impl_call_calloc (const call_details &cd); bool impl_call_error (const call_details &cd, unsigned min_args, @@ -816,6 +531,9 @@ class region_model const svalue *get_string_size (const svalue *sval) const; const svalue *get_string_size (const region *reg) const; + bool replay_call_summary (call_summary_replay &r, + const region_model &summary); + void maybe_complain_about_infoleak (const region *dst_reg, const svalue *copied_sval, const region *src_reg, @@ -857,8 +575,6 @@ class region_model region_model_context *ctxt); void update_for_return_superedge (const return_superedge &return_edge, region_model_context *ctxt); - void update_for_call_summary (const callgraph_superedge &cg_sedge, - region_model_context *ctxt); bool apply_constraints_for_gcond (const cfg_superedge &edge, const gcond *cond_stmt, region_model_context *ctxt, @@ -1282,6 +998,10 @@ struct model_merger } bool mergeable_svalue_p (const svalue *) const; + const function_point &get_function_point () const + { + return m_point.get_function_point (); + } const region_model *m_model_a; const region_model *m_model_b; diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 09646bf..da5a13e 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -40,11 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "diagnostic-color.h" #include "diagnostic-metadata.h" -#include "tristate.h" #include "bitmap.h" -#include "selftest.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "ordered-hash-map.h" diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc index 505d598..c4ad91c 100644 --- a/gcc/analyzer/sm-fd.cc +++ b/gcc/analyzer/sm-fd.cc @@ -28,8 +28,6 @@ along with GCC; see the file COPYING3. If not see #include "options.h" #include "diagnostic-path.h" #include "diagnostic-metadata.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -37,8 +35,6 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/pending-diagnostic.h" #include "analyzer/function-set.h" #include "analyzer/analyzer-selftests.h" -#include "tristate.h" -#include "selftest.h" #include "stringpool.h" #include "attribs.h" #include "analyzer/call-string.h" diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc index f6cb29c..13f2507 100644 --- a/gcc/analyzer/sm-file.cc +++ b/gcc/analyzer/sm-file.cc @@ -28,8 +28,6 @@ along with GCC; see the file COPYING3. If not see #include "options.h" #include "diagnostic-path.h" #include "diagnostic-metadata.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" @@ -37,7 +35,6 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/pending-diagnostic.h" #include "analyzer/function-set.h" #include "analyzer/analyzer-selftests.h" -#include "tristate.h" #include "selftest.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index 73c549f..fef6e63 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -29,15 +29,11 @@ along with GCC; see the file COPYING3. If not see #include "bitmap.h" #include "diagnostic-path.h" #include "diagnostic-metadata.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" -#include "tristate.h" -#include "selftest.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc index 9b2ad68..3208132 100644 --- a/gcc/analyzer/sm-pattern-test.cc +++ b/gcc/analyzer/sm-pattern-test.cc @@ -30,15 +30,11 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "diagnostic-path.h" #include "diagnostic-metadata.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" -#include "tristate.h" -#include "selftest.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc index 83c1906..cb5f859 100644 --- a/gcc/analyzer/sm-sensitive.cc +++ b/gcc/analyzer/sm-sensitive.cc @@ -24,14 +24,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "function.h" -#include "function.h" #include "basic-block.h" #include "gimple.h" #include "options.h" #include "diagnostic-path.h" #include "diagnostic-metadata.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index b601f45..e3b08c3 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -31,15 +31,12 @@ along with GCC; see the file COPYING3. If not see #include "bitmap.h" #include "diagnostic-path.h" #include "diagnostic-metadata.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "diagnostic-event-id.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" #include "sbitmap.h" -#include "tristate.h" #include "ordered-hash-map.h" #include "selftest.h" #include "analyzer/call-string.h" @@ -48,13 +45,10 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/region-model.h" #include "analyzer/program-state.h" #include "analyzer/checker-path.h" -#include "digraph.h" #include "cfg.h" #include "gimple-iterator.h" #include "cgraph.h" #include "analyzer/supergraph.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" #include "analyzer/diagnostic-manager.h" #include "shortest-paths.h" #include "analyzer/exploded-graph.h" diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc index f5c0cc1..bc27533 100644 --- a/gcc/analyzer/sm-taint.cc +++ b/gcc/analyzer/sm-taint.cc @@ -30,13 +30,9 @@ along with GCC; see the file COPYING3. If not see #include "options.h" #include "diagnostic-path.h" #include "diagnostic-metadata.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "gimple-iterator.h" -#include "tristate.h" -#include "selftest.h" #include "ordered-hash-map.h" #include "cgraph.h" #include "cfg.h" diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc index d17d5c7..1ab4c21 100644 --- a/gcc/analyzer/sm.cc +++ b/gcc/analyzer/sm.cc @@ -31,11 +31,9 @@ along with GCC; see the file COPYING3. If not see #include "pretty-print.h" #include "diagnostic.h" #include "tree-diagnostic.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" -#include "tristate.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc index 7a061a1..d3f516a 100644 --- a/gcc/analyzer/state-purge.cc +++ b/gcc/analyzer/state-purge.cc @@ -36,24 +36,16 @@ along with GCC; see the file COPYING3. If not see #include "ssa-iterators.h" #include "diagnostic-core.h" #include "gimple-pretty-print.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/call-string.h" -#include "digraph.h" -#include "ordered-hash-map.h" -#include "cfg.h" -#include "gimple-iterator.h" -#include "cgraph.h" #include "analyzer/supergraph.h" #include "analyzer/program-point.h" #include "analyzer/analyzer-logging.h" #include "analyzer/state-purge.h" -#include "tristate.h" -#include "selftest.h" #include "analyzer/store.h" #include "analyzer/region-model.h" #include "gimple-walk.h" +#include "cgraph.h" #if ENABLE_ANALYZER diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index 1857d95..2631ea2 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -38,24 +38,20 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "diagnostic-color.h" #include "diagnostic-metadata.h" -#include "tristate.h" #include "bitmap.h" #include "selftest.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "ordered-hash-map.h" #include "options.h" -#include "cgraph.h" #include "cfg.h" -#include "digraph.h" #include "analyzer/supergraph.h" #include "sbitmap.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" #include "analyzer/region-model.h" +#include "analyzer/call-summary.h" #include "analyzer/analyzer-selftests.h" #include "stor-layout.h" @@ -3130,6 +3126,148 @@ store::loop_replay_fixup (const store *other_store, } } +/* Use R to replay the bindings from SUMMARY into this object. */ + +void +store::replay_call_summary (call_summary_replay &r, + const store &summary) +{ + if (summary.m_called_unknown_fn) + { + /* A call to an external function occurred in the summary. + Hence we need to invalidate our knownledge of globals, + escaped regions, etc. */ + on_unknown_fncall (r.get_call_stmt (), + r.get_store_manager (), + conjured_purge (r.get_caller_model (), + r.get_ctxt ())); + } + + auto_vec<const region *> keys (summary.m_cluster_map.elements ()); + for (auto kv : summary.m_cluster_map) + keys.quick_push (kv.first); + keys.qsort (region::cmp_ptr_ptr); + for (auto base_reg : keys) + replay_call_summary_cluster (r, summary, base_reg); +} + +/* Use R and SUMMARY to replay the bindings in SUMMARY_CLUSTER + into this object. */ + +void +store::replay_call_summary_cluster (call_summary_replay &r, + const store &summary, + const region *summary_base_reg) +{ + const call_details &cd = r.get_call_details (); + region_model_manager *reg_mgr = r.get_manager (); + store_manager *mgr = reg_mgr->get_store_manager (); + const binding_cluster *summary_cluster + = summary.get_cluster (summary_base_reg); + + /* Handle "ESCAPED" and "TOUCHED" flags. */ + if (summary_cluster->escaped_p () || summary_cluster->touched_p ()) + if (const region *caller_reg + = r.convert_region_from_summary (summary_base_reg)) + { + const region *caller_base_reg = caller_reg->get_base_region (); + if (caller_base_reg->tracked_p () + && !caller_base_reg->symbolic_for_unknown_ptr_p ()) + { + binding_cluster *caller_cluster + = get_or_create_cluster (caller_base_reg); + if (summary_cluster->escaped_p ()) + caller_cluster->mark_as_escaped (); + if (summary_cluster->touched_p ()) + caller_cluster->m_touched = true; + } + } + + switch (summary_base_reg->get_kind ()) + { + /* Top-level regions. */ + case RK_FRAME: + case RK_GLOBALS: + case RK_CODE: + case RK_STACK: + case RK_HEAP: + case RK_ROOT: + /* Child regions. */ + case RK_FIELD: + case RK_ELEMENT: + case RK_OFFSET: + case RK_SIZED: + case RK_CAST: + case RK_BIT_RANGE: + /* Other regions. */ + case RK_VAR_ARG: + case RK_UNKNOWN: + /* These should never be the base region of a binding cluster. */ + gcc_unreachable (); + break; + + case RK_FUNCTION: + case RK_LABEL: + case RK_STRING: + /* These can be marked as escaping. */ + break; + + case RK_SYMBOLIC: + { + const symbolic_region *summary_symbolic_reg + = as_a <const symbolic_region *> (summary_base_reg); + const svalue *summary_ptr_sval = summary_symbolic_reg->get_pointer (); + const svalue *caller_ptr_sval + = r.convert_svalue_from_summary (summary_ptr_sval); + if (!caller_ptr_sval) + return; + const region *caller_dest_reg + = cd.get_model ()->deref_rvalue (caller_ptr_sval, + NULL_TREE, + cd.get_ctxt ()); + const svalue *summary_sval + = summary.get_any_binding (mgr, summary_base_reg); + if (!summary_sval) + return; + const svalue *caller_sval + = r.convert_svalue_from_summary (summary_sval); + if (!caller_sval) + caller_sval = + reg_mgr->get_or_create_unknown_svalue (summary_sval->get_type ()); + set_value (mgr, caller_dest_reg, + caller_sval, NULL /* uncertainty_t * */); + } + break; + + case RK_HEAP_ALLOCATED: + case RK_DECL: + { + const region *caller_dest_reg + = r.convert_region_from_summary (summary_base_reg); + if (!caller_dest_reg) + return; + const svalue *summary_sval + = summary.get_any_binding (mgr, summary_base_reg); + if (!summary_sval) + summary_sval = reg_mgr->get_or_create_compound_svalue + (summary_base_reg->get_type (), + summary_cluster->get_map ()); + const svalue *caller_sval + = r.convert_svalue_from_summary (summary_sval); + if (!caller_sval) + caller_sval = + reg_mgr->get_or_create_unknown_svalue (summary_sval->get_type ()); + set_value (mgr, caller_dest_reg, + caller_sval, NULL /* uncertainty_t * */); + } + break; + + case RK_ALLOCA: + /* Ignore bindings of alloca regions in the summary. */ + break; + } +} + #if CHECKING_P namespace selftest { diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h index d172ee7..1087782 100644 --- a/gcc/analyzer/store.h +++ b/gcc/analyzer/store.h @@ -418,6 +418,14 @@ private: } // namespace ana +template <> +template <> +inline bool +is_a_helper <const ana::concrete_binding *>::test (const ana::binding_key *key) +{ + return key->concrete_p (); +} + template <> struct default_hash_traits<ana::concrete_binding> : public member_function_hash_traits<ana::concrete_binding> { @@ -786,6 +794,12 @@ public: void loop_replay_fixup (const store *other_store, region_model_manager *mgr); + void replay_call_summary (call_summary_replay &r, + const store &summary); + void replay_call_summary_cluster (call_summary_replay &r, + const store &summary, + const region *base_reg); + private: void remove_overlapping_bindings (store_manager *mgr, const region *reg, uncertainty_t *uncertainty); diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc index 01e30f7..0e9a325 100644 --- a/gcc/analyzer/supergraph.cc +++ b/gcc/analyzer/supergraph.cc @@ -44,7 +44,6 @@ along with GCC; see the file COPYING3. If not see #include "bitmap.h" #include "cfganal.h" #include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "ordered-hash-map.h" #include "options.h" @@ -62,7 +61,7 @@ namespace ana { /* Get the function of the ultimate alias target being called at EDGE, if any. */ -static function * +function * get_ultimate_function_for_cgraph_edge (cgraph_edge *edge) { cgraph_node *ultimate_node = edge->callee->ultimate_alias_target (); @@ -74,12 +73,13 @@ get_ultimate_function_for_cgraph_edge (cgraph_edge *edge) /* Get the cgraph_edge, but only if there's an underlying function body. */ cgraph_edge * -supergraph_call_edge (function *fun, gimple *stmt) +supergraph_call_edge (function *fun, const gimple *stmt) { - gcall *call = dyn_cast<gcall *> (stmt); + const gcall *call = dyn_cast<const gcall *> (stmt); if (!call) return NULL; - cgraph_edge *edge = cgraph_node::get (fun->decl)->get_edge (stmt); + cgraph_edge *edge + = cgraph_node::get (fun->decl)->get_edge (const_cast <gimple *> (stmt)); if (!edge) return NULL; if (!edge->callee) diff --git a/gcc/analyzer/supergraph.h b/gcc/analyzer/supergraph.h index e9a5be2..f66058c 100644 --- a/gcc/analyzer/supergraph.h +++ b/gcc/analyzer/supergraph.h @@ -21,6 +21,13 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_ANALYZER_SUPERGRAPH_H #define GCC_ANALYZER_SUPERGRAPH_H +#include "ordered-hash-map.h" +#include "cfg.h" +#include "basic-block.h" +#include "gimple.h" +#include "gimple-iterator.h" +#include "digraph.h" + using namespace ana; namespace ana { @@ -605,7 +612,8 @@ class dot_annotator } }; -extern cgraph_edge *supergraph_call_edge (function *fun, gimple *stmt); +extern cgraph_edge *supergraph_call_edge (function *fun, const gimple *stmt); +extern function *get_ultimate_function_for_cgraph_edge (cgraph_edge *edge); } // namespace ana diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc index f5a5f1c..a0838c0 100644 --- a/gcc/analyzer/svalue.cc +++ b/gcc/analyzer/svalue.cc @@ -38,22 +38,16 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "fold-const.h" #include "tree-pretty-print.h" -#include "tristate.h" #include "bitmap.h" -#include "selftest.h" -#include "function.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" -#include "options.h" -#include "cgraph.h" -#include "cfg.h" -#include "digraph.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" #include "analyzer/svalue.h" #include "analyzer/region-model.h" +#include "diagnostic.h" +#include "tree-diagnostic.h" #if ENABLE_ANALYZER @@ -207,7 +201,7 @@ svalue::can_merge_p (const svalue *other, if (maybe_get_constant () && other->maybe_get_constant ()) { return mgr->get_or_create_widening_svalue (other->get_type (), - merger->m_point, + merger->get_function_point (), other, this); } @@ -220,7 +214,7 @@ svalue::can_merge_p (const svalue *other, && binop_sval->get_arg1 ()->get_kind () == SK_CONSTANT && other->get_kind () != SK_WIDENING) return mgr->get_or_create_widening_svalue (other->get_type (), - merger->m_point, + merger->get_function_point (), other, this); /* Merge: (Widen(existing_val, V), existing_val) -> Widen (existing_val, V) @@ -874,7 +868,7 @@ constant_svalue::eval_condition (const constant_svalue *lhs, const svalue * constant_svalue::maybe_fold_bits_within (tree type, - const bit_range &, + const bit_range &bits, region_model_manager *mgr) const { /* Bits within an all-zero value are also all zero. */ @@ -885,6 +879,21 @@ constant_svalue::maybe_fold_bits_within (tree type, else return this; } + + /* Handle the case of extracting a single bit. */ + if (bits.m_size_in_bits == 1 + && TREE_CODE (m_cst_expr) == INTEGER_CST + && type + && INTEGRAL_TYPE_P (type)) + { + unsigned HOST_WIDE_INT bit = bits.m_start_bit_offset.to_uhwi (); + unsigned HOST_WIDE_INT mask = (1 << bit); + unsigned HOST_WIDE_INT val_as_hwi = tree_to_uhwi (m_cst_expr); + unsigned HOST_WIDE_INT masked_val = val_as_hwi & mask; + int result = masked_val ? 1 : 0; + return mgr->get_or_create_int_cst (type, result); + } + /* Otherwise, don't fold. */ return NULL; } @@ -1728,13 +1737,17 @@ unmergeable_svalue::implicitly_live_p (const svalue_set *live_svalues, compound_svalue::compound_svalue (tree type, const binding_map &map) : svalue (calc_complexity (map), type), m_map (map) { - /* All keys within the underlying binding_map are required to be concrete, - not symbolic. */ #if CHECKING_P for (iterator_t iter = begin (); iter != end (); ++iter) { + /* All keys within the underlying binding_map are required to be concrete, + not symbolic. */ const binding_key *key = (*iter).first; gcc_assert (key->concrete_p ()); + + /* We don't nest compound svalues. */ + const svalue *sval = (*iter).second; + gcc_assert (sval->get_kind () != SK_COMPOUND); } #endif } diff --git a/gcc/analyzer/svalue.h b/gcc/analyzer/svalue.h index f4cab0d..382b083 100644 --- a/gcc/analyzer/svalue.h +++ b/gcc/analyzer/svalue.h @@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see #define GCC_ANALYZER_SVALUE_H #include "analyzer/complexity.h" +#include "analyzer/store.h" +#include "analyzer/program-point.h" using namespace ana; @@ -1113,9 +1115,9 @@ public: /* A support class for uniquifying instances of widening_svalue. */ struct key_t { - key_t (tree type, const program_point &point, + key_t (tree type, const function_point &point, const svalue *base_sval, const svalue *iter_sval) - : m_type (type), m_point (point.get_function_point ()), + : m_type (type), m_point (point), m_base_sval (base_sval), m_iter_sval (iter_sval) {} @@ -1153,12 +1155,12 @@ public: DIR_UNKNOWN }; - widening_svalue (tree type, const program_point &point, + widening_svalue (tree type, const function_point &point, const svalue *base_sval, const svalue *iter_sval) : svalue (complexity::from_pair (base_sval->get_complexity (), iter_sval->get_complexity ()), type), - m_point (point.get_function_point ()), + m_point (point), m_base_sval (base_sval), m_iter_sval (iter_sval) { gcc_assert (base_sval->can_have_associated_state_p ()); @@ -1527,6 +1529,7 @@ public: const char *get_asm_string () const { return m_asm_string; } unsigned get_output_idx () const { return m_output_idx; } + unsigned get_num_outputs () const { return m_num_outputs; } unsigned get_num_inputs () const { return m_num_inputs; } const svalue *get_input (unsigned idx) const { return m_input_arr[idx]; } diff --git a/gcc/analyzer/trimmed-graph.cc b/gcc/analyzer/trimmed-graph.cc index 6c85910..9fdb4a9 100644 --- a/gcc/analyzer/trimmed-graph.cc +++ b/gcc/analyzer/trimmed-graph.cc @@ -29,15 +29,8 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "diagnostic-event-id.h" #include "diagnostic-path.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" -#include "shortest-paths.h" -#include "sbitmap.h" #include "bitmap.h" -#include "tristate.h" -#include "selftest.h" #include "ordered-hash-map.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" @@ -48,12 +41,6 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/constraint-manager.h" -#include "cfg.h" -#include "basic-block.h" -#include "gimple.h" -#include "gimple-iterator.h" -#include "cgraph.h" -#include "digraph.h" #include "analyzer/supergraph.h" #include "analyzer/program-state.h" #include "analyzer/exploded-graph.h" diff --git a/gcc/analyzer/varargs.cc b/gcc/analyzer/varargs.cc index 9400086..b2e6cd5 100644 --- a/gcc/analyzer/varargs.cc +++ b/gcc/analyzer/varargs.cc @@ -26,28 +26,17 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple.h" #include "diagnostic-path.h" -#include "json.h" #include "analyzer/analyzer.h" #include "analyzer/analyzer-logging.h" #include "analyzer/sm.h" #include "analyzer/pending-diagnostic.h" -#include "tristate.h" -#include "selftest.h" #include "analyzer/call-string.h" #include "analyzer/program-point.h" #include "analyzer/store.h" #include "analyzer/region-model.h" #include "analyzer/program-state.h" #include "analyzer/checker-path.h" -#include "digraph.h" -#include "ordered-hash-map.h" -#include "cfg.h" -#include "gimple-iterator.h" #include "analyzer/supergraph.h" -#include "alloc-pool.h" -#include "fibonacci_heap.h" -#include "shortest-paths.h" -#include "sbitmap.h" #include "analyzer/diagnostic-manager.h" #include "analyzer/exploded-graph.h" #include "diagnostic-metadata.h" diff --git a/gcc/attribs.cc b/gcc/attribs.cc index b1f1032..27dea74 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -251,6 +251,7 @@ handle_ignored_attributes_option (vec<char *> *v) /* We don't accept '::attr'. */ if (cln == nullptr || cln == opt) { + auto_diagnostic_group d; error ("wrong argument to ignored attributes"); inform (input_location, "valid format is %<ns::attr%> or %<ns::%>"); continue; @@ -732,6 +733,7 @@ decl_attributes (tree *node, tree attributes, int flags, || (spec->max_length >= 0 && nargs > spec->max_length)) { + auto_diagnostic_group d; error ("wrong number of arguments specified for %qE attribute", name); if (spec->max_length < 0) @@ -1167,6 +1169,7 @@ common_function_versions (tree fn1, tree fn2) std::swap (fn1, fn2); attr1 = attr2; } + auto_diagnostic_group d; error_at (DECL_SOURCE_LOCATION (fn2), "missing %<target%> attribute for multi-versioned %qD", fn2); @@ -1642,6 +1645,33 @@ remove_attribute (const char *attr_name, tree list) return list; } +/* Similarly but also match namespace on the removed attributes. + ATTR_NS "" stands for NULL or "gnu" namespace. */ + +tree +remove_attribute (const char *attr_ns, const char *attr_name, tree list) +{ + tree *p; + gcc_checking_assert (attr_name[0] != '_'); + gcc_checking_assert (attr_ns == NULL || attr_ns[0] != '_'); + + for (p = &list; *p;) + { + tree l = *p; + + tree attr = get_attribute_name (l); + if (is_attribute_p (attr_name, attr) + && is_attribute_namespace_p (attr_ns, l)) + { + *p = TREE_CHAIN (l); + continue; + } + p = &TREE_CHAIN (l); + } + + return list; +} + /* Return an attribute list that is the union of a1 and a2. */ tree @@ -2039,6 +2069,45 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list) return list; } +/* Similarly but with also attribute namespace. */ + +tree +private_lookup_attribute (const char *attr_ns, const char *attr_name, + size_t attr_ns_len, size_t attr_len, tree list) +{ + while (list) + { + tree attr = get_attribute_name (list); + size_t ident_len = IDENTIFIER_LENGTH (attr); + if (cmp_attribs (attr_name, attr_len, IDENTIFIER_POINTER (attr), + ident_len)) + { + tree ns = get_attribute_namespace (list); + if (ns == NULL_TREE) + { + if (attr_ns_len == 0) + break; + } + else if (attr_ns) + { + ident_len = IDENTIFIER_LENGTH (ns); + if (attr_ns_len == 0) + { + if (cmp_attribs ("gnu", strlen ("gnu"), + IDENTIFIER_POINTER (ns), ident_len)) + break; + } + else if (cmp_attribs (attr_ns, attr_ns_len, + IDENTIFIER_POINTER (ns), ident_len)) + break; + } + } + list = TREE_CHAIN (list); + } + + return list; +} + /* Return true if the function decl or type NODE has been declared with attribute ANAME among attributes ATTRS. */ diff --git a/gcc/attribs.h b/gcc/attribs.h index 5b6f63e..1dc16e4 100644 --- a/gcc/attribs.h +++ b/gcc/attribs.h @@ -82,6 +82,10 @@ extern tree merge_type_attributes (tree, tree); extern tree remove_attribute (const char *, tree); +/* Similarly but also with specific attribute namespace. */ + +extern tree remove_attribute (const char *, const char *, tree); + /* Given two attributes lists, return a list of their union. */ extern tree merge_attributes (tree, tree); @@ -113,6 +117,10 @@ extern int attribute_list_contained (const_tree, const_tree); for size. */ extern tree private_lookup_attribute (const char *attr_name, size_t attr_len, tree list); +extern tree private_lookup_attribute (const char *attr_ns, + const char *attr_name, + size_t attr_ns_len, size_t attr_len, + tree list); extern unsigned decls_mismatched_attributes (tree, tree, tree, const char* const[], @@ -180,6 +188,22 @@ is_attribute_p (const char *attr_name, const_tree ident) IDENTIFIER_POINTER (ident), IDENTIFIER_LENGTH (ident)); } +/* Given an attribute ATTR and a string ATTR_NS, return true + if the attribute namespace is valid for the string. ATTR_NS "" stands + for standard attribute (NULL get_attribute_namespace) or "gnu" + namespace. */ + +static inline bool +is_attribute_namespace_p (const char *attr_ns, const_tree attr) +{ + tree ident = get_attribute_namespace (attr); + if (attr_ns == NULL) + return ident == NULL_TREE; + if (attr_ns[0]) + return ident && is_attribute_p (attr_ns, ident); + return ident == NULL_TREE || is_attribute_p ("gnu", ident); +} + /* Given an attribute name ATTR_NAME and a list of attributes LIST, return a pointer to the attribute's list element if the attribute is part of the list, or NULL_TREE if not found. If the attribute @@ -209,6 +233,37 @@ lookup_attribute (const char *attr_name, tree list) } } +/* Similar to lookup_attribute, but also match the attribute namespace. + ATTR_NS "" stands for either standard attribute or "gnu" namespace. */ + +static inline tree +lookup_attribute (const char *attr_ns, const char *attr_name, tree list) +{ + if (CHECKING_P && attr_name[0] != '_') + { + size_t attr_len = strlen (attr_name); + gcc_checking_assert (!canonicalize_attr_name (attr_name, attr_len)); + } + if (CHECKING_P && attr_ns && attr_ns[0] != '_') + { + size_t attr_ns_len = strlen (attr_ns); + gcc_checking_assert (!canonicalize_attr_name (attr_ns, attr_ns_len)); + } + /* In most cases, list is NULL_TREE. */ + if (list == NULL_TREE) + return NULL_TREE; + else + { + size_t attr_ns_len = attr_ns ? strlen (attr_ns) : 0; + size_t attr_len = strlen (attr_name); + /* Do the strlen() before calling the out-of-line implementation. + In most cases attr_name is a string constant, and the compiler + will optimize the strlen() away. */ + return private_lookup_attribute (attr_ns, attr_name, + attr_ns_len, attr_len, list); + } +} + /* Given an attribute name ATTR_NAME and a list of attributes LIST, return a pointer to the attribute's list first element if the attribute starts with ATTR_NAME. ATTR_NAME must be in the form 'text' (not @@ -236,8 +291,8 @@ lookup_attribute_by_prefix (const char *attr_name, tree list) } const char *p = IDENTIFIER_POINTER (name); - gcc_checking_assert (attr_len == 0 || p[0] != '_'); - + gcc_checking_assert (attr_len == 0 || p[0] != '_' + || (ident_len > 1 && p[1] != '_')); if (strncmp (attr_name, p, attr_len) == 0) break; diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc index 6533722..ca48404 100644 --- a/gcc/auto-profile.cc +++ b/gcc/auto-profile.cc @@ -388,7 +388,6 @@ get_inline_stack (location_t locus, inline_stack *stack) tree block = LOCATION_BLOCK (locus); if (block && TREE_CODE (block) == BLOCK) { - int level = 0; for (block = BLOCK_SUPERCONTEXT (block); block && (TREE_CODE (block) == BLOCK); block = BLOCK_SUPERCONTEXT (block)) @@ -401,7 +400,6 @@ get_inline_stack (location_t locus, inline_stack *stack) stack->safe_push ( std::make_pair (decl, get_combined_location (locus, decl))); locus = tmp_locus; - level++; } } stack->safe_push ( diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ea4b254..7bae1d5 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,40 @@ +2022-10-07 Qing Zhao <qing.zhao@oracle.com> + + * c-attribs.cc (handle_strict_flex_array_attribute): New function. + (c_common_attribute_table): New item for strict_flex_array. + * c.opt: (fstrict-flex-arrays): New option. + (fstrict-flex-arrays=): New option. + +2022-10-07 Martin Liska <mliska@suse.cz> + + * name-hint.h: Use std::move. + +2022-10-07 Jakub Jelinek <jakub@redhat.com> + + * c-common.cc (attribute_fallthrough_p): Lookup fallthrough attribute + only in gnu namespace or as standard attribute, treat fallthrough + attributes in other namespaces like any other unknown attribute. + +2022-10-06 Joseph Myers <joseph@codesourcery.com> + + * c-common.cc (c_common_reswords): Mark typeof as D_EXT11. Add + typeof_unqual. + * c-common.h (enum rid): Add RID_TYPEOF_UNQUAL. + (D_EXT11): New macro. Values of subsequent macros updated. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + PR c++/106654 + * c-attribs.cc (handle_assume_attribute): New function. + (c_common_attribute_table): Add entry for assume attribute. + * c-lex.cc (c_common_has_attribute): Handle + __have_cpp_attribute (assume). + +2022-10-04 Jakub Jelinek <jakub@redhat.com> + + * c-omp.cc (c_omp_directives): Uncomment begin declare target + entry. + 2022-10-03 Patrick Palka <ppalka@redhat.com> * c-common.cc (c_common_reswords): Use RID_IS_SAME instead of diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 8bb80e2..92ac93b 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -101,6 +101,8 @@ static tree handle_special_var_sec_attribute (tree *, tree, tree, int, bool *); static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree, int, bool *); +static tree handle_strict_flex_array_attribute (tree *, tree, tree, + int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *); @@ -144,6 +146,7 @@ static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *); static tree handle_alloc_align_attribute (tree *, tree, tree, int, bool *); static tree handle_assume_aligned_attribute (tree *, tree, tree, int, bool *); +static tree handle_assume_attribute (tree *, tree, tree, int, bool *); static tree handle_target_attribute (tree *, tree, tree, int, bool *); static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *); static tree handle_optimize_attribute (tree *, tree, tree, int, bool *); @@ -368,6 +371,8 @@ const struct attribute_spec c_common_attribute_table[] = attr_aligned_exclusions }, { "warn_if_not_aligned", 0, 1, false, false, false, false, handle_warn_if_not_aligned_attribute, NULL }, + { "strict_flex_array", 1, 1, true, false, false, false, + handle_strict_flex_array_attribute, NULL }, { "weak", 0, 0, true, false, false, false, handle_weak_attribute, NULL }, { "noplt", 0, 0, true, false, false, false, @@ -530,6 +535,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_designated_init_attribute, NULL }, { "fallthrough", 0, 0, false, false, false, false, handle_fallthrough_attribute, NULL }, + { "assume", 1, 1, false, false, false, false, + handle_assume_attribute, NULL }, { "patchable_function_entry", 1, 2, true, false, false, false, handle_patchable_function_entry_attribute, NULL }, @@ -2505,6 +2512,49 @@ handle_warn_if_not_aligned_attribute (tree *node, tree name, no_add_attrs, true); } +/* Handle a "strict_flex_array" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_strict_flex_array_attribute (tree *node, tree name, + tree args, int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + tree argval = TREE_VALUE (args); + + /* This attribute only applies to field decls of a structure. */ + if (TREE_CODE (decl) != FIELD_DECL) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute may not be specified for %q+D", name, decl); + *no_add_attrs = true; + } + /* This attribute only applies to field with array type. */ + else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute may not be specified for a non-array field", + name); + *no_add_attrs = true; + } + else if (TREE_CODE (argval) != INTEGER_CST) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute argument not an integer", name); + *no_add_attrs = true; + } + else if (!tree_fits_uhwi_p (argval) || tree_to_uhwi (argval) > 3) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute argument %qE is not an integer constant" + " between 0 and 3", name, argval); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle a "weak" attribute; arguments as in struct attribute_spec.handler. */ @@ -5741,6 +5791,18 @@ handle_fallthrough_attribute (tree *, tree name, tree, int, return NULL_TREE; } +/* Handle a "assume" attribute; arguments as in struct + attribute_spec.handler. */ + +tree +handle_assume_attribute (tree *, tree name, tree, int, + bool *no_add_attrs) +{ + pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + return NULL_TREE; +} + /* Handle a "patchable_function_entry" attributes; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 4f9878d..9ec9100 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -494,7 +494,8 @@ const struct c_common_resword c_common_reswords[] = { "typedef", RID_TYPEDEF, 0 }, { "typename", RID_TYPENAME, D_CXXONLY | D_CXXWARN }, { "typeid", RID_TYPEID, D_CXXONLY | D_CXXWARN }, - { "typeof", RID_TYPEOF, D_ASM | D_EXT }, + { "typeof", RID_TYPEOF, D_EXT11 }, + { "typeof_unqual", RID_TYPEOF_UNQUAL, D_CONLY | D_C2X }, { "union", RID_UNION, 0 }, { "unsigned", RID_UNSIGNED, 0 }, { "using", RID_USING, D_CXXONLY | D_CXXWARN }, @@ -6007,12 +6008,12 @@ attribute_fallthrough_p (tree attr) { if (attr == error_mark_node) return false; - tree t = lookup_attribute ("fallthrough", attr); + tree t = lookup_attribute ("", "fallthrough", attr); if (t == NULL_TREE) return false; /* It is no longer true that "this attribute shall appear at most once in each attribute-list", but we still give a warning. */ - if (lookup_attribute ("fallthrough", TREE_CHAIN (t))) + if (lookup_attribute ("", "fallthrough", TREE_CHAIN (t))) warning (OPT_Wattributes, "attribute %<fallthrough%> specified multiple " "times"); /* No attribute-argument-clause shall be present. */ @@ -6023,7 +6024,8 @@ attribute_fallthrough_p (tree attr) for (t = attr; t != NULL_TREE; t = TREE_CHAIN (t)) { tree name = get_attribute_name (t); - if (!is_attribute_p ("fallthrough", name)) + if (!is_attribute_p ("fallthrough", name) + || !is_attribute_namespace_p ("", t)) { if (!c_dialect_cxx () && get_attribute_namespace (t) == NULL_TREE) /* The specifications of standard attributes in C mean diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 5f470d9..62ab4ba 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -104,7 +104,8 @@ enum rid RID_SIZEOF, /* C extensions */ - RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG, + RID_ASM, RID_TYPEOF, RID_TYPEOF_UNQUAL, RID_ALIGNOF, RID_ATTRIBUTE, + RID_VA_ARG, RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH, @@ -438,16 +439,17 @@ extern machine_mode c_default_pointer_mode; #define D_CXX11 0x0010 /* In C++, C++11 only. */ #define D_EXT 0x0020 /* GCC extension. */ #define D_EXT89 0x0040 /* GCC extension incorporated in C99. */ -#define D_ASM 0x0080 /* Disabled by -fno-asm. */ -#define D_OBJC 0x0100 /* In Objective C and neither C nor C++. */ -#define D_CXX_OBJC 0x0200 /* In Objective C, and C++, but not C. */ -#define D_CXXWARN 0x0400 /* In C warn with -Wcxx-compat. */ -#define D_CXX_CONCEPTS 0x0800 /* In C++, only with concepts. */ -#define D_TRANSMEM 0x1000 /* C++ transactional memory TS. */ -#define D_CXX_CHAR8_T 0x2000 /* In C++, only with -fchar8_t. */ -#define D_CXX20 0x4000 /* In C++, C++20 only. */ -#define D_CXX_COROUTINES 0x8000 /* In C++, only with coroutines. */ -#define D_CXX_MODULES 0x10000 /* In C++, only with modules. */ +#define D_EXT11 0x0080 /* GCC extension incorporated in C2X. */ +#define D_ASM 0x0100 /* Disabled by -fno-asm. */ +#define D_OBJC 0x0200 /* In Objective C and neither C nor C++. */ +#define D_CXX_OBJC 0x0400 /* In Objective C, and C++, but not C. */ +#define D_CXXWARN 0x0800 /* In C warn with -Wcxx-compat. */ +#define D_CXX_CONCEPTS 0x1000 /* In C++, only with concepts. */ +#define D_TRANSMEM 0x2000 /* C++ transactional memory TS. */ +#define D_CXX_CHAR8_T 0x4000 /* In C++, only with -fchar8_t. */ +#define D_CXX20 0x8000 /* In C++, C++20 only. */ +#define D_CXX_COROUTINES 0x10000 /* In C++, only with coroutines. */ +#define D_CXX_MODULES 0x20000 /* In C++, only with modules. */ #define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS #define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc index d4e448a..050fa77 100644 --- a/gcc/c-family/c-lex.cc +++ b/gcc/c-family/c-lex.cc @@ -378,6 +378,8 @@ c_common_has_attribute (cpp_reader *pfile, bool std_syntax) result = 201803; else if (is_attribute_p ("nodiscard", attr_name)) result = 201907; + else if (is_attribute_p ("assume", attr_name)) + result = 202207; } else { diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 1c7f89e..01d4807 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -2076,6 +2076,13 @@ fsized-deallocation C++ ObjC++ Var(flag_sized_deallocation) Init(-1) Enable C++14 sized deallocation support. +fstrict-flex-arrays +C C++ Common Alias(fstrict-flex-arrays=,3,0) + +fstrict-flex-arrays= +C C++ Common Joined RejectNegative UInteger Var(flag_strict_flex_arrays) Init(0) IntegerRange(0,3) +-fstrict-flex-arrays=<level> Control when to treat the trailing array of a structure as a flexible array member for the purposes of accessing the elements of such an array. The default is treating all trailing arrays of structures as flexible array members. + fsquangle C++ ObjC++ WarnRemoved diff --git a/gcc/c-family/name-hint.h b/gcc/c-family/name-hint.h index df733e7..98392ce 100644 --- a/gcc/c-family/name-hint.h +++ b/gcc/c-family/name-hint.h @@ -106,7 +106,7 @@ public: /* Take ownership of this name_hint's deferred_diagnostic, for use in chaining up deferred diagnostics. */ - std::unique_ptr<deferred_diagnostic> take_deferred () { return move (m_deferred); } + std::unique_ptr<deferred_diagnostic> take_deferred () { return std::move (m_deferred); } /* Call this on a name_hint if the corresponding warning was not emitted, in which case we should also not emit the deferred_diagnostic. */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index f5c9a59..a25e1b4 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,72 @@ +2022-10-07 Qing Zhao <qing.zhao@oracle.com> + + * c-decl.cc (flexible_array_member_type_p): New function. + (one_element_array_type_p): Likewise. + (zero_length_array_type_p): Likewise. + (add_flexible_array_elts_to_size): Call new utility + routine flexible_array_member_type_p. + (is_flexible_array_member_p): New function. + (finish_struct): Set the new DECL_NOT_FLEXARRAY flag. + +2022-10-06 Joseph Myers <joseph@codesourcery.com> + + * c-parser.cc (c_parse_init): Add D_EXT11 to mask if flag_no_asm + and not C2x. + (c_keyword_starts_typename, c_token_starts_declspecs) + (c_parser_declspecs, c_parser_objc_selector): Handle + RID_TYPEOF_UNQUAL. + (c_parser_typeof_specifier): Handle RID_TYPEOF_UNQUAL. + Distinguish typeof for C2x from __typeof__ for all standard + versions and typeof before C2x. + * c-typeck.cc (build_function_call_vec): Use unqualified version + of non-void return type. + (build_unary_op): Use unqualified type for increment and + decrement. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + * c-parser.cc (c_parser_omp_assumption_clauses): Emit IFN_ASSUME + call for holds clause on assume construct. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + PR c++/106654 + * c-parser.cc (handle_assume_attribute): New function. + (c_parser_declaration_or_fndef): Handle assume attribute. + (c_parser_attribute_arguments): Add assume_attr argument, + if true, parse first argument as conditional expression. + (c_parser_gnu_attribute, c_parser_std_attribute): Adjust + c_parser_attribute_arguments callers. + (c_parser_statement_after_labels) <case RID_ATTRIBUTE>: Handle + assume attribute. + +2022-10-04 Jakub Jelinek <jakub@redhat.com> + + * c-lang.h (struct c_omp_declare_target_attr): New type. + (current_omp_declare_target_attribute): Change type from + int to vec<c_omp_declare_target_attr, va_gc> *. + * c-parser.cc (c_parser_translation_unit): Adjust for that change. + If last pushed directive was begin declare target, use different + wording and simplify format strings for easier translations. + (c_parser_omp_clause_device_type): Uncomment + check_no_duplicate_clause call. + (c_parser_omp_declare_target): Adjust for the + current_omp_declare_target_attribute type change, push { -1 }. + Use error_at rather than warning_at for declare target with + only device_type clauses. + (OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Define. + (c_parser_omp_begin): Add begin declare target support. + (c_parser_omp_end): Adjust for the + current_omp_declare_target_attribute type change, adjust + diagnostics wording and simplify format strings for easier + translations. + * c-decl.cc (current_omp_declare_target_attribute): Change type from + int to vec<c_omp_declare_target_attr, va_gc> *. + (c_decl_attributes): Adjust for the + current_omp_declare_target_attribute type change. If device_type + was present on begin declare target, add "omp declare target host" + and/or "omp declare target nohost" attributes. + 2022-09-29 Joseph Myers <joseph@codesourcery.com> * c-decl.cc (handle_std_noreturn_attribute): New function. diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index ffa63dc..193e268 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5034,6 +5034,41 @@ set_array_declarator_inner (struct c_declarator *decl, return decl; } +/* Determine whether TYPE is a ISO C99 flexible array memeber type "[]". */ +static bool +flexible_array_member_type_p (const_tree type) +{ + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_SIZE (type) == NULL_TREE + && TYPE_DOMAIN (type) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + return true; + + return false; +} + +/* Determine whether TYPE is a one-element array type "[1]". */ +static bool +one_element_array_type_p (const_tree type) +{ + if (TREE_CODE (type) != ARRAY_TYPE) + return false; + return integer_zerop (array_type_nelts (type)); +} + +/* Determine whether TYPE is a zero-length array type "[0]". */ +static bool +zero_length_array_type_p (const_tree type) +{ + if (TREE_CODE (type) == ARRAY_TYPE) + if (tree type_size = TYPE_SIZE_UNIT (type)) + if ((integer_zerop (type_size)) + && TYPE_DOMAIN (type) != NULL_TREE + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + return true; + return false; +} + /* INIT is a constructor that forms DECL's initializer. If the final element initializes a flexible array field, add the size of that initializer to DECL's size. */ @@ -5048,10 +5083,7 @@ add_flexible_array_elts_to_size (tree decl, tree init) elt = CONSTRUCTOR_ELTS (init)->last ().value; type = TREE_TYPE (elt); - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_SIZE (type) == NULL_TREE - && TYPE_DOMAIN (type) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE) + if (flexible_array_member_type_p (type)) { complete_array_type (&type, elt, false); DECL_SIZE (decl) @@ -8755,6 +8787,81 @@ finish_incomplete_vars (tree incomplete_vars, bool toplevel) } } + +/* Determine whether the FIELD_DECL X is a flexible array member according to + the following info: + A. whether the FIELD_DECL X is the last field of the DECL_CONTEXT; + B. whether the FIELD_DECL is an array that is declared as "[]", "[0]", + or "[1]"; + C. flag_strict_flex_arrays; + D. the attribute strict_flex_array that is attached to the field + if presenting. + Return TRUE when it's a flexible array member, FALSE otherwise. */ + +static bool +is_flexible_array_member_p (bool is_last_field, + tree x) +{ + /* If not the last field, return false. */ + if (!is_last_field) + return false; + + /* If not an array field, return false. */ + if (TREE_CODE (TREE_TYPE (x)) != ARRAY_TYPE) + return false; + + bool is_zero_length_array = zero_length_array_type_p (TREE_TYPE (x)); + bool is_one_element_array = one_element_array_type_p (TREE_TYPE (x)); + bool is_flexible_array = flexible_array_member_type_p (TREE_TYPE (x)); + + unsigned int strict_flex_array_level = flag_strict_flex_arrays; + + tree attr_strict_flex_array = lookup_attribute ("strict_flex_array", + DECL_ATTRIBUTES (x)); + /* If there is a strict_flex_array attribute attached to the field, + override the flag_strict_flex_arrays. */ + if (attr_strict_flex_array) + { + /* Get the value of the level first from the attribute. */ + unsigned HOST_WIDE_INT attr_strict_flex_array_level = 0; + gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE); + attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array); + gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE); + attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array); + gcc_assert (tree_fits_uhwi_p (attr_strict_flex_array)); + attr_strict_flex_array_level = tree_to_uhwi (attr_strict_flex_array); + + /* The attribute has higher priority than flag_struct_flex_array. */ + strict_flex_array_level = attr_strict_flex_array_level; + } + + switch (strict_flex_array_level) + { + case 0: + /* Default, all trailing arrays are flexible array members. */ + return true; + case 1: + /* Level 1: all "[1]", "[0]", and "[]" are flexible array members. */ + if (is_one_element_array) + return true; + /* FALLTHROUGH. */ + case 2: + /* Level 2: all "[0]", and "[]" are flexible array members. */ + if (is_zero_length_array) + return true; + /* FALLTHROUGH. */ + case 3: + /* Level 3: Only "[]" are flexible array members. */ + if (is_flexible_array) + return true; + break; + default: + gcc_unreachable (); + } + return false; +} + + /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. LOC is the location of the RECORD_TYPE or UNION_TYPE's definition. FIELDLIST is a chain of FIELD_DECL nodes for the fields. @@ -8816,6 +8923,11 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, bool saw_named_field = false; for (x = fieldlist; x; x = DECL_CHAIN (x)) { + /* Whether this field is the last field of the structure or union. + for UNION, any field is the last field of it. */ + bool is_last_field = (DECL_CHAIN (x) == NULL_TREE) + || (TREE_CODE (t) == UNION_TYPE); + if (TREE_TYPE (x) == error_mark_node) continue; @@ -8854,10 +8966,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, DECL_PACKED (x) = 1; /* Detect flexible array member in an invalid context. */ - if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE - && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE - && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE - && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE) + if (flexible_array_member_type_p (TREE_TYPE (x))) { if (TREE_CODE (t) == UNION_TYPE) { @@ -8865,7 +8974,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, "flexible array member in union"); TREE_TYPE (x) = error_mark_node; } - else if (DECL_CHAIN (x) != NULL_TREE) + else if (!is_last_field) { error_at (DECL_SOURCE_LOCATION (x), "flexible array member not at end of struct"); @@ -8885,6 +8994,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic, "invalid use of structure with flexible array member"); + /* Set DECL_NOT_FLEXARRAY flag for FIELD_DECL x. */ + DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x); + if (DECL_NAME (x) || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))) saw_named_field = true; diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index f6a94ba..89e0587 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -127,6 +127,8 @@ c_parse_init (void) mask |= D_ASM | D_EXT; if (!flag_isoc99) mask |= D_EXT89; + if (!flag_isoc2x) + mask |= D_EXT11; } if (!c_dialect_objc ()) mask |= D_OBJC | D_CXX_OBJC; @@ -580,6 +582,7 @@ c_keyword_starts_typename (enum rid keyword) case RID_STRUCT: case RID_UNION: case RID_TYPEOF: + case RID_TYPEOF_UNQUAL: case RID_CONST: case RID_ATOMIC: case RID_VOLATILE: @@ -757,6 +760,7 @@ c_token_starts_declspecs (c_token *token) case RID_STRUCT: case RID_UNION: case RID_TYPEOF: + case RID_TYPEOF_UNQUAL: case RID_CONST: case RID_VOLATILE: case RID_RESTRICT: @@ -1823,6 +1827,46 @@ add_debug_begin_stmt (location_t loc) add_stmt (stmt); } +/* Helper function for c_parser_declaration_or_fndef and + Handle assume attribute(s). */ + +static tree +handle_assume_attribute (location_t here, tree attrs, bool nested) +{ + if (nested) + for (tree attr = lookup_attribute ("gnu", "assume", attrs); attr; + attr = lookup_attribute ("gnu", "assume", TREE_CHAIN (attr))) + { + tree args = TREE_VALUE (attr); + int nargs = list_length (args); + if (nargs != 1) + { + error_at (here, "wrong number of arguments specified " + "for %qE attribute", + get_attribute_name (attr)); + inform (here, "expected %i, found %i", 1, nargs); + } + else + { + tree arg = TREE_VALUE (args); + arg = c_objc_common_truthvalue_conversion (here, arg); + arg = c_fully_fold (arg, false, NULL); + if (arg != error_mark_node) + { + tree fn = build_call_expr_internal_loc (here, IFN_ASSUME, + void_type_node, 1, + arg); + add_stmt (fn); + } + } + } + else + pedwarn (here, OPT_Wattributes, + "%<assume%> attribute at top level"); + + return remove_attribute ("gnu", "assume", attrs); +} + /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition is accepted; otherwise (old-style parameter declarations) only other @@ -2037,6 +2081,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool auto_type_p = specs->typespec_word == cts_auto_type; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { + bool handled_assume = false; + if (specs->typespec_kind == ctsk_none + && lookup_attribute ("gnu", "assume", specs->attrs)) + { + handled_assume = true; + specs->attrs + = handle_assume_attribute (here, specs->attrs, nested); + } if (auto_type_p) error_at (here, "%<__auto_type%> in empty declaration"); else if (specs->typespec_kind == ctsk_none @@ -2054,13 +2106,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, pedwarn (here, OPT_Wattributes, "%<fallthrough%> attribute at top level"); } - else if (empty_ok && !(have_attrs - && specs->non_std_attrs_seen_p)) + else if (empty_ok + && !(have_attrs && specs->non_std_attrs_seen_p) + && !handled_assume) shadow_tag (specs); else { shadow_tag_warned (specs, 1); - pedwarn (here, 0, "empty declaration"); + if (!handled_assume) + pedwarn (here, 0, "empty declaration"); } c_parser_consume_token (parser); if (oacc_routine_data) @@ -2160,6 +2214,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, else if (attribute_fallthrough_p (specs->attrs)) warning_at (here, OPT_Wattributes, "%<fallthrough%> attribute not followed by %<;%>"); + else if (lookup_attribute ("gnu", "assume", specs->attrs)) + warning_at (here, OPT_Wattributes, + "%<assume%> attribute not followed by %<;%>"); pending_xref_error (); prefix_attrs = specs->attrs; @@ -3028,6 +3085,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, declspecs_add_type (loc, specs, t); break; case RID_TYPEOF: + case RID_TYPEOF_UNQUAL: /* ??? The old parser rejected typeof after other type specifiers, but is a syntax error the best way of handling this? */ @@ -3715,22 +3773,38 @@ c_parser_struct_declaration (c_parser *parser) return decls; } -/* Parse a typeof specifier (a GNU extension). +/* Parse a typeof specifier (a GNU extension adopted in C2X). typeof-specifier: typeof ( expression ) typeof ( type-name ) + typeof_unqual ( expression ) + typeof_unqual ( type-name ) */ static struct c_typespec c_parser_typeof_specifier (c_parser *parser) { + bool is_unqual; + bool is_std; struct c_typespec ret; ret.kind = ctsk_typeof; ret.spec = error_mark_node; ret.expr = NULL_TREE; ret.expr_const_operands = true; - gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF)); + if (c_parser_next_token_is_keyword (parser, RID_TYPEOF)) + { + is_unqual = false; + tree spelling = c_parser_peek_token (parser)->value; + is_std = (flag_isoc2x + && strcmp (IDENTIFIER_POINTER (spelling), "typeof") == 0); + } + else + { + gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF_UNQUAL)); + is_unqual = true; + is_std = true; + } c_parser_consume_token (parser); c_inhibit_evaluation_warnings++; in_typeof++; @@ -3772,6 +3846,24 @@ c_parser_typeof_specifier (c_parser *parser) pop_maybe_used (was_vm); } parens.skip_until_found_close (parser); + if (ret.spec != error_mark_node) + { + if (is_unqual && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED) + ret.spec = TYPE_MAIN_VARIANT (ret.spec); + if (is_std) + { + /* In ISO C terms, _Noreturn is not part of the type of + expressions such as &abort, but in GCC it is represented + internally as a type qualifier. */ + if (TREE_CODE (ret.spec) == FUNCTION_TYPE + && TYPE_QUALS (ret.spec) != TYPE_UNQUALIFIED) + ret.spec = TYPE_MAIN_VARIANT (ret.spec); + else if (FUNCTION_POINTER_TYPE_P (ret.spec) + && TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED) + ret.spec + = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec))); + } + } return ret; } @@ -4598,7 +4690,8 @@ c_parser_gnu_attribute_any_word (c_parser *parser) static tree c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, - bool require_string, bool allow_empty_args) + bool require_string, bool assume_attr, + bool allow_empty_args) { vec<tree, va_gc> *expr_list; tree attr_args; @@ -4617,6 +4710,7 @@ c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, == CPP_CLOSE_PAREN)) && (takes_identifier || (c_dialect_objc () + && !assume_attr && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))) { @@ -4653,6 +4747,23 @@ c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, tree string = c_parser_string_literal (parser, false, true).value; attr_args = build_tree_list (NULL_TREE, string); } + else if (assume_attr) + { + tree cond + = c_parser_conditional_expression (parser, NULL, NULL_TREE).value; + if (!c_parser_next_token_is (parser, CPP_COMMA)) + attr_args = build_tree_list (NULL_TREE, cond); + else + { + tree tree_list; + c_parser_consume_token (parser); + expr_list = c_parser_expr_list (parser, false, true, + NULL, NULL, NULL, NULL); + tree_list = build_tree_list_vec (expr_list); + attr_args = tree_cons (NULL_TREE, cond, tree_list); + release_tree_vector (expr_list); + } + } else { expr_list = c_parser_expr_list (parser, false, true, @@ -4736,7 +4847,9 @@ c_parser_gnu_attribute (c_parser *parser, tree attrs, tree attr_args = c_parser_attribute_arguments (parser, attribute_takes_identifier_p (attr_name), - false, true); + false, + is_attribute_p ("assume", attr_name), + true); attr = build_tree_list (attr_name, attr_args); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) @@ -4982,9 +5095,13 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) = (ns == NULL_TREE && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0 || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0)); + bool assume_attr + = (ns != NULL_TREE + && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0 + && strcmp (IDENTIFIER_POINTER (name), "assume") == 0); TREE_VALUE (attribute) = c_parser_attribute_arguments (parser, takes_identifier, - require_string, false); + require_string, assume_attr, false); } else c_parser_balanced_token_sequence (parser); @@ -6264,8 +6381,21 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, break; case RID_ATTRIBUTE: { - /* Allow '__attribute__((fallthrough));'. */ + /* Allow '__attribute__((fallthrough));' or + '__attribute__((assume(cond)));'. */ tree attrs = c_parser_gnu_attributes (parser); + bool has_assume = lookup_attribute ("assume", attrs); + if (has_assume) + { + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + attrs = handle_assume_attribute (loc, attrs, true); + else + { + warning_at (loc, OPT_Wattributes, + "%<assume%> attribute not followed by %<;%>"); + has_assume = false; + } + } if (attribute_fallthrough_p (attrs)) { if (c_parser_next_token_is (parser, CPP_SEMICOLON)) @@ -6282,9 +6412,13 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, "%<fallthrough%> attribute not followed " "by %<;%>"); } + else if (has_assume) + /* Eat the ';'. */ + c_parser_consume_token (parser); else if (attrs != NULL_TREE) - warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>" - " can be applied to a null statement"); + warning_at (loc, OPT_Wattributes, + "only attribute %<fallthrough%> or %<assume%> can " + "be applied to a null statement"); break; } default: @@ -11866,7 +12000,7 @@ c_parser_objc_synchronized_statement (c_parser *parser) identifier one of enum struct union if else while do for switch case default - break continue return goto asm sizeof typeof __alignof + break continue return goto asm sizeof typeof typeof_unqual __alignof unsigned long const short volatile signed restrict _Complex in out inout bycopy byref oneway int char float double void _Bool _Atomic @@ -11906,6 +12040,7 @@ c_parser_objc_selector (c_parser *parser) case RID_ASM: case RID_SIZEOF: case RID_TYPEOF: + case RID_TYPEOF_UNQUAL: case RID_ALIGNOF: case RID_UNSIGNED: case RID_LONG: @@ -23476,10 +23611,12 @@ c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume) tree t = convert_lvalue_to_rvalue (eloc, expr, true, true).value; t = c_objc_common_truthvalue_conversion (eloc, t); t = c_fully_fold (t, false, NULL); - if (is_assume) + if (is_assume && t != error_mark_node) { - /* FIXME: Emit .ASSUME (t) call here. */ - (void) t; + tree fn = build_call_expr_internal_loc (eloc, IFN_ASSUME, + void_type_node, 1, + t); + add_stmt (fn); } parens.skip_until_found_close (parser); } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index ac242b5..f919068 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -3187,6 +3187,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc, /* fntype now gets the type of function pointed to. */ fntype = TREE_TYPE (fntype); + tree return_type = TREE_TYPE (fntype); /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ @@ -3203,8 +3204,6 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc, && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL && !comptypes (fntype, TREE_TYPE (tem))) { - tree return_type = TREE_TYPE (fntype); - /* This situation leads to run-time undefined behavior. We can't, therefore, simply error unless we can prove that all possible executions of the program must execute the code. */ @@ -3229,22 +3228,25 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc, bool warned_p = check_function_arguments (loc, fundecl, fntype, nargs, argarray, &arg_loc); + if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED + && !VOID_TYPE_P (return_type)) + return_type = c_build_qualified_type (return_type, TYPE_UNQUALIFIED); if (name != NULL_TREE && startswith (IDENTIFIER_POINTER (name), "__builtin_")) { if (require_constant_value) result - = fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype), + = fold_build_call_array_initializer_loc (loc, return_type, function, nargs, argarray); else - result = fold_build_call_array_loc (loc, TREE_TYPE (fntype), + result = fold_build_call_array_loc (loc, return_type, function, nargs, argarray); if (TREE_CODE (result) == NOP_EXPR && TREE_CODE (TREE_OPERAND (result, 0)) == INTEGER_CST) STRIP_TYPE_NOPS (result); } else - result = build_call_array_loc (loc, TREE_TYPE (fntype), + result = build_call_array_loc (loc, return_type, function, nargs, argarray); /* If -Wnonnull warning has been diagnosed, avoid diagnosing it again later. */ @@ -4831,6 +4833,9 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, else val = build2 (code, TREE_TYPE (arg), arg, inc); TREE_SIDE_EFFECTS (val) = 1; + if (TYPE_QUALS (TREE_TYPE (val)) != TYPE_UNQUALIFIED) + TREE_TYPE (val) = c_build_qualified_type (TREE_TYPE (val), + TYPE_UNQUALIFIED); ret = val; goto return_build_unary_op; } diff --git a/gcc/common.opt b/gcc/common.opt index 58dc1a0..3a97e67 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -3317,7 +3317,7 @@ Common Driver JoinedOrMissing Negative(gdwarf-) Generate debug information in default version of DWARF format. gdwarf- -Common Driver Joined UInteger Var(dwarf_version) Init(5) +Common Driver Joined UInteger Var(dwarf_version) Init(DWARF_VERSION_DEFAULT) Generate debug information in DWARF v2 (or later) format. gdwarf32 diff --git a/gcc/config.gcc b/gcc/config.gcc index 35dfc00..e73cb84 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -518,6 +518,7 @@ riscv*) extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-selftests.o" extra_objs="${extra_objs} riscv-vector-builtins.o" d_target_objs="riscv-d.o" + extra_headers="riscv_vector.h" ;; rs6000*-*-*) extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt" diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def index 9f82466..5a9eff3 100644 --- a/gcc/config/aarch64/aarch64-arches.def +++ b/gcc/config/aarch64/aarch64-arches.def @@ -33,7 +33,7 @@ AARCH64_ARCH("armv8-a", generic, V8A, 8, (SIMD)) AARCH64_ARCH("armv8.1-a", generic, V8_1A, 8, (V8A, LSE, CRC, RDMA)) AARCH64_ARCH("armv8.2-a", generic, V8_2A, 8, (V8_1A)) -AARCH64_ARCH("armv8.3-a", generic, V8_3A, 8, (V8_2A, PAUTH)) +AARCH64_ARCH("armv8.3-a", generic, V8_3A, 8, (V8_2A, PAUTH, RCPC)) AARCH64_ARCH("armv8.4-a", generic, V8_4A, 8, (V8_3A, F16FML, DOTPROD, FLAGM)) AARCH64_ARCH("armv8.5-a", generic, V8_5A, 8, (V8_4A, SB, SSBS, PREDRES)) AARCH64_ARCH("armv8.6-a", generic, V8_6A, 8, (V8_5A, I8MM, BF16)) diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index 592af8c..e296c73 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -202,6 +202,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile); aarch64_def_or_undef (TARGET_LS64, "__ARM_FEATURE_LS64", pfile); + aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile); /* Not for ACLE, but required to keep "float.h" correct if we switch target between implementations that do or do not support ARMv8.2-A diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index 6029916..e9a4b62 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -69,7 +69,7 @@ AARCH64_CORE("thunderxt81", thunderxt81, thunderx, V8A, (CRC, CRYPTO), thu AARCH64_CORE("thunderxt83", thunderxt83, thunderx, V8A, (CRC, CRYPTO), thunderx, 0x43, 0x0a3, -1) /* Ampere Computing ('\xC0') cores. */ -AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, (), ampere1, 0xC0, 0xac3, -1) +AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, (F16, RNG, AES, SHA3), ampere1, 0xC0, 0xac3, -1) /* Do not swap around "emag" and "xgene1", this order is required to handle variant correctly. */ AARCH64_CORE("emag", emag, xgene1, V8A, (CRC, CRYPTO), emag, 0x50, 0x000, 3) @@ -133,17 +133,17 @@ AARCH64_CORE("tsv110", tsv110, tsv110, V8_2A, (CRYPTO, F16), tsv110, 0x48, 0 /* ARMv8.3-A Architecture Processors. */ /* Marvell cores (TX3). */ -AARCH64_CORE("thunderx3t110", thunderx3t110, thunderx3t110, V8_3A, (CRYPTO, RCPC, SM4, SHA3, F16FML), thunderx3t110, 0x43, 0x0b8, 0x0a) +AARCH64_CORE("thunderx3t110", thunderx3t110, thunderx3t110, V8_3A, (CRYPTO, SM4, SHA3, F16FML), thunderx3t110, 0x43, 0x0b8, 0x0a) /* ARMv8.4-A Architecture Processors. */ /* Arm ('A') cores. */ -AARCH64_CORE("zeus", zeus, cortexa57, V8_4A, (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1) -AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A, (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1) -AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A, (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoverse512tvb, INVALID_IMP, INVALID_CORE, -1) +AARCH64_CORE("zeus", zeus, cortexa57, V8_4A, (SVE, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1) +AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A, (SVE, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1) +AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A, (SVE, I8MM, BF16, PROFILE, SSBS, RNG), neoverse512tvb, INVALID_IMP, INVALID_CORE, -1) /* Qualcomm ('Q') cores. */ -AARCH64_CORE("saphira", saphira, saphira, V8_4A, (CRYPTO, RCPC), saphira, 0x51, 0xC01, -1) +AARCH64_CORE("saphira", saphira, saphira, V8_4A, (CRYPTO), saphira, 0x51, 0xC01, -1) /* ARMv8-A big.LITTLE implementations. */ diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 2d62218..05da9af 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -201,6 +201,7 @@ enum class aarch64_feature : unsigned char { #define AARCH64_ISA_SM4 (aarch64_isa_flags & AARCH64_FL_SM4) #define AARCH64_ISA_SHA3 (aarch64_isa_flags & AARCH64_FL_SHA3) #define AARCH64_ISA_F16FML (aarch64_isa_flags & AARCH64_FL_F16FML) +#define AARCH64_ISA_RCPC (aarch64_isa_flags & AARCH64_FL_RCPC) #define AARCH64_ISA_RCPC8_4 (aarch64_isa_flags & AARCH64_FL_V8_4A) #define AARCH64_ISA_RNG (aarch64_isa_flags & AARCH64_FL_RNG) #define AARCH64_ISA_V8_5A (aarch64_isa_flags & AARCH64_FL_V8_5A) diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md index 9048700..bc95f6d 100644 --- a/gcc/config/aarch64/atomics.md +++ b/gcc/config/aarch64/atomics.md @@ -640,6 +640,23 @@ } ) +(define_insn "*atomic_load<ALLX:mode>_zext<SD_HSDI:mode>" + [(set (match_operand:SD_HSDI 0 "register_operand" "=r") + (zero_extend:SD_HSDI + (unspec_volatile:ALLX + [(match_operand:ALLX 1 "aarch64_sync_memory_operand" "Q") + (match_operand:SI 2 "const_int_operand")] ;; model + UNSPECV_LDA)))] + "GET_MODE_SIZE (<SD_HSDI:MODE>mode) > GET_MODE_SIZE (<ALLX:MODE>mode)" + { + enum memmodel model = memmodel_from_int (INTVAL (operands[2])); + if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_release (model)) + return "ldr<ALLX:atomic_sfx>\t%<ALLX:w>0, %1"; + else + return "ldar<ALLX:atomic_sfx>\t%<ALLX:w>0, %1"; + } +) + (define_insn "atomic_load<mode>" [(set (match_operand:ALLI 0 "register_operand" "=r") (unspec_volatile:ALLI diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc index 52ff537..2ae47c0 100644 --- a/gcc/config/aarch64/driver-aarch64.cc +++ b/gcc/config/aarch64/driver-aarch64.cc @@ -203,9 +203,9 @@ readline (FILE *f) return std::string (); /* If we're not at the end of the line then override the \0 added by fgets. */ - last = strnlen (buf, size) - 1; + last = strnlen (buf, size); } - while (!feof (f) && buf[last] != '\n'); + while (!feof (f) && last > 0 && buf[last - 1] != '\n'); std::string result (buf); free (buf); diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h index 0f1ff05..6ebbb14 100644 --- a/gcc/config/arc/linux.h +++ b/gcc/config/arc/linux.h @@ -45,7 +45,6 @@ along with GCC; see the file COPYING3. If not see %{!shared:-dynamic-linker " GNU_USER_DYNAMIC_LINKER "}} \ -X \ %{mbig-endian:-EB} %{EB} %{EL} \ - %{!z:-z max-page-size=0x2000 -z common-page-size=0x2000} \ %{mcpu=nps400:-marclinux_nps; :-marclinux}" #undef STARTFILE_SPEC diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 3b94efe..5318fc7 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -109,7 +109,7 @@ extern void ix86_expand_binary_operator (enum rtx_code, machine_mode, rtx[]); extern void ix86_expand_vector_logical_operator (enum rtx_code, machine_mode, rtx[]); -extern bool ix86_binary_operator_ok (enum rtx_code, machine_mode, rtx[]); +extern bool ix86_binary_operator_ok (enum rtx_code, machine_mode, rtx[3]); extern bool ix86_avoid_lea_for_add (rtx_insn *, rtx[]); extern bool ix86_use_lea_for_mov (rtx_insn *, rtx[]); extern bool ix86_avoid_lea_for_addr (rtx_insn *, rtx[]); @@ -140,7 +140,7 @@ extern void ix86_split_fp_absneg_operator (enum rtx_code, machine_mode, rtx[]); extern void ix86_expand_copysign (rtx []); extern void ix86_expand_xorsign (rtx []); -extern bool ix86_unary_operator_ok (enum rtx_code, machine_mode, rtx[]); +extern bool ix86_unary_operator_ok (enum rtx_code, machine_mode, rtx[2]); extern bool ix86_match_ccmode (rtx, machine_mode); extern void ix86_expand_branch (enum rtx_code, rtx, rtx, rtx); extern void ix86_expand_setcc (rtx, enum rtx_code, rtx, rtx); diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc index a51037a..14865d7 100644 --- a/gcc/config/riscv/riscv-builtins.cc +++ b/gcc/config/riscv/riscv-builtins.cc @@ -37,7 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "expr.h" #include "langhooks.h" -#include "riscv-vector-builtins.h" +#include "tm_p.h" /* Macros to create an enumeration identifier for a function prototype. */ #define RISCV_FTYPE_NAME0(A) RISCV_##A##_FTYPE diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc index eb7ef09..cac0043 100644 --- a/gcc/config/riscv/riscv-c.cc +++ b/gcc/config/riscv/riscv-c.cc @@ -27,6 +27,9 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "c-family/c-common.h" #include "cpplib.h" +#include "c-family/c-pragma.h" +#include "target.h" +#include "tm_p.h" #include "riscv-subset.h" #define builtin_define(TXT) cpp_define (pfile, TXT) @@ -93,11 +96,6 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) break; case CM_PIC: - /* __riscv_cmodel_pic is deprecated, and will removed in next GCC release. - see https://github.com/riscv/riscv-c-api-doc/pull/11 */ - builtin_define ("__riscv_cmodel_pic"); - /* FALLTHROUGH. */ - case CM_MEDANY: builtin_define ("__riscv_cmodel_medany"); break; @@ -155,3 +153,41 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) builtin_define_with_int_value (buf, version_value); } } + +/* Implement "#pragma riscv intrinsic". */ + +static void +riscv_pragma_intrinsic (cpp_reader *) +{ + tree x; + + if (pragma_lex (&x) != CPP_STRING) + { + error ("%<#pragma riscv intrinsic%> requires a string parameter"); + return; + } + + const char *name = TREE_STRING_POINTER (x); + + if (strcmp (name, "vector") == 0) + { + if (!TARGET_VECTOR) + { + error ("%<#pragma riscv intrinsic%> option %qs needs 'V' extension " + "enabled", + name); + return; + } + riscv_vector::handle_pragma_vector (); + } + else + error ("unknown %<#pragma riscv intrinsic%> option %qs", name); +} + +/* Implement REGISTER_TARGET_PRAGMAS. */ + +void +riscv_register_pragmas (void) +{ + c_register_pragma ("riscv", "intrinsic", riscv_pragma_intrinsic); +}
\ No newline at end of file diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 101361a..a44b34d 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -79,6 +79,7 @@ extern bool riscv_v_ext_enabled_vector_mode_p (machine_mode); /* Routines implemented in riscv-c.cc. */ void riscv_cpu_cpp_builtins (cpp_reader *); +void riscv_register_pragmas (void); /* Routines implemented in riscv-builtins.cc. */ extern void riscv_atomic_assign_expand_fenv (tree *, tree *, tree *); @@ -115,4 +116,14 @@ extern void riscv_run_selftests (void); } // namespace selftest #endif +namespace riscv_vector { +/* Routines implemented in riscv-vector-builtins.cc. */ +extern void init_builtins (void); +extern const char *mangle_builtin_type (const_tree); +#ifdef GCC_TARGET_H +extern bool verify_type_context (location_t, type_context_kind, const_tree, bool); +#endif +extern void handle_pragma_vector (void); +} + #endif /* ! GCC_RISCV_PROTOS_H */ diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc index 019a40d..0096e32 100644 --- a/gcc/config/riscv/riscv-vector-builtins.cc +++ b/gcc/config/riscv/riscv-vector-builtins.cc @@ -46,6 +46,8 @@ #include "regs.h" #include "riscv-vector-builtins.h" +using namespace riscv_vector; + namespace riscv_vector { /* Information about each RVV type. */ @@ -64,6 +66,10 @@ static GTY (()) machine_mode vector_modes[NUM_VECTOR_TYPES]; yields a null tree. */ static GTY(()) tree abi_vector_types[NUM_VECTOR_TYPES + 1]; +/* Same, but with the riscv_vector.h "v..._t" name. */ +extern GTY(()) tree builtin_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1]; +tree builtin_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1]; + rvv_switcher::rvv_switcher () { /* Set have_regs_of_mode before targetm.init_builtins (). */ @@ -183,6 +189,32 @@ register_builtin_types () } } +/* Register vector type TYPE under its risv_vector.h name. */ +static void +register_vector_type (vector_type_index type) +{ + tree vectype = abi_vector_types[type]; + /* When vectype is NULL, the corresponding builtin type + is disabled according to '-march'. */ + if (!vectype) + return; + tree id = get_identifier (vector_types[type].user_name); + tree decl = build_decl (input_location, TYPE_DECL, id, vectype); + decl = lang_hooks.decls.pushdecl (decl); + + /* Record the new RVV type if pushdecl succeeded without error. Use + the ABI type otherwise, so that the type we record at least has the + right form, even if it doesn't have the right name. This should give + better error recovery behavior than installing error_mark_node or + installing an incorrect type. */ + if (decl && TREE_CODE (decl) == TYPE_DECL + && TREE_TYPE (decl) != error_mark_node + && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == vectype) + vectype = TREE_TYPE (decl); + + builtin_vector_types[0][type] = vectype; +} + /* Initialize all compiler built-ins related to RVV that should be defined at start-up. */ void @@ -192,6 +224,8 @@ init_builtins () if (!TARGET_VECTOR) return; register_builtin_types (); + if (in_lto_p) + handle_pragma_vector (); } /* Implement TARGET_VERIFY_TYPE_CONTEXT for RVV types. */ @@ -276,4 +310,15 @@ verify_type_context (location_t loc, type_context_kind context, const_tree type, gcc_unreachable (); } +/* Implement #pragma riscv intrinsic vector. */ +void +handle_pragma_vector () +{ + rvv_switcher rvv; + + /* Define the vector and tuple types. */ + for (unsigned int type_i = 0; type_i < NUM_VECTOR_TYPES; ++type_i) + register_vector_type ((enum vector_type_index) type_i); +} + } // end namespace riscv_vector diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h index a4a8c11..6ca0b07 100644 --- a/gcc/config/riscv/riscv-vector-builtins.h +++ b/gcc/config/riscv/riscv-vector-builtins.h @@ -18,11 +18,14 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -#ifndef GCC_RISCV_V_BUILTINS_H -#define GCC_RISCV_V_BUILTINS_H +#ifndef GCC_RISCV_VECTOR_BUILTINS_H +#define GCC_RISCV_VECTOR_BUILTINS_H namespace riscv_vector { +/* This is for segment instructions. */ +const unsigned int MAX_TUPLE_SIZE = 8; + /* Static information about each vector type. */ struct vector_type_info { @@ -68,12 +71,6 @@ private: bool m_old_have_regs_of_mode[MAX_MACHINE_MODE]; }; -void init_builtins (); -const char *mangle_builtin_type (const_tree); -#ifdef GCC_TARGET_H -bool verify_type_context (location_t, type_context_kind, const_tree, bool); -#endif - } // end namespace riscv_vector #endif diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 0a4c37e..ad57b99 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "target.h" #include "tm.h" #include "rtl.h" #include "regs.h" @@ -45,8 +46,6 @@ along with GCC; see the file COPYING3. If not see #include "emit-rtl.h" #include "reload.h" #include "tm_p.h" -#include "target.h" -#include "target-def.h" #include "basic-block.h" #include "expr.h" #include "optabs.h" @@ -59,7 +58,9 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" #include "tm-constrs.h" #include "rtl-iter.h" -#include "riscv-vector-builtins.h" + +/* This file should be included last. */ +#include "target-def.h" /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ #define UNSPEC_ADDRESS_P(X) \ diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 363113c..acae68e 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -1078,4 +1078,6 @@ extern void riscv_remove_unneeded_save_restore_calls (void); #define TARGET_SUPPORTS_WIDE_INT 1 +#define REGISTER_TARGET_PRAGMAS() riscv_register_pragmas () + #endif /* ! GCC_RISCV_H */ diff --git a/gcc/config/riscv/riscv_vector.h b/gcc/config/riscv/riscv_vector.h new file mode 100644 index 0000000..1efe3f8 --- /dev/null +++ b/gcc/config/riscv/riscv_vector.h @@ -0,0 +1,100 @@ +/* RISC-V 'V' Extension intrinsics include file. + Copyright (C) 2022-2022 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef __RISCV_VECTOR_H +#define __RISCV_VECTOR_H + +#include <stdint.h> +#include <stddef.h> + +#ifndef __riscv_vector +#error "Vector intrinsics require the vector extension." +#else +#ifdef __cplusplus +extern "C" { +#endif + +enum RVV_CSR { + RVV_VSTART = 0, + RVV_VXSAT, + RVV_VXRM, + RVV_VCSR, +}; + +__extension__ extern __inline unsigned long +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vread_csr(enum RVV_CSR csr) +{ + unsigned long rv = 0; + switch (csr) + { + case RVV_VSTART: + __asm__ __volatile__ ("csrr\t%0,vstart" : "=r"(rv) : : "memory"); + break; + case RVV_VXSAT: + __asm__ __volatile__ ("csrr\t%0,vxsat" : "=r"(rv) : : "memory"); + break; + case RVV_VXRM: + __asm__ __volatile__ ("csrr\t%0,vxrm" : "=r"(rv) : : "memory"); + break; + case RVV_VCSR: + __asm__ __volatile__ ("csrr\t%0,vcsr" : "=r"(rv) : : "memory"); + break; + } + return rv; +} + +__extension__ extern __inline void +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vwrite_csr(enum RVV_CSR csr, unsigned long value) +{ + switch (csr) + { + case RVV_VSTART: + __asm__ __volatile__ ("csrw\tvstart,%z0" : : "rJ"(value) : "memory"); + break; + case RVV_VXSAT: + __asm__ __volatile__ ("csrw\tvxsat,%z0" : : "rJ"(value) : "memory"); + break; + case RVV_VXRM: + __asm__ __volatile__ ("csrw\tvxrm,%z0" : : "rJ"(value) : "memory"); + break; + case RVV_VCSR: + __asm__ __volatile__ ("csrw\tvcsr,%z0" : : "rJ"(value) : "memory"); + break; + } +} + +/* NOTE: This implementation of riscv_vector.h is intentionally short. It does + not define the RVV types and intrinsic functions directly in C and C++ + code, but instead uses the following pragma to tell GCC to insert the + necessary type and function definitions itself. The net effect is the + same, and the file is a complete implementation of riscv_vector.h. */ +#pragma riscv intrinsic "vector" + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // __riscv_vector +#endif // __RISCV_VECTOR_H diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv index ad9be09..2f06043 100644 --- a/gcc/config/riscv/t-riscv +++ b/gcc/config/riscv/t-riscv @@ -9,7 +9,7 @@ riscv-vector-builtins.o: $(srcdir)/config/riscv/riscv-vector-builtins.cc \ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) $(TM_P_H) \ memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_H) $(EXPR_H) \ $(FUNCTION_H) fold-const.h gimplify.h explow.h stor-layout.h $(REGS_H) \ - alias.h langhooks.h attribs.h stringpool.h $(REGS_H) \ + alias.h langhooks.h attribs.h stringpool.h \ $(srcdir)/config/riscv/riscv-vector-builtins.h \ $(srcdir)/config/riscv/riscv-vector-builtins.def $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md index 5a44a92..54fef8d 100644 --- a/gcc/config/rs6000/constraints.md +++ b/gcc/config/rs6000/constraints.md @@ -107,12 +107,6 @@ (match_test "TARGET_P8_VECTOR") (match_operand 0 "s5bit_cint_operand"))) -(define_constraint "wD" - "@internal Int constant that is the element number of the 64-bit scalar - in a vector." - (and (match_code "const_int") - (match_test "TARGET_VSX && (ival == VECTOR_ELEMENT_SCALAR_64BIT)"))) - (define_constraint "wE" "@internal Vector constant that can be loaded with the XXSPLTIB instruction." (match_test "xxspltib_constant_nosplit (op, mode)")) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index e226a93..e0e34a7 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -3388,59 +3388,53 @@ ;; Optimize cases were we can do a simple or direct move. ;; Or see if we can avoid doing the move at all -(define_insn "vsx_extract_<mode>" - [(set (match_operand:<VEC_base> 0 "gpc_reg_operand" "=wa, wa, wr, wr") +(define_expand "vsx_extract_<mode>" + [(set (match_operand:<VEC_base> 0 "gpc_reg_operand") (vec_select:<VEC_base> - (match_operand:VSX_D 1 "gpc_reg_operand" "wa, wa, wa, wa") + (match_operand:VSX_D 1 "gpc_reg_operand") (parallel - [(match_operand:QI 2 "const_0_to_1_operand" "wD, n, wD, n")])))] + [(match_operand:QI 2 "const_0_to_1_operand")])))] "VECTOR_MEM_VSX_P (<MODE>mode)" -{ - int element = INTVAL (operands[2]); - int op0_regno = REGNO (operands[0]); - int op1_regno = REGNO (operands[1]); - int fldDM; - - gcc_assert (IN_RANGE (element, 0, 1)); - gcc_assert (VSX_REGNO_P (op1_regno)); - - if (element == VECTOR_ELEMENT_SCALAR_64BIT) - { - if (op0_regno == op1_regno) - return ASM_COMMENT_START " vec_extract to same register"; - - else if (INT_REGNO_P (op0_regno) && TARGET_DIRECT_MOVE - && TARGET_POWERPC64) - return "mfvsrd %0,%x1"; + "") - else if (FP_REGNO_P (op0_regno) && FP_REGNO_P (op1_regno)) - return "fmr %0,%1"; +(define_insn "*vsx_extract_<mode>_0" + [(set (match_operand:<VEC_base> 0 "gpc_reg_operand" "=wa,wa,wr") + (vec_select:<VEC_base> + (match_operand:VSX_D 1 "gpc_reg_operand" "0,wa,wa") + (parallel + [(match_operand:QI 2 "const_0_to_1_operand" "n,n,n")])))] + "VECTOR_MEM_VSX_P (<MODE>mode) + && INTVAL (operands[2]) == (BYTES_BIG_ENDIAN ? 0 : 1)" +{ + if (which_alternative == 0) + return ASM_COMMENT_START " vec_extract to same register"; - else if (VSX_REGNO_P (op0_regno)) - return "xxlor %x0,%x1,%x1"; + if (which_alternative == 2) + return "mfvsrd %0,%x1"; - else - gcc_unreachable (); - } + return "xxlor %x0,%x1,%x1"; +} + [(set_attr "type" "*,veclogical,mfvsr") + (set_attr "isa" "*,*,p8v") + (set_attr "length" "0,*,*")]) - else if (element == VECTOR_ELEMENT_MFVSRLD_64BIT && INT_REGNO_P (op0_regno) - && TARGET_P9_VECTOR && TARGET_POWERPC64 && TARGET_DIRECT_MOVE) +(define_insn "*vsx_extract_<mode>_1" + [(set (match_operand:<VEC_base> 0 "gpc_reg_operand" "=wa,wr") + (vec_select:<VEC_base> + (match_operand:VSX_D 1 "gpc_reg_operand" "wa,wa") + (parallel + [(match_operand:QI 2 "const_0_to_1_operand" "n,n")])))] + "VECTOR_MEM_VSX_P (<MODE>mode) + && INTVAL (operands[2]) == (BYTES_BIG_ENDIAN ? 1 : 0)" +{ + if (which_alternative == 1) return "mfvsrld %0,%x1"; - else if (VSX_REGNO_P (op0_regno)) - { - fldDM = element << 1; - if (!BYTES_BIG_ENDIAN) - fldDM = 3 - fldDM; - operands[3] = GEN_INT (fldDM); - return "xxpermdi %x0,%x1,%x1,%3"; - } - - else - gcc_unreachable (); + operands[3] = GEN_INT (BYTES_BIG_ENDIAN ? 2 : 3); + return "xxpermdi %x0,%x1,%x1,%3"; } - [(set_attr "type" "veclogical,mfvsr,mfvsr,vecperm") - (set_attr "isa" "*,*,p8v,p9v")]) + [(set_attr "type" "mfvsr,vecperm") + (set_attr "isa" "*,p9v")]) ;; Optimize extracting a single scalar element from memory. (define_insn_and_split "*vsx_extract_<P:mode>_<VSX_D:mode>_load" @@ -3466,8 +3460,9 @@ [(set (match_operand:<VEC_base> 0 "memory_operand" "=m,Z,wY") (vec_select:<VEC_base> (match_operand:VSX_D 1 "register_operand" "d,v,v") - (parallel [(match_operand:QI 2 "vsx_scalar_64bit" "wD,wD,wD")])))] - "VECTOR_MEM_VSX_P (<MODE>mode)" + (parallel [(match_operand:QI 2 "vsx_scalar_64bit" "n,n,n")])))] + "VECTOR_MEM_VSX_P (<MODE>mode) + && INTVAL (operands[2]) == (BYTES_BIG_ENDIAN ? 0 : 1)" "@ stfd%U0%X0 %1,%0 stxsdx %x1,%y0 diff --git a/gcc/config/vxworks.cc b/gcc/config/vxworks.cc index 9d25873..f0c0df2 100644 --- a/gcc/config/vxworks.cc +++ b/gcc/config/vxworks.cc @@ -164,16 +164,10 @@ vxworks_override_options (void) if (flag_pic > 0 && !TARGET_VXWORKS_RTP) error ("PIC is only supported for RTPs"); - /* VxWorks comes with non-gdb debuggers which only support strict - dwarf up to certain version. Default dwarf control to friendly - values for these. */ - + /* VxWorks comes with non-gdb debuggers which only support strict dwarf + up to certain versions, as controlled by DWARF_VERSION_DEFAULT. */ if (!OPTION_SET_P (dwarf_strict)) dwarf_strict = 1; - - if (!OPTION_SET_P (dwarf_version)) - dwarf_version = VXWORKS_DWARF_VERSION_DEFAULT; - } /* We don't want to use library symbol __clear_cache on SR0640. Avoid diff --git a/gcc/config/vxworks.h b/gcc/config/vxworks.h index 84a9c93..075a451 100644 --- a/gcc/config/vxworks.h +++ b/gcc/config/vxworks.h @@ -376,11 +376,11 @@ extern void vxworks_asm_out_destructor (rtx symbol, int priority); vxworks_emit_call_builtin___clear_cache extern void vxworks_emit_call_builtin___clear_cache (rtx begin, rtx end); -/* Default dwarf control values, for non-gdb debuggers that come with - VxWorks. */ +/* Default dwarf control values, accounting for non-gdb debuggers that come + with VxWorks. */ -#undef VXWORKS_DWARF_VERSION_DEFAULT -#define VXWORKS_DWARF_VERSION_DEFAULT (TARGET_VXWORKS7 ? 4 : 2) +#undef DWARF_VERSION_DEFAULT +#define DWARF_VERSION_DEFAULT (TARGET_VXWORKS7 ? 3 : 2) #undef DWARF_GNAT_ENCODINGS_DEFAULT #define DWARF_GNAT_ENCODINGS_DEFAULT \ diff --git a/gcc/config/vxworks/_vxworks-versions.h b/gcc/config/vxworks/_vxworks-versions.h index 15e8bfe..994dda9 100644 --- a/gcc/config/vxworks/_vxworks-versions.h +++ b/gcc/config/vxworks/_vxworks-versions.h @@ -23,15 +23,24 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define _VXWORKS_VERSIONS_H 1 /* All we need is access to the bare _WRS_VXWORKS_MAJOR/MINOR macros, - exposed by version.h or already provided somehow (e.g. with a self - spec for some reason). When resorting to system headers, cheat a - bit to make sure we don't drag additional header files, which can - easily cause #include ordering nightmares. */ + exposed by version.h or already provided somehow (e.g. with a self spec + for some reason). When resorting to system headers, use typical os + paths to prevent possible confusion with a gcc version of version.h + visible during the build and temporarily #undef _WRS_KERNEL to prevent + indirect inclusion of internal header files, which can easily cause + #include ordering nightmares. */ #if !defined(_WRS_VXWORKS_MAJOR) + +#if defined(_VSB_CONFIG_FILE) +#define _VXWORKS_VERSION_H <../public/version.h> +#else +#define _VXWORKS_VERSION_H <../h/version.h> +#endif + #pragma push_macro("_WRS_KERNEL") #undef _WRS_KERNEL -#include <version.h> +#include _VXWORKS_VERSION_H #pragma pop_macro("_WRS_KERNEL") #endif diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index db6fea1..3aa9f03 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,154 @@ +2022-10-07 Marek Polacek <polacek@redhat.com> + + PR c++/107085 + * call.cc (conv_binds_ref_to_temporary): New. + (ref_conv_binds_directly): Rename to... + (ref_conv_binds_to_temporary): ...this. Use + conv_binds_ref_to_temporary. + * cp-tree.h (ref_conv_binds_directly): Rename to... + (ref_conv_binds_to_temporary): ...this. + * method.cc (ref_xes_from_temporary): Use ref_conv_binds_to_temporary. + * parser.cc (warn_for_range_copy): Likewise. + +2022-10-07 Qing Zhao <qing.zhao@oracle.com> + + * module.cc (trees_out::core_bools): Stream out new bit + decl_not_flexarray. + (trees_in::core_bools): Stream in new bit decl_not_flexarray. + +2022-10-07 Patrick Palka <ppalka@redhat.com> + + * module.cc (trees_out::mark_class_def): Guard against + DECL_BIT_FIELD_REPRESENTATIVE not being a decl. + +2022-10-07 Jason Merrill <jason@redhat.com> + + * init.cc (expand_default_init): Also push the INIT_EXPR inside a + CLEANUP_POINT_EXPR. + +2022-10-07 Patrick Palka <ppalka@redhat.com> + + PR c++/104433 + * module.cc (trees_out::core_bools): Don't override + DECL_EXTERNAL to true for static variables from an inline + function. + +2022-10-07 Martin Liska <mliska@suse.cz> + + * module.cc (enum module_state_counts): Use array size. + * name-lookup.cc (class namespace_limit_reached): Likewise. + (class module_state): Move up in the file. + +2022-10-07 Jakub Jelinek <jakub@redhat.com> + + * parser.cc (cp_parser_check_std_attribute): Only do checks if + attribute is a standard attribute or in gnu namespace and only + lookup other attributes in those namespaces. + * cp-gimplify.cc (lookup_hotness_attribute): Adjust function comment. + Only return true for standard attribute or gnu namespace attribute. + (remove_hotness_attribute): Only remove hotness attributes when + they are standard or in gnu namespace, implement it in a single + loop rather than former 4 now 8 remove_attribute calls. + +2022-10-06 Jason Merrill <jason@redhat.com> + + * coroutines.cc (expand_one_await_expression): Change conversion + to VIEW_CONVERT_EXPR. + * cp-gimplify.cc (cp_genericize_r) [CONVERT_EXPR]: Add assert. + +2022-10-06 Joseph Myers <joseph@codesourcery.com> + + * lex.cc (init_reswords): Handle D_EXT11. + +2022-10-06 Patrick Palka <ppalka@redhat.com> + + * pt.cc (optimize_specialization_lookup_p): Remove. + (retrieve_specialization): Assume the above returns false + and simplify accordingly. + (register_specialization): Likewise. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + * parser.cc (cp_parser_omp_assumption_clauses): Emit IFN_ASSUME + call for holds clause on assume construct. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + PR c++/106654 + * cp-tree.h (process_stmt_assume_attribute): Implement C++23 + P1774R8 - Portable assumptions. Declare. + (diagnose_failing_condition): Declare. + (find_failing_clause): Likewise. + * parser.cc (assume_attr): New enumerator. + (cp_parser_parenthesized_expression_list): Handle assume_attr. + Remove identifier variable, for id_attr push the identifier into + expression_list right away instead of inserting it before all the + others at the end. + (cp_parser_conditional_expression): New function. + (cp_parser_constant_expression): Use it. + (cp_parser_statement): Handle assume attribute. + (cp_parser_expression_statement): Likewise. + (cp_parser_gnu_attribute_list): Use assume_attr for assume + attribute. + (cp_parser_std_attribute): Likewise. Handle standard assume + attribute like gnu::assume. + * cp-gimplify.cc (process_stmt_assume_attribute): New function. + * constexpr.cc: Include fold-const.h. + (find_failing_clause_r, find_failing_clause): New functions, + moved from semantics.cc with ctx argument added and if non-NULL, + call cxx_eval_constant_expression rather than fold_non_dependent_expr. + (cxx_eval_internal_function): Handle IFN_ASSUME. + (potential_constant_expression_1): Likewise. + * pt.cc (tsubst_copy_and_build): Likewise. + * semantics.cc (diagnose_failing_condition): New function. + (find_failing_clause_r, find_failing_clause): Moved to constexpr.cc. + (finish_static_assert): Use it. Add auto_diagnostic_group. + +2022-10-05 Jason Merrill <jason@redhat.com> + + * tree.cc (lvalue_kind) [VIEW_CONVERT_EXPR]: Change prvalue to + xvalue. + +2022-10-04 Jason Merrill <jason@redhat.com> + + PR c++/107154 + * cp-gimplify.cc (cp_genericize_init_expr): Use iloc_sentinel. + (cp_genericize_target_expr): Likewise. + +2022-10-04 Patrick Palka <ppalka@redhat.com> + + PR c++/107136 + * Make-lang.in (CP_PLUGIN_HEADERS): Add cp-trait.def. + +2022-10-04 Jakub Jelinek <jakub@redhat.com> + + * cp-tree.h (struct omp_declare_target_attr): Rename to ... + (cp_omp_declare_target_attr): ... this. Add device_type member. + (omp_begin_assumes_data): Rename to ... + (cp_omp_begin_assumes_data): ... this. + (struct saved_scope): Change types of omp_declare_target_attribute + and omp_begin_assumes. + * parser.cc (cp_parser_omp_clause_device_type): Uncomment + check_no_duplicate_clause call. + (cp_parser_omp_all_clauses): Fix up pasto, c_name for OMP_CLAUSE_LINK + should be "link" rather than "to". + (cp_parser_omp_declare_target): Adjust for omp_declare_target_attr + to cp_omp_declare_target_attr changes, push -1 as device_type. Use + error_at rather than warning_at for declare target with only + device_type clauses. + (OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK): Define. + (cp_parser_omp_begin): Add begin declare target support. Adjust + for omp_begin_assumes_data to cp_omp_begin_assumes_data change. + (cp_parser_omp_end): Adjust for the + omp_declare_target_attr to cp_omp_declare_target_attr and + omp_begin_assumes_data to cp_omp_begin_assumes_data type changes, + adjust diagnostics wording and simplify format strings for easier + translations. + * semantics.cc (finish_translation_unit): Likewise. + * decl2.cc (cplus_decl_attributes): If device_type was present on + begin declare target, add "omp declare target host" and/or + "omp declare target nohost" attributes. + 2022-10-03 Jakub Jelinek <jakub@redhat.com> * cp-tree.h (BCS_STMT_EXPR): New enumerator. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 38d8eee..aa84d68 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -39,7 +39,7 @@ CXX_INSTALL_NAME := $(shell echo c++|sed '$(program_transform_name)') GXX_INSTALL_NAME := $(shell echo g++|sed '$(program_transform_name)') CXX_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo c++|sed '$(program_transform_name)') GXX_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo g++|sed '$(program_transform_name)') -CP_PLUGIN_HEADERS := cp-tree.h cxx-pretty-print.h name-lookup.h type-utils.h operators.def +CP_PLUGIN_HEADERS := cp-tree.h cxx-pretty-print.h name-lookup.h type-utils.h operators.def cp-trait.def # # Define the names for selecting c++ in LANGUAGES. diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index bd04a1d..70ec964 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -9144,7 +9144,7 @@ init_by_return_slot_p (tree exp) Places that use this function (or _opt) to decide to elide a copy should probably use make_safe_copy_elision instead. */ -static bool +bool unsafe_copy_elision_p (tree target, tree exp) { return unsafe_return_slot_p (target) && init_by_return_slot_p (exp); @@ -9210,15 +9210,47 @@ conv_binds_ref_to_prvalue (conversion *c) return conv_is_prvalue (next_conversion (c)); } -/* Return tristate::TS_TRUE if converting EXPR to a reference type TYPE does - not involve creating a temporary. Return tristate::TS_FALSE if converting - EXPR to a reference type TYPE binds the reference to a temporary. If the - conversion is invalid or bad, return tristate::TS_UNKNOWN. DIRECT_INIT_P +/* True iff C is a conversion that binds a reference to a temporary. + This is a superset of conv_binds_ref_to_prvalue: here we're also + interested in xvalues. */ + +static bool +conv_binds_ref_to_temporary (conversion *c) +{ + if (conv_binds_ref_to_prvalue (c)) + return true; + if (c->kind != ck_ref_bind) + return false; + c = next_conversion (c); + /* This is the case for + struct Base {}; + struct Derived : Base {}; + const Base& b(Derived{}); + where we bind 'b' to the Base subobject of a temporary object of type + Derived. The subobject is an xvalue; the whole object is a prvalue. */ + if (c->kind != ck_base) + return false; + c = next_conversion (c); + if (c->kind == ck_identity && c->u.expr) + { + tree expr = c->u.expr; + while (handled_component_p (expr)) + expr = TREE_OPERAND (expr, 0); + if (TREE_CODE (expr) == TARGET_EXPR) + return true; + } + return false; +} + +/* Return tristate::TS_TRUE if converting EXPR to a reference type TYPE binds + the reference to a temporary. Return tristate::TS_FALSE if converting + EXPR to a reference type TYPE doesn't bind the reference to a temporary. If + the conversion is invalid or bad, return tristate::TS_UNKNOWN. DIRECT_INIT_P says whether the conversion should be done in direct- or copy-initialization context. */ tristate -ref_conv_binds_directly (tree type, tree expr, bool direct_init_p /*= false*/) +ref_conv_binds_to_temporary (tree type, tree expr, bool direct_init_p/*=false*/) { gcc_assert (TYPE_REF_P (type)); @@ -9230,7 +9262,7 @@ ref_conv_binds_directly (tree type, tree expr, bool direct_init_p /*= false*/) /*c_cast_p=*/false, flags, tf_none); tristate ret (tristate::TS_UNKNOWN); if (conv && !conv->bad_p) - ret = tristate (!conv_binds_ref_to_prvalue (conv)); + ret = tristate (conv_binds_ref_to_temporary (conv)); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); @@ -9909,7 +9941,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) && !unsafe) { tree to = cp_build_fold_indirect_ref (fa); - val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg); + val = cp_build_init_expr (to, arg); return val; } } @@ -10068,7 +10100,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) } call = cxx_constant_value (call, obj_arg, complain); if (obj_arg && !error_operand_p (call)) - call = build2 (INIT_EXPR, void_type_node, obj_arg, call); + call = cp_build_init_expr (obj_arg, call); call = convert_from_reference (call); } } @@ -10733,7 +10765,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args, check_self_delegation (arg); /* Avoid change of behavior on Wunused-var-2.C. */ instance = mark_lvalue_use (instance); - return build2 (INIT_EXPR, class_type, instance, arg); + return cp_build_init_expr (instance, arg); } } @@ -11151,9 +11183,7 @@ build_new_method_call (tree instance, tree fns, vec<tree, va_gc> **args, { if (is_dummy_object (instance)) return get_target_expr (init, complain); - init = build2 (INIT_EXPR, TREE_TYPE (instance), instance, init); - TREE_SIDE_EFFECTS (init) = true; - return init; + return cp_build_init_expr (instance, init); } /* Otherwise go ahead with overload resolution. */ @@ -11200,9 +11230,7 @@ build_new_method_call (tree instance, tree fns, vec<tree, va_gc> **args, ctor = digest_init (basetype, ctor, complain); if (ctor == error_mark_node) return error_mark_node; - ctor = build2 (INIT_EXPR, TREE_TYPE (instance), instance, ctor); - TREE_SIDE_EFFECTS (ctor) = true; - return ctor; + return cp_build_init_expr (instance, ctor); } } if (complain & tf_error) diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index db7571d..06dcd71 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" #include "stringpool.h" #include "attribs.h" +#include "fold-const.h" static bool verify_constant (tree, bool, bool *, bool *); #define VERIFY_CONSTANT(X) \ @@ -1818,6 +1819,52 @@ cx_error_context (void) return r; } +/* If we have a condition in conjunctive normal form (CNF), find the first + failing clause. In other words, given an expression like + + true && true && false && true && false + + return the first 'false'. EXPR is the expression. */ + +static tree +find_failing_clause_r (constexpr_ctx *ctx, tree expr) +{ + if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR) + { + /* First check the left side... */ + tree e = find_failing_clause_r (ctx, TREE_OPERAND (expr, 0)); + if (e == NULL_TREE) + /* ...if we didn't find a false clause, check the right side. */ + e = find_failing_clause_r (ctx, TREE_OPERAND (expr, 1)); + return e; + } + tree e = contextual_conv_bool (expr, tf_none); + if (ctx) + { + bool new_non_constant_p = false, new_overflow_p = false; + e = cxx_eval_constant_expression (ctx, e, vc_prvalue, + &new_non_constant_p, + &new_overflow_p); + } + else + e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true); + if (integer_zerop (e)) + /* This is the failing clause. */ + return expr; + return NULL_TREE; +} + +/* Wrapper for find_failing_clause_r. */ + +tree +find_failing_clause (constexpr_ctx *ctx, tree expr) +{ + if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR) + if (tree e = find_failing_clause_r (ctx, expr)) + expr = e; + return expr; +} + /* Evaluate a call T to a GCC internal function when possible and return the evaluated result or, under the control of CTX, give an error, set NON_CONSTANT_P, and return the unevaluated call T otherwise. */ @@ -1837,6 +1884,48 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, case IFN_FALLTHROUGH: return void_node; + case IFN_ASSUME: + /* For now, restrict constexpr evaluation of [[assume (cond)]] + only to the cases which don't have side-effects. Evaluating + it even when it does would mean we'd need to somehow undo + all the side-effects e.g. in ctx->global->values. */ + if (!TREE_SIDE_EFFECTS (CALL_EXPR_ARG (t, 0)) + /* And it needs to be a potential constant expression. */ + && potential_rvalue_constant_expression (CALL_EXPR_ARG (t, 0))) + { + constexpr_ctx new_ctx = *ctx; + new_ctx.quiet = true; + tree arg = CALL_EXPR_ARG (t, 0); + bool new_non_constant_p = false, new_overflow_p = false; + arg = cxx_eval_constant_expression (&new_ctx, arg, vc_prvalue, + &new_non_constant_p, + &new_overflow_p); + if (!new_non_constant_p && !new_overflow_p && integer_zerop (arg)) + { + if (!*non_constant_p && !ctx->quiet) + { + /* See if we can find which clause was failing + (for logical AND). */ + tree bad = find_failing_clause (&new_ctx, + CALL_EXPR_ARG (t, 0)); + /* If not, or its location is unusable, fall back to the + previous location. */ + location_t cloc = cp_expr_loc_or_loc (bad, EXPR_LOCATION (t)); + + auto_diagnostic_group d; + + /* Report the error. */ + error_at (cloc, + "failed %<assume%> attribute assumption"); + diagnose_failing_condition (bad, cloc, false); + } + + *non_constant_p = true; + return t; + } + } + return void_node; + case IFN_ADD_OVERFLOW: opcode = PLUS_EXPR; break; @@ -8706,6 +8795,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case IFN_UBSAN_BOUNDS: case IFN_UBSAN_VPTR: case IFN_FALLTHROUGH: + case IFN_ASSUME: return true; case IFN_ADD_OVERFLOW: diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index eca01ab..01a3e83 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -1728,8 +1728,11 @@ expand_one_await_expression (tree *stmt, tree *await_expr, void *d) } else { - r = build1_loc (loc, CONVERT_EXPR, void_coro_handle_type, suspend); - r = build2_loc (loc, INIT_EXPR, void_coro_handle_type, data->conthand, r); + r = suspend; + if (!same_type_ignoring_top_level_qualifiers_p (susp_type, + void_coro_handle_type)) + r = build1_loc (loc, VIEW_CONVERT_EXPR, void_coro_handle_type, r); + r = cp_build_init_expr (loc, data->conthand, r); r = build1 (CONVERT_EXPR, void_type_node, r); append_to_statement_list (r, &body_list); is_cont = true; @@ -1752,7 +1755,7 @@ expand_one_await_expression (tree *stmt, tree *await_expr, void *d) r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5, susp_idx, final_susp, r_l, d_l, data->coro_fp); - r = build2 (INIT_EXPR, integer_type_node, cond, r); + r = cp_build_init_expr (cond, r); finish_switch_cond (r, sw); r = build_case_label (build_int_cst (integer_type_node, 0), NULL_TREE, create_anon_label_with_ctx (loc, actor)); @@ -2301,7 +2304,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, vec<tree, va_gc> *args = make_tree_vector_single (r); tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL, NULL, tf_warning_or_error); - r = build2 (INIT_EXPR, handle_type, ash, hfa); + r = cp_build_init_expr (ash, hfa); r = coro_build_cvt_void_expr_stmt (r, loc); add_stmt (r); release_tree_vector (args); @@ -2773,17 +2776,19 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted, if (!VOID_TYPE_P (TREE_TYPE (then_cl))) { gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST); - then_cl - = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type, - var, then_cl); + if (init_expr) + then_cl = cp_build_init_expr (var, then_cl); + else + then_cl = build2 (MODIFY_EXPR, var_type, var, then_cl); } tree else_cl = COND_EXPR_ELSE (old_expr); if (!VOID_TYPE_P (TREE_TYPE (else_cl))) { gcc_checking_assert (TREE_CODE (else_cl) != STATEMENT_LIST); - else_cl - = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type, - var, else_cl); + if (init_expr) + else_cl = cp_build_init_expr (var, else_cl); + else + else_cl = build2 (MODIFY_EXPR, var_type, var, else_cl); } n->init = build3 (COND_EXPR, var_type, cond, then_cl, else_cl); } @@ -2801,7 +2806,7 @@ flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted, DECL_ARTIFICIAL (cond_var) = true; layout_decl (cond_var, 0); gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type)); - cond = build2 (INIT_EXPR, cond_type, cond_var, cond); + cond = cp_build_init_expr (cond_var, cond); var_nest_node *ins = new var_nest_node (cond_var, cond, n->prev, n); COND_EXPR_COND (n->init) = cond_var; @@ -2954,8 +2959,7 @@ handle_nested_conditionals (var_nest_node *n, vec<tree>& list, expression that performs the init and then records that the variable is live (and the DTOR should be run at the scope exit. */ - tree set_flag = build2 (INIT_EXPR, boolean_type_node, - flag, boolean_true_node); + tree set_flag = cp_build_init_expr (flag, boolean_true_node); n->init = build2 (COMPOUND_EXPR, boolean_type_node, n->init, set_flag); } @@ -3468,8 +3472,7 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d) /* We want to initialize the new variable with the expression that contains the await(s) and potentially also needs to have truth_if expressions expanded. */ - tree new_s = build2_loc (sloc, INIT_EXPR, boolean_type_node, - newvar, cond_inner); + tree new_s = cp_build_init_expr (sloc, newvar, cond_inner); finish_expr_stmt (new_s); IF_COND (if_stmt) = newvar; add_stmt (if_stmt); @@ -3653,7 +3656,7 @@ await_statement_walker (tree *stmt, int *do_subtree, void *d) if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR) cond_inner = TREE_OPERAND (cond_inner, 0); location_t sloc = EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt)); - tree new_s = build2_loc (sloc, INIT_EXPR, sw_type, newvar, + tree new_s = cp_build_init_expr (sloc, newvar, cond_inner); finish_expr_stmt (new_s); SWITCH_STMT_COND (sw_stmt) = newvar; @@ -4732,7 +4735,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) } tree allocated = build1 (CONVERT_EXPR, coro_frame_ptr, new_fn); - tree r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, allocated); + tree r = cp_build_init_expr (coro_fp, allocated); r = coro_build_cvt_void_expr_stmt (r, fn_start); add_stmt (r); @@ -4793,7 +4796,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) 1, 0,tf_warning_or_error); tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE, false, tf_warning_or_error); - r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node); + r = cp_build_init_expr (fnf_x, boolean_true_node); r = coro_build_cvt_void_expr_stmt (r, fn_start); add_stmt (r); @@ -4805,7 +4808,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) /*protect=*/1, /*want_type=*/0, tf_warning_or_error); tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE, false, tf_warning_or_error); - r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr); + r = cp_build_init_expr (fn_start, resume_x, actor_addr); finish_expr_stmt (r); tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy); @@ -4815,7 +4818,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) tree destroy_x = build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false, tf_warning_or_error); - r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr); + r = cp_build_init_expr (fn_start, destroy_x, destroy_addr); finish_expr_stmt (r); /* [dcl.fct.def.coroutine] /13 @@ -5008,8 +5011,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) release_tree_vector (arg); } else - r = build2_loc (fn_start, INIT_EXPR, gro_type, - DECL_RESULT (orig), get_ro); + r = cp_build_init_expr (fn_start, DECL_RESULT (orig), get_ro); if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type)) /* If some part of the initalization code (prior to the await_resume @@ -5064,7 +5066,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) = build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false, tf_warning_or_error); r = build_int_cst (short_unsigned_type_node, 0); - r = build2_loc (fn_start, INIT_EXPR, short_unsigned_type_node, resume_idx, r); + r = cp_build_init_expr (fn_start, resume_idx, r); r = coro_build_cvt_void_expr_stmt (r, fn_start); add_stmt (r); diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index cca3b9f..d0e12c9 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -250,6 +250,7 @@ cp_gimplify_init_expr (tree *expr_p) if (TREE_CODE (from) == TARGET_EXPR) if (tree init = TARGET_EXPR_INITIAL (from)) { + gcc_checking_assert (TARGET_EXPR_ELIDING_P (from)); if (target_expr_needs_replace (from)) { /* If this was changed by cp_genericize_target_expr, we need to @@ -745,6 +746,11 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) /* A TARGET_EXPR that expresses direct-initialization should have been elided by cp_gimplify_init_expr. */ gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p)); + /* Likewise, but allow extra temps of trivial type so that + gimplify_init_ctor_preeval can materialize subobjects of a CONSTRUCTOR + on the rhs of an assignment, as in constexpr-aggr1.C. */ + gcc_checking_assert (!TARGET_EXPR_ELIDING_P (*expr_p) + || !TREE_ADDRESSABLE (TREE_TYPE (*expr_p))); ret = GS_UNHANDLED; break; @@ -920,6 +926,7 @@ cp_genericize_init (tree *replace, tree from, tree to) static void cp_genericize_init_expr (tree *stmt_p) { + iloc_sentinel ils = EXPR_LOCATION (*stmt_p); tree to = TREE_OPERAND (*stmt_p, 0); tree from = TREE_OPERAND (*stmt_p, 1); if (SIMPLE_TARGET_EXPR_P (from) @@ -935,6 +942,7 @@ cp_genericize_init_expr (tree *stmt_p) static void cp_genericize_target_expr (tree *stmt_p) { + iloc_sentinel ils = EXPR_LOCATION (*stmt_p); tree slot = TARGET_EXPR_SLOT (*stmt_p); cp_genericize_init (&TARGET_EXPR_INITIAL (*stmt_p), TARGET_EXPR_INITIAL (*stmt_p), slot); @@ -1108,7 +1116,10 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_) cp_walk_tree (&init, cp_fold_r, data, NULL); *walk_subtrees = 0; if (TREE_CODE (init) == TARGET_EXPR) - *stmt_p = init; + { + TARGET_EXPR_ELIDING_P (init) = TARGET_EXPR_ELIDING_P (stmt); + *stmt_p = init; + } } break; @@ -1587,6 +1598,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) break; case CONVERT_EXPR: + gcc_checking_assert (!AGGREGATE_TYPE_P (TREE_TYPE (stmt))); gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt)); break; @@ -2899,7 +2911,7 @@ cp_fold (tree x) loc = EXPR_LOCATION (x); tree s = build_fold_indirect_ref_loc (loc, CALL_EXPR_ARG (x, 0)); - r = build2_loc (loc, INIT_EXPR, TREE_TYPE (s), s, r); + r = cp_build_init_expr (s, r); } x = r; break; @@ -3025,7 +3037,7 @@ cp_fold (tree x) return x; } -/* Look up either "hot" or "cold" in attribute list LIST. */ +/* Look up "hot", "cold", "likely" or "unlikely" in attribute list LIST. */ tree lookup_hotness_attribute (tree list) @@ -3033,24 +3045,36 @@ lookup_hotness_attribute (tree list) for (; list; list = TREE_CHAIN (list)) { tree name = get_attribute_name (list); - if (is_attribute_p ("hot", name) - || is_attribute_p ("cold", name) - || is_attribute_p ("likely", name) - || is_attribute_p ("unlikely", name)) + if ((is_attribute_p ("hot", name) + || is_attribute_p ("cold", name) + || is_attribute_p ("likely", name) + || is_attribute_p ("unlikely", name)) + && is_attribute_namespace_p ("", list)) break; } return list; } -/* Remove both "hot" and "cold" attributes from LIST. */ +/* Remove "hot", "cold", "likely" and "unlikely" attributes from LIST. */ static tree remove_hotness_attribute (tree list) { - list = remove_attribute ("hot", list); - list = remove_attribute ("cold", list); - list = remove_attribute ("likely", list); - list = remove_attribute ("unlikely", list); + for (tree *p = &list; *p; ) + { + tree l = *p; + tree name = get_attribute_name (l); + if ((is_attribute_p ("hot", name) + || is_attribute_p ("cold", name) + || is_attribute_p ("likely", name) + || is_attribute_p ("unlikely", name)) + && is_attribute_namespace_p ("", l)) + { + *p = TREE_CHAIN (l); + continue; + } + p = &TREE_CHAIN (l); + } return list; } @@ -3079,6 +3103,50 @@ process_stmt_hotness_attribute (tree std_attrs, location_t attrs_loc) return std_attrs; } +/* If [[assume (cond)]] appears on this statement, handle it. */ + +tree +process_stmt_assume_attribute (tree std_attrs, tree statement, + location_t attrs_loc) +{ + if (std_attrs == error_mark_node) + return std_attrs; + tree attr = lookup_attribute ("gnu", "assume", std_attrs); + if (!attr) + return std_attrs; + /* The next token after the assume attribute is not ';'. */ + if (statement) + { + warning_at (attrs_loc, OPT_Wattributes, + "%<assume%> attribute not followed by %<;%>"); + attr = NULL_TREE; + } + for (; attr; attr = lookup_attribute ("gnu", "assume", TREE_CHAIN (attr))) + { + tree args = TREE_VALUE (attr); + int nargs = list_length (args); + if (nargs != 1) + { + auto_diagnostic_group d; + error_at (attrs_loc, "wrong number of arguments specified for " + "%qE attribute", get_attribute_name (attr)); + inform (attrs_loc, "expected %i, found %i", 1, nargs); + } + else + { + tree arg = TREE_VALUE (args); + if (!type_dependent_expression_p (arg)) + arg = contextual_conv_bool (arg, tf_warning_or_error); + if (error_operand_p (arg)) + continue; + statement = build_call_expr_internal_loc (attrs_loc, IFN_ASSUME, + void_type_node, 1, arg); + finish_expr_stmt (statement); + } + } + return remove_attribute ("gnu", "assume", std_attrs); +} + /* Helper of fold_builtin_source_location, return the std::source_location::__impl type after performing verification on it. LOC is used for reporting any errors. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8cf9707..ab6f85a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -505,6 +505,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; DECL_MODULE_EXPORT_P (in _DECL) PACK_EXPANSION_FORCE_EXTRA_ARGS_P (in *_PACK_EXPANSION) LAMBDA_EXPR_STATIC_P (in LAMBDA_EXPR) + TARGET_EXPR_ELIDING_P (in TARGET_EXPR) 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs) TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). @@ -5370,6 +5371,11 @@ get_vec_init_expr (tree t) #define TARGET_EXPR_DIRECT_INIT_P(NODE) \ TREE_LANG_FLAG_2 (TARGET_EXPR_CHECK (NODE)) +/* True if we expect this TARGET_EXPR to be used as an initializer, not to + materialize as a temporary. */ +#define TARGET_EXPR_ELIDING_P(NODE) \ + TREE_LANG_FLAG_3 (TARGET_EXPR_CHECK (NODE)) + /* True if NODE is a TARGET_EXPR that just expresses a copy of its INITIAL; if the initializer has void type, it's doing something more complicated. */ #define SIMPLE_TARGET_EXPR_P(NODE) \ @@ -6534,7 +6540,7 @@ extern bool sufficient_parms_p (const_tree); extern tree type_decays_to (tree); extern tree extract_call_expr (tree); extern tree build_trivial_dtor_call (tree, bool = false); -extern tristate ref_conv_binds_directly (tree, tree, bool = false); +extern tristate ref_conv_binds_to_temporary (tree, tree, bool = false); extern tree build_user_type_conversion (tree, tree, int, tsubst_flags_t); extern tree build_new_function_call (tree, vec<tree, va_gc> **, @@ -6657,6 +6663,7 @@ extern bool is_list_ctor (tree); extern void validate_conversion_obstack (void); extern void mark_versions_used (tree); extern int unsafe_return_slot_p (tree); +extern bool unsafe_copy_elision_p (tree, tree); extern bool make_safe_copy_elision (tree, tree); extern bool cp_handle_deprecated_or_unavailable (tree, tsubst_flags_t = tf_warning_or_error); extern void cp_warn_deprecated_use_scopes (tree); @@ -7715,6 +7722,7 @@ extern tree build_transaction_expr (location_t, tree, int, tree); extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool, bool); extern tree baselink_for_fns (tree); +extern void diagnose_failing_condition (tree, location_t, bool); extern void finish_static_assert (tree, tree, location_t, bool, bool); extern tree finish_decltype_type (tree, bool, tsubst_flags_t); @@ -8181,6 +8189,10 @@ extern tree build_functional_cast (location_t, tree, tree, tsubst_flags_t); extern tree add_exception_specifier (tree, tree, tsubst_flags_t); extern tree merge_exception_specifiers (tree, tree); +extern void set_target_expr_eliding (tree); +extern tree cp_build_init_expr (location_t, tree, tree); +inline tree cp_build_init_expr (tree t, tree i) +{ return cp_build_init_expr (input_location, t, i); } /* in mangle.cc */ extern void init_mangle (void); @@ -8242,6 +8254,7 @@ extern tree predeclare_vla (tree); extern void clear_fold_cache (void); extern tree lookup_hotness_attribute (tree); extern tree process_stmt_hotness_attribute (tree, location_t); +extern tree process_stmt_assume_attribute (tree, tree, location_t); extern bool simple_empty_class_p (tree, tree, tree_code); extern tree fold_builtin_source_location (location_t); @@ -8447,6 +8460,8 @@ extern tree fold_sizeof_expr (tree); extern void clear_cv_and_fold_caches (void); extern tree unshare_constructor (tree CXX_MEM_STAT_INFO); extern bool decl_implicit_constexpr_p (tree); +struct constexpr_ctx; +extern tree find_failing_clause (constexpr_ctx *ctx, tree); extern bool replace_decl (tree *, tree, tree); /* An RAII sentinel used to restrict constexpr evaluation so that it diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 07148b9..82eb0c2 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -7500,7 +7500,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) } if (init && init != error_mark_node) - init_code = build2 (INIT_EXPR, type, decl, init); + init_code = cp_build_init_expr (decl, init); if (init_code && !TREE_SIDE_EFFECTS (init_code) && init_code != error_mark_node) diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc index 048612d..b8a85ed 100644 --- a/gcc/cp/except.cc +++ b/gcc/cp/except.cc @@ -755,7 +755,7 @@ build_throw (location_t loc, tree exp) tree tmp = decay_conversion (exp, tf_warning_or_error); if (tmp == error_mark_node) return error_mark_node; - exp = build2 (INIT_EXPR, temp_type, object, tmp); + exp = cp_build_init_expr (object, tmp); } /* Mark any cleanups from the initialization as MUST_NOT_THROW, since diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index bf46578..3d5d390 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -686,6 +686,8 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) /* Now put it back so C++17 copy elision works. */ init = get_target_expr (init); + set_target_expr_eliding (init); + current_class_ptr = save_ccp; current_class_ref = save_ccr; return init; @@ -1006,7 +1008,7 @@ perform_member_init (tree member, tree init, hash_set<tree> &uninitialized) if (TREE_CODE (type) == ARRAY_TYPE) { init = build_vec_init_expr (type, init, tf_warning_or_error); - init = build2 (INIT_EXPR, type, decl, init); + init = cp_build_init_expr (decl, init); finish_expr_stmt (init); } else @@ -1014,7 +1016,7 @@ perform_member_init (tree member, tree init, hash_set<tree> &uninitialized) tree value = build_value_init (type, tf_warning_or_error); if (value == error_mark_node) return; - init = build2 (INIT_EXPR, type, decl, value); + init = cp_build_init_expr (decl, value); finish_expr_stmt (init); } } @@ -1025,7 +1027,7 @@ perform_member_init (tree member, tree init, hash_set<tree> &uninitialized) { if (init) { - init = build2 (INIT_EXPR, type, decl, TREE_VALUE (init)); + init = cp_build_init_expr (decl, TREE_VALUE (init)); finish_expr_stmt (init); } } @@ -1062,7 +1064,7 @@ perform_member_init (tree member, tree init, hash_set<tree> &uninitialized) if (TREE_CODE (type) == ARRAY_TYPE && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type))) init = build_vec_init_expr (type, init, tf_warning_or_error); - init = build2 (INIT_EXPR, type, decl, init); + init = cp_build_init_expr (decl, init); finish_expr_stmt (init); FOR_EACH_VEC_ELT (*cleanups, i, t) push_cleanup (NULL_TREE, t, false); @@ -1081,7 +1083,7 @@ perform_member_init (tree member, tree init, hash_set<tree> &uninitialized) /* Initialize the array only if it's not a flexible array member (i.e., if it has an upper bound). */ init = build_vec_init_expr (type, init, tf_warning_or_error); - init = build2 (INIT_EXPR, type, decl, init); + init = cp_build_init_expr (decl, init); finish_expr_stmt (init); } } @@ -2097,7 +2099,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, complete objects. */ gcc_assert (TREE_CODE (init) == CONSTRUCTOR || true_exp == exp); - init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); + init = cp_build_init_expr (exp, init); TREE_SIDE_EFFECTS (init) = 1; finish_expr_stmt (init); return true; @@ -2124,19 +2126,19 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, return false; } - if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) - /* We need to protect the initialization of a catch parm with a - call to terminate(), which shows up as a MUST_NOT_THROW_EXPR - around the TARGET_EXPR for the copy constructor. See - initialize_handler_parm. */ + /* We need to protect the initialization of a catch parm with a + call to terminate(), which shows up as a MUST_NOT_THROW_EXPR + around the TARGET_EXPR for the copy constructor. See + initialize_handler_parm. */ + tree *p = &init; + while (TREE_CODE (*p) == MUST_NOT_THROW_EXPR + || TREE_CODE (*p) == CLEANUP_POINT_EXPR) { - TREE_OPERAND (init, 0) = build2 (INIT_EXPR, TREE_TYPE (exp), exp, - TREE_OPERAND (init, 0)); - TREE_TYPE (init) = void_type_node; + /* Avoid voidify_wrapper_expr making a temporary. */ + TREE_TYPE (*p) = void_type_node; + p = &TREE_OPERAND (*p, 0); } - else - init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init); - TREE_SIDE_EFFECTS (init) = 1; + *p = cp_build_init_expr (exp, *p); finish_expr_stmt (init); return true; } @@ -2201,7 +2203,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, { tree e = maybe_constant_init (rval, exp); if (TREE_CONSTANT (e)) - rval = build2 (INIT_EXPR, type, exp, e); + rval = cp_build_init_expr (exp, e); } } @@ -2289,7 +2291,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, field_size = TYPE_SIZE (CLASSTYPE_AS_BASE (type)); init = build_zero_init_1 (type, NULL_TREE, /*static_storage_p=*/false, field_size); - init = build2 (INIT_EXPR, type, exp, init); + init = cp_build_init_expr (exp, init); finish_expr_stmt (init); } @@ -3677,7 +3679,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, tree val = build_value_init (type, complain | tf_no_cleanup); if (val == error_mark_node) return error_mark_node; - init_expr = build2 (INIT_EXPR, type, init_expr, val); + init_expr = cp_build_init_expr (init_expr, val); } else { @@ -4429,7 +4431,7 @@ build_vec_init (tree base, tree maxindex, tree init, if (BRACE_ENCLOSED_INITIALIZER_P (init)) init = digest_init (atype, init, complain); - stmt_expr = build2 (INIT_EXPR, atype, base, init); + stmt_expr = cp_build_init_expr (base, init); return stmt_expr; } @@ -4601,7 +4603,7 @@ build_vec_init (tree base, tree maxindex, tree init, gcc_checking_assert (!target_expr_needs_replace (elt)); if (digested) - one_init = build2 (INIT_EXPR, type, baseref, elt); + one_init = cp_build_init_expr (baseref, elt); else if (tree vi = get_vec_init_expr (elt)) one_init = expand_vec_init_expr (baseref, vi, complain, flags); else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) @@ -4622,7 +4624,7 @@ build_vec_init (tree base, tree maxindex, tree init, if (do_static_init) one_init = NULL_TREE; else - one_init = build2 (INIT_EXPR, type, baseref, e); + one_init = cp_build_init_expr (baseref, e); } else { @@ -4804,7 +4806,7 @@ build_vec_init (tree base, tree maxindex, tree init, { elt_init = build_value_init (type, complain); if (elt_init != error_mark_node) - elt_init = build2 (INIT_EXPR, type, to, elt_init); + elt_init = cp_build_init_expr (to, elt_init); } else { diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc index 0b121a9..22d1ab9 100644 --- a/gcc/cp/lex.cc +++ b/gcc/cp/lex.cc @@ -241,9 +241,9 @@ init_reswords (void) if (!flag_char8_t) mask |= D_CXX_CHAR8_T; if (flag_no_asm) - mask |= D_ASM | D_EXT; + mask |= D_ASM | D_EXT | D_EXT11; if (flag_no_gnu_keywords) - mask |= D_EXT; + mask |= D_EXT | D_EXT11; /* The Objective-C keywords are all context-dependent. */ mask |= D_OBJC; diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 55af5c4..c217d7e 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -680,7 +680,7 @@ do_build_copy_constructor (tree fndecl) else if (tree_int_cst_equal (TYPE_SIZE (current_class_type), CLASSTYPE_SIZE (current_class_type))) { - tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm); + tree t = cp_build_init_expr (current_class_ref, parm); finish_expr_stmt (t); } else @@ -695,7 +695,7 @@ do_build_copy_constructor (tree fndecl) current_class_ptr, alias_set); tree rhs = build2 (MEM_REF, array_type, TREE_OPERAND (parm, 0), alias_set); - tree t = build2 (INIT_EXPR, void_type_node, lhs, rhs); + tree t = cp_build_init_expr (lhs, rhs); finish_expr_stmt (t); } } @@ -2233,7 +2233,7 @@ ref_xes_from_temporary (tree to, tree from, bool direct_init_p) tree val = build_stub_object (from); if (!TYPE_REF_P (from) && TREE_CODE (from) != FUNCTION_TYPE) val = CLASS_TYPE_P (from) ? force_rvalue (val, tf_none) : rvalue (val); - return ref_conv_binds_directly (to, val, direct_init_p).is_false (); + return ref_conv_binds_to_temporary (to, val, direct_init_p).is_true (); } /* Worker for is_{,nothrow_}convertible. Attempt to perform an implicit diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 500ac06..4d27ceb 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -3469,6 +3469,20 @@ enum streamed_extensions { SE_BITS = 1 }; +/* Counter indices. */ +enum module_state_counts +{ + MSC_sec_lwm, + MSC_sec_hwm, + MSC_pendings, + MSC_entities, + MSC_namespaces, + MSC_bindings, + MSC_macros, + MSC_inits, + MSC_HWM +}; + /********************************************************************/ struct module_state_config; @@ -3666,8 +3680,8 @@ class GTY((chain_next ("%h.parent"), for_user)) module_state { private: void write_config (elf_out *to, struct module_state_config &, unsigned crc); bool read_config (struct module_state_config &); - static void write_counts (elf_out *to, unsigned [], unsigned *crc_ptr); - bool read_counts (unsigned []); + static void write_counts (elf_out *to, unsigned [MSC_HWM], unsigned *crc_ptr); + bool read_counts (unsigned *); public: void note_cmi_name (); @@ -5397,6 +5411,9 @@ trees_out::core_bools (tree t) case VAR_DECL: if (TREE_PUBLIC (t) + && !(TREE_STATIC (t) + && DECL_FUNCTION_SCOPE_P (t) + && DECL_DECLARED_INLINE_P (DECL_CONTEXT (t))) && !DECL_VAR_DECLARED_INLINE_P (t)) is_external = true; break; @@ -5416,6 +5433,7 @@ trees_out::core_bools (tree t) WB (t->decl_common.decl_by_reference_flag); WB (t->decl_common.decl_read_flag); WB (t->decl_common.decl_nonshareable_flag); + WB (t->decl_common.decl_not_flexarray); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) @@ -5560,6 +5578,7 @@ trees_in::core_bools (tree t) RB (t->decl_common.decl_by_reference_flag); RB (t->decl_common.decl_read_flag); RB (t->decl_common.decl_nonshareable_flag); + RB (t->decl_common.decl_not_flexarray); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) @@ -11902,7 +11921,11 @@ trees_out::mark_class_def (tree defn) mark_class_member (member); if (TREE_CODE (member) == FIELD_DECL) if (tree repr = DECL_BIT_FIELD_REPRESENTATIVE (member)) - mark_declaration (repr, false); + /* If we're marking a class template definition, then + this'll contain the width (as set by grokbitfield) + instead of a decl. */ + if (DECL_P (repr)) + mark_declaration (repr, false); } /* Mark the binfo hierarchy. */ @@ -14541,20 +14564,6 @@ module_state::read_partitions (unsigned count) return true; } -/* Counter indices. */ -enum module_state_counts -{ - MSC_sec_lwm, - MSC_sec_hwm, - MSC_pendings, - MSC_entities, - MSC_namespaces, - MSC_bindings, - MSC_macros, - MSC_inits, - MSC_HWM -}; - /* Data for config reading and writing. */ struct module_state_config { const char *dialect_str; diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index d6757d1..25657cf 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -6382,7 +6382,7 @@ class namespace_limit_reached : public deferred_diagnostic std::unique_ptr<deferred_diagnostic> wrapped) : deferred_diagnostic (loc), m_limit (limit), m_name (name), - m_wrapped (move (wrapped)) + m_wrapped (std::move (wrapped)) { } diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 7b41635..dc3d17c 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -2258,7 +2258,7 @@ static vec<tree, va_gc> *cp_parser_parenthesized_expression_list (cp_parser *, int, bool, bool, bool *, location_t * = NULL, bool = false); /* Values for the second parameter of cp_parser_parenthesized_expression_list. */ -enum { non_attr = 0, normal_attr = 1, id_attr = 2 }; +enum { non_attr = 0, normal_attr = 1, id_attr = 2, assume_attr = 3 }; static void cp_parser_pseudo_destructor_name (cp_parser *, tree, tree *, tree *); static cp_expr cp_parser_unary_expression @@ -2287,6 +2287,7 @@ static cp_expr cp_parser_binary_expression (cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *); static tree cp_parser_question_colon_clause (cp_parser *, cp_expr); +static cp_expr cp_parser_conditional_expression (cp_parser *); static cp_expr cp_parser_assignment_expression (cp_parser *, cp_id_kind * = NULL, bool = false, bool = false); static enum tree_code cp_parser_assignment_operator_opt @@ -8480,7 +8481,6 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, bool wrap_locations_p) { vec<tree, va_gc> *expression_list; - tree identifier = NULL_TREE; bool saved_greater_than_is_operator_p; /* Assume all the expressions will be constant. */ @@ -8509,33 +8509,26 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, next token is an identifier. */ if (is_attribute_list == id_attr && cp_lexer_peek_token (parser->lexer)->type == CPP_NAME) - { - cp_token *token; - - /* Consume the identifier. */ - token = cp_lexer_consume_token (parser->lexer); - /* Save the identifier. */ - identifier = token->u.value; - } + expr = cp_lexer_consume_token (parser->lexer)->u.value; + else if (is_attribute_list == assume_attr) + expr = cp_parser_conditional_expression (parser); else - { - expr - = cp_parser_parenthesized_expression_list_elt (parser, cast_p, - allow_expansion_p, - non_constant_p); + expr + = cp_parser_parenthesized_expression_list_elt (parser, cast_p, + allow_expansion_p, + non_constant_p); - if (wrap_locations_p) - expr.maybe_add_location_wrapper (); + if (wrap_locations_p) + expr.maybe_add_location_wrapper (); - /* Add it to the list. We add error_mark_node - expressions to the list, so that we can still tell if - the correct form for a parenthesized expression-list - is found. That gives better errors. */ - vec_safe_push (expression_list, expr.get_value ()); + /* Add it to the list. We add error_mark_node + expressions to the list, so that we can still tell if + the correct form for a parenthesized expression-list + is found. That gives better errors. */ + vec_safe_push (expression_list, expr.get_value ()); - if (expr == error_mark_node) - goto skip_comma; - } + if (expr == error_mark_node) + goto skip_comma; /* After the first item, attribute lists look the same as expression lists. */ @@ -8577,9 +8570,6 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; - if (identifier) - vec_safe_insert (expression_list, 0, identifier); - return expression_list; } @@ -10310,7 +10300,8 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, logical-or-expression that started the conditional-expression. Returns a representation of the entire conditional-expression. - This routine is used by cp_parser_assignment_expression. + This routine is used by cp_parser_assignment_expression + and cp_parser_conditional_expression. ? expression : assignment-expression @@ -10377,6 +10368,28 @@ cp_parser_question_colon_clause (cp_parser* parser, cp_expr logical_or_expr) tf_warning_or_error); } +/* Parse a conditional-expression. + + conditional-expression: + logical-or-expression + logical-or-expression ? expression : assignment-expression + + GNU Extensions: + + logical-or-expression ? : assignment-expression */ + +static cp_expr +cp_parser_conditional_expression (cp_parser *parser) +{ + cp_expr expr = cp_parser_binary_expression (parser, false, false, false, + PREC_NOT_OPERATOR, NULL); + /* If the next token is a `?' then we're actually looking at + a conditional-expression; otherwise we're done. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY)) + return cp_parser_question_colon_clause (parser, expr); + return expr; +} + /* Parse an assignment-expression. assignment-expression: @@ -10702,15 +10715,7 @@ cp_parser_constant_expression (cp_parser* parser, determine whether a particular assignment-expression is in fact constant. */ if (strict_p) - { - /* Parse the binary expressions (logical-or-expression). */ - expression = cp_parser_binary_expression (parser, false, false, false, - PREC_NOT_OPERATOR, NULL); - /* If the next token is a `?' then we're actually looking at - a conditional-expression; otherwise we're done. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY)) - expression = cp_parser_question_colon_clause (parser, expression); - } + expression = cp_parser_conditional_expression (parser); else expression = cp_parser_assignment_expression (parser); /* Restore the old settings. */ @@ -12503,6 +12508,9 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, /* Look for an expression-statement instead. */ statement = cp_parser_expression_statement (parser, in_statement_expr); + std_attrs = process_stmt_assume_attribute (std_attrs, statement, + attrs_loc); + /* Handle [[fallthrough]];. */ if (attribute_fallthrough_p (std_attrs)) { @@ -12526,7 +12534,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, if (statement && STATEMENT_CODE_P (TREE_CODE (statement))) SET_EXPR_LOCATION (statement, statement_location); - /* Allow "[[fallthrough]];", but warn otherwise. */ + /* Allow "[[fallthrough]];" or "[[assume(cond)]];", but warn otherwise. */ if (std_attrs != NULL_TREE) warning_at (attrs_loc, OPT_Wattributes, @@ -12718,6 +12726,8 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) } } + attr = process_stmt_assume_attribute (attr, statement, loc); + /* Handle [[fallthrough]];. */ if (attribute_fallthrough_p (attr)) { @@ -13721,7 +13731,8 @@ warn_for_range_copy (tree decl, tree expr) if (TYPE_REF_P (type)) { - if (glvalue_p (expr) && ref_conv_binds_directly (type, expr).is_false ()) + if (glvalue_p (expr) + && ref_conv_binds_to_temporary (type, expr).is_true ()) { auto_diagnostic_group d; if (warning_at (loc, OPT_Wrange_loop_construct, @@ -13752,7 +13763,7 @@ warn_for_range_copy (tree decl, tree expr) /* If we can initialize a reference directly, suggest that to avoid the copy. */ tree rtype = cp_build_reference_type (type, /*rval*/false); - if (ref_conv_binds_directly (rtype, expr).is_true ()) + if (ref_conv_binds_to_temporary (rtype, expr).is_false ()) { auto_diagnostic_group d; if (warning_at (loc, OPT_Wrange_loop_construct, @@ -28876,6 +28887,8 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */) vec<tree, va_gc> *vec; int attr_flag = (attribute_takes_identifier_p (identifier) ? id_attr : normal_attr); + if (is_attribute_p ("assume", identifier)) + attr_flag = assume_attr; vec = cp_parser_parenthesized_expression_list (parser, attr_flag, /*cast_p=*/false, /*allow_expansion_p=*/false, @@ -29127,6 +29140,9 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) /* C++17 fallthrough attribute is equivalent to GNU's. */ else if (is_attribute_p ("fallthrough", attr_id)) TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier; + /* C++23 assume attribute is equivalent to GNU's. */ + else if (is_attribute_p ("assume", attr_id)) + TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier; /* Transactional Memory TS optimize_for_synchronized attribute is equivalent to GNU transaction_callable. */ else if (is_attribute_p ("optimize_for_synchronized", attr_id)) @@ -29171,8 +29187,12 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns) return error_mark_node; } - if (attr_ns == gnu_identifier - && attribute_takes_identifier_p (attr_id)) + if (is_attribute_p ("assume", attr_id) + && (attr_ns == NULL_TREE || attr_ns == gnu_identifier)) + /* The assume attribute needs special handling of the argument. */ + attr_flag = assume_attr; + else if (attr_ns == gnu_identifier + && attribute_takes_identifier_p (attr_id)) /* A GNU attribute that takes an identifier in parameter. */ attr_flag = id_attr; @@ -29246,7 +29266,8 @@ cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute) if (attributes) for (const auto &a : alist) if (is_attribute_p (a, get_attribute_name (attribute)) - && lookup_attribute (a, attributes)) + && is_attribute_namespace_p ("", attribute) + && lookup_attribute ("", a, attributes)) { if (!from_macro_expansion_at (loc)) warning_at (loc, OPT_Wattributes, "attribute %qs specified " @@ -46004,13 +46025,15 @@ cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, matching_parens parens; if (parens.require_open (parser)) { + location_t eloc = cp_lexer_peek_token (parser->lexer)->location; tree t = cp_parser_assignment_expression (parser); if (!type_dependent_expression_p (t)) t = contextual_conv_bool (t, tf_warning_or_error); - if (is_assume) + if (is_assume && !error_operand_p (t)) { - /* FIXME: Emit .ASSUME (t) call here. */ - (void) t; + t = build_call_expr_internal_loc (eloc, IFN_ASSUME, + void_type_node, 1, t); + finish_expr_stmt (t); } if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index bce2a77..5b9fc58 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -1170,39 +1170,6 @@ maybe_process_partial_specialization (tree type) return type; } -/* Returns nonzero if we can optimize the retrieval of specializations - for TMPL, a TEMPLATE_DECL. In particular, for such a template, we - do not use DECL_TEMPLATE_SPECIALIZATIONS at all. */ - -static inline bool -optimize_specialization_lookup_p (tree tmpl) -{ - return (DECL_FUNCTION_TEMPLATE_P (tmpl) - && DECL_CLASS_SCOPE_P (tmpl) - /* DECL_CLASS_SCOPE_P holds of T::f even if T is a template - parameter. */ - && CLASS_TYPE_P (DECL_CONTEXT (tmpl)) - /* The optimized lookup depends on the fact that the - template arguments for the member function template apply - purely to the containing class, which is not true if the - containing class is an explicit or partial - specialization. */ - && !CLASSTYPE_TEMPLATE_SPECIALIZATION (DECL_CONTEXT (tmpl)) - && !DECL_MEMBER_TEMPLATE_P (tmpl) - && !DECL_CONV_FN_P (tmpl) - /* It is possible to have a template that is not a member - template and is not a member of a template class: - - template <typename T> - struct S { friend A::f(); }; - - Here, the friend function is a template, but the context does - not have template information. The optimized lookup relies - on having ARGS be the template arguments for both the class - and the function template. */ - && !DECL_UNIQUE_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl))); -} - /* Make sure ARGS doesn't use any inappropriate typedefs; we should have gone through coerce_template_parms by now. */ @@ -1276,54 +1243,21 @@ retrieve_specialization (tree tmpl, tree args, hashval_t hash) if (lambda_fn_in_template_p (tmpl)) return NULL_TREE; - if (optimize_specialization_lookup_p (tmpl)) - { - /* The template arguments actually apply to the containing - class. Find the class specialization with those - arguments. */ - tree class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl)); - tree class_specialization - = retrieve_specialization (class_template, args, 0); - if (!class_specialization) - return NULL_TREE; + spec_entry elt; + elt.tmpl = tmpl; + elt.args = args; + elt.spec = NULL_TREE; - /* Find the instance of TMPL. */ - tree fns = get_class_binding (class_specialization, DECL_NAME (tmpl)); - for (ovl_iterator iter (fns); iter; ++iter) - { - tree fn = *iter; - if (tree ti = get_template_info (fn)) - if (TI_TEMPLATE (ti) == tmpl - /* using-declarations can bring in a different - instantiation of tmpl as a member of a different - instantiation of tmpl's class. We don't want those - here. */ - && DECL_CONTEXT (fn) == class_specialization) - return fn; - } - return NULL_TREE; - } + spec_hash_table *specializations; + if (DECL_CLASS_TEMPLATE_P (tmpl)) + specializations = type_specializations; else - { - spec_entry *found; - spec_entry elt; - spec_hash_table *specializations; - - elt.tmpl = tmpl; - elt.args = args; - elt.spec = NULL_TREE; - - if (DECL_CLASS_TEMPLATE_P (tmpl)) - specializations = type_specializations; - else - specializations = decl_specializations; + specializations = decl_specializations; - if (hash == 0) - hash = spec_hasher::hash (&elt); - found = specializations->find_with_hash (&elt, hash); - if (found) - return found->spec; - } + if (hash == 0) + hash = spec_hasher::hash (&elt); + if (spec_entry *found = specializations->find_with_hash (&elt, hash)) + return found->spec; return NULL_TREE; } @@ -1567,8 +1501,6 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend, hashval_t hash) { tree fn; - spec_entry **slot = NULL; - spec_entry elt; gcc_assert ((TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec)) || (TREE_CODE (tmpl) == FIELD_DECL @@ -1589,25 +1521,19 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend, instantiation unless and until it is actually needed. */ return spec; - if (optimize_specialization_lookup_p (tmpl)) - /* We don't put these specializations in the hash table, but we might - want to give an error about a mismatch. */ - fn = retrieve_specialization (tmpl, args, 0); - else - { - elt.tmpl = tmpl; - elt.args = args; - elt.spec = spec; + spec_entry elt; + elt.tmpl = tmpl; + elt.args = args; + elt.spec = spec; - if (hash == 0) - hash = spec_hasher::hash (&elt); + if (hash == 0) + hash = spec_hasher::hash (&elt); - slot = decl_specializations->find_slot_with_hash (&elt, hash, INSERT); - if (*slot) - fn = (*slot)->spec; - else - fn = NULL_TREE; - } + spec_entry **slot = decl_specializations->find_slot_with_hash (&elt, hash, INSERT); + if (*slot) + fn = (*slot)->spec; + else + fn = NULL_TREE; /* We can sometimes try to re-register a specialization that we've already got. In particular, regenerate_decl_from_template calls @@ -1704,26 +1630,23 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend, && !check_specialization_namespace (tmpl)) DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl); - if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */) - { - spec_entry *entry = ggc_alloc<spec_entry> (); - gcc_assert (tmpl && args && spec); - *entry = elt; - *slot = entry; - if ((TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec) - && PRIMARY_TEMPLATE_P (tmpl) - && DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE) - || variable_template_p (tmpl)) - /* If TMPL is a forward declaration of a template function, keep a list - of all specializations in case we need to reassign them to a friend - template later in tsubst_friend_function. - - Also keep a list of all variable template instantiations so that - process_partial_specialization can check whether a later partial - specialization would have used it. */ - DECL_TEMPLATE_INSTANTIATIONS (tmpl) - = tree_cons (args, spec, DECL_TEMPLATE_INSTANTIATIONS (tmpl)); - } + spec_entry *entry = ggc_alloc<spec_entry> (); + gcc_assert (tmpl && args && spec); + *entry = elt; + *slot = entry; + if ((TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec) + && PRIMARY_TEMPLATE_P (tmpl) + && DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE) + || variable_template_p (tmpl)) + /* If TMPL is a forward declaration of a template function, keep a list + of all specializations in case we need to reassign them to a friend + template later in tsubst_friend_function. + + Also keep a list of all variable template instantiations so that + process_partial_specialization can check whether a later partial + specialization would have used it. */ + DECL_TEMPLATE_INSTANTIATIONS (tmpl) + = tree_cons (args, spec, DECL_TEMPLATE_INSTANTIATIONS (tmpl)); return spec; } @@ -21163,6 +21086,33 @@ tsubst_copy_and_build (tree t, break; } + case IFN_ASSUME: + gcc_assert (nargs == 1); + if (vec_safe_length (call_args) != 1) + { + error_at (cp_expr_loc_or_input_loc (t), + "wrong number of arguments to " + "%<assume%> attribute"); + ret = error_mark_node; + } + else + { + tree &arg = (*call_args)[0]; + if (!type_dependent_expression_p (arg)) + arg = contextual_conv_bool (arg, tf_warning_or_error); + if (error_operand_p (arg)) + { + ret = error_mark_node; + break; + } + ret = build_call_expr_internal_loc (EXPR_LOCATION (t), + IFN_ASSUME, + void_type_node, 1, + arg); + RETURN (ret); + } + break; + default: /* Unsupported internal function with arguments. */ gcc_unreachable (); diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 30cf2f9..7d46c3c 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -2519,6 +2519,10 @@ finish_stmt_expr_expr (tree expr, tree stmt_expr) /* Update for array-to-pointer decay. */ type = TREE_TYPE (expr); + /* This TARGET_EXPR will initialize the outer one added by + finish_stmt_expr. */ + set_target_expr_eliding (expr); + /* Wrap it in a CLEANUP_POINT_EXPR and add it to the list like a normal statement, but don't convert to void or actually add the EXPR_STMT. */ @@ -4668,7 +4672,7 @@ simplify_aggr_init_expr (tree *tp) expand_call{,_inline}. */ cxx_mark_addressable (slot); CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true; - call_expr = build2 (INIT_EXPR, TREE_TYPE (call_expr), slot, call_expr); + call_expr = cp_build_init_expr (slot, call_expr); } else if (style == pcc) { @@ -4687,7 +4691,7 @@ simplify_aggr_init_expr (tree *tp) { tree init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false); - init = build2 (INIT_EXPR, void_type_node, slot, init); + init = cp_build_init_expr (slot, init); call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (call_expr), init, call_expr); } @@ -4882,7 +4886,7 @@ finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) tree init; if (DECL_INITIAL (dp->var) && DECL_INITIAL (dp->var) != error_mark_node) - init = build2 (INIT_EXPR, void_type_node, dp->result, + init = cp_build_init_expr (dp->result, DECL_INITIAL (dp->var)); else init = build_empty_stmt (EXPR_LOCATION (*tp)); @@ -6426,7 +6430,7 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) else init = fold_convert (TREE_TYPE (v), integer_zero_node); OMP_CLAUSE_REDUCTION_INIT (c) - = build2 (INIT_EXPR, TREE_TYPE (v), v, init); + = cp_build_init_expr (v, init); } } } @@ -11172,42 +11176,31 @@ init_cp_semantics (void) } -/* If we have a condition in conjunctive normal form (CNF), find the first - failing clause. In other words, given an expression like - - true && true && false && true && false +/* Emit additional diagnostics for failing condition BAD. + Used by finish_static_assert and IFN_ASSUME constexpr diagnostics. + If SHOW_EXPR_P is true, print the condition (because it was + instantiation-dependent). */ - return the first 'false'. EXPR is the expression. */ - -static tree -find_failing_clause_r (tree expr) +void +diagnose_failing_condition (tree bad, location_t cloc, bool show_expr_p) { - if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR) + /* Nobody wants to see the artificial (bool) cast. */ + bad = tree_strip_nop_conversions (bad); + + /* Actually explain the failure if this is a concept check or a + requires-expression. */ + if (concept_check_p (bad) || TREE_CODE (bad) == REQUIRES_EXPR) + diagnose_constraints (cloc, bad, NULL_TREE); + else if (COMPARISON_CLASS_P (bad) + && ARITHMETIC_TYPE_P (TREE_TYPE (TREE_OPERAND (bad, 0)))) { - /* First check the left side... */ - tree e = find_failing_clause_r (TREE_OPERAND (expr, 0)); - if (e == NULL_TREE) - /* ...if we didn't find a false clause, check the right side. */ - e = find_failing_clause_r (TREE_OPERAND (expr, 1)); - return e; + tree op0 = fold_non_dependent_expr (TREE_OPERAND (bad, 0)); + tree op1 = fold_non_dependent_expr (TREE_OPERAND (bad, 1)); + tree cond = build2 (TREE_CODE (bad), boolean_type_node, op0, op1); + inform (cloc, "the comparison reduces to %qE", cond); } - tree e = contextual_conv_bool (expr, tf_none); - e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true); - if (integer_zerop (e)) - /* This is the failing clause. */ - return expr; - return NULL_TREE; -} - -/* Wrapper for find_failing_clause_r. */ - -static tree -find_failing_clause (tree expr) -{ - if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR) - if (tree e = find_failing_clause_r (expr)) - expr = e; - return expr; + else if (show_expr_p) + inform (cloc, "%qE evaluates to false", bad); } /* Build a STATIC_ASSERT for a static assertion with the condition @@ -11274,12 +11267,12 @@ finish_static_assert (tree condition, tree message, location_t location, int len = TREE_STRING_LENGTH (message) / sz - 1; /* See if we can find which clause was failing (for logical AND). */ - tree bad = find_failing_clause (orig_condition); + tree bad = find_failing_clause (NULL, orig_condition); /* If not, or its location is unusable, fall back to the previous location. */ location_t cloc = cp_expr_loc_or_loc (bad, location); - /* Nobody wants to see the artificial (bool) cast. */ - bad = tree_strip_nop_conversions (bad); + + auto_diagnostic_group d; /* Report the error. */ if (len == 0) @@ -11288,21 +11281,7 @@ finish_static_assert (tree condition, tree message, location_t location, error_at (cloc, "static assertion failed: %s", TREE_STRING_POINTER (message)); - /* Actually explain the failure if this is a concept check or a - requires-expression. */ - if (concept_check_p (bad) - || TREE_CODE (bad) == REQUIRES_EXPR) - diagnose_constraints (location, bad, NULL_TREE); - else if (COMPARISON_CLASS_P (bad) - && ARITHMETIC_TYPE_P (TREE_TYPE (TREE_OPERAND (bad, 0)))) - { - tree op0 = fold_non_dependent_expr (TREE_OPERAND (bad, 0)); - tree op1 = fold_non_dependent_expr (TREE_OPERAND (bad, 1)); - tree cond = build2 (TREE_CODE (bad), boolean_type_node, op0, op1); - inform (cloc, "the comparison reduces to %qE", cond); - } - else if (show_expr_p) - inform (cloc, "%qE evaluates to false", bad); + diagnose_failing_condition (bad, cloc, show_expr_p); } else if (condition && condition != error_mark_node) { diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index aa9c1b7..3532e44 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -104,7 +104,17 @@ lvalue_kind (const_tree ref) case REALPART_EXPR: case IMAGPART_EXPR: case VIEW_CONVERT_EXPR: - return lvalue_kind (TREE_OPERAND (ref, 0)); + op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); + /* As for ARRAY_REF and COMPONENT_REF, these codes turn a class prvalue + into an xvalue: we need to materialize the temporary before we mess + with it. Except VIEW_CONVERT_EXPR that doesn't actually change the + type, as in location wrapper and REF_PARENTHESIZED_P. */ + if (op1_lvalue_kind == clk_class + && !(TREE_CODE (ref) == VIEW_CONVERT_EXPR + && (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (ref), TREE_TYPE (TREE_OPERAND (ref, 0)))))) + return clk_rvalueref; + return op1_lvalue_kind; case ARRAY_REF: { @@ -523,6 +533,9 @@ build_target_expr (tree decl, tree value, tsubst_flags_t complain) if (t == error_mark_node) return error_mark_node; } + + set_target_expr_eliding (value); + t = build4 (TARGET_EXPR, type, decl, value, t, NULL_TREE); if (location_t eloc = cp_expr_location (value)) SET_EXPR_LOCATION (t, eloc); @@ -3184,6 +3197,7 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_) TARGET_EXPR_IMPLICIT_P (u) = TARGET_EXPR_IMPLICIT_P (t); TARGET_EXPR_LIST_INIT_P (u) = TARGET_EXPR_LIST_INIT_P (t); TARGET_EXPR_DIRECT_INIT_P (u) = TARGET_EXPR_DIRECT_INIT_P (t); + TARGET_EXPR_ELIDING_P (u) = TARGET_EXPR_ELIDING_P (t); /* Map the old variable to the new one. */ splay_tree_insert (target_remap, diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index cecf825..b4a8e3c 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -9294,7 +9294,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, if (! same_type_p (TREE_TYPE (rhs), lhstype)) /* Call convert to generate an error; see PR 11063. */ rhs = convert (lhstype, rhs); - result = build2 (INIT_EXPR, lhstype, lhs, rhs); + result = cp_build_init_expr (lhs, rhs); TREE_SIDE_EFFECTS (result) = 1; goto ret; } @@ -9542,6 +9542,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, result = build2_loc (loc, modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, lhstype, lhs, newrhs); + if (modifycode == INIT_EXPR) + set_target_expr_eliding (newrhs); TREE_SIDE_EFFECTS (result) = 1; if (!plain_assign) @@ -11105,7 +11107,7 @@ check_return_expr (tree retval, bool *no_warning) /* Actually copy the value returned into the appropriate location. */ if (retval && retval != result) - retval = build2 (INIT_EXPR, TREE_TYPE (result), result, retval); + retval = cp_build_init_expr (result, retval); if (tree set = maybe_set_retval_sentinel ()) retval = build2 (COMPOUND_EXPR, void_type_node, retval, set); diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc index d5236d1..2644472 100644 --- a/gcc/cp/typeck2.cc +++ b/gcc/cp/typeck2.cc @@ -649,7 +649,7 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, else { build_init: - code = build2 (INIT_EXPR, inner_type, sub, value); + code = cp_build_init_expr (sub, value); } code = build_stmt (input_location, EXPR_STMT, code); add_stmt (code); @@ -764,7 +764,7 @@ split_nonconstant_init (tree dest, tree init) } else if (init) { - tree ie = build2 (INIT_EXPR, void_type_node, dest, init); + tree ie = cp_build_init_expr (dest, init); code = add_stmt_to_compound (ie, code); } } @@ -773,7 +773,7 @@ split_nonconstant_init (tree dest, tree init) code = build_vec_init (dest, NULL_TREE, init, /*value-init*/false, /*from array*/1, tf_warning_or_error); else - code = build2 (INIT_EXPR, TREE_TYPE (dest), dest, init); + code = cp_build_init_expr (dest, init); return code; } @@ -1464,6 +1464,7 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain) && CP_AGGREGATE_TYPE_P (type)) init = reshape_init (type, init, complain); init = digest_init_flags (type, init, flags, complain); + set_target_expr_eliding (init); /* We may have temporary materialization in a NSDMI, if the initializer has something like A{} in it. Digesting the {} could have introduced @@ -1542,6 +1543,7 @@ massage_init_elt (tree type, tree init, int nested, int flags, tree t = fold_non_dependent_init (init, complain); if (TREE_CONSTANT (t)) init = t; + set_target_expr_eliding (init); } return init; } @@ -1771,6 +1773,13 @@ process_init_constructor_record (tree type, tree init, int nested, int flags, { gcc_assert (ce->value); next = massage_init_elt (fldtype, next, nested, flags, complain); + /* We can't actually elide the temporary when initializing a + potentially-overlapping field from a function that returns by + value. */ + if (ce->index + && TREE_CODE (next) == TARGET_EXPR + && unsafe_copy_elision_p (ce->index, next)) + TARGET_EXPR_ELIDING_P (next) = false; ++idx; } } @@ -1804,6 +1813,9 @@ process_init_constructor_record (tree type, tree init, int nested, int flags, a class, just build one up; if it's an array, recurse. */ next = build_constructor (init_list_type_node, NULL); next = massage_init_elt (fldtype, next, nested, flags, complain); + if (TREE_CODE (next) == TARGET_EXPR + && unsafe_copy_elision_p (field, next)) + TARGET_EXPR_ELIDING_P (next) = false; /* Warn when some struct elements are implicitly initialized. */ if ((complain & tf_warning) @@ -2727,3 +2739,41 @@ require_complete_eh_spec_types (tree fntype, tree decl) } } } + +/* Record that any TARGET_EXPR in T are going to be elided in + cp_gimplify_init_expr (or sooner). */ + +void +set_target_expr_eliding (tree t) +{ + if (!t) + return; + switch (TREE_CODE (t)) + { + case TARGET_EXPR: + TARGET_EXPR_ELIDING_P (t) = true; + break; + case COMPOUND_EXPR: + set_target_expr_eliding (TREE_OPERAND (t, 1)); + break; + case COND_EXPR: + set_target_expr_eliding (TREE_OPERAND (t, 1)); + set_target_expr_eliding (TREE_OPERAND (t, 2)); + break; + + default: + break; + } +} + +/* Call the above in the process of building an INIT_EXPR. */ + +tree +cp_build_init_expr (location_t loc, tree target, tree init) +{ + set_target_expr_eliding (init); + tree ie = build2_loc (loc, INIT_EXPR, TREE_TYPE (target), + target, init); + TREE_SIDE_EFFECTS (ie) = true; + return ie; +} diff --git a/gcc/cselib.cc b/gcc/cselib.cc index 9b582e5..2abc763 100644 --- a/gcc/cselib.cc +++ b/gcc/cselib.cc @@ -1571,6 +1571,7 @@ new_cselib_val (unsigned int hash, machine_mode mode, rtx x) scalar_int_mode int_mode; if (REG_P (x) && is_int_mode (mode, &int_mode) + && GET_MODE_SIZE (int_mode) > 1 && REG_VALUES (REGNO (x)) != NULL && (!cselib_current_insn || !DEBUG_INSN_P (cselib_current_insn))) { diff --git a/gcc/defaults.h b/gcc/defaults.h index 953605c..376687d 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -1441,6 +1441,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define DWARF_GNAT_ENCODINGS_DEFAULT DWARF_GNAT_ENCODINGS_GDB #endif +/* When generating dwarf info, the default standard version we'll honor + and advertise in absence of -gdwarf-<N> on the command line. */ +#ifndef DWARF_VERSION_DEFAULT +#define DWARF_VERSION_DEFAULT 5 +#endif + #ifndef USED_FOR_TARGET /* Done this way to keep gengtype happy. */ #if BITS_PER_UNIT == 8 diff --git a/gcc/df-scan.cc b/gcc/df-scan.cc index 9b2375d..1a41e6d 100644 --- a/gcc/df-scan.cc +++ b/gcc/df-scan.cc @@ -2475,10 +2475,11 @@ df_ref_create_structure (enum df_ref_class cl, enum df_ref_type ref_type, int ref_flags) { - df_ref this_ref = NULL; - unsigned int regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg); + const unsigned int regno + = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg); struct df_scan_problem_data *problem_data = (struct df_scan_problem_data *) df_scan->problem_data; + df_ref this_ref; switch (cl) { @@ -2498,12 +2499,15 @@ df_ref_create_structure (enum df_ref_class cl, this_ref->regular_ref.loc = loc; gcc_checking_assert (loc); break; + + default: + gcc_unreachable (); } DF_REF_CLASS (this_ref) = cl; DF_REF_ID (this_ref) = -1; DF_REF_REG (this_ref) = reg; - DF_REF_REGNO (this_ref) = regno; + DF_REF_REGNO (this_ref) = regno; DF_REF_TYPE (this_ref) = ref_type; DF_REF_INSN_INFO (this_ref) = info; DF_REF_CHAIN (this_ref) = NULL; @@ -2512,17 +2516,17 @@ df_ref_create_structure (enum df_ref_class cl, DF_REF_PREV_REG (this_ref) = NULL; DF_REF_ORDER (this_ref) = df->ref_order++; - /* We need to clear this bit because fwprop, and in the future - possibly other optimizations sometimes create new refs using ond - refs as the model. */ + /* We need to clear the DF_HARD_REG_LIVE bit because fwprop, and in the + future possibly other optimizations, sometimes create new refs using + live refs as the model. */ DF_REF_FLAGS_CLEAR (this_ref, DF_HARD_REG_LIVE); - /* See if this ref needs to have DF_HARD_REG_LIVE bit set. */ + /* Now see if this ref really needs to have the bit set. */ if (regno < FIRST_PSEUDO_REGISTER - && !DF_REF_IS_ARTIFICIAL (this_ref) - && !DEBUG_INSN_P (DF_REF_INSN (this_ref))) + && cl != DF_REF_ARTIFICIAL + && !DEBUG_INSN_P (info->insn)) { - if (DF_REF_REG_DEF_P (this_ref)) + if (ref_type == DF_REF_REG_DEF) { if (!DF_REF_FLAGS_IS_SET (this_ref, DF_REF_MAY_CLOBBER)) DF_REF_FLAGS_SET (this_ref, DF_HARD_REG_LIVE); diff --git a/gcc/doc/analyzer.texi b/gcc/doc/analyzer.texi index 06eb98f..ec49f95 100644 --- a/gcc/doc/analyzer.texi +++ b/gcc/doc/analyzer.texi @@ -544,6 +544,10 @@ __analyzer_eval (expr); will emit a warning with text "TRUE", FALSE" or "UNKNOWN" based on the truthfulness of the argument. This is useful for writing DejaGnu tests. +@smallexample +__analyzer_get_unknown_ptr (); +@end smallexample +will obtain an unknown @code{void *}. @subsection Other Debugging Techniques diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 46eeb98..71a4c1b 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7454,6 +7454,32 @@ This warning can be disabled by @option{-Wno-if-not-aligned}. The @code{warn_if_not_aligned} attribute can also be used for types (@pxref{Common Type Attributes}.) +@cindex @code{strict_flex_array} variable attribute +@item strict_flex_array (@var{level}) +The @code{strict_flex_array} attribute should be attached to the trailing +array field of a structure. It controls when to treat the trailing array +field of a structure as a flexible array member for the purposes of accessing +the elements of such an array. +@var{level} must be an integer betwen 0 to 3. + +@var{level}=0 is the least strict level, all trailing arrays of structures +are treated as flexible array members. @var{level}=3 is the strictest level, +only when the trailing array is declared as a flexible array member per C99 +standard onwards (@samp{[]}), it is treated as a flexible array member. + +There are two more levels in between 0 and 3, which are provided to support +older codes that use GCC zero-length array extension (@samp{[0]}) or one-element +array as flexible array members (@samp{[1]}): +When @var{level} is 1, the trailing array is treated as a flexible array member +when it is declared as either @samp{[]}, @samp{[0]}, or @samp{[1]}; +When @var{level} is 2, the trailing array is treated as a flexible array member +when it is declared as either @samp{[]}, or @samp{[0]}. + +This attribute can be used with or without the @option{-fstrict-flex-arrays}. +When both the attribute and the option present at the same time, the level of +the strictness for the specific trailing array field is determined by the +attribute. + @item alloc_size (@var{position}) @itemx alloc_size (@var{position-1}, @var{position-2}) @cindex @code{alloc_size} variable attribute @@ -9182,6 +9208,20 @@ available for functions (@pxref{Function Attributes}), variables (@pxref{Variable Attributes}), labels (@pxref{Label Attributes}), enumerators (@pxref{Enumerator Attributes}), and for types (@pxref{Type Attributes}). +@table @code +@item fallthrough +@cindex @code{fallthrough} statement attribute +The @code{fallthrough} attribute with a null statement serves as a +fallthrough statement. It hints to the compiler that a statement +that falls through to another case label, or user-defined label +in a switch statement is intentional and thus the +@option{-Wimplicit-fallthrough} warning must not trigger. The +fallthrough attribute may appear at most once in each attribute +list, and may not be mixed with other attributes. It can only +be used in a switch statement (the compiler will issue an error +otherwise), after a preceding statement and before a logically +succeeding case label, or user-defined label. + This example uses the @code{fallthrough} statement attribute to indicate that the @option{-Wimplicit-fallthrough} warning should not be emitted: @@ -9196,19 +9236,28 @@ switch (cond) @} @end smallexample -@table @code -@item fallthrough -@cindex @code{fallthrough} statement attribute -The @code{fallthrough} attribute with a null statement serves as a -fallthrough statement. It hints to the compiler that a statement -that falls through to another case label, or user-defined label -in a switch statement is intentional and thus the -@option{-Wimplicit-fallthrough} warning must not trigger. The -fallthrough attribute may appear at most once in each attribute -list, and may not be mixed with other attributes. It can only -be used in a switch statement (the compiler will issue an error -otherwise), after a preceding statement and before a logically -succeeding case label, or user-defined label. +@item assume +@cindex @code{assume} statement attribute +The @code{assume} attribute with a null statement serves as portable +assumption. It should have a single argument, a conditional expression, +which is not evaluated. If the argument would evaluate to true +at the point where it appears, it has no effect, otherwise there +is undefined behavior. This is a GNU variant of the ISO C++23 +standard @code{assume} attribute, but it can be used in any version of +both C and C++. + +@smallexample +int +foo (int x, int y) +@{ + __attribute__((assume(x == 42))); + __attribute__((assume(++y == 43))); + return x + y; +@} +@end smallexample + +@code{y} is not actually incremented and the compiler can but does not +have to optimize it to just @code{return 42 + 42;}. @end table diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index cc9754b..3101021 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -169,7 +169,8 @@ in the following sections. -fopenmp -fopenmp-simd @gol -fpermitted-flt-eval-methods=@var{standard} @gol -fplan9-extensions -fsigned-bitfields -funsigned-bitfields @gol --fsigned-char -funsigned-char -fsso-struct=@var{endianness}} +-fsigned-char -funsigned-char -fstrict-flex-arrays[=@var{n}] @gol +-fsso-struct=@var{endianness}} @item C++ Language Options @xref{C++ Dialect Options,,Options Controlling C++ Dialect}. @@ -2496,7 +2497,10 @@ this switch. You may want to use the @option{-fno-gnu-keywords} flag instead, which disables @code{typeof} but not @code{asm} and @code{inline}. In C99 mode (@option{-std=c99} or @option{-std=gnu99}), this switch only affects the @code{asm} and @code{typeof} keywords, -since @code{inline} is a standard keyword in ISO C99. +since @code{inline} is a standard keyword in ISO C99. In C2X mode +(@option{-std=c2x} or @option{-std=gnu2x}), this switch only affects +the @code{asm} keyword, since @code{typeof} is a standard keyword in +ISO C2X. @item -fno-builtin @itemx -fno-builtin-@var{function} @@ -2699,7 +2703,8 @@ can be omitted, to use a target-specific default value. @item -fopenmp @opindex fopenmp @cindex OpenMP parallel -Enable handling of OpenMP directives @code{#pragma omp} in C/C++ and +Enable handling of OpenMP directives @code{#pragma omp} in C/C++, +@code{[[omp::directive(...)]]} and @code{[[omp::sequence(...)]]} in C++ and @code{!$omp} in Fortran. When @option{-fopenmp} is specified, the compiler generates parallel code according to the OpenMP Application Program Interface v4.5 @w{@uref{https://www.openmp.org}}. This option @@ -2711,9 +2716,12 @@ have support for @option{-pthread}. @option{-fopenmp} implies @opindex fopenmp-simd @cindex OpenMP SIMD @cindex SIMD -Enable handling of OpenMP's SIMD directives with @code{#pragma omp} -in C/C++ and @code{!$omp} in Fortran. Other OpenMP directives -are ignored. +Enable handling of OpenMP's @code{simd}, @code{declare simd}, +@code{declare reduction}, @code{assume}, @code{ordered}, @code{scan}, +@code{loop} directives and combined or composite directives with +@code{simd} as constituent with @code{#pragma omp} in C/C++, +@code{[[omp::directive(...)]]} and @code{[[omp::sequence(...)]]} in C++ +and @code{!$omp} in Fortran. Other OpenMP directives are ignored. @item -fpermitted-flt-eval-methods=@var{style} @opindex fpermitted-flt-eval-methods @@ -2790,6 +2798,31 @@ The type @code{char} is always a distinct type from each of @code{signed char} or @code{unsigned char}, even though its behavior is always just like one of those two. +@item -fstrict-flex-arrays +@opindex fstrict-flex-arrays +@opindex fno-strict-flex-arrays +Control when to treat the trailing array of a structure as a flexible array +member for the purpose of accessing the elements of such an array. +The positive form is equivalent to @option{-fstrict-flex-arrays=3}, which is the +strictest. A trailing array is treated as a flexible array member only when it +is declared as a flexible array member per C99 standard onwards. +The negative form is equivalent to @option{-fstrict-flex-arrays=0}, which is the +least strict. All trailing arrays of structures are treated as flexible array +members. + +@item -fstrict-flex-arrays=@var{level} +@opindex fstrict-flex-arrays=@var{level} +Control when to treat the trailing array of a structure as a flexible array +member for the purpose of accessing the elements of such an array. The value +of @var{level} controls the level of strictness. + +The possible values of @var{level} are the same as for the +@code{strict_flex_array} attribute (@pxref{Variable Attributes}). + +You can control this behavior for a specific trailing array field of a +structure by using the variable attribute @code{strict_flex_array} attribute +(@pxref{Variable Attributes}). + @item -fsso-struct=@var{endianness} @opindex fsso-struct Set the default scalar storage order of structures and unions to the diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index bb42ee1..d0a71ecb 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -3267,9 +3267,6 @@ Like @code{b}, if @option{-mpowerpc64} is used; otherwise, @code{NO_REGS}. @item wB Signed 5-bit constant integer that can be loaded into an Altivec register. -@item wD -Int constant that is the element number of the 64-bit scalar in a vector. - @item wE Vector constant that can be loaded with the XXSPLTIB instruction. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 4f4f090..4ce7574 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -3423,6 +3423,12 @@ someone decided it was a good idea to use that register number to terminate the stack backtrace. New ports should avoid this. @end defmac +@defmac DWARF_VERSION_DEFAULT +A C expression whose value is the default dwarf standard version we'll honor +and advertise when generating dwarf debug information, in absence of +an explicit @option{-gdwarf-@var{version}} option on the command line. +@end defmac + @deftypefn {Target Hook} void TARGET_DWARF_HANDLE_FRAME_UNSPEC (const char *@var{label}, rtx @var{pattern}, int @var{index}) @c hook-start:TARGET_DWARF_HANDLE_FRAME_UNSPEC This target hook allows the backend to emit frame-related insns that diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 21b849e..501ddf1 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -2575,6 +2575,12 @@ someone decided it was a good idea to use that register number to terminate the stack backtrace. New ports should avoid this. @end defmac +@defmac DWARF_VERSION_DEFAULT +A C expression whose value is the default dwarf standard version we'll honor +and advertise when generating dwarf debug information, in absence of +an explicit @option{-gdwarf-@var{version}} option on the command line. +@end defmac + @hook TARGET_DWARF_HANDLE_FRAME_UNSPEC @hook TARGET_DWARF_POLY_INDETERMINATE_VALUE diff --git a/gcc/expr.cc b/gcc/expr.cc index 80bb1b8..ba627f1 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -6207,7 +6207,9 @@ store_expr (tree exp, rtx target, int call_param_p, if ((! rtx_equal_p (temp, target) || (temp != target && (side_effects_p (temp) - || side_effects_p (target)))) + || side_effects_p (target) + || (MEM_P (temp) + && !mems_same_for_tbaa_p (temp, target))))) && TREE_CODE (exp) != ERROR_MARK /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET, but TARGET is not valid memory reference, TEMP will differ diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 4f4ec81..9f7beae 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -130,7 +130,6 @@ static tree eval_subst (location_t, tree, tree, tree, tree, tree); static tree optimize_bit_field_compare (location_t, enum tree_code, tree, tree, tree); static bool simple_operand_p (const_tree); -static bool simple_operand_p_2 (tree); static tree range_binop (enum tree_code, tree, tree, int, tree, int); static tree range_predecessor (tree); static tree range_successor (tree); @@ -4868,8 +4867,8 @@ sign_bit_p (tree exp, const_tree val) return NULL_TREE; } -/* Subroutine for fold_truth_andor_1: determine if an operand is simple enough - to be evaluated unconditionally. */ +/* Subroutine for fold_truth_andor_1 and simple_condition_p: determine if an + operand is simple enough to be evaluated unconditionally. */ static bool simple_operand_p (const_tree exp) @@ -4897,13 +4896,12 @@ simple_operand_p (const_tree exp) && (! TREE_STATIC (exp) || DECL_REGISTER (exp)))); } -/* Subroutine for fold_truth_andor: determine if an operand is simple enough - to be evaluated unconditionally. - I addition to simple_operand_p, we assume that comparisons, conversions, +/* Determine if an operand is simple enough to be evaluated unconditionally. + In addition to simple_operand_p, we assume that comparisons, conversions, and logic-not operations are simple, if their operands are simple, too. */ -static bool -simple_operand_p_2 (tree exp) +bool +simple_condition_p (tree exp) { enum tree_code code; @@ -4920,7 +4918,7 @@ simple_operand_p_2 (tree exp) && simple_operand_p (TREE_OPERAND (exp, 1))); if (code == TRUTH_NOT_EXPR) - return simple_operand_p_2 (TREE_OPERAND (exp, 0)); + return simple_condition_p (TREE_OPERAND (exp, 0)); return simple_operand_p (exp); } @@ -9787,10 +9785,10 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type, side-effects, or isn't simple, then we can't add to it, as otherwise we might destroy if-sequence. */ if (TREE_CODE (arg0) == icode - && simple_operand_p_2 (arg1) + && simple_condition_p (arg1) /* Needed for sequence points to handle trappings, and side-effects. */ - && simple_operand_p_2 (TREE_OPERAND (arg0, 1))) + && simple_condition_p (TREE_OPERAND (arg0, 1))) { tem = fold_build2_loc (loc, ncode, type, TREE_OPERAND (arg0, 1), arg1); @@ -9800,10 +9798,10 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type, /* Same as above but for (A AND[-IF] (B AND-IF C)) -> ((A AND B) AND-IF C), or (A OR[-IF] (B OR-IF C) -> ((A OR B) OR-IF C). */ else if (TREE_CODE (arg1) == icode - && simple_operand_p_2 (arg0) + && simple_condition_p (arg0) /* Needed for sequence points to handle trappings, and side-effects. */ - && simple_operand_p_2 (TREE_OPERAND (arg1, 0))) + && simple_condition_p (TREE_OPERAND (arg1, 0))) { tem = fold_build2_loc (loc, ncode, type, arg0, TREE_OPERAND (arg1, 0)); @@ -9814,8 +9812,8 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type, into (A OR B). For sequence point consistancy, we need to check for trapping, and side-effects. */ - else if (code == icode && simple_operand_p_2 (arg0) - && simple_operand_p_2 (arg1)) + else if (code == icode && simple_condition_p (arg0) + && simple_condition_p (arg1)) return fold_build2_loc (loc, ncode, type, arg0, arg1); } diff --git a/gcc/fold-const.h b/gcc/fold-const.h index fe78a4d..fa284c7 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -215,6 +215,7 @@ extern tree build_range_check (location_t, tree, tree, int, tree, tree); extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree, tree); extern tree sign_bit_p (tree, const_tree); +extern bool simple_condition_p (tree); extern tree exact_inverse (tree, tree); extern bool expr_not_equal_to (tree t, const wide_int &); extern tree const_unop (enum tree_code, tree, tree); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 0559fc3..535b9ae 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,53 @@ +2022-10-06 Tobias Burnus <tobias@codesourcery.com> + + * trans-openmp.cc (gfc_trans_omp_assume): New. + (gfc_trans_omp_directive): Call it. + +2022-10-05 Tobias Burnus <tobias@codesourcery.com> + + * dump-parse-tree.cc (show_omp_assumes): New. + (show_omp_clauses, show_namespace): Call it. + (show_omp_node, show_code_node): Handle OpenMP ASSUME. + * gfortran.h (enum gfc_statement): Add ST_OMP_ASSUME, + ST_OMP_END_ASSUME, ST_OMP_ASSUMES and ST_NOTHING. + (gfc_exec_op): Add EXEC_OMP_ASSUME. + (gfc_omp_assumptions): New struct. + (gfc_get_omp_assumptions): New XCNEW #define. + (gfc_omp_clauses, gfc_namespace): Add assume member. + (gfc_resolve_omp_assumptions): New prototype. + * match.h (gfc_match_omp_assume, gfc_match_omp_assumes): New. + * openmp.cc (omp_code_to_statement): Forward declare. + (enum gfc_omp_directive_kind, struct gfc_omp_directive): New. + (gfc_free_omp_clauses): Free assume member and its struct data. + (enum omp_mask2): Add OMP_CLAUSE_ASSUMPTIONS. + (gfc_omp_absent_contains_clause): New. + (gfc_match_omp_clauses): Call it; optionally use passed + omp_clauses argument. + (omp_verify_merge_absent_contains, gfc_match_omp_assume, + gfc_match_omp_assumes, gfc_resolve_omp_assumptions): New. + (resolve_omp_clauses): Call the latter. + (gfc_resolve_omp_directive, omp_code_to_statement): Handle + EXEC_OMP_ASSUME. + * parse.cc (decode_omp_directive): Parse OpenMP ASSUME(S). + (next_statement, parse_executable, parse_omp_structured_block): + Handle ST_OMP_ASSUME. + (case_omp_decl): Add ST_OMP_ASSUMES. + (gfc_ascii_statement): Handle Assumes, optional return + string without '!$OMP '/'!$ACC ' prefix. + * parse.h (gfc_ascii_statement): Add optional bool arg to prototype. + * resolve.cc (gfc_resolve_blocks, gfc_resolve_code): Add + EXEC_OMP_ASSUME. + (gfc_resolve): Resolve ASSUMES directive. + * symbol.cc (gfc_free_namespace): Free omp_assumes member. + * st.cc (gfc_free_statement): Handle EXEC_OMP_ASSUME. + * trans-openmp.cc (gfc_trans_omp_directive): Likewise. + * trans.cc (trans_code): Likewise. + +2022-10-04 Tobias Burnus <tobias@codesourcery.com> + + * parse.cc (decode_omp_directive): Handle '(end) loop' and 'scan' + also with -fopenmp-simd. + 2022-10-01 José Rui Faustino de Sousa <jrfsousa@gmail.com> PR fortran/100040 diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index 40c690c..2f042ab 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "gfortran.h" #include "constructor.h" #include "version.h" +#include "parse.h" /* For gfc_ascii_statement. */ /* Keep track of indentation for symbol tree dumps. */ static int show_level = 0; @@ -1458,6 +1459,34 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n) gfc_current_ns = ns_curr; } +static void +show_omp_assumes (gfc_omp_assumptions *assume) +{ + for (int i = 0; i < assume->n_absent; i++) + { + fputs (" ABSENT (", dumpfile); + fputs (gfc_ascii_statement (assume->absent[i], true), dumpfile); + fputc (')', dumpfile); + } + for (int i = 0; i < assume->n_contains; i++) + { + fputs (" CONTAINS (", dumpfile); + fputs (gfc_ascii_statement (assume->contains[i], true), dumpfile); + fputc (')', dumpfile); + } + for (gfc_expr_list *el = assume->holds; el; el = el->next) + { + fputs (" HOLDS (", dumpfile); + show_expr (el->expr); + fputc (')', dumpfile); + } + if (assume->no_openmp) + fputs (" NO_OPENMP", dumpfile); + if (assume->no_openmp_routines) + fputs (" NO_OPENMP_ROUTINES", dumpfile); + if (assume->no_parallelism) + fputs (" NO_PARALLELISM", dumpfile); +} /* Show OpenMP or OpenACC clauses. */ @@ -1998,6 +2027,8 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses) show_expr (omp_clauses->message); fputc (')', dumpfile); } + if (omp_clauses->assume) + show_omp_assumes (omp_clauses->assume); } /* Show a single OpenMP or OpenACC directive node and everything underneath it @@ -2027,6 +2058,7 @@ show_omp_node (int level, gfc_code *c) case EXEC_OACC_CACHE: name = "CACHE"; is_oacc = true; break; case EXEC_OACC_ENTER_DATA: name = "ENTER DATA"; is_oacc = true; break; case EXEC_OACC_EXIT_DATA: name = "EXIT DATA"; is_oacc = true; break; + case EXEC_OMP_ASSUME: name = "ASSUME"; break; case EXEC_OMP_ATOMIC: name = "ATOMIC"; break; case EXEC_OMP_BARRIER: name = "BARRIER"; break; case EXEC_OMP_CANCEL: name = "CANCEL"; break; @@ -2128,6 +2160,7 @@ show_omp_node (int level, gfc_code *c) case EXEC_OACC_CACHE: case EXEC_OACC_ENTER_DATA: case EXEC_OACC_EXIT_DATA: + case EXEC_OMP_ASSUME: case EXEC_OMP_CANCEL: case EXEC_OMP_CANCELLATION_POINT: case EXEC_OMP_DISTRIBUTE: @@ -3353,6 +3386,7 @@ show_code_node (int level, gfc_code *c) case EXEC_OACC_CACHE: case EXEC_OACC_ENTER_DATA: case EXEC_OACC_EXIT_DATA: + case EXEC_OMP_ASSUME: case EXEC_OMP_ATOMIC: case EXEC_OMP_CANCEL: case EXEC_OMP_CANCELLATION_POINT: @@ -3531,6 +3565,13 @@ show_namespace (gfc_namespace *ns) } } + if (ns->omp_assumes) + { + show_indent (); + fprintf (dumpfile, "!$OMP ASSUMES"); + show_omp_assumes (ns->omp_assumes); + } + fputc ('\n', dumpfile); show_indent (); fputs ("code:", dumpfile); diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 4babd77..608dda4 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -316,7 +316,9 @@ enum gfc_statement ST_OMP_END_PARALLEL_MASKED_TASKLOOP_SIMD, ST_OMP_MASKED_TASKLOOP, ST_OMP_END_MASKED_TASKLOOP, ST_OMP_MASKED_TASKLOOP_SIMD, ST_OMP_END_MASKED_TASKLOOP_SIMD, ST_OMP_SCOPE, ST_OMP_END_SCOPE, - ST_OMP_ERROR, ST_NONE + ST_OMP_ERROR, ST_OMP_ASSUME, ST_OMP_END_ASSUME, ST_OMP_ASSUMES, + /* Note: gfc_match_omp_nothing returns ST_NONE. */ + ST_OMP_NOTHING, ST_NONE }; /* Types of interfaces that we can have. Assignment interfaces are @@ -1506,6 +1508,18 @@ enum gfc_omp_bind_type OMP_BIND_THREAD }; +typedef struct gfc_omp_assumptions +{ + int n_absent, n_contains; + enum gfc_statement *absent, *contains; + gfc_expr_list *holds; + bool no_openmp:1, no_openmp_routines:1, no_parallelism:1; +} +gfc_omp_assumptions; + +#define gfc_get_omp_assumptions() XCNEW (gfc_omp_assumptions) + + typedef struct gfc_omp_clauses { gfc_omp_namelist *lists[OMP_LIST_NUM]; @@ -1529,6 +1543,7 @@ typedef struct gfc_omp_clauses struct gfc_expr *if_exprs[OMP_IF_LAST]; struct gfc_expr *dist_chunk_size; struct gfc_expr *message; + struct gfc_omp_assumptions *assume; const char *critical_name; enum gfc_omp_default_sharing default_sharing; enum gfc_omp_atomic_op atomic_op; @@ -2145,6 +2160,9 @@ typedef struct gfc_namespace /* Linked list of !$omp declare variant constructs. */ struct gfc_omp_declare_variant *omp_declare_variant; + /* OpenMP assumptions. */ + struct gfc_omp_assumptions *omp_assumes; + /* A hash set for the gfc expressions that have already been finalized in this namespace. */ @@ -2913,7 +2931,7 @@ enum gfc_exec_op EXEC_OMP_ORDERED, EXEC_OMP_PARALLEL, EXEC_OMP_PARALLEL_DO, EXEC_OMP_PARALLEL_SECTIONS, EXEC_OMP_PARALLEL_WORKSHARE, EXEC_OMP_SECTIONS, EXEC_OMP_SINGLE, EXEC_OMP_WORKSHARE, - EXEC_OMP_ATOMIC, EXEC_OMP_BARRIER, EXEC_OMP_END_NOWAIT, + EXEC_OMP_ASSUME, EXEC_OMP_ATOMIC, EXEC_OMP_BARRIER, EXEC_OMP_END_NOWAIT, EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT, EXEC_OMP_TASKYIELD, EXEC_OMP_CANCEL, EXEC_OMP_CANCELLATION_POINT, EXEC_OMP_TASKGROUP, EXEC_OMP_SIMD, EXEC_OMP_DO_SIMD, @@ -3576,6 +3594,7 @@ void gfc_free_omp_declare_simd (gfc_omp_declare_simd *); void gfc_free_omp_declare_simd_list (gfc_omp_declare_simd *); void gfc_free_omp_udr (gfc_omp_udr *); gfc_omp_udr *gfc_omp_udr_find (gfc_symtree *, gfc_typespec *); +void gfc_resolve_omp_assumptions (gfc_omp_assumptions *); void gfc_resolve_omp_directive (gfc_code *, gfc_namespace *); void gfc_resolve_do_iterator (gfc_code *, gfc_symbol *, bool); void gfc_resolve_omp_local_vars (gfc_namespace *); diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h index 1f53e0c..2a80581 100644 --- a/gcc/fortran/match.h +++ b/gcc/fortran/match.h @@ -149,6 +149,8 @@ match gfc_match_oacc_routine (void); /* OpenMP directive matchers. */ match gfc_match_omp_eos_error (void); +match gfc_match_omp_assume (void); +match gfc_match_omp_assumes (void); match gfc_match_omp_atomic (void); match gfc_match_omp_barrier (void); match gfc_match_omp_cancel (void); diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index ce719bd..653c43f 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -29,6 +29,86 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "gomp-constants.h" #include "target-memory.h" /* For gfc_encode_character. */ +#include "bitmap.h" + + +static gfc_statement omp_code_to_statement (gfc_code *); + +enum gfc_omp_directive_kind { + GFC_OMP_DIR_DECLARATIVE, + GFC_OMP_DIR_EXECUTABLE, + GFC_OMP_DIR_INFORMATIONAL, + GFC_OMP_DIR_META, + GFC_OMP_DIR_SUBSIDIARY, + GFC_OMP_DIR_UTILITY +}; + +struct gfc_omp_directive { + const char *name; + enum gfc_omp_directive_kind kind; + gfc_statement st; +}; + +/* Alphabetically sorted OpenMP clauses, except that longer strings are before + substrings; excludes combined/composite directives. See note for "ordered" + and "nothing". */ + +static const struct gfc_omp_directive gfc_omp_directives[] = { + /* {"allocate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_ALLOCATE}, */ + /* {"allocators", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ALLOCATORS}, */ + {"assumes", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_ASSUMES}, + {"assume", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_ASSUME}, + {"atomic", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ATOMIC}, + {"barrier", GFC_OMP_DIR_EXECUTABLE, ST_OMP_BARRIER}, + {"cancellation point", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCELLATION_POINT}, + {"cancel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CANCEL}, + {"critical", GFC_OMP_DIR_EXECUTABLE, ST_OMP_CRITICAL}, + /* {"declare mapper", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_MAPPER}, */ + {"declare reduction", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_REDUCTION}, + {"declare simd", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_SIMD}, + {"declare target", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_TARGET}, + {"declare variant", GFC_OMP_DIR_DECLARATIVE, ST_OMP_DECLARE_VARIANT}, + {"depobj", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DEPOBJ}, + /* {"dispatch", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISPATCH}, */ + {"distribute", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DISTRIBUTE}, + {"do", GFC_OMP_DIR_EXECUTABLE, ST_OMP_DO}, + /* "error" becomes GFC_OMP_DIR_EXECUTABLE with at(execution) */ + {"error", GFC_OMP_DIR_UTILITY, ST_OMP_ERROR}, + {"flush", GFC_OMP_DIR_EXECUTABLE, ST_OMP_FLUSH}, + /* {"interop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_INTEROP}, */ + {"loop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_LOOP}, + {"masked", GFC_OMP_DIR_EXECUTABLE, ST_OMP_MASKED}, + /* {"metadirective", GFC_OMP_DIR_META, ST_OMP_METADIRECTIVE}, */ + /* Note: gfc_match_omp_nothing returns ST_NONE. */ + {"nothing", GFC_OMP_DIR_UTILITY, ST_OMP_NOTHING}, + /* Special case; for now map to the first one. + ordered-blockassoc = ST_OMP_ORDERED + ordered-standalone = ST_OMP_ORDERED_DEPEND + depend/doacross. */ + {"ordered", GFC_OMP_DIR_EXECUTABLE, ST_OMP_ORDERED}, + {"parallel", GFC_OMP_DIR_EXECUTABLE, ST_OMP_PARALLEL}, + {"requires", GFC_OMP_DIR_INFORMATIONAL, ST_OMP_REQUIRES}, + {"scan", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SCAN}, + {"scope", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SCOPE}, + {"sections", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SECTIONS}, + {"section", GFC_OMP_DIR_SUBSIDIARY, ST_OMP_SECTION}, + {"simd", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SIMD}, + {"single", GFC_OMP_DIR_EXECUTABLE, ST_OMP_SINGLE}, + {"target data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_DATA}, + {"target enter data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_ENTER_DATA}, + {"target exit data", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_EXIT_DATA}, + {"target update", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET_UPDATE}, + {"target", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TARGET}, + {"taskloop", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKLOOP}, + {"taskwait", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKWAIT}, + {"taskyield", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASKYIELD}, + {"task", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TASK}, + {"teams", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TEAMS}, + {"threadprivate", GFC_OMP_DIR_DECLARATIVE, ST_OMP_THREADPRIVATE}, + /* {"tile", GFC_OMP_DIR_EXECUTABLE, ST_OMP_TILE}, */ + /* {"unroll", GFC_OMP_DIR_EXECUTABLE, ST_OMP_UNROLL}, */ + {"workshare", GFC_OMP_DIR_EXECUTABLE, ST_OMP_WORKSHARE}, +}; + /* Match an end of OpenMP directive. End of OpenMP directive is optional whitespace, followed by '\n' or comment '!'. */ @@ -111,6 +191,13 @@ gfc_free_omp_clauses (gfc_omp_clauses *c) gfc_free_expr_list (c->wait_list); gfc_free_expr_list (c->tile_list); free (CONST_CAST (char *, c->critical_name)); + if (c->assume) + { + free (c->assume->absent); + free (c->assume->contains); + gfc_free_expr_list (c->assume->holds); + free (c->assume); + } free (c); } @@ -992,6 +1079,7 @@ enum omp_mask2 OMP_CLAUSE_HAS_DEVICE_ADDR, /* OpenMP 5.1 */ OMP_CLAUSE_ENTER, /* OpenMP 5.2 */ OMP_CLAUSE_DOACROSS, /* OpenMP 5.2 */ + OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */ /* This must come last. */ OMP_MASK2_LAST }; @@ -1407,6 +1495,173 @@ gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc, return MATCH_YES; } +static match +gfc_omp_absent_contains_clause (gfc_omp_assumptions **assume, bool is_absent) +{ + if (*assume == NULL) + *assume = gfc_get_omp_assumptions (); + do + { + gfc_statement st = ST_NONE; + gfc_gobble_whitespace (); + locus old_loc = gfc_current_locus; + char c = gfc_peek_ascii_char (); + enum gfc_omp_directive_kind kind + = GFC_OMP_DIR_DECLARATIVE; /* Silence warning. */ + for (size_t i = 0; i < ARRAY_SIZE (gfc_omp_directives); i++) + { + if (gfc_omp_directives[i].name[0] > c) + break; + if (gfc_omp_directives[i].name[0] != c) + continue; + if (gfc_match (gfc_omp_directives[i].name) == MATCH_YES) + { + st = gfc_omp_directives[i].st; + kind = gfc_omp_directives[i].kind; + } + } + gfc_gobble_whitespace (); + c = gfc_peek_ascii_char (); + if (st == ST_NONE || (c != ',' && c != ')')) + { + if (st == ST_NONE) + gfc_error ("Unknown directive at %L", &old_loc); + else + gfc_error ("Invalid combined or composit directive at %L", + &old_loc); + return MATCH_ERROR; + } + if (kind == GFC_OMP_DIR_DECLARATIVE + || kind == GFC_OMP_DIR_INFORMATIONAL + || kind == GFC_OMP_DIR_META) + { + gfc_error ("Invalid %qs directive at %L in %s clause: declarative, " + "informational and meta directives not permitted", + gfc_ascii_statement (st, true), &old_loc, + is_absent ? "ABSENT" : "CONTAINS"); + return MATCH_ERROR; + } + if (is_absent) + { + /* Use exponential allocation; equivalent to pow2p(x). */ + int i = (*assume)->n_absent; + int size = ((i == 0) ? 4 + : pow2p_hwi (i) == 1 ? i*2 : 0); + if (size != 0) + (*assume)->absent = XRESIZEVEC (gfc_statement, + (*assume)->absent, size); + (*assume)->absent[(*assume)->n_absent++] = st; + } + else + { + int i = (*assume)->n_contains; + int size = ((i == 0) ? 4 + : pow2p_hwi (i) == 1 ? i*2 : 0); + if (size != 0) + (*assume)->contains = XRESIZEVEC (gfc_statement, + (*assume)->contains, size); + (*assume)->contains[(*assume)->n_contains++] = st; + } + gfc_gobble_whitespace (); + if (gfc_match(",") == MATCH_YES) + continue; + if (gfc_match(")") == MATCH_YES) + break; + gfc_error ("Expected %<,%> or %<)%> at %C"); + return MATCH_ERROR; + } + while (true); + + return MATCH_YES; +} + +/* Check 'check' argument for duplicated statements in absent and/or contains + clauses. If 'merge', merge them from check to 'merge'. */ + +static match +omp_verify_merge_absent_contains (gfc_statement st, gfc_omp_assumptions *check, + gfc_omp_assumptions *merge, locus *loc) +{ + if (check == NULL) + return MATCH_YES; + bitmap_head absent_head, contains_head; + bitmap_obstack_initialize (NULL); + bitmap_initialize (&absent_head, &bitmap_default_obstack); + bitmap_initialize (&contains_head, &bitmap_default_obstack); + + match m = MATCH_YES; + for (int i = 0; i < check->n_absent; i++) + if (!bitmap_set_bit (&absent_head, check->absent[i])) + { + gfc_error ("%qs directive mentioned multiple times in %s clause in %s " + "directive at %L", + gfc_ascii_statement (check->absent[i], true), + "ABSENT", gfc_ascii_statement (st), loc); + m = MATCH_ERROR; + } + for (int i = 0; i < check->n_contains; i++) + { + if (!bitmap_set_bit (&contains_head, check->contains[i])) + { + gfc_error ("%qs directive mentioned multiple times in %s clause in %s " + "directive at %L", + gfc_ascii_statement (check->contains[i], true), + "CONTAINS", gfc_ascii_statement (st), loc); + m = MATCH_ERROR; + } + if (bitmap_bit_p (&absent_head, check->contains[i])) + { + gfc_error ("%qs directive mentioned both times in ABSENT and CONTAINS " + "clauses in %s directive at %L", + gfc_ascii_statement (check->absent[i], true), + gfc_ascii_statement (st), loc); + m = MATCH_ERROR; + } + } + + if (m == MATCH_ERROR) + return MATCH_ERROR; + if (merge == NULL) + return MATCH_YES; + if (merge->absent == NULL && check->absent) + { + merge->n_absent = check->n_absent; + merge->absent = check->absent; + check->absent = NULL; + } + else if (merge->absent && check->absent) + { + check->absent = XRESIZEVEC (gfc_statement, check->absent, + merge->n_absent + check->n_absent); + for (int i = 0; i < merge->n_absent; i++) + if (!bitmap_bit_p (&absent_head, merge->absent[i])) + check->absent[check->n_absent++] = merge->absent[i]; + free (merge->absent); + merge->absent = check->absent; + merge->n_absent = check->n_absent; + check->absent = NULL; + } + if (merge->contains == NULL && check->contains) + { + merge->n_contains = check->n_contains; + merge->contains = check->contains; + check->contains = NULL; + } + else if (merge->contains && check->contains) + { + check->contains = XRESIZEVEC (gfc_statement, check->contains, + merge->n_contains + check->n_contains); + for (int i = 0; i < merge->n_contains; i++) + if (!bitmap_bit_p (&contains_head, merge->contains[i])) + check->contains[check->n_contains++] = merge->contains[i]; + free (merge->contains); + merge->contains = check->contains; + merge->n_contains = check->n_contains; + check->contains = NULL; + } + return MATCH_YES; +} + /* Match with duplicate check. Matches 'name'. If expr != NULL, it then matches '(expr)', otherwise, if open_parens is true, @@ -1511,6 +1766,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, case 'a': end_colon = false; head = NULL; + if ((mask & OMP_CLAUSE_ASSUMPTIONS) + && gfc_match ("absent ( ") == MATCH_YES) + { + if (gfc_omp_absent_contains_clause (&c->assume, true) + != MATCH_YES) + goto error; + continue; + } if ((mask & OMP_CLAUSE_ALIGNED) && gfc_match_omp_variable_list ("aligned (", &c->lists[OMP_LIST_ALIGNED], @@ -1743,6 +2006,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, needs_space = true; continue; } + if ((mask & OMP_CLAUSE_ASSUMPTIONS) + && gfc_match ("contains ( ") == MATCH_YES) + { + if (gfc_omp_absent_contains_clause (&c->assume, false) + != MATCH_YES) + goto error; + continue; + } if ((mask & OMP_CLAUSE_COPY) && gfc_match ("copy ( ") == MATCH_YES && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], @@ -2277,6 +2548,20 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, goto error; continue; } + if ((mask & OMP_CLAUSE_ASSUMPTIONS) + && gfc_match ("holds ( ") == MATCH_YES) + { + gfc_expr *e; + if (gfc_match ("%e )", &e) != MATCH_YES) + goto error; + if (c->assume == NULL) + c->assume = gfc_get_omp_assumptions (); + gfc_expr_list *el = XCNEW (gfc_expr_list); + el->expr = e; + el->next = c->assume->holds; + c->assume->holds = el; + continue; + } if ((mask & OMP_CLAUSE_HOST_SELF) && gfc_match ("host ( ") == MATCH_YES && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], @@ -2664,6 +2949,41 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, OMP_MAP_IF_PRESENT, true, allow_derived)) continue; + if ((mask & OMP_CLAUSE_ASSUMPTIONS) + && (m = gfc_match_dupl_check (!c->assume + || !c->assume->no_openmp_routines, + "no_openmp_routines")) == MATCH_YES) + { + if (m == MATCH_ERROR) + goto error; + if (c->assume == NULL) + c->assume = gfc_get_omp_assumptions (); + c->assume->no_openmp_routines = needs_space = true; + continue; + } + if ((mask & OMP_CLAUSE_ASSUMPTIONS) + && (m = gfc_match_dupl_check (!c->assume || !c->assume->no_openmp, + "no_openmp")) == MATCH_YES) + { + if (m == MATCH_ERROR) + goto error; + if (c->assume == NULL) + c->assume = gfc_get_omp_assumptions (); + c->assume->no_openmp = needs_space = true; + continue; + } + if ((mask & OMP_CLAUSE_ASSUMPTIONS) + && (m = gfc_match_dupl_check (!c->assume + || !c->assume->no_parallelism, + "no_parallelism")) == MATCH_YES) + { + if (m == MATCH_ERROR) + goto error; + if (c->assume == NULL) + c->assume = gfc_get_omp_assumptions (); + c->assume->no_parallelism = needs_space = true; + continue; + } if ((mask & OMP_CLAUSE_NOGROUP) && (m = gfc_match_dupl_check (!c->nogroup, "nogroup")) != MATCH_NO) @@ -3942,6 +4262,69 @@ match_omp (gfc_exec_op op, const omp_mask mask) match +gfc_match_omp_assume (void) +{ + gfc_omp_clauses *c; + locus loc = gfc_current_locus; + if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS)) + != MATCH_YES) + || (omp_verify_merge_absent_contains (ST_OMP_ASSUME, c->assume, NULL, + &loc) != MATCH_YES)) + return MATCH_ERROR; + new_st.op = EXEC_OMP_ASSUME; + new_st.ext.omp_clauses = c; + return MATCH_YES; +} + + +match +gfc_match_omp_assumes (void) +{ + gfc_omp_clauses *c; + locus loc = gfc_current_locus; + if (!gfc_current_ns->proc_name + || (gfc_current_ns->proc_name->attr.flavor != FL_MODULE + && !gfc_current_ns->proc_name->attr.subroutine + && !gfc_current_ns->proc_name->attr.function)) + { + gfc_error ("!$OMP ASSUMES at %C must be in the specification part of a " + "subprogram or module"); + return MATCH_ERROR; + } + if ((gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_ASSUMPTIONS)) + != MATCH_YES) + || (omp_verify_merge_absent_contains (ST_OMP_ASSUMES, c->assume, + gfc_current_ns->omp_assumes, &loc) + != MATCH_YES)) + return MATCH_ERROR; + if (gfc_current_ns->omp_assumes == NULL) + { + gfc_current_ns->omp_assumes = c->assume; + c->assume = NULL; + } + else if (gfc_current_ns->omp_assumes && c->assume) + { + gfc_current_ns->omp_assumes->no_openmp |= c->assume->no_openmp; + gfc_current_ns->omp_assumes->no_openmp_routines + |= c->assume->no_openmp_routines; + gfc_current_ns->omp_assumes->no_parallelism |= c->assume->no_parallelism; + if (gfc_current_ns->omp_assumes->holds && c->assume->holds) + { + gfc_expr_list *el = gfc_current_ns->omp_assumes->holds; + for ( ; el->next ; el = el->next) + ; + el->next = c->assume->holds; + } + else if (c->assume->holds) + gfc_current_ns->omp_assumes->holds = c->assume->holds; + c->assume->holds = NULL; + } + gfc_free_omp_clauses (c); + return MATCH_YES; +} + + +match gfc_match_omp_critical (void) { char n[GFC_MAX_SYMBOL_LEN+1]; @@ -6505,6 +6888,20 @@ resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns, return copy; } + +/* Resolve ASSUME's and ASSUMES' assumption clauses. Note that absent/contains + is handled during parse time in omp_verify_merge_absent_contains. */ + +void +gfc_resolve_omp_assumptions (gfc_omp_assumptions *assume) +{ + for (gfc_expr_list *el = assume->holds; el; el = el->next) + if (!gfc_resolve_expr (el->expr) || el->expr->ts.type != BT_LOGICAL) + gfc_error ("HOLDS expression at %L must be a logical expression", + &el->expr->where); +} + + /* OpenMP directive resolving routines. */ static void @@ -7888,6 +8285,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, gfc_error ("%<DETACH%> clause at %L must not be used together with " "%<MERGEABLE%> clause", &omp_clauses->detach->where); } + + if (omp_clauses->assume) + gfc_resolve_omp_assumptions (omp_clauses->assume); } @@ -9116,6 +9516,8 @@ omp_code_to_statement (gfc_code *code) return ST_OMP_DO; case EXEC_OMP_LOOP: return ST_OMP_LOOP; + case EXEC_OMP_ASSUME: + return ST_OMP_ASSUME; case EXEC_OMP_ATOMIC: return ST_OMP_ATOMIC; case EXEC_OMP_BARRIER: @@ -9635,6 +10037,7 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns) case EXEC_OMP_TEAMS_LOOP: resolve_omp_do (code); break; + case EXEC_OMP_ASSUME: case EXEC_OMP_CANCEL: case EXEC_OMP_ERROR: case EXEC_OMP_MASKED: diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc index 5b13441..f04fd13 100644 --- a/gcc/fortran/parse.cc +++ b/gcc/fortran/parse.cc @@ -885,6 +885,8 @@ decode_omp_directive (void) switch (c) { case 'a': + matcho ("assumes", gfc_match_omp_assumes, ST_OMP_ASSUMES); + matchs ("assume", gfc_match_omp_assume, ST_OMP_ASSUME); matcho ("atomic", gfc_match_omp_atomic, ST_OMP_ATOMIC); break; case 'b': @@ -913,6 +915,7 @@ decode_omp_directive (void) break; case 'e': matcho ("error", gfc_match_omp_error, ST_OMP_ERROR); + matchs ("end assume", gfc_match_omp_eos_error, ST_OMP_END_ASSUME); matcho ("end atomic", gfc_match_omp_eos_error, ST_OMP_END_ATOMIC); matcho ("end critical", gfc_match_omp_end_critical, ST_OMP_END_CRITICAL); matchs ("end distribute parallel do simd", gfc_match_omp_eos_error, @@ -924,7 +927,7 @@ decode_omp_directive (void) matcho ("end distribute", gfc_match_omp_eos_error, ST_OMP_END_DISTRIBUTE); matchs ("end do simd", gfc_match_omp_end_nowait, ST_OMP_END_DO_SIMD); matcho ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO); - matcho ("end loop", gfc_match_omp_eos_error, ST_OMP_END_LOOP); + matchs ("end loop", gfc_match_omp_eos_error, ST_OMP_END_LOOP); matchs ("end simd", gfc_match_omp_eos_error, ST_OMP_END_SIMD); matcho ("end masked taskloop simd", gfc_match_omp_eos_error, ST_OMP_END_MASKED_TASKLOOP_SIMD); @@ -1023,7 +1026,7 @@ decode_omp_directive (void) matcho ("nothing", gfc_match_omp_nothing, ST_NONE); break; case 'l': - matcho ("loop", gfc_match_omp_loop, ST_OMP_LOOP); + matchs ("loop", gfc_match_omp_loop, ST_OMP_LOOP); break; case 'o': if (gfc_match ("ordered depend (") == MATCH_YES @@ -1070,7 +1073,7 @@ decode_omp_directive (void) matcho ("requires", gfc_match_omp_requires, ST_OMP_REQUIRES); break; case 's': - matcho ("scan", gfc_match_omp_scan, ST_OMP_SCAN); + matchs ("scan", gfc_match_omp_scan, ST_OMP_SCAN); matcho ("scope", gfc_match_omp_scope, ST_OMP_SCOPE); matcho ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS); matcho ("section", gfc_match_omp_eos_error, ST_OMP_SECTION); @@ -1716,6 +1719,7 @@ next_statement (void) case ST_OMP_TARGET_SIMD: case ST_OMP_TASKLOOP: case ST_OMP_TASKLOOP_SIMD: \ case ST_OMP_LOOP: case ST_OMP_PARALLEL_LOOP: case ST_OMP_TEAMS_LOOP: \ case ST_OMP_TARGET_PARALLEL_LOOP: case ST_OMP_TARGET_TEAMS_LOOP: \ + case ST_OMP_ASSUME: \ case ST_CRITICAL: \ case ST_OACC_PARALLEL_LOOP: case ST_OACC_PARALLEL: case ST_OACC_KERNELS: \ case ST_OACC_DATA: case ST_OACC_HOST_DATA: case ST_OACC_LOOP: \ @@ -1733,7 +1737,7 @@ next_statement (void) #define case_omp_decl case ST_OMP_THREADPRIVATE: case ST_OMP_DECLARE_SIMD: \ case ST_OMP_DECLARE_TARGET: case ST_OMP_DECLARE_REDUCTION: \ - case ST_OMP_DECLARE_VARIANT: \ + case ST_OMP_DECLARE_VARIANT: case ST_OMP_ASSUMES: \ case ST_OMP_REQUIRES: case ST_OACC_ROUTINE: case ST_OACC_DECLARE /* Block end statements. Errors associated with interchanging these @@ -1925,10 +1929,11 @@ gfc_enclosing_unit (gfc_compile_state * result) } -/* Translate a statement enum to a string. */ +/* Translate a statement enum to a string. If strip_sentinel is true, + the !$OMP/!$ACC sentinel is excluded. */ const char * -gfc_ascii_statement (gfc_statement st) +gfc_ascii_statement (gfc_statement st, bool strip_sentinel) { const char *p; @@ -2353,6 +2358,12 @@ gfc_ascii_statement (gfc_statement st) case ST_OACC_END_ATOMIC: p = "!$ACC END ATOMIC"; break; + case ST_OMP_ASSUME: + p = "!$OMP ASSUME"; + break; + case ST_OMP_ASSUMES: + p = "!$OMP ASSUMES"; + break; case ST_OMP_ATOMIC: p = "!$OMP ATOMIC"; break; @@ -2401,6 +2412,9 @@ gfc_ascii_statement (gfc_statement st) case ST_OMP_DO_SIMD: p = "!$OMP DO SIMD"; break; + case ST_OMP_END_ASSUME: + p = "!$OMP END ASSUME"; + break; case ST_OMP_END_ATOMIC: p = "!$OMP END ATOMIC"; break; @@ -2600,6 +2614,10 @@ gfc_ascii_statement (gfc_statement st) case ST_OMP_ORDERED_DEPEND: p = "!$OMP ORDERED"; break; + case ST_OMP_NOTHING: + /* Note: gfc_match_omp_nothing returns ST_NONE. */ + p = "!$OMP NOTHING"; + break; case ST_OMP_PARALLEL: p = "!$OMP PARALLEL"; break; @@ -2751,6 +2769,8 @@ gfc_ascii_statement (gfc_statement st) gfc_internal_error ("gfc_ascii_statement(): Bad statement code"); } + if (strip_sentinel && p[0] == '!') + return p + strlen ("!$OMP "); return p; } @@ -5518,6 +5538,9 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) switch (omp_st) { + case ST_OMP_ASSUME: + omp_end_st = ST_OMP_END_ASSUME; + break; case ST_OMP_PARALLEL: omp_end_st = ST_OMP_END_PARALLEL; break; @@ -5651,6 +5674,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) parse_forall_block (); break; + case ST_OMP_ASSUME: case ST_OMP_PARALLEL: case ST_OMP_PARALLEL_MASKED: case ST_OMP_PARALLEL_MASTER: @@ -5874,6 +5898,7 @@ parse_executable (gfc_statement st) parse_oacc_structured_block (st); break; + case ST_OMP_ASSUME: case ST_OMP_PARALLEL: case ST_OMP_PARALLEL_MASKED: case ST_OMP_PARALLEL_MASTER: diff --git a/gcc/fortran/parse.h b/gcc/fortran/parse.h index 7ddea10..013aeae 100644 --- a/gcc/fortran/parse.h +++ b/gcc/fortran/parse.h @@ -66,7 +66,7 @@ extern gfc_state_data *gfc_state_stack; int gfc_check_do_variable (gfc_symtree *); bool gfc_find_state (gfc_compile_state); gfc_state_data *gfc_enclosing_unit (gfc_compile_state *); -const char *gfc_ascii_statement (gfc_statement); +const char *gfc_ascii_statement (gfc_statement, bool strip_sentinel = false) ; match gfc_match_enum (void); match gfc_match_enumerator_def (void); void gfc_free_enum_history (void); diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index ae7ebb6..d133bc2 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -10902,6 +10902,7 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns) case EXEC_OACC_ENTER_DATA: case EXEC_OACC_EXIT_DATA: case EXEC_OACC_ROUTINE: + case EXEC_OMP_ASSUME: case EXEC_OMP_CRITICAL: case EXEC_OMP_DISTRIBUTE: case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: @@ -12376,6 +12377,7 @@ start: gfc_resolve_oacc_directive (code, ns); break; + case EXEC_OMP_ASSUME: case EXEC_OMP_ATOMIC: case EXEC_OMP_BARRIER: case EXEC_OMP_CANCEL: @@ -17651,6 +17653,9 @@ gfc_resolve (gfc_namespace *ns) component_assignment_level = 0; resolve_codes (ns); + if (ns->omp_assumes) + gfc_resolve_omp_assumptions (ns->omp_assumes); + gfc_current_ns = old_ns; cs_base = old_cs_base; ns->resolved = 1; diff --git a/gcc/fortran/st.cc b/gcc/fortran/st.cc index 73f30c2..3c8ca66 100644 --- a/gcc/fortran/st.cc +++ b/gcc/fortran/st.cc @@ -214,6 +214,7 @@ gfc_free_statement (gfc_code *p) case EXEC_OACC_ENTER_DATA: case EXEC_OACC_EXIT_DATA: case EXEC_OACC_ROUTINE: + case EXEC_OMP_ASSUME: case EXEC_OMP_ATOMIC: case EXEC_OMP_CANCEL: case EXEC_OMP_CANCELLATION_POINT: diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc index 7a80dfd0..6050359 100644 --- a/gcc/fortran/symbol.cc +++ b/gcc/fortran/symbol.cc @@ -4071,7 +4071,13 @@ gfc_free_namespace (gfc_namespace *&ns) f = f->next; free (current); } - + if (ns->omp_assumes) + { + free (ns->omp_assumes->absent); + free (ns->omp_assumes->contains); + gfc_free_expr_list (ns->omp_assumes->holds); + free (ns->omp_assumes); + } p = ns->contained; free (ns); ns = NULL; diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 8e9d534..8ea573f 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -4571,6 +4571,41 @@ static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *); static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *); static tree +gfc_trans_omp_assume (gfc_code *code) +{ + stmtblock_t block; + gfc_init_block (&block); + gfc_omp_assumptions *assume = code->ext.omp_clauses->assume; + if (assume) + for (gfc_expr_list *el = assume->holds; el; el = el->next) + { + location_t loc = gfc_get_location (&el->expr->where); + gfc_se se; + gfc_init_se (&se, NULL); + gfc_conv_expr (&se, el->expr); + tree t; + if (se.pre.head == NULL_TREE && se.post.head == NULL_TREE) + t = se.expr; + else + { + tree var = gfc_create_var (TREE_TYPE (se.expr), NULL); + stmtblock_t block2; + gfc_init_block (&block2); + gfc_add_block_to_block (&block2, &se.pre); + gfc_add_modify_loc (loc, &block2, var, se.expr); + gfc_add_block_to_block (&block2, &se.post); + t = gfc_finish_block (&block2); + t = build4 (TARGET_EXPR, boolean_type_node, var, t, NULL, NULL); + } + t = build_call_expr_internal_loc (loc, IFN_ASSUME, + void_type_node, 1, t); + gfc_add_expr_to_block (&block, t); + } + gfc_add_expr_to_block (&block, gfc_trans_omp_code (code->block->next, true)); + return gfc_finish_block (&block); +} + +static tree gfc_trans_omp_atomic (gfc_code *code) { gfc_code *atomic_code = code->block; @@ -7487,6 +7522,8 @@ gfc_trans_omp_directive (gfc_code *code) { switch (code->op) { + case EXEC_OMP_ASSUME: + return gfc_trans_omp_assume (code); case EXEC_OMP_ATOMIC: return gfc_trans_omp_atomic (code); case EXEC_OMP_BARRIER: diff --git a/gcc/fortran/trans.cc b/gcc/fortran/trans.cc index 912a206..8a64882 100644 --- a/gcc/fortran/trans.cc +++ b/gcc/fortran/trans.cc @@ -2174,6 +2174,7 @@ trans_code (gfc_code * code, tree cond) res = gfc_trans_dt_end (code); break; + case EXEC_OMP_ASSUME: case EXEC_OMP_ATOMIC: case EXEC_OMP_BARRIER: case EXEC_OMP_CANCEL: diff --git a/gcc/function.cc b/gcc/function.cc index 5498a71..6474a66 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -6249,10 +6249,15 @@ thread_prologue_and_epilogue_insns (void) } } - /* Threading the prologue and epilogue changes the artificial refs - in the entry and exit blocks. */ - epilogue_completed = 1; - df_update_entry_exit_and_calls (); + /* Threading the prologue and epilogue changes the artificial refs in the + entry and exit blocks, and may invalidate DF info for tail calls. */ + if (optimize) + df_update_entry_exit_and_calls (); + else + { + df_update_entry_block_defs (); + df_update_exit_block_uses (); + } } /* Reposition the prologue-end and epilogue-begin notes after diff --git a/gcc/gimple-loop-jam.cc b/gcc/gimple-loop-jam.cc index a8a57d3..4f7a6e5 100644 --- a/gcc/gimple-loop-jam.cc +++ b/gcc/gimple-loop-jam.cc @@ -545,11 +545,25 @@ tree_loop_unroll_and_jam (void) /* If the refs are independend there's nothing to do. */ if (DDR_ARE_DEPENDENT (ddr) == chrec_known) continue; + dra = DDR_A (ddr); drb = DDR_B (ddr); - /* Nothing interesting for the self dependencies. */ + + /* Nothing interesting for the self dependencies, except for WAW if + the access function is not affine or constant because we may end + up reordering writes to the same location. */ if (dra == drb) - continue; + { + if (DR_IS_WRITE (dra) + && !DR_ACCESS_FNS (dra).is_empty () + && DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) + { + unroll_factor = 0; + break; + } + else + continue; + } /* Now check the distance vector, for determining a sensible outer unroll factor, and for validity of merging the inner diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc index bc9ed84..5013a44 100644 --- a/gcc/gimple-predicate-analysis.cc +++ b/gcc/gimple-predicate-analysis.cc @@ -1369,7 +1369,7 @@ predicate::simplify_3 () /* Implement rule 4 for the OR predicate PREDS: 2) ((x AND y) != 0) OR (x != 0 AND y != 0) is equivalent to - (x != 0 ANd y != 0). */ + (x != 0 AND y != 0). */ bool predicate::simplify_4 () diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index 5b71d1c..42ebc7d 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -422,15 +422,24 @@ public: virtual bool fold_range (irange &r, tree type, const irange &lh, const irange &rh, relation_kind rel) const { + if (lh.undefined_p ()) + return false; + unsigned prec = TYPE_PRECISION (type); + wide_int nz = lh.get_nonzero_bits (); + wide_int pop = wi::shwi (wi::popcount (nz), prec); // Calculating the popcount of a singleton is trivial. if (lh.singleton_p ()) { - wide_int nz = lh.get_nonzero_bits (); - wide_int pop = wi::shwi (wi::popcount (nz), TYPE_PRECISION (type)); r.set (type, pop, pop); return true; } - return cfn_ffs::fold_range (r, type, lh, rh, rel); + if (cfn_ffs::fold_range (r, type, lh, rh, rel)) + { + int_range<2> tmp (type, wi::zero (prec), pop); + r.intersect (tmp); + return true; + } + return false; } } op_cfn_popcount; diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 9e0e342..d4209ea 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -3554,6 +3554,25 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) enum internal_fn ifn = CALL_EXPR_IFN (*expr_p); auto_vec<tree> vargs (nargs); + if (ifn == IFN_ASSUME) + { + if (simple_condition_p (CALL_EXPR_ARG (*expr_p, 0))) + { + /* If the [[assume (cond)]]; condition is simple + enough and can be evaluated unconditionally + without side-effects, expand it as + if (!cond) __builtin_unreachable (); */ + tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE); + *expr_p = build3 (COND_EXPR, void_type_node, + CALL_EXPR_ARG (*expr_p, 0), void_node, + build_call_expr_loc (EXPR_LOCATION (*expr_p), + fndecl, 0)); + return GS_OK; + } + /* FIXME: Otherwise expand it specially. */ + return GS_ALL_DONE; + } + for (i = 0; i < nargs; i++) { gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p, @@ -5601,7 +5620,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, } break; case INDIRECT_REF: - { + if (!TREE_ADDRESSABLE (TREE_TYPE (*from_p))) /* If we have code like *(const A*)(A*)&x @@ -5610,11 +5629,13 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, of "A"), treat the entire expression as identical to "x". This kind of code arises in C++ when an object is bound to a const reference, and if "x" is a TARGET_EXPR we want - to take advantage of the optimization below. */ - bool volatile_p = TREE_THIS_VOLATILE (*from_p); - tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)); - if (t) + to take advantage of the optimization below. But not if + the type is TREE_ADDRESSABLE; then C++17 says that the + TARGET_EXPR needs to be a temporary. */ + if (tree t + = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0))) { + bool volatile_p = TREE_THIS_VOLATILE (*from_p); if (TREE_THIS_VOLATILE (t) != volatile_p) { if (DECL_P (t)) @@ -5627,8 +5648,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, ret = GS_OK; changed = true; } - break; - } + break; case TARGET_EXPR: { diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h index 3d29213..2767edf 100644 --- a/gcc/ginclude/stddef.h +++ b/gcc/ginclude/stddef.h @@ -412,6 +412,7 @@ typedef __WINT_TYPE__ wint_t; #ifdef _STDDEF_H /* Offset of member MEMBER in a struct of type TYPE. */ +#undef offsetof /* in case a system header has defined it. */ #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \ diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 4793c82..10ed3fe 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -8f1a91aeff400d572857895b7f5e863ec5a4d93e +50707b4b51266166ce9bcf9de187e35760ec50f9 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 2492d9f..247ae1b 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -10316,7 +10316,12 @@ Builtin_call_expression::do_check_types(Gogo*) case BUILTIN_PANIC: case BUILTIN_SIZEOF: case BUILTIN_ALIGNOF: - this->check_one_arg(); + if (this->check_one_arg()) + { + Expression* arg = this->one_arg(); + if (arg->type()->is_void_type()) + this->report_error(_("argument to builtin has void type")); + } break; case BUILTIN_RECOVER: diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index c306240..de608bd4 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -4522,3 +4522,9 @@ expand_TRAP (internal_fn, gcall *) { expand_builtin_trap (); } + +void +expand_ASSUME (internal_fn, gcall *) +{ + gcc_unreachable (); +} diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index f49b395..61516da 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -462,6 +462,10 @@ DEF_INTERNAL_FN (TRAP, ECF_CONST | ECF_LEAF | ECF_NORETURN | ECF_NOTHROW | ECF_COLD | ECF_LOOPING_CONST_OR_PURE, NULL) +/* [[assume (cond)]]. */ +DEF_INTERNAL_FN (ASSUME, ECF_CONST | ECF_LEAF | ECF_NOTHROW + | ECF_LOOPING_CONST_OR_PURE, NULL) + #undef DEF_INTERNAL_INT_FN #undef DEF_INTERNAL_FLT_FN #undef DEF_INTERNAL_FLT_FLOATN_FN diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h index c4c94f8..21b1ce4 100644 --- a/gcc/internal-fn.h +++ b/gcc/internal-fn.h @@ -243,6 +243,7 @@ extern void expand_PHI (internal_fn, gcall *); extern void expand_SHUFFLEVECTOR (internal_fn, gcall *); extern void expand_SPACESHIP (internal_fn, gcall *); extern void expand_TRAP (internal_fn, gcall *); +extern void expand_ASSUME (internal_fn, gcall *); extern bool vectorized_internal_fn_supported_p (internal_fn, tree); diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 8811e0e..e54842d 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -78,7 +78,7 @@ struct ipa_cst_ref_desc; /* Structure holding data required to describe a constant jump function. */ struct GTY(()) ipa_constant_data { - /* THe value of the constant. */ + /* The value of the constant. */ tree value; /* Pointer to the structure that describes the reference. */ struct ipa_cst_ref_desc GTY((skip)) *rdesc; diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 01720f7..a83c3c7 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2022-10-07 Martin Liska <mliska@suse.cz> + + * objc-gnu-runtime-abi-01.cc (generate_static_references): + Remove unused variable. + 2022-06-02 David Malcolm <dmalcolm@redhat.com> * objc-act.h (objc_get_sarif_source_language): New decl. diff --git a/gcc/objc/objc-gnu-runtime-abi-01.cc b/gcc/objc/objc-gnu-runtime-abi-01.cc index 9413314..e76c486 100644 --- a/gcc/objc/objc-gnu-runtime-abi-01.cc +++ b/gcc/objc/objc-gnu-runtime-abi-01.cc @@ -1852,7 +1852,7 @@ generate_static_references (void) tree class_name, klass, decl; tree cl_chain, in_chain, type = build_array_type (build_pointer_type (void_type_node), NULL_TREE); - int num_inst, num_class; + int num_class; char buf[BUFSIZE]; vec<constructor_elt, va_gc> *decls = NULL; @@ -1861,8 +1861,8 @@ generate_static_references (void) { vec<constructor_elt, va_gc> *v = NULL; - for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain); - in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain)); + for (in_chain = TREE_PURPOSE (cl_chain); + in_chain; in_chain = TREE_CHAIN (in_chain)); snprintf (buf, BUFSIZE, "_OBJC_STATIC_INSTANCES_%d", num_class); decl = start_var_decl (type, buf); diff --git a/gcc/opts.cc b/gcc/opts.cc index eb5db01..ae079fc 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -1288,8 +1288,9 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, "%<-fsanitize=kernel-address%>"); /* Currently live patching is not support for LTO. */ - if (opts->x_flag_live_patching && opts->x_flag_lto) - sorry ("live patching is not supported with LTO"); + if (opts->x_flag_live_patching == LIVE_PATCHING_INLINE_ONLY_STATIC && opts->x_flag_lto) + sorry ("live patching (with %qs) is not supported with LTO", + "inline-only-static"); /* Currently vtable verification is not supported for LTO */ if (opts->x_flag_vtable_verify && opts->x_flag_lto) diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index ae56173..0f01002 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -1796,14 +1796,19 @@ handle_array_ref (tree aref, gimple *stmt, bool addr, int ostype, orng[0] = -orng[1] - 1; } - /* Convert the array index range determined above to a byte - offset. */ + /* Convert the array index range determined above to a byte offset. */ tree lowbnd = array_ref_low_bound (aref); - if (!integer_zerop (lowbnd) && tree_fits_uhwi_p (lowbnd)) - { - /* Adjust the index by the low bound of the array domain - (normally zero but 1 in Fortran). */ - unsigned HOST_WIDE_INT lb = tree_to_uhwi (lowbnd); + if (TREE_CODE (lowbnd) == INTEGER_CST && !integer_zerop (lowbnd)) + { + /* Adjust the index by the low bound of the array domain (0 in C/C++, + 1 in Fortran and anything in Ada) by applying the same processing + as in get_offset_range. */ + const wide_int wlb = wi::to_wide (lowbnd); + signop sgn = SIGNED; + if (TYPE_UNSIGNED (TREE_TYPE (lowbnd)) + && wlb.get_precision () < TYPE_PRECISION (sizetype)) + sgn = UNSIGNED; + const offset_int lb = offset_int::from (wlb, sgn); orng[0] -= lb; orng[1] -= lb; } diff --git a/gcc/print-tree.cc b/gcc/print-tree.cc index 6d45a4a..58a9825 100644 --- a/gcc/print-tree.cc +++ b/gcc/print-tree.cc @@ -517,8 +517,12 @@ print_node (FILE *file, const char *prefix, tree node, int indent, fprintf (file, " align:%d warn_if_not_align:%d", DECL_ALIGN (node), DECL_WARN_IF_NOT_ALIGN (node)); if (code == FIELD_DECL) - fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED, - DECL_OFFSET_ALIGN (node)); + { + fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED, + DECL_OFFSET_ALIGN (node)); + fprintf (file, " decl_not_flexarray: %d", + DECL_NOT_FLEXARRAY (node)); + } if (code == FUNCTION_DECL && fndecl_built_in_p (node)) { diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index 6e9d51d..68578aa 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -572,8 +572,7 @@ foperator_lt::fold_range (irange &r, tree type, { if (real_less (&op1.upper_bound (), &op2.lower_bound ())) r = range_true (type); - else if (finite_operands_p (op1, op2) - && !real_less (&op1.lower_bound (), &op2.upper_bound ())) + else if (!real_less (&op1.lower_bound (), &op2.upper_bound ())) r = range_false (type); else r = range_true_and_false (type); @@ -688,8 +687,7 @@ foperator_le::fold_range (irange &r, tree type, { if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) r = range_true (type); - else if (finite_operands_p (op1, op2) - && !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) + else if (!real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) r = range_false (type); else r = range_true_and_false (type); @@ -796,8 +794,7 @@ foperator_gt::fold_range (irange &r, tree type, { if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ())) r = range_true (type); - else if (finite_operands_p (op1, op2) - && !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ())) + else if (!real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ())) r = range_false (type); else r = range_true_and_false (type); @@ -912,8 +909,7 @@ foperator_ge::fold_range (irange &r, tree type, { if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) r = range_true (type); - else if (finite_operands_p (op1, op2) - && !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) + else if (!real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) r = range_false (type); else r = range_true_and_false (type); diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 4f647ab..df0735c 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -2515,6 +2515,18 @@ operator_cast::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, if (r.varying_p ()) return true; } + + // Update the nonzero mask. Truncating casts are problematic unless + // the conversion fits in the resulting outer type. + wide_int nz = inner.get_nonzero_bits (); + if (truncating_cast_p (inner, outer) + && wi::rshift (nz, wi::uhwi (TYPE_PRECISION (outer.type ()), + TYPE_PRECISION (inner.type ())), + TYPE_SIGN (inner.type ())) != 0) + return true; + nz = wide_int::from (nz, TYPE_PRECISION (type), TYPE_SIGN (inner.type ())); + r.set_nonzero_bits (nz); + return true; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0c6e5d4..af8fc3f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,263 @@ +2022-10-07 Marek Polacek <polacek@redhat.com> + + PR c++/107085 + * g++.dg/ext/reference_constructs_from_temporary1.C: Adjust expected + result. + * g++.dg/ext/reference_converts_from_temporary1.C: Likewise. + * g++.dg/cpp0x/elision4.C: New test. + +2022-10-07 Qing Zhao <qing.zhao@oracle.com> + + PR tree-optimization/101836 + * gcc.dg/pr101836.c: New test. + * gcc.dg/pr101836_1.c: New test. + * gcc.dg/pr101836_2.c: New test. + * gcc.dg/pr101836_3.c: New test. + * gcc.dg/pr101836_4.c: New test. + * gcc.dg/pr101836_5.c: New test. + * gcc.dg/strict-flex-array-2.c: New test. + * gcc.dg/strict-flex-array-3.c: New test. + +2022-10-07 Qing Zhao <qing.zhao@oracle.com> + + * g++.dg/strict-flex-array-1.C: New test. + * gcc.dg/strict-flex-array-1.c: New test. + +2022-10-07 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/105783 + * gcc.dg/analyzer/pr105783.c: New test. + +2022-10-07 Patrick Palka <ppalka@redhat.com> + + * g++.dg/modules/bfield-3.H: New test. + +2022-10-07 Martin Liska <mliska@suse.cz> + + * gcc.dg/live-patching-2.c: Update scanned pattern. + * gcc.dg/live-patching-5.c: New test. + +2022-10-07 Patrick Palka <ppalka@redhat.com> + + PR c++/104433 + * g++.dg/modules/static-2_a.H: New test. + * g++.dg/modules/static-2_b.C: New test. + +2022-10-07 Jason Merrill <jason@redhat.com> + + * g++.dg/init/elide9.C: New test. + +2022-10-07 Richard Biener <rguenther@suse.de> + + PR tree-optimization/107153 + * gcc.dg/autopar/pr107153.c: New testcase. + +2022-10-07 Jakub Jelinek <jakub@redhat.com> + + * g++.dg/cpp1z/fallthrough2.C: New test. + * g++.dg/cpp2a/attr-likely7.C: New test. + +2022-10-06 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/107170 + * gcc.dg/tree-ssa/pr107170.c: New test. + +2022-10-06 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107158 + * gcc.dg/analyzer/call-summaries-pr107158-2.c: New test. + +2022-10-06 Tobias Burnus <tobias@codesourcery.com> + + * gfortran.dg/gomp/assume-3.f90: New test. + * gfortran.dg/gomp/assume-4.f90: New test. + +2022-10-06 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/c11-typeof-1.c, gcc.dg/c2x-typeof-1.c, + gcc.dg/c2x-typeof-2.c, gcc.dg/c2x-typeof-3.c, + gcc.dg/gnu11-typeof-1.c, gcc.dg/gnu11-typeof-2.c, + gcc.dg/gnu2x-typeof-1.c: New tests. + +2022-10-06 Patrick Palka <ppalka@redhat.com> + + * g++.dg/modules/indirect-3_b.C: Expect that the entity + foo::TPL<0>::frob is tagged as a specialization instead + of as a declaration. + * g++.dg/modules/tpl-spec-8_a.H: New test. + * g++.dg/modules/tpl-spec-8_b.C: New test. + +2022-10-06 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.c-torture/execute/20221006-1.c: New test. + +2022-10-06 Richard Biener <rguenther@suse.de> + + PR middle-end/107115 + * gcc.dg/torture/pr107115.c: New testcase. + +2022-10-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * gcc.target/aarch64/ldar_2.c: New test. + +2022-10-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * gcc.target/aarch64/ldar_1.c: New test. + +2022-10-06 Philipp Tomsich <philipp.tomsich@vrull.eu> + + * gcc.target/aarch64/cpunative/info_18: New test. + * gcc.target/aarch64/cpunative/native_cpu_18.c: New test. + +2022-10-06 Richard Biener <rguenther@suse.de> + + PR tree-optimization/107107 + * gcc.dg/pr107107.c: New testcase. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/gomp/assume-4.c: New test. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + PR c++/106654 + * gcc.dg/attr-assume-1.c: New test. + * gcc.dg/attr-assume-2.c: New test. + * gcc.dg/attr-assume-3.c: New test. + * g++.dg/cpp2a/feat-cxx2a.C: Add colon to C++20 features + comment, add C++20 attributes comment and move C++20 + new features after the attributes before them. + * g++.dg/cpp23/feat-cxx2b.C: Likewise. Test + __has_cpp_attribute(assume). + * g++.dg/cpp23/attr-assume1.C: New test. + * g++.dg/cpp23/attr-assume2.C: New test. + * g++.dg/cpp23/attr-assume3.C: New test. + * g++.dg/cpp23/attr-assume4.C: New test. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107158 + * gcc.dg/analyzer/call-summaries-pr107158.c: New test. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107060 + * gcc.dg/analyzer/analyzer-decls.h (__analyzer_get_unknown_ptr): + New decl. + * gcc.dg/analyzer/call-summaries-2.c + (test_summarized_writes_param_to_ptr_unknown): New test. + +2022-10-05 Tobias Burnus <tobias@codesourcery.com> + + * gfortran.dg/gomp/assume-1.f90: New test. + * gfortran.dg/gomp/assume-2.f90: New test. + * gfortran.dg/gomp/assumes-1.f90: New test. + * gfortran.dg/gomp/assumes-2.f90: New test. + +2022-10-05 Ju-Zhe Zhong <juzhe.zhong@rivai.ai> + + * gcc.target/riscv/rvv/base/pragma-1.c: New test. + * gcc.target/riscv/rvv/base/pragma-2.c: New test. + * gcc.target/riscv/rvv/base/pragma-3.c: New test. + * gcc.target/riscv/rvv/base/user-1.c: New test. + * gcc.target/riscv/rvv/base/user-2.c: New test. + * gcc.target/riscv/rvv/base/user-3.c: New test. + * gcc.target/riscv/rvv/base/user-4.c: New test. + * gcc.target/riscv/rvv/base/user-5.c: New test. + * gcc.target/riscv/rvv/base/user-6.c: New test. + * gcc.target/riscv/rvv/base/vread_csr.c: New test. + * gcc.target/riscv/rvv/base/vwrite_csr.c: New test. + +2022-10-05 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/107052 + * gcc.dg/tree-ssa/pr107052.c: New file. + +2022-10-05 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/lto26.adb: New test. + * gnat.dg/lto26_pkg1.ads, gnat.dg/lto26_pkg1.adb: New helper. + * gnat.dg/lto26_pkg2.ads, gnat.dg/lto26_pkg2.adb: Likewise. + +2022-10-05 Martin Liska <mliska@suse.cz> + + PR tree-optimization/106679 + * gcc.dg/tree-prof/cmpsf-1.c: Mark as a known limitation. + +2022-10-05 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> + Yvan ROUX <yvan.roux@foss.st.com> + + * gcc.target/arm/stack-protector-1.c: Use 'bl' instead of 'b' + instruction. + * gcc.target/arm/stack-protector-3.c: Likewise. + +2022-10-05 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> + Yvan ROUX <yvan.roux@foss.st.com> + + * g++.dg/modules/bad-mapper-1.C: Also accept CreateProcess. + +2022-10-05 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> + Yvan ROUX <yvan.roux@foss.st.com> + + * gcc.misc-tests/outputs.exp: Use "@nul" for Windows, + "@/dev/null" for other environments. + +2022-10-05 Vineet Gupta <vineetg@rivosinc.com> + + * gcc.target/riscv/predef-1.c: Remove __riscv_cmodel_pic check. + * gcc.target/riscv/predef-2.c: Ditto. + * gcc.target/riscv/predef-3.c: Ditto. + * gcc.target/riscv/predef-4.c: Ditto. + * gcc.target/riscv/predef-5.c: Ditto. + * gcc.target/riscv/predef-6.c: Ditto. + * gcc.target/riscv/predef-7.c: Ditto. + * gcc.target/riscv/predef-8.c: Ditto. + +2022-10-05 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107072 + * gcc.dg/analyzer/call-summaries-2.c: New test. + * gcc.dg/analyzer/call-summaries-3.c: New test. + * gcc.dg/analyzer/call-summaries-asm-x86.c: New test. + * gcc.dg/analyzer/call-summaries-malloc.c: New test. + * gcc.dg/analyzer/call-summaries-pr107072.c: New test. + +2022-10-04 Jason Merrill <jason@redhat.com> + + PR c++/107154 + * g++.dg/debug/dwarf2/lineno-array1.C: New test. + +2022-10-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/pragma_cpp_predefs_1.c: Add RCPC tests. + +2022-10-04 Tobias Burnus <tobias@codesourcery.com> + + * gfortran.dg/gomp/openmp-simd-7.f90: New test. + +2022-10-04 Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/gomp/declare-target-4.c: Move tests that are now + rejected into declare-target-7.c. + * c-c++-common/gomp/declare-target-6.c: Adjust expected diagnostics. + * c-c++-common/gomp/declare-target-7.c: New test. + * c-c++-common/gomp/begin-declare-target-1.c: New test. + * c-c++-common/gomp/begin-declare-target-2.c: New test. + * c-c++-common/gomp/begin-declare-target-3.c: New test. + * c-c++-common/gomp/begin-declare-target-4.c: New test. + * g++.dg/gomp/attrs-9.C: Add begin declare target tests. + * g++.dg/gomp/attrs-18.C: New test. + +2022-10-04 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/107130 + * gcc.dg/tree-ssa/pr107130.c: New test. + +2022-10-04 Lewis Hyatt <lhyatt@gmail.com> + + PR c/91669 + * c-c++-common/pr91669.c: New test. + 2022-10-03 Torbjörn SVENSSON <torbjorn.svensson@foss.st.com> Yvan ROUX <yvan.roux@foss.st.com> diff --git a/gcc/testsuite/c-c++-common/gomp/assume-4.c b/gcc/testsuite/c-c++-common/gomp/assume-4.c new file mode 100644 index 0000000..9da2296 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/assume-4.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-times "return 42;" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-not "return -1;" "optimized" } } */ + +int +foo (int x) +{ + int y; + #pragma omp assume holds (x == 42) + y = x; + return y; +} + +int +bar (int x) +{ + #pragma omp assume holds (x < 42) + ; + if (x == 42) + return -1; + return 42; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/elision4.C b/gcc/testsuite/g++.dg/cpp0x/elision4.C new file mode 100644 index 0000000..3cc2e3a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/elision4.C @@ -0,0 +1,15 @@ +// PR c++/107085 +// { dg-do compile { target c++11 } } + +struct X { + X(); + X(X&&); +}; +struct Z : X {}; +X x1 = Z(); +X x2 = X(Z()); + +struct B { }; +struct D : B { }; +B b1 = D(); +B b2 = B(D()); diff --git a/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C b/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C new file mode 100644 index 0000000..b74323f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/fallthrough2.C @@ -0,0 +1,24 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-Wextra -Wall -Wpedantic" } + +int +foo (int i) +{ + switch (i) + { + case 2: + ++i; + [[fallthrough, whatever::fallthrough]]; // { dg-bogus "attribute 'fallthrough' specified multiple times" } + case 3: // { dg-warning "'fallthrough' attribute ignored" "" { target *-*-* } .-1 } + ++i; + [[fallthrough, whatever2::fallthrough(1, 2, 3)]]; // { dg-bogus "attribute 'fallthrough' specified multiple times" } + case 4: // { dg-warning "'fallthrough' attribute ignored" "" { target *-*-* } .-1 } + [[whatever3::fallthrough("abcd")]]; // { dg-warning "attributes at the beginning of statement are ignored" } + case 5: + [[whatever4::fallthrough]]; // { dg-bogus "attribute 'fallthrough' not preceding a case label or default label" } + ++i; // { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 } + default: + break; + } + return i; +} diff --git a/gcc/testsuite/g++.dg/cpp23/attr-assume1.C b/gcc/testsuite/g++.dg/cpp23/attr-assume1.C new file mode 100644 index 0000000..76b61e9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/attr-assume1.C @@ -0,0 +1,191 @@ +// P1774R8 - Portable assumptions +// { dg-do run { target c++11 } } + +namespace std +{ + constexpr bool + isfinite (float x) + { return __builtin_isfinite (x); } + + constexpr bool + isfinite (double x) + { return __builtin_isfinite (x); } + + constexpr bool + isfinite (long double x) + { return __builtin_isfinite (x); } + + constexpr float + sqrt (float x) + { return __builtin_sqrtf (x); } + + constexpr double + sqrt (double x) + { return __builtin_sqrt (x); } + + constexpr long double + sqrt (long double x) + { return __builtin_sqrtl (x); } + + extern "C" void + abort (); +} + +constexpr int +f1 (int i) +{ +#if __cpp_constexpr >= 201603L + auto f = [=] { [[assume (i == 0)]]; }; + return sizeof (f); +#else + return sizeof (int); +#endif +} + +void +f2 () +{ + static_assert (f1 (0) >= sizeof (int), ""); +} + +int +f3 (int i) +{ + [[assume (i == 42)]]; + return i; +} + +int +f4 (int i) +{ + [[assume (++i == 44)]]; + return i; +} + +int a; +int *volatile c; + +bool +f5 () +{ + ++a; + return true; +} + +constexpr int +f6 () +{ +#if __cpp_constexpr >= 201304L + [[assume (f5 ())]]; +#endif + return 1; +} + +template <int ...args> +bool +f7 () +{ +#if __cpp_fold_expressions >= 201411L + [[assume (((args >= 0) && ...))]]; + return ((args >= 0) && ...); +#else + return true; +#endif +} + +bool +f8 (double x) +{ + [[assume (std::isfinite (x) && x >= 0.0)]]; + return std::isfinite (std::sqrt (x)); +} + +double +f9 (double x) +{ + [[assume (std::isfinite (std::sqrt (x)))]]; + return std::sqrt (x); +} + +template <typename T, T N> +T +f10 (T x) +{ + [[assume (x == N)]]; + return x; +} + +int +f11 (int x) +{ + [[assume (x == 93 ? true : throw 1)]]; + return x; +} + +constexpr int +f12 (int x) +{ +#if __cpp_constexpr >= 201304L + [[assume (++x == 43)]]; +#endif + return x; +} + +static_assert (f12 (42) == 42, ""); + +struct S +{ + operator bool () { return true; } +}; + +int +f13 () +{ + S s; + [[assume (s)]]; + return 0; +} + +template <typename T> +int +f14 () +{ + T t; + [[assume (t)]]; + return 0; +} + +int +main () +{ + int b = 42; + double d = 42.0, e = 43.0; + c = &b; + [[assume (f5 ())]]; + if (a) + std::abort (); + [[assume (++b == 43)]]; + if (b != 42 || *c != 42) + std::abort (); + static_assert (f6 () == 1, ""); + if (f6 () != 1) + std::abort (); + if (a) + std::abort (); + if (!f7 <0> () || !f7 <1, 2, 3, 4> ()) + std::abort (); + [[assume (d < e)]]; + if (f10 <int, 45> (45) != 45 + || f10 <long long, 128LL> (128LL) != 128LL +#if __cpp_nontype_template_args >= 201911L + || f10 <long double, -42.0L> (-42.0L) != -42.0L +#endif + || false) + std::abort (); + int i = 90, j = 91, k = 92; + [[assume (i == 90), assume (j <= 91)]] [[assume (k >= 92)]]; + if (f11 (93) != 93) + std::abort (); + if (f14 <S> () != 0) + std::abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp23/attr-assume2.C b/gcc/testsuite/g++.dg/cpp23/attr-assume2.C new file mode 100644 index 0000000..9e54c14 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/attr-assume2.C @@ -0,0 +1,83 @@ +// P1774R8 - Portable assumptions +// { dg-do compile { target c++11 } } + +[[assume (true)]] void f1 (); // { dg-error "'assume' attribute ignored" } +typedef int intx [[assume (true)]]; // { dg-error "'assume' attribute ignored" } +[[assume (true)]]; // { dg-warning "attribute ignored" } + +void +foo () +{ + int i; + [[assume]]; // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 0" "" { target *-*-* } .-1 } + [[assume ()]]; // { dg-error "parentheses must be omitted if 'assume' attribute argument list is empty" } + // { dg-error "wrong number of arguments specified for 'assume' attribute" "" { target *-*-* } .-1 } + // { dg-message "expected 1, found 0" "" { target *-*-* } .-2 } + [[assume (true, true)]]; // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 2" "" { target *-*-* } .-1 } + [[assume (true)]] i = 1; // { dg-warning "'assume' attribute not followed by ';'" } + [[assume (throw 1)]]; // { dg-error "expected primary-expression before 'throw'" } + [[assume (i = 1)]]; // { dg-error "expected '\\\)' before '=' token" } +} + +constexpr int +f2 (int x) +{ +#if __cpp_constexpr >= 201304L + [[assume (x == 42)]]; // { dg-error "failed 'assume' attribute assumption" "" { target c++14 } } +#endif // { dg-message "the comparison reduces to '\\\(x == 42\\\)'" "" { target c++14 } .-1 } + return x; +} + +constexpr int a = f2 (44); + +int +f3 (int x) +{ + __asm ("" : "+r" (x)); + return x; +} + +constexpr int +f4 (int x) +{ +#if __cpp_constexpr >= 201304L + [[assume (f3 (42) == 42)]]; +#endif + return x; +} + +static_assert (f4 (42) == 42, ""); + +struct S {}; + +int +f5 () +{ + S s; + [[assume (s)]]; // { dg-error "could not convert 's' from 'S' to 'bool'" } + return 0; +} + +template <typename T> +int +f6 () +{ + T t; + [[assume (t)]]; // { dg-error "could not convert 't' from 'S' to 'bool'" } + return 0; +} + +int z = f6 <S> (); + +constexpr int +f7 (int x, int y, int z, int w) +{ +#if __cpp_constexpr >= 201304L + [[assume (x == 42 && y == 43 && z == 44 && w == 45)]]; // { dg-error "failed 'assume' attribute assumption" "" { target c++14 } } +#endif // { dg-message "the comparison reduces to '\\\(z == 44\\\)'" "" { target c++14 } .-1 } + return x; +} + +constexpr int w = f7 (42, 43, 45, 44); diff --git a/gcc/testsuite/g++.dg/cpp23/attr-assume3.C b/gcc/testsuite/g++.dg/cpp23/attr-assume3.C new file mode 100644 index 0000000..0be28c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/attr-assume3.C @@ -0,0 +1,198 @@ +// P1774R8 - Portable assumptions +// { dg-do run { target c++11 } } + +namespace std +{ + constexpr bool + isfinite (float x) + { return __builtin_isfinite (x); } + + constexpr bool + isfinite (double x) + { return __builtin_isfinite (x); } + + constexpr bool + isfinite (long double x) + { return __builtin_isfinite (x); } + + constexpr float + sqrt (float x) + { return __builtin_sqrtf (x); } + + constexpr double + sqrt (double x) + { return __builtin_sqrt (x); } + + constexpr long double + sqrt (long double x) + { return __builtin_sqrtl (x); } + + extern "C" void + abort (); +} + +constexpr int +f1 (int i) +{ +#if __cpp_constexpr >= 201603L + auto f = [=] { [[__assume__ (i == 0)]]; }; + return sizeof (f); +#else + return sizeof (int); +#endif +} + +void +f2 () +{ + static_assert (f1 (0) >= sizeof (int), ""); +} + +int +f3 (int i) +{ + [[gnu::assume (i == 42)]]; + return i; +} + +int +f4 (int i) +{ + __attribute__ ((assume (++i == 44))); + return i; +} + +int a; +int *volatile c; + +bool +f5 () +{ + ++a; + return true; +} + +constexpr int +f6 () +{ +#if __cpp_constexpr >= 201304L + [[__assume__ (f5 ())]]; +#endif + return 1; +} + +template <int ...args> +bool +f7 () +{ +#if __cpp_fold_expressions >= 201411L + [[__gnu__::__assume__ (((args >= 0) && ...))]]; + return ((args >= 0) && ...); +#else + return true; +#endif +} + +bool +f8 (double x) +{ + [[gnu::assume (std::isfinite (x) && x >= 0.0)]]; + return std::isfinite (std::sqrt (x)); +} + +double +f9 (double x) +{ + __attribute__((assume (std::isfinite (std::sqrt (x))))); + return std::sqrt (x); +} + +template <typename T, T N> +T +f10 (T x) +{ + [[__assume__ (x == N)]]; + return x; +} + +int +f11 (int x) +{ + [[gnu::assume (x == 93 ? true : throw 1)]]; + return x; +} + +constexpr int +f12 (int x) +{ +#if __cpp_constexpr >= 201304L + __attribute__((assume (++x == 43))); +#endif + return x; +} + +static_assert (f12 (42) == 42, ""); + +struct S +{ + operator bool () { return true; } +}; + +int +f13 () +{ + S s; + [[__gnu__::__assume__ (s)]]; + return 0; +} + +template <typename T> +int +f14 () +{ + T t; + __attribute__((assume (t))); + return 0; +} + +int +main () +{ + int b = 42; + double d = 42.0, e = 43.0; + c = &b; + [[__assume__ (f5 ())]]; + if (a) + std::abort (); + [[gnu::assume (++b == 43)]]; + if (b != 42 || *c != 42) + std::abort (); + static_assert (f6 () == 1, ""); + if (f6 () != 1) + std::abort (); + if (a) + std::abort (); + if (!f7 <0> () || !f7 <1, 2, 3, 4> ()) + std::abort (); + __attribute__((assume (d < e))); + if (f10 <int, 45> (45) != 45 + || f10 <long long, 128LL> (128LL) != 128LL +#if __cpp_nontype_template_args >= 201911L + || f10 <long double, -42.0L> (-42.0L) != -42.0L +#endif + || false) + std::abort (); + int i = 90, j = 91, k = 92; + [[__assume__ (i == 90), gnu::assume (j <= 91)]] +#if __cplusplus >= 201703L + [[using gnu:assume (k >= 92)]] +#else + [[gnu::assume (k >= 92)]] +#endif + ; + __attribute__((__assume__ (i == 90), assume (j <= 91))) __attribute__((assume (k >= 92))); + if (f11 (93) != 93) + std::abort (); + if (f14 <S> () != 0) + std::abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp23/attr-assume4.C b/gcc/testsuite/g++.dg/cpp23/attr-assume4.C new file mode 100644 index 0000000..059d47b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/attr-assume4.C @@ -0,0 +1,136 @@ +// P1774R8 - Portable assumptions +// { dg-do compile { target c++11 } } + +[[__assume__ (true)]] void f1 (); // { dg-error "'assume' attribute ignored" } +typedef int intx [[__assume__ (true)]]; // { dg-error "'assume' attribute ignored" } +[[__assume__ (true)]]; // { dg-warning "attribute ignored" } +[[gnu::assume (true)]] void f1a (); // { dg-error "'assume' attribute ignored" } +typedef int inty [[gnu::__assume__ (true)]]; // { dg-error "'assume' attribute ignored" } +[[__gnu__::assume (true)]]; // { dg-warning "attribute ignored" } +__attribute__((assume (true))) void f1b (); // { dg-error "'assume' attribute ignored" } +typedef int intz __attribute__((assume (true)));// { dg-error "'assume' attribute ignored" } + +void +foo () +{ + int i; + [[__assume__]]; // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 0" "" { target *-*-* } .-1 } + [[__assume__ ()]]; // { dg-error "parentheses must be omitted if 'assume' attribute argument list is empty" } + // { dg-error "wrong number of arguments specified for 'assume' attribute" "" { target *-*-* } .-1 } + // { dg-message "expected 1, found 0" "" { target *-*-* } .-2 } + [[__assume__ (true, true)]]; // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 2" "" { target *-*-* } .-1 } + [[__assume__ (true)]] i = 1; // { dg-warning "'assume' attribute not followed by ';'" } + [[__assume__ (throw 1)]]; // { dg-error "expected primary-expression before 'throw'" } + [[__assume__ (i = 1)]]; // { dg-error "expected '\\\)' before '=' token" } + [[gnu::assume]]; // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 0" "" { target *-*-* } .-1 } + [[gnu::assume ()]]; // { dg-error "parentheses must be omitted if 'assume' attribute argument list is empty" } + // { dg-error "wrong number of arguments specified for 'assume' attribute" "" { target *-*-* } .-1 } + // { dg-message "expected 1, found 0" "" { target *-*-* } .-2 } + [[gnu::assume (true, true)]]; // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 2" "" { target *-*-* } .-1 } + [[gnu::assume (true)]] i = 1; // { dg-warning "'assume' attribute not followed by ';'" } + [[gnu::assume (throw 1)]]; // { dg-error "expected primary-expression before 'throw'" } + [[gnu::assume (i = 1)]]; // { dg-error "expected '\\\)' before '=' token" } + __attribute__((assume)); // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 0" "" { target *-*-* } .-1 } + __attribute__((assume ())); // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 0" "" { target *-*-* } .-1 } + __attribute__((assume (true, true))); // { dg-error "wrong number of arguments specified for 'assume' attribute" } + // { dg-message "expected 1, found 2" "" { target *-*-* } .-1 } + __attribute__((assume (true))) i = 1; // { dg-warning "'assume' attribute not followed by ';'" } + __attribute__((assume (throw 1))); // { dg-error "expected primary-expression before 'throw'" } + __attribute__((assume (i = 1))); // { dg-error "expected '\\\)' before '=' token" } +} + +constexpr int +f2 (int x) +{ +#if __cpp_constexpr >= 201304L + [[__assume__ (x == 42)]]; // { dg-error "failed 'assume' attribute assumption" "" { target c++14 } } +#endif + return x; +} + +constexpr int +f2a (int x) +{ +#if __cpp_constexpr >= 201304L + [[gnu::__assume__ (x == 42)]]; // { dg-error "failed 'assume' attribute assumption" "" { target c++14 } } +#endif + return x; +} + +constexpr int +f2b (int x) +{ +#if __cpp_constexpr >= 201304L + __attribute__((__assume__ (x == 42)));// { dg-error "failed 'assume' attribute assumption" "" { target c++14 } } +#endif + return x; +} + +constexpr int a = f2 (44); +constexpr int aa = f2a (44); +constexpr int ab = f2b (44); + +int +f3 (int x) +{ + __asm ("" : "+r" (x)); + return x; +} + +constexpr int +f4 (int x) +{ +#if __cpp_constexpr >= 201304L + [[__assume__ (f3 (42) == 42)]]; +#endif + return x; +} + +constexpr int +f4a (int x) +{ +#if __cpp_constexpr >= 201304L + [[gnu::assume (f3 (42) == 42)]]; +#endif + return x; +} + +constexpr int +f4b (int x) +{ +#if __cpp_constexpr >= 201304L + __attribute__((assume (f3 (42) == 42))); +#endif + return x; +} + +static_assert (f4 (42) == 42, ""); +static_assert (f4a (42) == 42, ""); +static_assert (f4b (42) == 42, ""); + +struct S {}; + +int +f5 () +{ + S s; + [[gnu::assume (s)]]; // { dg-error "could not convert 's' from 'S' to 'bool'" } + return 0; +} + +template <typename T> +int +f6 () +{ + T t; + __attribute__((assume (t))); // { dg-error "could not convert 't' from 'S' to 'bool'" } + return 0; +} + +int z = f6 <S> (); diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C index b52cf37..efe9770 100644 --- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C +++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C @@ -422,7 +422,7 @@ # error "__cpp_nontype_template_parameter_auto != 201606" #endif -// C++20 features +// C++20 features: #ifndef __cpp_conditional_explicit # error "__cpp_conditional_explicit" @@ -460,6 +460,44 @@ # error "__cpp_aggregate_paren_init != 201902" #endif +#ifndef __cpp_char8_t +# error "__cpp_char8_t" +#elif __cpp_char8_t != 202207 +# error "__cpp_char8_t != 202207" +#endif + +#ifndef __cpp_designated_initializers +# error "__cpp_designated_initializers" +#elif __cpp_designated_initializers != 201707 +# error "__cpp_designated_initializers != 201707" +#endif + +#ifndef __cpp_constexpr_in_decltype +# error "__cpp_constexpr_in_decltype" +#elif __cpp_constexpr_in_decltype != 201711 +# error "__cpp_constexpr_in_decltype != 201711" +#endif + +#ifndef __cpp_consteval +# error "__cpp_consteval" +#elif __cpp_consteval != 201811 +# error "__cpp_consteval != 201811" +#endif + +#ifndef __cpp_concepts +# error "__cpp_concepts" +#elif __cpp_concepts != 202002 +# error "__cpp_concepts != 202002" +#endif + +#ifndef __cpp_using_enum +# error "__cpp_using_enum" +#elif __cpp_using_enum != 201907 +# error "__cpp_using_enum != 201907" +#endif + +// C++20 attributes: + #ifdef __has_cpp_attribute # if ! __has_cpp_attribute(maybe_unused) @@ -502,42 +540,6 @@ # error "__has_cpp_attribute" #endif -#ifndef __cpp_char8_t -# error "__cpp_char8_t" -#elif __cpp_char8_t != 202207 -# error "__cpp_char8_t != 202207" -#endif - -#ifndef __cpp_designated_initializers -# error "__cpp_designated_initializers" -#elif __cpp_designated_initializers != 201707 -# error "__cpp_designated_initializers != 201707" -#endif - -#ifndef __cpp_constexpr_in_decltype -# error "__cpp_constexpr_in_decltype" -#elif __cpp_constexpr_in_decltype != 201711 -# error "__cpp_constexpr_in_decltype != 201711" -#endif - -#ifndef __cpp_consteval -# error "__cpp_consteval" -#elif __cpp_consteval != 201811 -# error "__cpp_consteval != 201811" -#endif - -#ifndef __cpp_concepts -# error "__cpp_concepts" -#elif __cpp_concepts != 202002 -# error "__cpp_concepts != 202002" -#endif - -#ifndef __cpp_using_enum -# error "__cpp_using_enum" -#elif __cpp_using_enum != 201907 -# error "__cpp_using_enum != 201907" -#endif - // C++23 features: #ifndef __cpp_size_t_suffix @@ -575,3 +577,15 @@ #elif __cpp_implicit_move != 202207 # error "__cpp_implicit_move != 202207" #endif + +// C++23 attributes: + +#ifdef __has_cpp_attribute +# if ! __has_cpp_attribute(assume) +# error "__has_cpp_attribute(assume)" +# elif __has_cpp_attribute(assume) != 202207 +# error "__has_cpp_attribute(assume) != 202207" +# endif +#else +# error "__has_cpp_attribute" +#endif diff --git a/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C b/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C new file mode 100644 index 0000000..638a6d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/attr-likely7.C @@ -0,0 +1,38 @@ +// { dg-do compile { target c++20 } } +// { dg-additional-options -fdump-tree-gimple } +// { dg-final { scan-tree-dump-times "hot label" 5 "gimple" } } +// { dg-final { scan-tree-dump-times "cold label" 3 "gimple" } } + +bool b; + +template <class T> int f() +{ + if (b) + [[likely, whatever::unlikely ("abcd")]] return 0; // { dg-bogus "ignoring attribute 'unlikely' after earlier 'likely'" } + else // { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 } + [[unlikely, whatever2::hot]] flabel: return 1; // { dg-warning "'whatever2::hot' scoped attribute directive ignored" } + switch (b) + { + [[likely, whatever3::cold (1, 2, 3)]] case true: break; // { dg-warning "'whatever3::cold' scoped attribute directive ignored" } + }; + return 1; +} + +int main() +{ + if (b) + [[whatever4::unlikely (1), likely]] return 0; // { dg-bogus "ignoring attribute 'likely' after earlier 'unlikely'" } + else if (b) // { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 } + [[whatever5::hot, unlikely]] elabel: // { dg-warning "'whatever5::hot' scoped attribute directive ignored" } + return 1; + else + [[whatever6::cold, likely]] b = false; // { dg-bogus "ignoring attribute 'likely' after earlier 'cold'" } + // { dg-warning "attributes at the beginning of statement are ignored" "" { target *-*-* } .-1 } + f<int>(); + + switch (b) + { + [[whatever7::unlikely (1), likely]] case true: break; // { dg-warning "'whatever7::unlikely' scoped attribute directive ignored" } + [[whatever8::unlikely, unlikely]] case false: break; // { dg-bogus "attribute 'unlikely' specified multiple times" } + }; // { dg-warning "'whatever8::unlikely' scoped attribute directive ignored" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C index 02f3a37..16bc0b8 100644 --- a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C +++ b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C @@ -422,7 +422,7 @@ # error "__cpp_nontype_template_parameter_auto != 201606" #endif -// C++20 features +// C++20 features: #ifndef __cpp_conditional_explicit # error "__cpp_conditional_explicit" @@ -460,6 +460,44 @@ # error "__cpp_aggregate_paren_init != 201902" #endif +#ifndef __cpp_char8_t +# error "__cpp_char8_t" +#elif __cpp_char8_t != 202207 +# error "__cpp_char8_t != 202207" +#endif + +#ifndef __cpp_designated_initializers +# error "__cpp_designated_initializers" +#elif __cpp_designated_initializers != 201707 +# error "__cpp_designated_initializers != 201707" +#endif + +#ifndef __cpp_constexpr_in_decltype +# error "__cpp_constexpr_in_decltype" +#elif __cpp_constexpr_in_decltype != 201711 +# error "__cpp_constexpr_in_decltype != 201711" +#endif + +#ifndef __cpp_consteval +# error "__cpp_consteval" +#elif __cpp_consteval != 201811 +# error "__cpp_consteval != 201811" +#endif + +#ifndef __cpp_concepts +# error "__cpp_concepts" +#elif __cpp_concepts != 202002 +# error "__cpp_concepts != 202002" +#endif + +#ifndef __cpp_using_enum +# error "__cpp_using_enum" +#elif __cpp_using_enum != 201907 +# error "__cpp_using_enum != 201907" +#endif + +// C++20 attributes: + #ifdef __has_cpp_attribute # if ! __has_cpp_attribute(maybe_unused) @@ -501,39 +539,3 @@ #else # error "__has_cpp_attribute" #endif - -#ifndef __cpp_char8_t -# error "__cpp_char8_t" -#elif __cpp_char8_t != 202207 -# error "__cpp_char8_t != 202207" -#endif - -#ifndef __cpp_designated_initializers -# error "__cpp_designated_initializers" -#elif __cpp_designated_initializers != 201707 -# error "__cpp_designated_initializers != 201707" -#endif - -#ifndef __cpp_constexpr_in_decltype -# error "__cpp_constexpr_in_decltype" -#elif __cpp_constexpr_in_decltype != 201711 -# error "__cpp_constexpr_in_decltype != 201711" -#endif - -#ifndef __cpp_consteval -# error "__cpp_consteval" -#elif __cpp_consteval != 201811 -# error "__cpp_consteval != 201811" -#endif - -#ifndef __cpp_concepts -# error "__cpp_concepts" -#elif __cpp_concepts != 202002 -# error "__cpp_concepts != 202002" -#endif - -#ifndef __cpp_using_enum -# error "__cpp_using_enum" -#elif __cpp_using_enum != 201907 -# error "__cpp_using_enum != 201907" -#endif diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/lineno-array1.C b/gcc/testsuite/g++.dg/debug/dwarf2/lineno-array1.C new file mode 100644 index 0000000..befac5f --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/lineno-array1.C @@ -0,0 +1,25 @@ +// PR c++/107154 +// { dg-do compile { target c++11 } } +// { dg-additional-options "-gno-as-loc-support -dA" } +// Test that we emit debug info exactly once for the last line. +// { dg-final { scan-assembler-times {:25:1} 1 } } + +bool dummy; + +struct S { + const char *p; + S(const char *p): p(p) {} + ~S() { dummy = true; } +}; + +using Sar = S[]; + +struct X { + X(Sar&&) { } +}; + +int main() +{ + X x(Sar{"", ""}); + return 0; +} diff --git a/gcc/testsuite/g++.dg/ext/reference_constructs_from_temporary1.C b/gcc/testsuite/g++.dg/ext/reference_constructs_from_temporary1.C index 76de905..5354b1d 100644 --- a/gcc/testsuite/g++.dg/ext/reference_constructs_from_temporary1.C +++ b/gcc/testsuite/g++.dg/ext/reference_constructs_from_temporary1.C @@ -201,7 +201,7 @@ SA(!__reference_constructs_from_temporary(const int&, H)); SA(!__reference_constructs_from_temporary(int&&, G2)); SA(!__reference_constructs_from_temporary(const int&, H2)); -SA(!__reference_constructs_from_temporary(const Base&, Der)); +SA(__reference_constructs_from_temporary(const Base&, Der)); // This fails because std::is_constructible_v<int&&, id<int[3]>> is false. SA(!__reference_constructs_from_temporary(int&&, id<int[3]>)); diff --git a/gcc/testsuite/g++.dg/ext/reference_converts_from_temporary1.C b/gcc/testsuite/g++.dg/ext/reference_converts_from_temporary1.C index 90196c3..e6c159e 100644 --- a/gcc/testsuite/g++.dg/ext/reference_converts_from_temporary1.C +++ b/gcc/testsuite/g++.dg/ext/reference_converts_from_temporary1.C @@ -201,7 +201,7 @@ SA( __reference_converts_from_temporary(const int&, H)); SA(!__reference_converts_from_temporary(int&&, G2)); SA(!__reference_converts_from_temporary(const int&, H2)); -SA(!__reference_converts_from_temporary(const Base&, Der)); +SA(__reference_converts_from_temporary(const Base&, Der)); // This fails because std::is_constructible_v<int&&, id<int[3]>> is false. SA(!__reference_converts_from_temporary(int&&, id<int[3]>)); diff --git a/gcc/testsuite/g++.dg/init/elide9.C b/gcc/testsuite/g++.dg/init/elide9.C new file mode 100644 index 0000000..810d60a --- /dev/null +++ b/gcc/testsuite/g++.dg/init/elide9.C @@ -0,0 +1,25 @@ +// The static_cast should prevent temporary elision. +// { dg-do run { target c++11 } } + +int d; +struct A +{ + int i; + A() { } + ~A() { ++d; } +}; + +A f() { return A(); } + +struct B +{ + A a; + B(): a(static_cast<A&&>(f())) {} +}; + +int main() +{ + { B b; } + if (d != 2) + return -1; +} diff --git a/gcc/testsuite/g++.dg/modules/bad-mapper-1.C b/gcc/testsuite/g++.dg/modules/bad-mapper-1.C index 6d0ed4b..4b23128 100644 --- a/gcc/testsuite/g++.dg/modules/bad-mapper-1.C +++ b/gcc/testsuite/g++.dg/modules/bad-mapper-1.C @@ -1,6 +1,6 @@ // { dg-additional-options "-fmodules-ts -fmodule-mapper=|this-will-not-work" } import unique1.bob; -// { dg-error "-:failed exec.*mapper.* .*this-will-not-work" "" { target { ! { *-*-darwin[89]* *-*-darwin10* } } } 0 } +// { dg-error "-:failed (exec|CreateProcess).*mapper.* .*this-will-not-work" "" { target { ! { *-*-darwin[89]* *-*-darwin10* } } } 0 } // { dg-prune-output "fatal error:" } // { dg-prune-output "failed to read" } // { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/modules/bfield-3.H b/gcc/testsuite/g++.dg/modules/bfield-3.H new file mode 100644 index 0000000..4fd4db7 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/bfield-3.H @@ -0,0 +1,8 @@ +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +template<int N> +struct A { + int x : 1; + int y : N; +}; diff --git a/gcc/testsuite/g++.dg/modules/indirect-3_b.C b/gcc/testsuite/g++.dg/modules/indirect-3_b.C index 5bdfc1d..038b01e 100644 --- a/gcc/testsuite/g++.dg/modules/indirect-3_b.C +++ b/gcc/testsuite/g++.dg/modules/indirect-3_b.C @@ -23,7 +23,7 @@ namespace bar // { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::TPL'@'foo' section} module } } // { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } } -// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::TPL<0x0>'\n \[1\]=specialization declaration '::foo@foo:.::TPL<0x0>::TPL<0x0>'\n( \[.\]=[^\n]* '\n)* \[.\]=decl definition '::foo@foo:.::TPL<0x0>::frob<0x0>'\n} module } } +// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::TPL<0x0>'\n \[1\]=specialization definition '::foo@foo:.::TPL<0x0>::frob<0x0>'\n \[2\]=specialization declaration '::foo@foo:.::TPL<0x0>::TPL<0x0>'} module } } // { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::X@foo:.::frob<0x0>'} module } } // { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::TPL<0x0>'} module } } diff --git a/gcc/testsuite/g++.dg/modules/static-2_a.H b/gcc/testsuite/g++.dg/modules/static-2_a.H new file mode 100644 index 0000000..65c7619 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/static-2_a.H @@ -0,0 +1,8 @@ +// PR c++/104433 +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +inline int* f() { + static int y; + return &y; +} diff --git a/gcc/testsuite/g++.dg/modules/static-2_b.C b/gcc/testsuite/g++.dg/modules/static-2_b.C new file mode 100644 index 0000000..bfd35b0 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/static-2_b.C @@ -0,0 +1,9 @@ +// PR c++/104433 +// { dg-additional-options -fmodules-ts } +// { dg-do link } + +import "static-2_a.H"; + +int main() { + f(); +} diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-8_a.H b/gcc/testsuite/g++.dg/modules/tpl-spec-8_a.H new file mode 100644 index 0000000..5309130 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/tpl-spec-8_a.H @@ -0,0 +1,10 @@ +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +template<class T> +struct A { + static void f() { T::nonexistent; } +}; + +template<> +inline void A<int>::f() { } diff --git a/gcc/testsuite/g++.dg/modules/tpl-spec-8_b.C b/gcc/testsuite/g++.dg/modules/tpl-spec-8_b.C new file mode 100644 index 0000000..f23eb37 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/tpl-spec-8_b.C @@ -0,0 +1,8 @@ +// { dg-additional-options -fmodules-ts } +// { dg-do link } + +import "tpl-spec-8_a.H"; + +int main() { + A<int>::f(); +} diff --git a/gcc/testsuite/g++.dg/strict-flex-array-1.C b/gcc/testsuite/g++.dg/strict-flex-array-1.C new file mode 100644 index 0000000..92fcffe --- /dev/null +++ b/gcc/testsuite/g++.dg/strict-flex-array-1.C @@ -0,0 +1,31 @@ +/* testing the correct usage of attribute strict_flex_array. */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + + +int x __attribute__ ((strict_flex_array (1))); /* { dg-error "'strict_flex_array' attribute may not be specified for 'x'" } */ + +struct trailing { + int a; + int c __attribute ((strict_flex_array)); /* { dg-error "wrong number of arguments specified for 'strict_flex_array' attribute" } */ +}; + +struct trailing_1 { + int a; + int b; + int c __attribute ((strict_flex_array (2))); /* { dg-error "'strict_flex_array' attribute may not be specified for a non-array field" } */ +}; + +extern int d; + +struct trailing_array_2 { + int a; + int b; + int c[1] __attribute ((strict_flex_array (d))); /* { dg-error "'strict_flex_array' attribute argument not an integer" } */ +}; + +struct trailing_array_3 { + int a; + int b; + int c[0] __attribute ((strict_flex_array (5))); /* { dg-error "'strict_flex_array' attribute argument '5' is not an integer constant between 0 and 3" } */ +}; diff --git a/gcc/testsuite/gcc.c-torture/execute/20221006-1.c b/gcc/testsuite/gcc.c-torture/execute/20221006-1.c new file mode 100644 index 0000000..80deb3a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20221006-1.c @@ -0,0 +1,29 @@ +#include <stdlib.h> + +int +main (int argc, char** argv) +{ + const int len = argc == 2 ? atoi(argv[1]) : 4; + + int count; + int data[64]; + int M1[len][len]; + int M2[len][len]; + + for (int i = 0; i < len; i++) + for (int j = 0 ; j < len ; j++) + M1[i][j] = M2[i][j] = i*len + j; + + M2[1][0] = M2[0][1]; + + /* This writes successively 0 and 1 into data[M2[0][1]]. */ + for (int i = 0; i < len - 1; i++) + for (int j = 0 ; j < len ; j++) + if (M1[i+1][j] > M1[i][j]) + data[M2[i][j]] = i; + + if (data [M2[0][1]] != 1) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h b/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h index d052579..4478d74 100644 --- a/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h +++ b/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h @@ -47,4 +47,7 @@ extern void __analyzer_dump_state (const char *name, ...); truthfulness of the argument. */ extern void __analyzer_eval (int); +/* Obtain an "unknown" void *. */ +extern void *__analyzer_get_unknown_ptr (void); + #endif /* #ifndef ANALYZER_DECLS_H. */ diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c new file mode 100644 index 0000000..85cece7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c @@ -0,0 +1,653 @@ +/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */ + +/* There need to be at least two calls to a function for the + call-summarization code to be used. + TODO: add some kind of test that summarization *was* used. */ + +#include <stdlib.h> +#include "analyzer-decls.h" + +extern int external_fn (void *); + +int returns_const (void) +{ + return 42; +} + +void test_summarized_returns_const (void) +{ + __analyzer_eval (returns_const () == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_const () == 42); /* { dg-warning "TRUE" } */ +} + +void test_summarized_returns_const_2 (void) +{ + returns_const (); /* { dg-message "when 'returns_const' returns" } */ + __analyzer_dump_path (); /* { dg-message "path" } */ +} + +int returns_param (int i) +{ + return i; +} + +void test_summarized_returns_param (int j) +{ + __analyzer_eval (returns_param (j) == j); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_param (j) == j); /* { dg-warning "TRUE" } */ +} + +void writes_const_to_ptr (int *p) +{ + *p = 42; +} + +void test_summarized_writes_const_to_ptr (void) +{ + int i, j; + writes_const_to_ptr (&i); + writes_const_to_ptr (&j); + __analyzer_eval (i == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (j == 42); /* { dg-warning "TRUE" } */ +} + +// TODO: we should complain about this: + +void test_summarized_write_through_null (void) +{ + writes_const_to_ptr (NULL); +} + +void writes_param_to_ptr (int i, int *p) +{ + *p = i; +} + +void test_summarized_writes_param_to_ptr (int j) +{ + int x, y; + writes_param_to_ptr (j, &x); + writes_param_to_ptr (j, &y); + __analyzer_eval (x == j); /* { dg-warning "TRUE" } */ + __analyzer_eval (y == j); /* { dg-warning "TRUE" } */ +} + +void test_summarized_writes_param_to_ptr_unknown (int j) +{ + int *p = (int *)__analyzer_get_unknown_ptr (); + writes_param_to_ptr (j, p); + __analyzer_eval (*p == j); /* { dg-warning "UNKNOWN" } */ +} + +int g; + +void writes_to_global (int i) +{ + g = i; +} + +void test_writes_to_global (int x, int y) +{ + writes_to_global (x); + __analyzer_eval (g == x); /* { dg-warning "TRUE" } */ + + writes_to_global (y); + __analyzer_eval (g == y); /* { dg-warning "TRUE" } */ +} + +int reads_from_global (void) +{ + return g; +} + +void test_reads_from_global (int x, int y) +{ + g = x; + __analyzer_eval (reads_from_global () == x); /* { dg-warning "TRUE" } */ + + g = y; + __analyzer_eval (reads_from_global () == y); /* { dg-warning "TRUE" } */ +} + +/* Example of a unary op. */ + +int returns_negation (int i) +{ + return -i; +} + +void test_returns_negation (int x) +{ + __analyzer_eval (returns_negation (5) == -5); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_negation (x) == -x); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_negation (-x) == x); /* { dg-warning "TRUE" } */ +} + +/* Example of a binary op. */ + +int returns_sum (int i, int j) +{ + return i + j; +} + +void test_returns_sum (int x, int y) +{ + __analyzer_eval (returns_sum (5, 3) == 8); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_sum (7, 2) == 9); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_sum (x, y) == x + y); /* { dg-warning "TRUE" } */ +} + +struct coord +{ + int x; + int y; +}; + +struct coord make_coord (int x, int y) +{ + struct coord result = {x, y}; + return result; +} + +void test_make_coord (int i, int j) +{ + struct coord c1 = make_coord (3, 4); + __analyzer_eval (c1.x == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (c1.y == 4); /* { dg-warning "TRUE" } */ + + struct coord c2 = make_coord (i, j); + __analyzer_eval (c2.x == i); /* { dg-warning "TRUE" } */ + __analyzer_eval (c2.y == j); /* { dg-warning "TRUE" } */ +} + +/* Example of nested usage of summaries. */ + +struct rect +{ + struct coord nw; + struct coord se; +}; + +struct rect make_rect (int top, int bottom, int left, int right) +{ + struct rect result = {make_coord (left, top), + make_coord (right, bottom)}; + return result; +} + +void test_make_rect (int top, int bottom, int left, int right) +{ + struct rect r1 = make_rect (3, 4, 5, 6); + __analyzer_eval (r1.nw.y == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (r1.se.y == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (r1.nw.x == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (r1.se.x == 6); /* { dg-warning "TRUE" } */ + + struct rect r2 = make_rect (top, bottom, left, right); + __analyzer_eval (r2.nw.y == top); /* { dg-warning "TRUE" } */ + __analyzer_eval (r2.se.y == bottom); /* { dg-warning "TRUE" } */ + __analyzer_eval (r2.nw.x == left); /* { dg-warning "TRUE" } */ + __analyzer_eval (r2.se.x == right); /* { dg-warning "TRUE" } */ +} + +const char *returns_str (void) +{ + return "abc"; +} + +void test_returns_str (void) +{ + __analyzer_eval (returns_str () != NULL); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_str ()[0] == 'a'); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_str ()[1] == 'b'); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_str ()[2] == 'c'); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_str ()[3] == '\0'); /* { dg-warning "TRUE" } */ +} + +int returns_field (struct coord *p) +{ + return p->y; +} + +void test_returns_field (struct coord *q) +{ + __analyzer_eval (returns_field (q) == q->y); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_field (q) == q->y); /* { dg-warning "TRUE" } */ +} + +void writes_to_fields (struct coord *p, int x, int y) +{ + p->x = x; + p->y = y; +} + +void test_writes_to_field (struct coord *q, int qx, int qy) +{ + struct coord a, b; + writes_to_fields (&a, 1, 2); + __analyzer_eval (a.x == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (a.y == 2); /* { dg-warning "TRUE" } */ + writes_to_fields (&b, 3, 4); + __analyzer_eval (b.x == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (b.y == 4); /* { dg-warning "TRUE" } */ + writes_to_fields (q, qx, qy); + __analyzer_eval (q->x == qx); /* { dg-warning "TRUE" } */ + __analyzer_eval (q->y == qy); /* { dg-warning "TRUE" } */ +} + +/* Example of nested function summarization. */ + +int get_min_x (struct rect *p) +{ + return p->nw.x; +} + +int get_min_y (struct rect *p) +{ + return p->nw.y; +} + +int get_max_x (struct rect *p) +{ + return p->se.x; +} + +int get_max_y (struct rect *p) +{ + return p->se.y; +} + +int get_area (struct rect *p) +{ + return ((get_max_x (p) - get_min_x (p)) + * (get_max_y (p) - get_min_y (p))); +} + +void test_get_area (int top, int bottom, int left, int right, struct rect *p) +{ + { + /* 1x1 at origin. */ + struct rect a = make_rect (0, 1, 0, 1); + __analyzer_eval (get_min_y (&a) == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_max_y (&a) == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_min_x (&a) == 0); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_max_x (&a) == 1); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_area (&a) == 1); /* { dg-warning "TRUE" } */ + } + + { + /* 4x5. */ + struct rect b = make_rect (3, 7, 4, 9); + __analyzer_eval (get_min_y (&b) == 3); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_max_y (&b) == 7); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_min_x (&b) == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_max_x (&b) == 9); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_area (&b) == 20); /* { dg-warning "TRUE" } */ + } + + { + /* Symbolic. */ + struct rect c = make_rect (top, bottom, left, right); + __analyzer_eval (get_min_y (&c) == top); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_max_y (&c) == bottom); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_min_x (&c) == left); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_max_x (&c) == right); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_area (&c) == ((right - left) * (bottom - top))); /* { dg-warning "TRUE" } */ + } + + /* Symbolic via ptr. */ + __analyzer_eval (get_min_y (p) == p->nw.y); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_max_y (p) == p->se.y); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_min_x (p) == p->nw.x); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_max_x (p) == p->se.x); /* { dg-warning "TRUE" } */ + __analyzer_eval (get_area (p) == ((p->se.x - p->nw.x) * (p->se.y - p->nw.y))); /* { dg-warning "TRUE" } */ +} + +int returns_element (int i) +{ + static const int arr[3] = {7, 8, 9}; + return arr[i]; +} + +void test_returns_element (int j) +{ + __analyzer_eval (returns_element (0) == 7); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_element (1) == 8); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_element (2) == 9); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_element (3) == 10); /* { dg-warning "UNKNOWN" } */ + // TODO: out of bounds +} + +const int *returns_element_ptr (int i) +{ + static const int arr[3] = {7, 8, 9}; + return &arr[i]; +} + +int test_returns_element_ptr (int j) +{ + __analyzer_eval (*returns_element_ptr (0) == 7); /* { dg-warning "TRUE" } */ + __analyzer_eval (*returns_element_ptr (1) == 8); /* { dg-warning "TRUE" } */ + __analyzer_eval (*returns_element_ptr (2) == 9); /* { dg-warning "TRUE" } */ + return *returns_element_ptr (3); /* { dg-warning "buffer overread" } */ +} + +int returns_offset (int arr[3], int i) +{ + return arr[i]; +} + +void test_returns_offset (int outer_arr[3], int idx) +{ + int a[3] = {4, 5, 6}; + __analyzer_eval (returns_offset (a, 0) == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset (a, 1) == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset (a, 2) == 6); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset (a, idx) == a[idx]); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_offset (outer_arr, 0) == outer_arr[0]); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset (outer_arr, idx) == outer_arr[idx]); /* { dg-warning "TRUE" } */ +} + +int returns_offset_2 (int arr[], int i) +{ + return arr[i]; +} + +void test_returns_offset_2 (int outer_arr[], int idx) +{ + int a[3] = {4, 5, 6}; + __analyzer_eval (returns_offset_2 (a, 0) == 4); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset_2 (a, 1) == 5); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset_2 (a, 2) == 6); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset_2 (a, idx) == a[idx]); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_offset_2 (outer_arr, 0) == outer_arr[0]); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset_2 (outer_arr, idx) == outer_arr[idx]); /* { dg-warning "TRUE" } */ +} + +int returns_offset_3 (int *p, int i) +{ + return p[i]; +} + +void test_returns_offset_3 (int *q, int j) +{ + __analyzer_eval (returns_offset_3 (q, j) == q[j]); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_offset_3 (q, j) == q[j]); /* { dg-warning "TRUE" } */ +} + +/* With state merging, this is summarized as returning "UNKNOWN". */ + +int two_outcomes (int flag, int x, int y) +{ + if (flag) + return x; + else + return y; +} + +void test_two_outcomes (int outer_flag, int a, int b) +{ + int r; + __analyzer_eval (two_outcomes (1, a, b) == a); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (two_outcomes (0, a, b) == b); /* { dg-warning "UNKNOWN" } */ + r = two_outcomes (outer_flag, a, b); + if (outer_flag) + __analyzer_eval (r == a); /* { dg-warning "UNKNOWN" } */ + else + __analyzer_eval (r == b); /* { dg-warning "UNKNOWN" } */ +} + +/* Verify that summary replays capture postconditions. */ + +void check_int_nonnegative (int i) +{ + if (i < 0) + __builtin_unreachable (); +} + +void test_check_int_nonnegative (int i, int j) +{ + __analyzer_eval (i >= 0); /* { dg-warning "UNKNOWN" } */ + check_int_nonnegative (i); + __analyzer_eval (i >= 0); /* { dg-warning "TRUE" } */ + + __analyzer_eval (j >= 0); /* { dg-warning "UNKNOWN" } */ + check_int_nonnegative (j); + __analyzer_eval (j >= 0); /* { dg-warning "TRUE" } */ +} + +void calls_external_fn (void) +{ + external_fn (NULL); +} + +void test_calls_external_fn (void) +{ + g = 1; + __analyzer_eval (g == 1); /* { dg-warning "TRUE" } */ + calls_external_fn (); + calls_external_fn (); + __analyzer_eval (g == 1); /* { dg-warning "UNKNOWN" "expected" { xfail *-*-* } } */ + /* { dg-bogus "TRUE" "bogus" { xfail *-*-* } .-1 } */ + // TODO(xfails) +} + +int returns_iterator (int n) +{ + int i; + for (i = 0; i < n; i++) + { + } + return i; +} + +void test_returns_iterator (int j, int k) +{ + __analyzer_eval (returns_iterator (j) == j); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_iterator (k) == k); /* { dg-warning "UNKNOWN" } */ + /* TODO: ideally we'd capture these equalities, but this is an issue + with how we handle loops. */ +} + +int returns_external_result (void) +{ + return external_fn (NULL); +} + +int test_returns_external_result (void) +{ + int i, j; + i = returns_external_result (); + j = returns_external_result (); + __analyzer_eval (i == j); /* { dg-warning "UNKNOWN" } */ + return i * j; +} + +int uses_alloca (int i) +{ + int *p = alloca (sizeof (int)); + *p = i; + return *p; +} + +void test_uses_alloca (int x) +{ + __analyzer_eval (uses_alloca (42) == 42); /* { dg-warning "TRUE" } */ + __analyzer_eval (uses_alloca (x) == x); /* { dg-warning "TRUE" } */ +} + +struct bits +{ + unsigned b0 : 1; + unsigned b1 : 1; + unsigned b2 : 1; + unsigned b3 : 1; + unsigned b4 : 1; + unsigned b5 : 1; + unsigned b6 : 1; + unsigned b7 : 1; +}; + +int returns_bitfield (struct bits b) +{ + return b.b3; +} + +void test_returns_bitfield (struct bits s) +{ + __analyzer_eval (returns_bitfield (s) == s.b3); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_bitfield (s) == s.b3); /* { dg-warning "UNKNOWN" } */ + // TODO: ideally it would figure out that these are equal +} + +int consume_two_ints_from_va_list (__builtin_va_list ap) +{ + int i, j; + i = __builtin_va_arg (ap, int); + j = __builtin_va_arg (ap, int); + return i * j; +} + +int test_consume_two_ints_from_va_list (__builtin_va_list ap1) +{ + int p1, p2; + __builtin_va_list ap2; + __builtin_va_copy (ap2, ap1); + p1 = consume_two_ints_from_va_list (ap1); + p2 = consume_two_ints_from_va_list (ap2); + __analyzer_eval (p1 == p2); /* { dg-warning "UNKNOWN" } */ + // TODO: ideally it would figure out these are equal + __builtin_va_end (ap2); +} + +int consume_two_ints_from_varargs (int placeholder, ...) +{ + int i, j; + __builtin_va_list ap; + __builtin_va_start (ap, placeholder); + i = __builtin_va_arg (ap, int); + j = __builtin_va_arg (ap, int); + __builtin_va_end (ap); + return i * j; +} + +void test_consume_two_ints_from_varargs (int x, int y) +{ + __analyzer_eval (consume_two_ints_from_varargs (0, 4, 5) == 20); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (consume_two_ints_from_varargs (0, 3, 6) == 18); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (consume_two_ints_from_varargs (0, x, 6) == x * y); /* { dg-warning "UNKNOWN" } */ + // TODO: ideally it would figure these out +} + +extern int const_fn_1 (int) __attribute__ ((const)); +int calls_const_fn (int i) +{ + return const_fn_1 (i); +} + +void test_calls_const_fn (int x) +{ + int r1, r2; + r1 = calls_const_fn (x); + r2 = calls_const_fn (x); + __analyzer_eval (r1 == r2); /* { dg-warning "TRUE" } */ +} + +typedef struct iv2 { int arr[2]; } iv2_t; +typedef struct iv4 { int arr[4]; } iv4_t; + +iv2_t returns_iv2_t (int x, int y) +{ + iv2_t result = {x, y}; + return result; +} + +void test_returns_iv2_t (int a, int b) +{ + __analyzer_eval (returns_iv2_t (a, b).arr[0] == a); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_iv2_t (a, b).arr[1] == b); /* { dg-warning "TRUE" } */ +} + +iv4_t returns_iv4_t (int a, iv2_t bc, int d) +{ + iv4_t result = {a, bc.arr[0], bc.arr[1], d}; + return result; +} + +void test_returns_iv4_t (int p, iv2_t qr, int s) +{ + __analyzer_eval (returns_iv4_t (p, qr, s).arr[0] == p); /* { dg-warning "TRUE" } */ + __analyzer_eval (returns_iv4_t (p, qr, s).arr[1] == qr.arr[0]); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_iv4_t (p, qr, s).arr[2] == qr.arr[1]); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_iv4_t (p, qr, s).arr[3] == s); /* { dg-warning "TRUE" } */ + // TODO: ideally the UNKNOWNs would be TRUEs. +} + +void copies_iv2_t (int *p, iv2_t xy) +{ + __builtin_memcpy (p, &xy, sizeof (xy)); +} + +void test_copies_iv2_t (iv2_t ab, iv2_t cd) +{ + iv4_t t; + copies_iv2_t (&t.arr[0], ab); + copies_iv2_t (&t.arr[2], cd); + __analyzer_eval (t.arr[0] = ab.arr[0]); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (t.arr[1] = ab.arr[1]); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (t.arr[2] = cd.arr[0]); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (t.arr[3] = cd.arr[1]); /* { dg-warning "UNKNOWN" } */ + // TODO: ideally the UNKNOWNs would be TRUEs. +} + +void partially_inits (int *p, int v) +{ + p[1] = v; +} + +void test_partially_inits (int x) +{ + int arr[2]; + partially_inits (arr, x); + partially_inits (arr, x); + + __analyzer_eval (arr[0]); /* { dg-warning "UNKNOWN" "eval" } */ + /* { dg-warning "use of uninitialized value 'arr\\\[0\\\]'" "uninit" { target *-*-* } .-1 } */ + + __analyzer_eval (arr[1] == x); /* { dg-warning "UNKNOWN" "eval" } */ + /* { dg-bogus "use of uninitialized value 'arr\\\[1\\\]'" "uninit" { xfail *-*-* } .-1 } */ + // TODO(xfail), and eval should be "TRUE" +} + +int uses_switch (int i) +{ + switch (i) + { + case 0: + return 42; + case 1: + return 17; + default: + return i * 2; + } +} + +void test_uses_switch (int x) +{ + __analyzer_eval (uses_switch (0) == 42); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (uses_switch (1) == 17); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (uses_switch (2) == x * 2); /* { dg-warning "UNKNOWN" } */ + // TODO: ideally the UNKNOWNs would be TRUEs. +} + +int *returns_ptr_to_first_field (struct coord *p) +{ + return &p->x; +} + +void test_returns_ptr_to_first_field (struct coord *q) +{ + __analyzer_eval (returns_ptr_to_first_field (q) == (int *)q); /* { dg-warning "UNKNOWN" } */ + __analyzer_eval (returns_ptr_to_first_field (q) == (int *)q); /* { dg-warning "UNKNOWN" } */ + // TODO: ideally the UNKNOWNs would be TRUEs. +} diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-3.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-3.c new file mode 100644 index 0000000..d63eb0c --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-3.c @@ -0,0 +1,29 @@ +/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0 -fno-analyzer-state-merge" } */ + +/* There need to be at least two calls to a function for the + call-summarization code to be used. + TODO: add some kind of test that summarization *was* used. */ + +#include "analyzer-decls.h" + +/* With state merging disabled, we get two summaries here. */ + +int two_outcomes (int flag, int x, int y) +{ + if (flag) + return x; + else + return y; +} + +void test_two_outcomes (int outer_flag, int a, int b) +{ + int r; + __analyzer_eval (two_outcomes (1, a, b) == a); /* { dg-warning "TRUE" } */ + __analyzer_eval (two_outcomes (0, a, b) == b); /* { dg-warning "TRUE" } */ + r = two_outcomes (outer_flag, a, b); + if (outer_flag) + __analyzer_eval (r == a); /* { dg-warning "TRUE" } */ + else + __analyzer_eval (r == b); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-asm-x86.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-asm-x86.c new file mode 100644 index 0000000..cc23283 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-asm-x86.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */ + +#include "analyzer-decls.h" + +int returns_asm_value (void) +{ + int dst; + asm ("mov 42, %0" + : "=r" (dst)); + return dst; +} + +void test_returns_asm_value (void) +{ + int a, b; + a = returns_asm_value (); + b = returns_asm_value (); + __analyzer_eval (a == b); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-malloc.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-malloc.c new file mode 100644 index 0000000..87173a0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-malloc.c @@ -0,0 +1,80 @@ +/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */ + +/* There need to be at least two calls to a function for the + call-summarization code to be used. + TODO: add some kind of test that summarization *was* used. */ + +#include <stdlib.h> +#include <string.h> +#include "analyzer-decls.h" + +int *malloc_int (int i) +{ + int *res = malloc (sizeof (int)); + if (!res) + return NULL; + *res = i; + return res; +} + +void test_malloc_int (int x) +{ + int *p, *q; + + p = malloc_int (42); + if (p) + __analyzer_eval (*p == 42); /* { dg-warning "TRUE" } */ + free (p); + + q = malloc_int (x); + if (q) + __analyzer_eval (*q == x); /* { dg-warning "TRUE" } */ + free (q); +} + +void test_leak (int x) +{ + int *p = malloc_int (x); /* { dg-message "when 'malloc_int' returns pointer to heap-allocated buffer" } */ +} /* { dg-message "leak of 'p'" } */ + +void *wrapped_malloc (size_t sz) +{ + return malloc (sz); +} + +void wrapped_free (void *p) +{ + free (p); +} + +void test_wrapped_malloc_and_free (size_t sz) +{ + void *p = wrapped_malloc (100); + void *q = wrapped_malloc (sz); + __analyzer_dump_capacity (p); /* { dg-warning "capacity: '\\(\[^\n\r\]*\\)100'" } */ + __analyzer_dump_capacity (q); /* { dg-warning "capacity: 'INIT_VAL\\(sz_\[^\n\r\]*\\)'" } */ + wrapped_free (p); + wrapped_free (q); +} + +void test_use_after_free (void) +{ + // TODO +} + +void test_use_without_check (size_t sz) +{ + char *buf = wrapped_malloc (sz); /* { dg-message "this call could return NULL" } */ + memset (buf, 'x', sz); /* { dg-warning "use of possibly-NULL 'buf' where non-null expected" } */ + wrapped_free (buf); +} + +void test_out_of_bounds (size_t sz) +{ + char *buf = wrapped_malloc (sz); + if (!buf) + return; + memset (buf, 'x', sz); + buf[sz] = '\0'; /* { dg-warning "heap-based buffer overflow" } */ + wrapped_free (buf); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c new file mode 100644 index 0000000..1e689b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c @@ -0,0 +1,90 @@ +/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */ + +/* There need to be at least two calls to a function for the + call-summarization code to be used. + TODO: add some kind of test that summarization *was* used. */ + +/* Reduced from an example in Emacs in which string_char_and_length + was being incorrectly summarized, failing to see the write to *length. */ + +typedef long int ptrdiff_t; +typedef struct Lisp_X *Lisp_Word; +typedef Lisp_Word Lisp_Object; +extern _Bool STRING_MULTIBYTE(Lisp_Object str); +extern unsigned char *SDATA(Lisp_Object string); +enum { MAX_2_BYTE_CHAR = 0x7FF }; +enum { MAX_3_BYTE_CHAR = 0xFFFF }; +enum { MAX_4_BYTE_CHAR = 0x1FFFFF }; +enum { MAX_5_BYTE_CHAR = 0x3FFF7F }; +extern int make_char_multibyte(int c); +static inline int string_char_and_length(unsigned char const *p, int *length) { + int c = p[0]; + if (!(c & 0x80)) { + *length = 1; + return c; + } + ((0xC0 <= c) ? (void)0 : __builtin_unreachable()); + int d = (c << 6) + p[1] - ((0xC0 << 6) + 0x80); + if (!(c & 0x20)) { + *length = 2; + return d + (c < 0xC2 ? 0x3FFF80 : 0); + } + d = (d << 6) + p[2] - ((0x20 << 12) + 0x80); + if (!(c & 0x10)) { + *length = 3; + ((MAX_2_BYTE_CHAR < d && d <= MAX_3_BYTE_CHAR) + ? (void)0 + : __builtin_unreachable()); + return d; + } + d = (d << 6) + p[3] - ((0x10 << 18) + 0x80); + if (!(c & 0x08)) { + *length = 4; + ((MAX_3_BYTE_CHAR < d && d <= MAX_4_BYTE_CHAR) + ? (void)0 + : __builtin_unreachable()); + return d; + } + d = (d << 6) + p[4] - ((0x08 << 24) + 0x80); + *length = 5; + ((MAX_4_BYTE_CHAR < d && d <= MAX_5_BYTE_CHAR) + ? (void)0 + : __builtin_unreachable()); + return d; +} +int fetch_string_char_advance(Lisp_Object string, + ptrdiff_t *charidx, + ptrdiff_t *byteidx) { + int output; + ptrdiff_t b = *byteidx; + unsigned char *chp = SDATA(string) + b; + if (STRING_MULTIBYTE(string)) { + int chlen; + output = string_char_and_length(chp, &chlen); + b += chlen; + } else { + output = *chp; + b++; + } + (*charidx)++; + *byteidx = b; + return output; +} +int fetch_string_char_as_multibyte_advance(Lisp_Object string, + ptrdiff_t *charidx, + ptrdiff_t *byteidx) { + int output; + ptrdiff_t b = *byteidx; + unsigned char *chp = SDATA(string) + b; + if (STRING_MULTIBYTE(string)) { + int chlen; + output = string_char_and_length(chp, &chlen); + b += chlen; + } else { + output = make_char_multibyte(*chp); + b++; + } + (*charidx)++; + *byteidx = b; + return output; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107158-2.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107158-2.c new file mode 100644 index 0000000..c2e9e2ba --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107158-2.c @@ -0,0 +1,108 @@ +/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-too-complex" } */ + +typedef __SIZE_TYPE__ size_t; +typedef struct _IO_FILE FILE; +extern char *fgets(char *__restrict __s, int __n, FILE *__restrict __stream) + __attribute__((__access__(__write_only__, 1, 2))); +extern void perror(const char *__s); +enum { + _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)), +}; +extern const unsigned short int **__ctype_b_loc(void) + __attribute__((__nothrow__, __leaf__)) __attribute__((__const__)); +extern void *malloc(size_t __size) __attribute__((__nothrow__, __leaf__)) +__attribute__((__malloc__)) __attribute__((__alloc_size__(1))); +extern void exit(int __status) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +extern char *strcpy(char *__restrict __dest, const char *__restrict __src) + __attribute__((__nothrow__, __leaf__)) __attribute__((__nonnull__(1, 2))); +extern size_t strlen(const char *__s) __attribute__((__nothrow__, __leaf__)) +__attribute__((__pure__)) __attribute__((__nonnull__(1))); + +struct mydata { + struct mydata *link; + char *name; + char *type; +}; + +static struct mydata *all_data; +static int line_no; + +_Noreturn static void failed(const char *message) { + perror(message); + exit(1); +} + +static char *string_dup(const char *string) { + char *buf; + + if ((buf = malloc(strlen(string) + 1)) == ((void *)0)) + failed("malloc() failed"); + + return strcpy(buf, string); +} + +static void store_data(const char *name, const char *type) { + struct mydata *p, *q; + + if ((p = (struct mydata *)malloc(sizeof(struct mydata))) == ((void *)0)) + failed("malloc() failed"); + + p->link = ((void *)0); + p->name = string_dup(name); + p->type = string_dup(type); + + if ((q = all_data) == ((void *)0)) + all_data = p; + else { + while (q->link != ((void *)0)) + q = q->link; + q->link = p; + } +} + +static void parse_tbl(char *buffer) { + char *s = buffer; + char *t = s + strlen(s); + + do { + t--; + if (((*__ctype_b_loc())[(int)(((int)*t))] & (unsigned short int)_ISspace)) + *t = '\0'; + else + break; + } while (t > s); + while (((*__ctype_b_loc())[(int)(((int)*s))] & (unsigned short int)_ISspace)) + s++; + buffer = s; + + line_no++; + if (*buffer != ';' && *buffer != '\0') { + if (*buffer == '#') { + store_data(buffer, ""); /* { dg-bogus "leak" "PR analyzer/107158" { xfail *-*-* } } */ + } else { + + while (*s && !((*__ctype_b_loc())[(int)(((int)*s))] & + (unsigned short int)_ISspace)) + s++; + while ( + ((*__ctype_b_loc())[(int)(((int)*s))] & (unsigned short int)_ISspace)) + *s++ = '\0'; + store_data(buffer, s); /* { dg-bogus "leak" "PR analyzer/107158" { xfail *-*-* } } */ + } + } +} + +/* [...snip...] */ + +static void makecfg(FILE *ifp, FILE *ofp, FILE *ofp2) { + char buffer[8192]; + + /* [...snip...] */ + + line_no = 0; + while (fgets(buffer, sizeof(buffer) - 1, ifp)) + parse_tbl(buffer); + + /* [...snip...] */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107158.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107158.c new file mode 100644 index 0000000..54f442f --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107158.c @@ -0,0 +1,83 @@ +/* { dg-additional-options "-fanalyzer-call-summaries" } */ + +typedef __SIZE_TYPE__ size_t; +enum { _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)) }; +extern const unsigned short int **__ctype_b_loc(void) + __attribute__((__nothrow__, __leaf__, __const__)); +extern void *malloc(size_t __size) + __attribute__((__nothrow__, __leaf__, __malloc__, __alloc_size__(1))); +extern char *strcpy(char *__restrict __dest, const char *__restrict __src) + __attribute__((__nothrow__, __leaf__, __nonnull__(1, 2))); +extern size_t strlen(const char *__s) + __attribute__((__nothrow__, __leaf__, __pure__, __nonnull__(1))); + +struct mydata { + struct mydata *link; + char *name; + char *type; +}; + +static struct mydata *all_data; +static int line_no; + +__attribute__((__noreturn__)) void failed(const char *message); + +static char *string_dup(const char *string) { + char *buf; + + if ((buf = malloc(strlen(string) + 1)) == ((void *)0)) + failed("malloc() failed"); + + return strcpy(buf, string); +} + +static void store_data(const char *name, const char *type) { + struct mydata *p, *q; + + if ((p = (struct mydata *)malloc(sizeof(struct mydata))) == ((void *)0)) + failed("malloc() failed"); + + p->link = ((void *)0); + p->name = string_dup(name); + p->type = string_dup(type); + + if ((q = all_data) == ((void *)0)) + all_data = p; + else { + while (q->link != ((void *)0)) + q = q->link; + q->link = p; + } +} + +static void parse_tbl(char *buffer) { + char *s = buffer; + char *t = s + strlen(s); + + do { + t--; + if (((*__ctype_b_loc())[(int)(((int)*t))] & (unsigned short int)_ISspace)) + *t = '\0'; + else + break; + } while (t > s); + while (((*__ctype_b_loc())[(int)(((int)*s))] & (unsigned short int)_ISspace)) + s++; + buffer = s; + + line_no++; + if (*buffer != ';' && *buffer != '\0') { + if (*buffer == '#') { + store_data(buffer, ""); /* { dg-bogus "leak" "PR analyzer/107158" { xfail *-*-* } } */ + } else { + + while (*s && !((*__ctype_b_loc())[(int)(((int)*s))] & + (unsigned short int)_ISspace)) + s++; + while ( + ((*__ctype_b_loc())[(int)(((int)*s))] & (unsigned short int)_ISspace)) + *s++ = '\0'; + store_data(buffer, s); /* { dg-bogus "leak" "PR analyzer/107158" { xfail *-*-* } } */ + } + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr105783.c b/gcc/testsuite/gcc.dg/analyzer/pr105783.c new file mode 100644 index 0000000..00f44d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr105783.c @@ -0,0 +1,26 @@ +/* { dg-additional-options "-O" } */ + +struct ss_s { + union out_or_counting_u { + char *newstr; + unsigned long long cnt; + } uu; + _Bool counting; +}; + +struct ss_s ss_init(void) { + struct ss_s rr = { .counting = 1 }; + return rr; +} + +void ss_out(struct ss_s *t, char cc) { + if (!t->counting) { + *t->uu.newstr++ = cc; + } +} + +int main() { + struct ss_s ss = ss_init(); + ss_out(&ss, 'a'); +} + diff --git a/gcc/testsuite/gcc.dg/attr-assume-1.c b/gcc/testsuite/gcc.dg/attr-assume-1.c new file mode 100644 index 0000000..16e919e --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-assume-1.c @@ -0,0 +1,69 @@ +/* Portable assumptions */ +/* { dg-do run } */ +/* { dg-options "-std=c2x" } */ + +int +f1 (int i) +{ + [[gnu::assume (i == 42)]]; + return i; +} + +int +f2 (int i) +{ + __attribute__ ((assume (++i == 44))); + return i; +} + +int a; +int *volatile c; + +int +f3 () +{ + ++a; + return 1; +} + +int +f4 (double x) +{ + [[gnu::assume (__builtin_isfinite (x) && x >= 0.0)]]; + return __builtin_isfinite (__builtin_sqrt (x)); +} + +double +f5 (double x) +{ + __attribute__((assume (__builtin_isfinite (__builtin_sqrt (x))))); + return __builtin_sqrt (x); +} + +int +f6 (int x) +{ + [[gnu::assume (x == 93 ? 1 : 0)]]; + return x; +} + +int +main () +{ + int b = 42; + double d = 42.0, e = 43.0; + c = &b; + [[__gnu__::__assume__ (f3 ())]]; + if (a) + __builtin_abort (); + [[gnu::assume (++b == 43)]]; + if (b != 42 || *c != 42) + __builtin_abort (); + __attribute__((assume (d < e))); + int i = 90, j = 91, k = 92; + [[gnu::__assume__ (i == 90), gnu::assume (j <= 91)]] [[gnu::assume (k >= 92)]] + ; + __attribute__((__assume__ (i == 90), assume (j <= 91))) __attribute__((assume (k >= 92))); + if (f6 (93) != 93) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/attr-assume-2.c b/gcc/testsuite/gcc.dg/attr-assume-2.c new file mode 100644 index 0000000..aa782e7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-assume-2.c @@ -0,0 +1,66 @@ +/* Portable assumptions */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x" } */ + +[[gnu::__assume__ (1)]] void f1 (void); /* { dg-warning "'assume' attribute not followed by ';'" } */ + /* { dg-warning "'assume' attribute ignored" "" { target *-*-* } .-1 } */ +typedef int intx [[gnu::assume (1)]]; /* { dg-warning "'assume' attribute ignored" } */ +[[__gnu__::assume (1)]]; /* { dg-warning "'assume' attribute at top level" } */ +__attribute__((assume (1))) void f1b ();/* { dg-warning "'assume' attribute not followed by ';'" } */ + /* { dg-warning "'assume' attribute ignored" "" { target *-*-* } .-1 } */ +typedef int inty __attribute__((assume (1))); /* { dg-warning "'assume' attribute ignored" } */ + +void +foo () +{ + int i; + [[gnu::assume]]; /* { dg-error "wrong number of arguments specified for 'assume' attribute" } */ + /* { dg-message "expected 1, found 0" "" { target *-*-* } .-1 } */ + [[gnu::__assume__ ()]]; /* { dg-error "parentheses must be omitted if attribute argument list is empty" } */ + /* { dg-error "wrong number of arguments specified for 'assume' attribute" "" { target *-*-* } .-1 } */ + /* { dg-message "expected 1, found 0" "" { target *-*-* } .-2 } */ + [[gnu::assume (1, 1)]]; /* { dg-error "wrong number of arguments specified for 'assume' attribute" } */ + /* { dg-message "expected 1, found 2" "" { target *-*-* } .-1 } */ + [[gnu::assume (1)]] i = 1; /* { dg-warning "'assume' attribute ignored" } */ + [[gnu::assume (i = 1)]]; /* { dg-error "expected" } */ + /* { dg-warning "'assume' attribute ignored" "" { target *-*-* } .-1 } */ + __attribute__((assume)); /* { dg-error "wrong number of arguments specified for 'assume' attribute" } */ + /* { dg-message "expected 1, found 0" "" { target *-*-* } .-1 } */ + __attribute__((assume ())); /* { dg-error "wrong number of arguments specified for 'assume' attribute" } */ + /* { dg-message "expected 1, found 0" "" { target *-*-* } .-1 } */ + __attribute__((assume (1, 1))); /* { dg-error "wrong number of arguments specified for 'assume' attribute" } */ + /* { dg-message "expected 1, found 2" "" { target *-*-* } .-1 } */ + __attribute__((assume (i = 1))); /* { dg-error "expected" } */ +} + +int +f2 (int x) +{ + __asm ("" : "+r" (x)); + return x; +} + +int +f3 (int x) +{ + [[gnu::assume (f2 (42) == 42)]]; + return x; +} + +int +f3a (int x) +{ + __attribute__((assume (f2 (42) == 42))); + return x; +} + +struct S {}; + +int +f4 () +{ + struct S s; + [[gnu::assume (s)]]; /* { dg-error "used struct type value where scalar is required" } */ + __attribute__((assume (s))); /* { dg-error "used struct type value where scalar is required" } */ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/attr-assume-3.c b/gcc/testsuite/gcc.dg/attr-assume-3.c new file mode 100644 index 0000000..c611a8f --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-assume-3.c @@ -0,0 +1,35 @@ +/* Portable assumptions */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x" } */ + +void +foo (int x) +{ + if (x == 1) + goto l1; /* { dg-error "jump into statement expression" } */ + else if (x == 2) + goto l2; /* { dg-error "jump into statement expression" } */ + else if (x == 3) + goto l3; /* { dg-error "jump into statement expression" } */ + [[gnu::assume (({ l0:; if (x == 0) goto l0; 1; }))]]; + [[gnu::assume (({ if (x == 0) __builtin_abort (); 1; }))]]; + [[gnu::assume (({ l1:; 1; }))]]; /* { dg-message "label 'l1' defined here" } */ + [[gnu::assume (({ l2:; 1; }))]]; /* { dg-message "label 'l2' defined here" } */ + __attribute__((assume (({ l3:; 1; })))); /* { dg-message "label 'l3' defined here" } */ + [[gnu::assume (({ l4:; 1; }))]]; /* { dg-message "label 'l4' defined here" } */ + [[gnu::assume (({ l5:; 1; }))]]; /* { dg-message "label 'l5' defined here" } */ + __attribute__((assume (({ l6:; 1; })))); /* { dg-message "label 'l6' defined here" } */ + switch (x) /* { dg-message "switch starts here" } */ + { + case 7: + [[gnu::assume (({ case 8:; 1; }))]]; /* { dg-error "switch jumps into statement expression" } */ + __attribute__((assume (({ default:; 1; })))); /* { dg-error "switch jumps into statement expression" } */ + break; + } + if (x == 4) + goto l4; /* { dg-error "jump into statement expression" } */ + else if (x == 5) + goto l5; /* { dg-error "jump into statement expression" } */ + else if (x == 6) + goto l6; /* { dg-error "jump into statement expression" } */ +} diff --git a/gcc/testsuite/gcc.dg/autopar/pr107153.c b/gcc/testsuite/gcc.dg/autopar/pr107153.c new file mode 100644 index 0000000..2391a67 --- /dev/null +++ b/gcc/testsuite/gcc.dg/autopar/pr107153.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -floop-parallelize-all -ftree-parallelize-loops=2 -fno-tree-dominator-opts" } */ + +void +foo (int x, int y) +{ + int i; + + for (i = 0; i < 2; i++) + { + } + + while (x) + if (!y) + while (y) + ++y; +} diff --git a/gcc/testsuite/gcc.dg/c11-typeof-1.c b/gcc/testsuite/gcc.dg/c11-typeof-1.c new file mode 100644 index 0000000..a2abe8e --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-typeof-1.c @@ -0,0 +1,6 @@ +/* Test typeof and typeof_unqual not keywords in C11. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +int typeof = 1; +long typeof_unqual = 2; diff --git a/gcc/testsuite/gcc.dg/c2x-typeof-1.c b/gcc/testsuite/gcc.dg/c2x-typeof-1.c new file mode 100644 index 0000000..0b721fe --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-typeof-1.c @@ -0,0 +1,208 @@ +/* Test C2x typeof and typeof_unqual. Valid code. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +int i; +extern typeof (i) i; +extern typeof (int) i; +extern typeof_unqual (i) i; +extern typeof_unqual (int) i; + +volatile int vi; +extern typeof (volatile int) vi; +extern typeof (vi) vi; + +extern typeof_unqual (volatile int) i; +extern typeof_unqual (vi) i; +extern typeof ((const int) vi) i; +extern typeof ((volatile int) vi) i; + +const int ci; +extern typeof (const int) ci; +extern typeof (ci) ci; + +extern typeof_unqual (const int) i; +extern typeof_unqual (ci) i; +extern typeof ((const int) ci) i; +extern typeof (+ci) i; +extern typeof (0, ci) i; +extern typeof (1 ? ci : ci) i; +extern typeof (0) i; + +const int fci (void); +extern typeof (fci ()) i; + +_Atomic int ai; +extern typeof (_Atomic int) ai; +extern typeof (_Atomic (int)) ai; +extern typeof (ai) ai; + +extern typeof_unqual (_Atomic int) i; +extern typeof_unqual (_Atomic (int)) i; +extern typeof_unqual (ai) i; +extern typeof (+ai) i; +extern typeof ((_Atomic int) ai) i; +extern typeof (0, ai) i; +extern typeof (1 ? ai : ai) i; + +_Atomic int fai (void); +extern typeof (fai ()) i; + +_Atomic const volatile int acvi; +extern typeof (int volatile const _Atomic) acvi; +extern typeof (acvi) acvi; +extern const _Atomic volatile typeof (acvi) acvi; +extern _Atomic volatile typeof (ci) acvi; +extern _Atomic const typeof (vi) acvi; +extern const typeof (ai) volatile acvi; + +extern typeof_unqual (acvi) i; +extern typeof_unqual (typeof (acvi)) i; +extern typeof_unqual (_Atomic typeof_unqual (acvi)) i; + +extern _Atomic typeof_unqual (acvi) ai; + +char c; +volatile char vc; +volatile char *pvc; +volatile char *const cpvc; +const char *pcc; +const char *volatile vpcc; +typeof (*vpcc) cc; + +extern typeof (*cpvc) vc; +extern typeof_unqual (*cpvc) c; +extern typeof_unqual (cpvc) pvc; +extern typeof_unqual (vpcc) pcc; +extern const char cc; + +extern typeof (++vi) i; +extern typeof (++ai) i; +extern typeof (--vi) i; +extern typeof (--ai) i; +extern typeof (vi++) i; +extern typeof (ai++) i; +extern typeof (vi--) i; +extern typeof (ai--) i; + +bool b; +volatile bool vb; +_Atomic bool ab; +extern typeof (++vb) b; +extern typeof (++ab) b; +extern typeof (--vb) b; +extern typeof (--ab) b; +extern typeof (vb++) b; +extern typeof (ab++) b; +extern typeof (vb--) b; +extern typeof (ab--) b; + +extern typeof (vc = 1) c; +extern typeof (vpcc = 0) pcc; +extern typeof (ai *= 2) i; + +int s = sizeof (typeof (int (*)[++i])); + +void *vp; + +/* The non-returning property of a function is not part of the type given by + ISO C typeof. */ +_Noreturn void nf1 (void); +[[noreturn]] void nf2 (void); +void fg (void) {} +typeof (&nf1) pnf1 = fg; +typeof (&nf2) pnf2 = fg; +extern void (*pnf1) (void); +extern void (*pnf2) (void); +extern typeof (nf1) *pnf1; +extern typeof (nf1) *pnf2; +extern typeof (nf2) *pnf1; +extern typeof (nf2) *pnf2; +typeof (*&nf1) fg2, fg2a, fg2b; +typeof (*&nf2) fg3, fg3a, fg3b; +typeof (nf1) fg4, fg4a, fg4b; +typeof (nf2) fg5, fg5a, fg5b; + +extern void abort (void); +extern void exit (int); + +void fg2 (void) {} +_Noreturn void fg2a (void) { abort (); } +[[noreturn]] void fg2b (void) { abort (); } +void fg3 (void) {} +_Noreturn void fg3a (void) { abort (); } +[[noreturn]] void fg3b (void) { abort (); } +void fg4 (void) {} +_Noreturn void fg4a (void) { abort (); } +[[noreturn]] void fg4b (void) { abort (); } +void fg5 (void) {} +_Noreturn void fg5a (void) { abort (); } +[[noreturn]] void fg5b (void) { abort (); } + +extern int only_used_in_typeof; + +static int not_defined (void); + +typeof (i) +main (typeof (*vp)) +{ + volatile typeof (only_used_in_typeof) ii = 2; + if (ii != 2) + abort (); + const typeof (not_defined ()) jj = 3; + if (jj != 3) + abort (); + unsigned int u = 1; + typeof (u) u2 = 0; + typeof (int (*)[++u2]) p = 0; + if (u2 != 1) + abort (); + if (sizeof (*p) != sizeof (int)) + abort (); + typeof_unqual (int (*)[++u2]) q = 0; + if (u2 != 2) + abort (); + if (sizeof (*q) != 2 * sizeof (int)) + abort (); + if (sizeof (*p) != sizeof (int)) + abort (); + typeof (++u2) u3 = 1; + if (u2 != u + u3) + abort (); + typeof_unqual (++u2) u4 = 2; + if (u2 != u4) + abort (); + u = sizeof (typeof (int (*)[++u2])); + if (u2 != 2) + abort (); + u = sizeof (typeof_unqual (int (*)[++u2])); + if (u2 != 2) + abort (); + typeof ((int (*)[++u2]) 0) q2; + if (u2 != 3) + abort (); + typeof ((void) 0, (int (*)[++u2]) 0) q3; + if (u2 != 4) + abort (); + typeof ((int (*)[++u2]) 0, 0) q4; + if (u2 != 4) + abort (); + typeof_unqual ((int (*)[++u2]) 0) q5; + if (u2 != 5) + abort (); + typeof_unqual ((void) 0, (int (*)[++u2]) 0) q6; + if (u2 != 6) + abort (); + typeof_unqual ((int (*)[++u2]) 0, 0) q7; + if (u2 != 6) + abort (); + int a1[6], a2[6]; + int (*pa)[u2] = &a1; + typeof (pa = &a2) pp; + if (pa != &a2) + abort (); + typeof_unqual (pa = &a1) pp2; + if (pa != &a1) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-typeof-2.c b/gcc/testsuite/gcc.dg/c2x-typeof-2.c new file mode 100644 index 0000000..f1c30a0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-typeof-2.c @@ -0,0 +1,27 @@ +/* Test C2x typeof and typeof_unqual. Invalid code. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +struct s { int i : 2; } x; +union u { unsigned int j : 1; } y; + +typeof (x.i) j; /* { dg-error "applied to a bit-field" } */ +typeof_unqual (x.i) j2; /* { dg-error "applied to a bit-field" } */ +typeof (y.j) j3; /* { dg-error "applied to a bit-field" } */ +typeof_unqual (y.j) j4; /* { dg-error "applied to a bit-field" } */ + +static int ok (void); +static int also_ok (void); +static int not_defined (void); /* { dg-error "used but never defined" } */ +static int also_not_defined (void); /* { dg-error "used but never defined" } */ + +void +f (void) +{ + typeof (ok ()) x = 2; + typeof_unqual (also_ok ()) y = 2; + int a[2]; + int (*p)[x] = &a; + typeof (p + not_defined ()) q; + typeof_unqual (p + also_not_defined ()) q2; +} diff --git a/gcc/testsuite/gcc.dg/c2x-typeof-3.c b/gcc/testsuite/gcc.dg/c2x-typeof-3.c new file mode 100644 index 0000000..c7a0577 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-typeof-3.c @@ -0,0 +1,7 @@ +/* Test C2x typeof and typeof_unqual. -fno-asm has no effect on keywords in + C2x mode. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -fno-asm" } */ + +int i; +extern typeof (i) i; diff --git a/gcc/testsuite/gcc.dg/gnu11-typeof-1.c b/gcc/testsuite/gcc.dg/gnu11-typeof-1.c new file mode 100644 index 0000000..6477c78 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu11-typeof-1.c @@ -0,0 +1,6 @@ +/* Test typeof and typeof_unqual not keywords with -std=gnu11 -fno-asm. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu11 -fno-asm" } */ + +int typeof = 1; +long typeof_unqual = 2; diff --git a/gcc/testsuite/gcc.dg/gnu11-typeof-2.c b/gcc/testsuite/gcc.dg/gnu11-typeof-2.c new file mode 100644 index 0000000..e60ad46 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu11-typeof-2.c @@ -0,0 +1,39 @@ +/* Test typeof propagation of noreturn function attributes with -std=gnu11: + these are part of the type of a function pointer with GNU typeof, but not + with C2x typeof. */ +/* { dg-do link } */ +/* { dg-options "-std=gnu11 -O2" } */ + +_Noreturn void f (void); + +typeof (&f) volatile p; +typeof (&p) volatile pp; + +void link_failure (void); + +void +g (void) +{ + (*p) (); + link_failure (); +} + +void +h (void) +{ + (**pp) (); + link_failure (); +} + +volatile int flag; +volatile int x; + +int +main (void) +{ + if (flag) + g (); + if (flag) + h (); + return x; +} diff --git a/gcc/testsuite/gcc.dg/gnu2x-typeof-1.c b/gcc/testsuite/gcc.dg/gnu2x-typeof-1.c new file mode 100644 index 0000000..f14b54f --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu2x-typeof-1.c @@ -0,0 +1,39 @@ +/* Test __typeof__ propagation of noreturn function attributes with -std=gnu2x: + these are part of the type of a function pointer with GNU __typeof__, but + not with C2x typeof. */ +/* { dg-do link } */ +/* { dg-options "-std=gnu2x -O2" } */ + +_Noreturn void f (void); + +__typeof__ (&f) volatile p; +__typeof__ (&p) volatile pp; + +void link_failure (void); + +void +g (void) +{ + (*p) (); + link_failure (); +} + +void +h (void) +{ + (**pp) (); + link_failure (); +} + +volatile int flag; +volatile int x; + +int +main (void) +{ + if (flag) + g (); + if (flag) + h (); + return x; +} diff --git a/gcc/testsuite/gcc.dg/live-patching-2.c b/gcc/testsuite/gcc.dg/live-patching-2.c index 0dde4e9..1c4f922 100644 --- a/gcc/testsuite/gcc.dg/live-patching-2.c +++ b/gcc/testsuite/gcc.dg/live-patching-2.c @@ -1,10 +1,10 @@ /* { dg-do compile } */ /* { dg-require-effective-target lto } */ -/* { dg-options "-O2 -flive-patching -flto" } */ +/* { dg-options "-O2 -flive-patching=inline-only-static -flto" } */ int main() { return 0; } -/* { dg-message "sorry, unimplemented: live patching is not supported with LTO" "-flive-patching and -flto together" { target *-*-* } 0 } */ +/* { dg-message "sorry, unimplemented: live patching \\(with 'inline-only-static'\\) is not supported with LTO" "-flive-patching and -flto together" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.dg/live-patching-5.c b/gcc/testsuite/gcc.dg/live-patching-5.c new file mode 100644 index 0000000..098047a --- /dev/null +++ b/gcc/testsuite/gcc.dg/live-patching-5.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-O2 -flive-patching -flto" } */ + +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr101836.c b/gcc/testsuite/gcc.dg/pr101836.c new file mode 100644 index 0000000..efad02c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101836.c @@ -0,0 +1,60 @@ +/* -fstrict-flex-arrays is aliased with -ftrict-flex-arrays=3, which is the + strictest, only [] is treated as flexible array. */ +/* PR tree-optimization/101836 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays" } */ + +#include <stdio.h> + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else \ + { \ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + __builtin_abort (); \ + } \ +} while (0); + +struct trailing_array_1 { + int a; + int b; + int c[4]; +}; + +struct trailing_array_2 { + int a; + int b; + int c[1]; +}; + +struct trailing_array_3 { + int a; + int b; + int c[0]; +}; +struct trailing_array_4 { + int a; + int b; + int c[]; +}; + +void __attribute__((__noinline__)) stuff( + struct trailing_array_1 *normal, + struct trailing_array_2 *trailing_1, + struct trailing_array_3 *trailing_0, + struct trailing_array_4 *trailing_flex) +{ + expect(__builtin_object_size(normal->c, 1), 16); + expect(__builtin_object_size(trailing_1->c, 1), 4); + expect(__builtin_object_size(trailing_0->c, 1), 0); + expect(__builtin_object_size(trailing_flex->c, 1), -1); +} + +int main(int argc, char *argv[]) +{ + stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr101836_1.c b/gcc/testsuite/gcc.dg/pr101836_1.c new file mode 100644 index 0000000..e2931ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101836_1.c @@ -0,0 +1,60 @@ +/* -fstrict-flex-arrays=3 is the strictest, only [] is treated as + flexible array. */ +/* PR tree-optimization/101836 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=3" } */ + +#include <stdio.h> + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else \ + { \ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + __builtin_abort (); \ + } \ +} while (0); + +struct trailing_array_1 { + int a; + int b; + int c[4]; +}; + +struct trailing_array_2 { + int a; + int b; + int c[1]; +}; + +struct trailing_array_3 { + int a; + int b; + int c[0]; +}; +struct trailing_array_4 { + int a; + int b; + int c[]; +}; + +void __attribute__((__noinline__)) stuff( + struct trailing_array_1 *normal, + struct trailing_array_2 *trailing_1, + struct trailing_array_3 *trailing_0, + struct trailing_array_4 *trailing_flex) +{ + expect(__builtin_object_size(normal->c, 1), 16); + expect(__builtin_object_size(trailing_1->c, 1), 4); + expect(__builtin_object_size(trailing_0->c, 1), 0); + expect(__builtin_object_size(trailing_flex->c, 1), -1); +} + +int main(int argc, char *argv[]) +{ + stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr101836_2.c b/gcc/testsuite/gcc.dg/pr101836_2.c new file mode 100644 index 0000000..7897418 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101836_2.c @@ -0,0 +1,60 @@ +/* When -fstrict-flex-arrays=2, only [] and [0] are treated as flexiable + arrays. */ +/* PR tree-optimization/101836 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=2" } */ + +#include <stdio.h> + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else \ + { \ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + __builtin_abort (); \ + } \ +} while (0); + +struct trailing_array_1 { + int a; + int b; + int c[4]; +}; + +struct trailing_array_2 { + int a; + int b; + int c[1]; +}; + +struct trailing_array_3 { + int a; + int b; + int c[0]; +}; +struct trailing_array_4 { + int a; + int b; + int c[]; +}; + +void __attribute__((__noinline__)) stuff( + struct trailing_array_1 *normal, + struct trailing_array_2 *trailing_1, + struct trailing_array_3 *trailing_0, + struct trailing_array_4 *trailing_flex) +{ + expect(__builtin_object_size(normal->c, 1), 16); + expect(__builtin_object_size(trailing_1->c, 1), 4); + expect(__builtin_object_size(trailing_0->c, 1), -1); + expect(__builtin_object_size(trailing_flex->c, 1), -1); +} + +int main(int argc, char *argv[]) +{ + stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr101836_3.c b/gcc/testsuite/gcc.dg/pr101836_3.c new file mode 100644 index 0000000..0e69388 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101836_3.c @@ -0,0 +1,60 @@ +/* When -fstrict-flex-arrays=1, [], [0], and [1] are treated as flexible + arrays. */ +/* PR tree-optimization/101836 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=1" } */ + +#include <stdio.h> + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else \ + { \ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + __builtin_abort (); \ + } \ +} while (0); + +struct trailing_array_1 { + int a; + int b; + int c[4]; +}; + +struct trailing_array_2 { + int a; + int b; + int c[1]; +}; + +struct trailing_array_3 { + int a; + int b; + int c[0]; +}; +struct trailing_array_4 { + int a; + int b; + int c[]; +}; + +void __attribute__((__noinline__)) stuff( + struct trailing_array_1 *normal, + struct trailing_array_2 *trailing_1, + struct trailing_array_3 *trailing_0, + struct trailing_array_4 *trailing_flex) +{ + expect(__builtin_object_size(normal->c, 1), 16); + expect(__builtin_object_size(trailing_1->c, 1), -1); + expect(__builtin_object_size(trailing_0->c, 1), -1); + expect(__builtin_object_size(trailing_flex->c, 1), -1); +} + +int main(int argc, char *argv[]) +{ + stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr101836_4.c b/gcc/testsuite/gcc.dg/pr101836_4.c new file mode 100644 index 0000000..e0025aa --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101836_4.c @@ -0,0 +1,60 @@ +/* when -fstrict-flex-arrays=0, all trailing arrays are treated as + flexible arrays. */ +/* PR tree-optimization/101836 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=0" } */ + +#include <stdio.h> + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else \ + { \ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + __builtin_abort (); \ + } \ +} while (0); + +struct trailing_array_1 { + int a; + int b; + int c[4]; +}; + +struct trailing_array_2 { + int a; + int b; + int c[1]; +}; + +struct trailing_array_3 { + int a; + int b; + int c[0]; +}; +struct trailing_array_4 { + int a; + int b; + int c[]; +}; + +void __attribute__((__noinline__)) stuff( + struct trailing_array_1 *normal, + struct trailing_array_2 *trailing_1, + struct trailing_array_3 *trailing_0, + struct trailing_array_4 *trailing_flex) +{ + expect(__builtin_object_size(normal->c, 1), -1); + expect(__builtin_object_size(trailing_1->c, 1), -1); + expect(__builtin_object_size(trailing_0->c, 1), -1); + expect(__builtin_object_size(trailing_flex->c, 1), -1); +} + +int main(int argc, char *argv[]) +{ + stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr101836_5.c b/gcc/testsuite/gcc.dg/pr101836_5.c new file mode 100644 index 0000000..0ad8bbf --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101836_5.c @@ -0,0 +1,60 @@ +/* -fno-strict-flex-arrays is aliased to -fstrict-flex-arrays=0, + all trailing arrays are treated as flexible array. */ +/* PR tree-optimization/101836 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fno-strict-flex-arrays" } */ + +#include <stdio.h> + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else \ + { \ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + __builtin_abort (); \ + } \ +} while (0); + +struct trailing_array_1 { + int a; + int b; + int c[4]; +}; + +struct trailing_array_2 { + int a; + int b; + int c[1]; +}; + +struct trailing_array_3 { + int a; + int b; + int c[0]; +}; +struct trailing_array_4 { + int a; + int b; + int c[]; +}; + +void __attribute__((__noinline__)) stuff( + struct trailing_array_1 *normal, + struct trailing_array_2 *trailing_1, + struct trailing_array_3 *trailing_0, + struct trailing_array_4 *trailing_flex) +{ + expect(__builtin_object_size(normal->c, 1), -1); + expect(__builtin_object_size(trailing_1->c, 1), -1); + expect(__builtin_object_size(trailing_0->c, 1), -1); + expect(__builtin_object_size(trailing_flex->c, 1), -1); +} + +int main(int argc, char *argv[]) +{ + stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr107107.c b/gcc/testsuite/gcc.dg/pr107107.c new file mode 100644 index 0000000..5ad6a63 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr107107.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-tail-merge" } */ + +static inline void set_longish(int is_long_long, void *p, long x) +{ + if (is_long_long) + *(long long*)p = x; + else + *(long*)p = x; +} +static long test(long long *p, int index, int mode) +{ + *p = 1; + set_longish(mode, p+index, 2); + return *p; +} +long (*volatile vtest)(long long*, int, int) = test; +int main(void) +{ + long long x; + long result = vtest(&x, 0, 1); + if (result != 2 || x != 2) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/strict-flex-array-1.c b/gcc/testsuite/gcc.dg/strict-flex-array-1.c new file mode 100644 index 0000000..5b8a793 --- /dev/null +++ b/gcc/testsuite/gcc.dg/strict-flex-array-1.c @@ -0,0 +1,33 @@ +/* testing the correct usage of attribute strict_flex_array. */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + + +int x __attribute__ ((strict_flex_array (1))); /* { dg-error "'strict_flex_array' attribute may not be specified for 'x'" } */ + +int [[gnu::strict_flex_array(1)]] x; /* { dg-warning "'strict_flex_array' attribute does not apply to types" } */ + +struct trailing { + int a; + int c __attribute ((strict_flex_array)); /* { dg-error "wrong number of arguments specified for 'strict_flex_array' attribute" } */ +}; + +struct trailing_1 { + int a; + int b; + int c __attribute ((strict_flex_array (2))); /* { dg-error "'strict_flex_array' attribute may not be specified for a non-array field" } */ +}; + +extern int d; + +struct trailing_array_2 { + int a; + int b; + int c[1] __attribute ((strict_flex_array (d))); /* { dg-error "'strict_flex_array' attribute argument not an integer" } */ +}; + +struct trailing_array_3 { + int a; + int b; + int c[0] __attribute ((strict_flex_array (5))); /* { dg-error "'strict_flex_array' attribute argument '5' is not an integer constant between 0 and 3" } */ +}; diff --git a/gcc/testsuite/gcc.dg/strict-flex-array-2.c b/gcc/testsuite/gcc.dg/strict-flex-array-2.c new file mode 100644 index 0000000..2b80c23 --- /dev/null +++ b/gcc/testsuite/gcc.dg/strict-flex-array-2.c @@ -0,0 +1,60 @@ +/* test the combination of attribute strict_flex_array and option + -fstrict-flex-arrays: when both attribute and option specified, + attribute will have higher priority. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=3" } */ + +#include <stdio.h> + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else \ + { \ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + __builtin_abort (); \ + } \ +} while (0); + +struct trailing_array_1 { + int a; + int b; + int c[4] __attribute__ ((strict_flex_array (0))); +}; + +struct trailing_array_2 { + int a; + int b; + int c[1] __attribute__ ((strict_flex_array (1))); +}; + +struct trailing_array_3 { + int a; + int b; + int c[0] __attribute__ ((strict_flex_array (2))); +}; +struct trailing_array_4 { + int a; + int b; + int c[]; +}; + +void __attribute__((__noinline__)) stuff( + struct trailing_array_1 *normal, + struct trailing_array_2 *trailing_1, + struct trailing_array_3 *trailing_0, + struct trailing_array_4 *trailing_flex) +{ + expect(__builtin_object_size(normal->c, 1), -1); + expect(__builtin_object_size(trailing_1->c, 1), -1); + expect(__builtin_object_size(trailing_0->c, 1), -1); + expect(__builtin_object_size(trailing_flex->c, 1), -1); +} + +int main(int argc, char *argv[]) +{ + stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/strict-flex-array-3.c b/gcc/testsuite/gcc.dg/strict-flex-array-3.c new file mode 100644 index 0000000..602f99d --- /dev/null +++ b/gcc/testsuite/gcc.dg/strict-flex-array-3.c @@ -0,0 +1,60 @@ +/* test the combination of attribute strict_flex_array and option + -fstrict-flex-arrays: when both attribute and option specified, + attribute will have higher priority. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fstrict-flex-arrays=0" } */ + +#include <stdio.h> + +#define expect(p, _v) do { \ + size_t v = _v; \ + if (p == v) \ + printf("ok: %s == %zd\n", #p, p); \ + else \ + { \ + printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \ + __builtin_abort (); \ + } \ +} while (0); + +struct trailing_array_1 { + int a; + int b; + int c[4] __attribute__ ((strict_flex_array (1))); +}; + +struct trailing_array_2 { + int a; + int b; + int c[1] __attribute__ ((strict_flex_array (2))); +}; + +struct trailing_array_3 { + int a; + int b; + int c[0] __attribute__ ((strict_flex_array (3))); +}; +struct trailing_array_4 { + int a; + int b; + int c[]; +}; + +void __attribute__((__noinline__)) stuff( + struct trailing_array_1 *normal, + struct trailing_array_2 *trailing_1, + struct trailing_array_3 *trailing_0, + struct trailing_array_4 *trailing_flex) +{ + expect(__builtin_object_size(normal->c, 1), 16); + expect(__builtin_object_size(trailing_1->c, 1), 4); + expect(__builtin_object_size(trailing_0->c, 1), 0); + expect(__builtin_object_size(trailing_flex->c, 1), -1); +} + +int main(int argc, char *argv[]) +{ + stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr107115.c b/gcc/testsuite/gcc.dg/torture/pr107115.c new file mode 100644 index 0000000..5f7b6ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr107115.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* PR/107115 */ +/* { dg-additional-options "-fno-schedule-insns -fno-schedule-insns2" } */ + +#include <stdlib.h> + +void test1(long *p1) +{ + p1[0] = 1; +} +long test2(long long *p2, int index1, int index2) +{ + p2[index1] = 2; + return p2[index2]; +} +long test3(long *p3, int index2, long value) +{ + p3[index2] = 3; + p3[index2] = value; + return p3[0]; +} +long test4(void *p4, int index1, int index2) +{ + test1(p4); + long temp = test2(p4, index1, index2); + return test3(p4, index2, temp); +} +long (*volatile vtest)(void *, int, int) = test4; +int main(void) +{ + void *pp = malloc(sizeof (long) + sizeof(long long)); + if (!pp) abort(); + long result = vtest(pp, 0, 0); + if (*(long *)pp != 2 || result != 2) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-prof/cmpsf-1.c b/gcc/testsuite/gcc.dg/tree-prof/cmpsf-1.c index 16adb92..696f459 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/cmpsf-1.c +++ b/gcc/testsuite/gcc.dg/tree-prof/cmpsf-1.c @@ -181,4 +181,4 @@ main (void) exit (0); } -/* { dg-final-use-not-autofdo { scan-tree-dump-not "Invalid sum" "dom2"} } */ +/* { dg-final-use-not-autofdo { scan-tree-dump-not "Invalid sum" "dom2" { xfail *-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107052.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107052.c new file mode 100644 index 0000000..88b5213 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107052.c @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-evrp" } + +void link_failure(); +void f(int a) +{ + a &= 0x300; + int b = __builtin_popcount(a); + if (b > 3) + link_failure(); +} + +// { dg-final { scan-tree-dump-not "link_failure" "evrp" } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107170.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107170.c new file mode 100644 index 0000000..7a5a4a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107170.c @@ -0,0 +1,8 @@ +// { dg-do compile } +// { dg-options "-O2" } + +int main() { + double a; + if (__builtin_signbit(a)) + __builtin_abort(); +} diff --git a/gcc/testsuite/gcc.misc-tests/outputs.exp b/gcc/testsuite/gcc.misc-tests/outputs.exp index ab919db..3fe7270 100644 --- a/gcc/testsuite/gcc.misc-tests/outputs.exp +++ b/gcc/testsuite/gcc.misc-tests/outputs.exp @@ -78,6 +78,13 @@ if {[board_info $dest exists output_format]} { append link_options " additional_flags=-Wl,-oformat,[board_info $dest output_format]" } + +set devnull "/dev/null" +if { [info exists ::env(OS)] && [string match "Windows*" $::env(OS)] } { + # Windows uses special file named "nul" as a substitute for /dev/null + set devnull "nul" +} + # Avoid possible influence from the make jobserver, # otherwise ltrans0.ltrans_args files may be missing. if [info exists env(MAKEFLAGS)] { @@ -353,10 +360,10 @@ outest "$b-21 exe savetmp named2" $mult "-o $b.exe -save-temps" {} {{--1.i --1.s # Additional files are created when an @file is used if !$skip_atsave { -outest "$b-22 exe savetmp namedb-2" $sing "@/dev/null -o $b.exe -save-temps" {} {{--0.i --0.s --0.o .args.0 !!$gld .ld1_args !0 .exe}} -outest "$b-23 exe savetmp named2-2" $mult "@/dev/null -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o .args.0 !!$gld .ld1_args !0 .exe}} -outest "$b-24 exe savetmp named2-3" $mult "@/dev/null -I dummy -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o -args.0 -args.1 .args.2 !!$gld .ld1_args !0 .exe}} -outest "$b-25 exe savetmp named2-4" $mult "@/dev/null -I dummy -L dummy -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o -args.0 -args.1 .args.2 .args.3 !!$gld .ld1_args !0 .exe}} +outest "$b-22 exe savetmp namedb-2" $sing "@$devnull -o $b.exe -save-temps" {} {{--0.i --0.s --0.o .args.0 !!$gld .ld1_args !0 .exe}} +outest "$b-23 exe savetmp named2-2" $mult "@$devnull -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o .args.0 !!$gld .ld1_args !0 .exe}} +outest "$b-24 exe savetmp named2-3" $mult "@$devnull -I dummy -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o -args.0 -args.1 .args.2 !!$gld .ld1_args !0 .exe}} +outest "$b-25 exe savetmp named2-4" $mult "@$devnull -I dummy -L dummy -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o -args.0 -args.1 .args.2 .args.3 !!$gld .ld1_args !0 .exe}} } # Setting the main output to a dir selects it as the default aux&dump @@ -714,7 +721,7 @@ outest "$b-291 lto mult named-2" $mult "-o $b.exe -O2 -flto -fno-use-linker-plug outest "$b-292 lto sing nameddir-2" $sing "-o dir/$b.exe -O2 -flto -fno-use-linker-plugin -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--0.c.???i.icf --0.c.???r.final .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe} {}} outest "$b-293 lto mult nameddir-2" $mult "-o dir/$b.exe -O2 -flto -fno-use-linker-plugin -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage" {dir/} {{--1.c.???i.icf --1.c.???r.final --2.c.???i.icf --2.c.???r.final .wpa.???i.icf .ltrans0.ltrans.???r.final .ltrans0.ltrans.su .exe} {}} if !$skip_atsave { -outest "$b-294 lto sing unnamed-3" $sing "@/dev/null -O2 -flto -fno-use-linker-plugin -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage -save-temps $oaout" {} {{a--0.c.???i.icf a--0.c.???r.final a.wpa.???i.icf a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a--0.o a--0.s a--0.i a.ltrans0.o a.ltrans.out a.ltrans0.ltrans.o a.ltrans0.ltrans_args a.args.0 a.ltrans0.ltrans.s a.wpa.args.0 a.lto_args a.ld1_args a.ltrans_args a.ltrans0.ltrans.args.0 a.ld_args $aout}} +outest "$b-294 lto sing unnamed-3" $sing "@$devnull -O2 -flto -fno-use-linker-plugin -flto-partition=one -fdump-ipa-icf-optimized -fdump-rtl-final -fstack-usage -save-temps $oaout" {} {{a--0.c.???i.icf a--0.c.???r.final a.wpa.???i.icf a.ltrans0.ltrans.???r.final a.ltrans0.ltrans.su a--0.o a--0.s a--0.i a.ltrans0.o a.ltrans.out a.ltrans0.ltrans.o a.ltrans0.ltrans_args a.args.0 a.ltrans0.ltrans.s a.wpa.args.0 a.lto_args a.ld1_args a.ltrans_args a.ltrans0.ltrans.args.0 a.ld_args $aout}} } } diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_18 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_18 new file mode 100644 index 0000000..25061a4 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_18 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 2000.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 asimddp sha512 asimdfhm dit uscat ilrcpc flagm ssbs sb dcpodp flagm2 frint i8mm bf16 rng ecv +CPU implementer : 0xc0 +CPU architecture: 8 +CPU variant : 0x0 +CPU part : 0xac3 +CPU revision : 0 diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_18.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_18.c new file mode 100644 index 0000000..b5f0a30 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_18.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target { { aarch64*-*-linux*} && native } } } */ +/* { dg-set-compiler-env-var GCC_CPUINFO "$srcdir/gcc.target/aarch64/cpunative/info_18" } */ +/* { dg-additional-options "-mcpu=native" } */ + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler {\.arch armv8.6-a\+crc\+fp16\+aes\+sha3\+rng} } } */ + +/* Test one where the boundary of buffer size would overwrite the last + character read when stitching the fgets-calls together. With the + test data provided, this would truncate the 'sha512' into 'ha512' + (dropping the 'sha3' feature). */ diff --git a/gcc/testsuite/gcc.target/aarch64/ldar_1.c b/gcc/testsuite/gcc.target/aarch64/ldar_1.c new file mode 100644 index 0000000..d968a72 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/ldar_1.c @@ -0,0 +1,66 @@ +/* Test the LDAR instruction generation from atomic acquire loads. */ +/* { dg-do assemble } */ +/* { dg-additional-options "--save-temps -O1" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#include <stdint.h> + +#pragma GCC target "+norcpc" + +uint8_t v_uint8_t; +uint16_t v_uint16_t; +uint32_t v_uint32_t; +uint64_t v_uint64_t; + +/* +** load_uint8_t: +** ... +** ldarb w0, \[x[0-9]+\] +** ret +*/ + +uint8_t +load_uint8_t (void) +{ + return __atomic_load_n (&v_uint8_t, __ATOMIC_ACQUIRE); +} + +/* +** load_uint16_t: +** ... +** ldarh w0, \[x[0-9]+\] +** ret +*/ + +uint16_t +load_uint16_t (void) +{ + return __atomic_load_n (&v_uint16_t, __ATOMIC_ACQUIRE); +} + +/* +** load_uint32_t: +** ... +** ldar w0, \[x[0-9]+\] +** ret +*/ + +uint32_t +load_uint32_t (void) +{ + return __atomic_load_n (&v_uint32_t, __ATOMIC_ACQUIRE); +} + +/* +** load_uint64_t: +** ... +** ldar x0, \[x[0-9]+\] +** ret +*/ + +uint64_t +load_uint64_t (void) +{ + return __atomic_load_n (&v_uint64_t, __ATOMIC_ACQUIRE); +} + diff --git a/gcc/testsuite/gcc.target/aarch64/ldar_2.c b/gcc/testsuite/gcc.target/aarch64/ldar_2.c new file mode 100644 index 0000000..60b0717 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/ldar_2.c @@ -0,0 +1,27 @@ +/* Test that the zero-extending patterns for LDAR are used. */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +#include <stdint.h> + +uint8_t v_uint8_t; +uint16_t v_uint16_t; +uint32_t v_uint32_t; +uint64_t v_uint64_t; + +#define FUNC(FROM, TO) \ +TO \ +load_##FROM##_ext_##TO (void) \ +{ \ + return __atomic_load_n (&v_##FROM, __ATOMIC_ACQUIRE); \ +} + +FUNC (uint8_t, uint16_t) +FUNC (uint8_t, uint32_t) +FUNC (uint8_t, uint64_t) +FUNC (uint16_t, uint32_t) +FUNC (uint16_t, uint64_t) +FUNC (uint32_t, uint64_t) + +/* { dg-final { scan-assembler-not {and\tw[0-9+], w[0-9]+, 255} } } */ +/* { dg-final { scan-assembler-not {uxtw\tx[0-9+], w[0-9]+} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c index bfb044f..307fa3d 100644 --- a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c +++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c @@ -248,6 +248,26 @@ #error "__ARM_FEATURE_CRC32 is not defined but should be!" #endif +#pragma GCC target ("arch=armv8.2-a") +#ifdef __ARM_FEATURE_RCPC +#error "__ARM_FEATURE_RCPC is defined but should not be!" +#endif + +#pragma GCC target ("arch=armv8.2-a+rcpc") +#ifndef __ARM_FEATURE_RCPC +#error "__ARM_FEATURE_RCPC is not defined but should be!" +#endif + +#pragma GCC target ("+norcpc") +#ifdef __ARM_FEATURE_RCPC +#error "__ARM_FEATURE_RCPC is defined but should not be!" +#endif + +#pragma GCC target ("arch=armv8.3-a") +#ifndef __ARM_FEATURE_RCPC +#error "__ARM_FEATURE_RCPC is not defined but should be!" +#endif + int foo (int a) { diff --git a/gcc/testsuite/gcc.target/arm/stack-protector-1.c b/gcc/testsuite/gcc.target/arm/stack-protector-1.c index 8d28b0a..3f0ffc9 100644 --- a/gcc/testsuite/gcc.target/arm/stack-protector-1.c +++ b/gcc/testsuite/gcc.target/arm/stack-protector-1.c @@ -56,8 +56,8 @@ asm ( " ldr r1, [sp, #4]\n" CHECK (r1) " mov r0, #0\n" -" b exit\n" +" bl exit\n" "1:\n" -" b abort\n" +" bl abort\n" " .size main, .-main" ); diff --git a/gcc/testsuite/gcc.target/arm/stack-protector-3.c b/gcc/testsuite/gcc.target/arm/stack-protector-3.c index b8f77fa..2f71052 100644 --- a/gcc/testsuite/gcc.target/arm/stack-protector-3.c +++ b/gcc/testsuite/gcc.target/arm/stack-protector-3.c @@ -26,7 +26,7 @@ asm ( " .type __stack_chk_fail, %function\n" "__stack_chk_fail:\n" " movs r0, #0\n" -" b exit\n" +" bl exit\n" " .size __stack_chk_fail, .-__stack_chk_fail" ); diff --git a/gcc/testsuite/gcc.target/riscv/predef-1.c b/gcc/testsuite/gcc.target/riscv/predef-1.c index 2e57ce6..9dddc18 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-1.c +++ b/gcc/testsuite/gcc.target/riscv/predef-1.c @@ -58,9 +58,6 @@ int main () { #if defined(__riscv_cmodel_medany) #error "__riscv_cmodel_medlow" #endif -#if defined(__riscv_cmodel_pic) -#error "__riscv_cmodel_medlow" -#endif return 0; } diff --git a/gcc/testsuite/gcc.target/riscv/predef-2.c b/gcc/testsuite/gcc.target/riscv/predef-2.c index c85b3c9..755fe4e 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-2.c +++ b/gcc/testsuite/gcc.target/riscv/predef-2.c @@ -58,9 +58,6 @@ int main () { #if !defined(__riscv_cmodel_medany) #error "__riscv_cmodel_medlow" #endif -#if defined(__riscv_cmodel_pic) -#error "__riscv_cmodel_medlow" -#endif return 0; } diff --git a/gcc/testsuite/gcc.target/riscv/predef-3.c b/gcc/testsuite/gcc.target/riscv/predef-3.c index 82a89d4..5136453 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-3.c +++ b/gcc/testsuite/gcc.target/riscv/predef-3.c @@ -58,9 +58,6 @@ int main () { #if !defined(__riscv_cmodel_medany) #error "__riscv_cmodel_medany" #endif -#if !defined(__riscv_cmodel_pic) -#error "__riscv_cmodel_pic" -#endif return 0; } diff --git a/gcc/testsuite/gcc.target/riscv/predef-4.c b/gcc/testsuite/gcc.target/riscv/predef-4.c index 5868d39..76b6fee 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-4.c +++ b/gcc/testsuite/gcc.target/riscv/predef-4.c @@ -58,9 +58,6 @@ int main () { #if defined(__riscv_cmodel_medany) #error "__riscv_cmodel_medlow" #endif -#if defined(__riscv_cmodel_pic) -#error "__riscv_cmodel_medlow" -#endif return 0; } diff --git a/gcc/testsuite/gcc.target/riscv/predef-5.c b/gcc/testsuite/gcc.target/riscv/predef-5.c index 4b2bd38..54a5150 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-5.c +++ b/gcc/testsuite/gcc.target/riscv/predef-5.c @@ -58,9 +58,6 @@ int main () { #if !defined(__riscv_cmodel_medany) #error "__riscv_cmodel_medlow" #endif -#if defined(__riscv_cmodel_pic) -#error "__riscv_cmodel_medlow" -#endif return 0; } diff --git a/gcc/testsuite/gcc.target/riscv/predef-6.c b/gcc/testsuite/gcc.target/riscv/predef-6.c index 8e5ea36..f61709f 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-6.c +++ b/gcc/testsuite/gcc.target/riscv/predef-6.c @@ -58,9 +58,6 @@ int main () { #if !defined(__riscv_cmodel_medany) #error "__riscv_cmodel_medany" #endif -#if !defined(__riscv_cmodel_pic) -#error "__riscv_cmodel_medpic" -#endif return 0; } diff --git a/gcc/testsuite/gcc.target/riscv/predef-7.c b/gcc/testsuite/gcc.target/riscv/predef-7.c index 0bde299..4121755 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-7.c +++ b/gcc/testsuite/gcc.target/riscv/predef-7.c @@ -58,9 +58,6 @@ int main () { #if defined(__riscv_cmodel_medany) #error "__riscv_cmodel_medlow" #endif -#if defined(__riscv_cmodel_pic) -#error "__riscv_cmodel_medlow" -#endif return 0; } diff --git a/gcc/testsuite/gcc.target/riscv/predef-8.c b/gcc/testsuite/gcc.target/riscv/predef-8.c index 18aa591..982056a 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-8.c +++ b/gcc/testsuite/gcc.target/riscv/predef-8.c @@ -58,9 +58,6 @@ int main () { #if !defined(__riscv_cmodel_medany) #error "__riscv_cmodel_medlow" #endif -#if defined(__riscv_cmodel_pic) -#error "__riscv_cmodel_medlow" -#endif return 0; } diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-1.c new file mode 100644 index 0000000..79b1159 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-1.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv32gc -mabi=ilp32d" } */ + +#pragma riscv intrinsic "vector" /* { dg-error {#pragma riscv intrinsic' option 'vector' needs 'V' extension enabled} } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-2.c new file mode 100644 index 0000000..fa790b1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-2.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test rvv intrinsic" { *-*-* } { "*" } { "-march=rv*v*" } } */ + +#pragma riscv intrinsic "vector"
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-3.c new file mode 100644 index 0000000..86da678 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pragma-3.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test rvv intrinsic" { *-*-* } { "*" } { "-march=rv*v*" } } */ + +#pragma riscv intrinsic "report-error" /* { dg-error {unknown '#pragma riscv intrinsic' option 'report-error'} } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/user-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/user-1.c new file mode 100644 index 0000000..299e393 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/user-1.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-skip-if "test rvv intrinsic" { *-*-* } { "*" } { "-march=rv*v*" } } */ + +#include "riscv_vector.h" + +void foo0 () {vbool64_t t;} +void foo1 () {vbool32_t t;} +void foo2 () {vbool16_t t;} +void foo3 () {vbool8_t t;} +void foo4 () {vbool4_t t;} +void foo5 () {vbool2_t t;} +void foo6 () {vbool1_t t;} +void foo7 () {vint8mf8_t t;} +void foo8 () {vuint8mf8_t t;} +void foo9 () {vint8mf4_t t;} +void foo10 () {vuint8mf4_t t;} +void foo11 () {vint8mf2_t t;} +void foo12 () {vuint8mf2_t t;} +void foo13 () {vint8m1_t t;} +void foo14 () {vuint8m1_t t;} +void foo15 () {vint8m2_t t;} +void foo16 () {vuint8m2_t t;} +void foo17 () {vint8m4_t t;} +void foo18 () {vuint8m4_t t;} +void foo19 () {vint8m8_t t;} +void foo20 () {vuint8m8_t t;} +void foo21 () {vint16mf4_t t;} +void foo22 () {vuint16mf4_t t;} +void foo23 () {vint16mf2_t t;} +void foo24 () {vuint16mf2_t t;} +void foo25 () {vint16m1_t t;} +void foo26 () {vuint16m1_t t;} +void foo27 () {vint16m2_t t;} +void foo28 () {vuint16m2_t t;} +void foo29 () {vint16m4_t t;} +void foo30 () {vuint16m4_t t;} +void foo31 () {vint16m8_t t;} +void foo32 () {vuint16m8_t t;} +void foo33 () {vint32mf2_t t;} +void foo34 () {vuint32mf2_t t;} +void foo35 () {vint32m1_t t;} +void foo36 () {vuint32m1_t t;} +void foo37 () {vint32m2_t t;} +void foo38 () {vuint32m2_t t;} +void foo39 () {vint32m4_t t;} +void foo40 () {vuint32m4_t t;} +void foo41 () {vint32m8_t t;} +void foo42 () {vuint32m8_t t;} +void foo43 () {vint64m1_t t;} +void foo44 () {vuint64m1_t t;} +void foo45 () {vint64m2_t t;} +void foo46 () {vuint64m2_t t;} +void foo47 () {vint64m4_t t;} +void foo48 () {vuint64m4_t t;} +void foo49 () {vint64m8_t t;} +void foo50 () {vuint64m8_t t;} +void foo57 () {vfloat32mf2_t t;} +void foo58 () {vfloat32m1_t t;} +void foo59 () {vfloat32m2_t t;} +void foo60 () {vfloat32m4_t t;} +void foo61 () {vfloat32m8_t t;} +void foo62 () {vfloat64m1_t t;} +void foo63 () {vfloat64m2_t t;} +void foo64 () {vfloat64m4_t t;} +void foo65 () {vfloat64m8_t t;}
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/user-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/user-2.c new file mode 100644 index 0000000..2a88467 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/user-2.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv32gc_zve64x -mabi=ilp32d" } */ + +#include "riscv_vector.h" + +void foo0 () {vbool64_t t;} +void foo1 () {vbool32_t t;} +void foo2 () {vbool16_t t;} +void foo3 () {vbool8_t t;} +void foo4 () {vbool4_t t;} +void foo5 () {vbool2_t t;} +void foo6 () {vbool1_t t;} +void foo7 () {vint8mf8_t t;} +void foo8 () {vuint8mf8_t t;} +void foo9 () {vint8mf4_t t;} +void foo10 () {vuint8mf4_t t;} +void foo11 () {vint8mf2_t t;} +void foo12 () {vuint8mf2_t t;} +void foo13 () {vint8m1_t t;} +void foo14 () {vuint8m1_t t;} +void foo15 () {vint8m2_t t;} +void foo16 () {vuint8m2_t t;} +void foo17 () {vint8m4_t t;} +void foo18 () {vuint8m4_t t;} +void foo19 () {vint8m8_t t;} +void foo20 () {vuint8m8_t t;} +void foo21 () {vint16mf4_t t;} +void foo22 () {vuint16mf4_t t;} +void foo23 () {vint16mf2_t t;} +void foo24 () {vuint16mf2_t t;} +void foo25 () {vint16m1_t t;} +void foo26 () {vuint16m1_t t;} +void foo27 () {vint16m2_t t;} +void foo28 () {vuint16m2_t t;} +void foo29 () {vint16m4_t t;} +void foo30 () {vuint16m4_t t;} +void foo31 () {vint16m8_t t;} +void foo32 () {vuint16m8_t t;} +void foo33 () {vint32mf2_t t;} +void foo34 () {vuint32mf2_t t;} +void foo35 () {vint32m1_t t;} +void foo36 () {vuint32m1_t t;} +void foo37 () {vint32m2_t t;} +void foo38 () {vuint32m2_t t;} +void foo39 () {vint32m4_t t;} +void foo40 () {vuint32m4_t t;} +void foo41 () {vint32m8_t t;} +void foo42 () {vuint32m8_t t;} +void foo43 () {vint64m1_t t;} +void foo44 () {vuint64m1_t t;} +void foo45 () {vint64m2_t t;} +void foo46 () {vuint64m2_t t;} +void foo47 () {vint64m4_t t;} +void foo48 () {vuint64m4_t t;} +void foo49 () {vint64m8_t t;} +void foo50 () {vuint64m8_t t;} +void foo57 () {vfloat32mf2_t t;} /* { dg-error {unknown type name 'vfloat32mf2_t'} } */ +void foo58 () {vfloat32m1_t t;} /* { dg-error {unknown type name 'vfloat32m1_t'} } */ +void foo59 () {vfloat32m2_t t;} /* { dg-error {unknown type name 'vfloat32m2_t'} } */ +void foo60 () {vfloat32m4_t t;} /* { dg-error {unknown type name 'vfloat32m4_t'} } */ +void foo61 () {vfloat32m8_t t;} /* { dg-error {unknown type name 'vfloat32m8_t'} } */ +void foo62 () {vfloat64m1_t t;} /* { dg-error {unknown type name 'vfloat64m1_t'} } */ +void foo63 () {vfloat64m2_t t;} /* { dg-error {unknown type name 'vfloat64m2_t'} } */ +void foo64 () {vfloat64m4_t t;} /* { dg-error {unknown type name 'vfloat64m4_t'} } */ +void foo65 () {vfloat64m8_t t;} /* { dg-error {unknown type name 'vfloat64m8_t'} } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/user-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/user-3.c new file mode 100644 index 0000000..85a6d04 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/user-3.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv32gc_zve64f -mabi=ilp32d" } */ + +#include "riscv_vector.h" + +void foo0 () {vbool64_t t;} +void foo1 () {vbool32_t t;} +void foo2 () {vbool16_t t;} +void foo3 () {vbool8_t t;} +void foo4 () {vbool4_t t;} +void foo5 () {vbool2_t t;} +void foo6 () {vbool1_t t;} +void foo7 () {vint8mf8_t t;} +void foo8 () {vuint8mf8_t t;} +void foo9 () {vint8mf4_t t;} +void foo10 () {vuint8mf4_t t;} +void foo11 () {vint8mf2_t t;} +void foo12 () {vuint8mf2_t t;} +void foo13 () {vint8m1_t t;} +void foo14 () {vuint8m1_t t;} +void foo15 () {vint8m2_t t;} +void foo16 () {vuint8m2_t t;} +void foo17 () {vint8m4_t t;} +void foo18 () {vuint8m4_t t;} +void foo19 () {vint8m8_t t;} +void foo20 () {vuint8m8_t t;} +void foo21 () {vint16mf4_t t;} +void foo22 () {vuint16mf4_t t;} +void foo23 () {vint16mf2_t t;} +void foo24 () {vuint16mf2_t t;} +void foo25 () {vint16m1_t t;} +void foo26 () {vuint16m1_t t;} +void foo27 () {vint16m2_t t;} +void foo28 () {vuint16m2_t t;} +void foo29 () {vint16m4_t t;} +void foo30 () {vuint16m4_t t;} +void foo31 () {vint16m8_t t;} +void foo32 () {vuint16m8_t t;} +void foo33 () {vint32mf2_t t;} +void foo34 () {vuint32mf2_t t;} +void foo35 () {vint32m1_t t;} +void foo36 () {vuint32m1_t t;} +void foo37 () {vint32m2_t t;} +void foo38 () {vuint32m2_t t;} +void foo39 () {vint32m4_t t;} +void foo40 () {vuint32m4_t t;} +void foo41 () {vint32m8_t t;} +void foo42 () {vuint32m8_t t;} +void foo43 () {vint64m1_t t;} +void foo44 () {vuint64m1_t t;} +void foo45 () {vint64m2_t t;} +void foo46 () {vuint64m2_t t;} +void foo47 () {vint64m4_t t;} +void foo48 () {vuint64m4_t t;} +void foo49 () {vint64m8_t t;} +void foo50 () {vuint64m8_t t;} +void foo57 () {vfloat32mf2_t t;} +void foo58 () {vfloat32m1_t t;} +void foo59 () {vfloat32m2_t t;} +void foo60 () {vfloat32m4_t t;} +void foo61 () {vfloat32m8_t t;} +void foo62 () {vfloat64m1_t t;} /* { dg-error {unknown type name 'vfloat64m1_t'} } */ +void foo63 () {vfloat64m2_t t;} /* { dg-error {unknown type name 'vfloat64m2_t'} } */ +void foo64 () {vfloat64m4_t t;} /* { dg-error {unknown type name 'vfloat64m4_t'} } */ +void foo65 () {vfloat64m8_t t;} /* { dg-error {unknown type name 'vfloat64m8_t'} } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/user-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/user-4.c new file mode 100644 index 0000000..c51c03e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/user-4.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv32gc_zve64d -mabi=ilp32d" } */ + +#include "riscv_vector.h" + +void foo0 () {vbool64_t t;} +void foo1 () {vbool32_t t;} +void foo2 () {vbool16_t t;} +void foo3 () {vbool8_t t;} +void foo4 () {vbool4_t t;} +void foo5 () {vbool2_t t;} +void foo6 () {vbool1_t t;} +void foo7 () {vint8mf8_t t;} +void foo8 () {vuint8mf8_t t;} +void foo9 () {vint8mf4_t t;} +void foo10 () {vuint8mf4_t t;} +void foo11 () {vint8mf2_t t;} +void foo12 () {vuint8mf2_t t;} +void foo13 () {vint8m1_t t;} +void foo14 () {vuint8m1_t t;} +void foo15 () {vint8m2_t t;} +void foo16 () {vuint8m2_t t;} +void foo17 () {vint8m4_t t;} +void foo18 () {vuint8m4_t t;} +void foo19 () {vint8m8_t t;} +void foo20 () {vuint8m8_t t;} +void foo21 () {vint16mf4_t t;} +void foo22 () {vuint16mf4_t t;} +void foo23 () {vint16mf2_t t;} +void foo24 () {vuint16mf2_t t;} +void foo25 () {vint16m1_t t;} +void foo26 () {vuint16m1_t t;} +void foo27 () {vint16m2_t t;} +void foo28 () {vuint16m2_t t;} +void foo29 () {vint16m4_t t;} +void foo30 () {vuint16m4_t t;} +void foo31 () {vint16m8_t t;} +void foo32 () {vuint16m8_t t;} +void foo33 () {vint32mf2_t t;} +void foo34 () {vuint32mf2_t t;} +void foo35 () {vint32m1_t t;} +void foo36 () {vuint32m1_t t;} +void foo37 () {vint32m2_t t;} +void foo38 () {vuint32m2_t t;} +void foo39 () {vint32m4_t t;} +void foo40 () {vuint32m4_t t;} +void foo41 () {vint32m8_t t;} +void foo42 () {vuint32m8_t t;} +void foo43 () {vint64m1_t t;} +void foo44 () {vuint64m1_t t;} +void foo45 () {vint64m2_t t;} +void foo46 () {vuint64m2_t t;} +void foo47 () {vint64m4_t t;} +void foo48 () {vuint64m4_t t;} +void foo49 () {vint64m8_t t;} +void foo50 () {vuint64m8_t t;} +void foo57 () {vfloat32mf2_t t;} +void foo58 () {vfloat32m1_t t;} +void foo59 () {vfloat32m2_t t;} +void foo60 () {vfloat32m4_t t;} +void foo61 () {vfloat32m8_t t;} +void foo62 () {vfloat64m1_t t;} +void foo63 () {vfloat64m2_t t;} +void foo64 () {vfloat64m4_t t;} +void foo65 () {vfloat64m8_t t;}
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/user-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/user-5.c new file mode 100644 index 0000000..fb1c684 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/user-5.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv32gc_zve32x -mabi=ilp32d" } */ + +#include "riscv_vector.h" + +void foo0 () {vbool64_t t;} /* { dg-error {unknown type name 'vbool64_t'} } */ +void foo1 () {vbool32_t t;} +void foo2 () {vbool16_t t;} +void foo3 () {vbool8_t t;} +void foo4 () {vbool4_t t;} +void foo5 () {vbool2_t t;} +void foo6 () {vbool1_t t;} +void foo7 () {vint8mf8_t t;} /* { dg-error {unknown type name 'vint8mf8_t'} } */ +void foo8 () {vuint8mf8_t t;} /* { dg-error {unknown type name 'vuint8mf8_t'} } */ +void foo9 () {vint8mf4_t t;} +void foo10 () {vuint8mf4_t t;} +void foo11 () {vint8mf2_t t;} +void foo12 () {vuint8mf2_t t;} +void foo13 () {vint8m1_t t;} +void foo14 () {vuint8m1_t t;} +void foo15 () {vint8m2_t t;} +void foo16 () {vuint8m2_t t;} +void foo17 () {vint8m4_t t;} +void foo18 () {vuint8m4_t t;} +void foo19 () {vint8m8_t t;} +void foo20 () {vuint8m8_t t;} +void foo21 () {vint16mf4_t t;} /* { dg-error {unknown type name 'vint16mf4_t'} } */ +void foo22 () {vuint16mf4_t t;} /* { dg-error {unknown type name 'vuint16mf4_t'} } */ +void foo23 () {vint16mf2_t t;} +void foo24 () {vuint16mf2_t t;} +void foo25 () {vint16m1_t t;} +void foo26 () {vuint16m1_t t;} +void foo27 () {vint16m2_t t;} +void foo28 () {vuint16m2_t t;} +void foo29 () {vint16m4_t t;} +void foo30 () {vuint16m4_t t;} +void foo31 () {vint16m8_t t;} +void foo32 () {vuint16m8_t t;} +void foo33 () {vint32mf2_t t;} /* { dg-error {unknown type name 'vint32mf2_t'} } */ +void foo34 () {vuint32mf2_t t;} /* { dg-error {unknown type name 'vuint32mf2_t'} } */ +void foo35 () {vint32m1_t t;} +void foo36 () {vuint32m1_t t;} +void foo37 () {vint32m2_t t;} +void foo38 () {vuint32m2_t t;} +void foo39 () {vint32m4_t t;} +void foo40 () {vuint32m4_t t;} +void foo41 () {vint32m8_t t;} +void foo42 () {vuint32m8_t t;} +void foo43 () {vint64m1_t t;} /* { dg-error {unknown type name 'vint64m1_t'} } */ +void foo44 () {vuint64m1_t t;} /* { dg-error {unknown type name 'vuint64m1_t'} } */ +void foo45 () {vint64m2_t t;} /* { dg-error {unknown type name 'vint64m2_t'} } */ +void foo46 () {vuint64m2_t t;} /* { dg-error {unknown type name 'vuint64m2_t'} } */ +void foo47 () {vint64m4_t t;} /* { dg-error {unknown type name 'vint64m4_t'} } */ +void foo48 () {vuint64m4_t t;} /* { dg-error {unknown type name 'vuint64m4_t'} } */ +void foo49 () {vint64m8_t t;} /* { dg-error {unknown type name 'vint64m8_t'} } */ +void foo50 () {vuint64m8_t t;} /* { dg-error {unknown type name 'vuint64m8_t'} } */ +void foo57 () {vfloat32mf2_t t;} /* { dg-error {unknown type name 'vfloat32mf2_t'} } */ +void foo58 () {vfloat32m1_t t;} /* { dg-error {unknown type name 'vfloat32m1_t'} } */ +void foo59 () {vfloat32m2_t t;} /* { dg-error {unknown type name 'vfloat32m2_t'} } */ +void foo60 () {vfloat32m4_t t;} /* { dg-error {unknown type name 'vfloat32m4_t'} } */ +void foo61 () {vfloat32m8_t t;} /* { dg-error {unknown type name 'vfloat32m8_t'} } */ +void foo62 () {vfloat64m1_t t;} /* { dg-error {unknown type name 'vfloat64m1_t'} } */ +void foo63 () {vfloat64m2_t t;} /* { dg-error {unknown type name 'vfloat64m2_t'} } */ +void foo64 () {vfloat64m4_t t;} /* { dg-error {unknown type name 'vfloat64m4_t'} } */ +void foo65 () {vfloat64m8_t t;} /* { dg-error {unknown type name 'vfloat64m8_t'} } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/user-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/user-6.c new file mode 100644 index 0000000..5361fbd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/user-6.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv32gc_zve32f -mabi=ilp32d" } */ + +#include "riscv_vector.h" + +void foo0 () {vbool64_t t;} /* { dg-error {unknown type name 'vbool64_t'} } */ +void foo1 () {vbool32_t t;} +void foo2 () {vbool16_t t;} +void foo3 () {vbool8_t t;} +void foo4 () {vbool4_t t;} +void foo5 () {vbool2_t t;} +void foo6 () {vbool1_t t;} +void foo7 () {vint8mf8_t t;} /* { dg-error {unknown type name 'vint8mf8_t'} } */ +void foo8 () {vuint8mf8_t t;} /* { dg-error {unknown type name 'vuint8mf8_t'} } */ +void foo9 () {vint8mf4_t t;} +void foo10 () {vuint8mf4_t t;} +void foo11 () {vint8mf2_t t;} +void foo12 () {vuint8mf2_t t;} +void foo13 () {vint8m1_t t;} +void foo14 () {vuint8m1_t t;} +void foo15 () {vint8m2_t t;} +void foo16 () {vuint8m2_t t;} +void foo17 () {vint8m4_t t;} +void foo18 () {vuint8m4_t t;} +void foo19 () {vint8m8_t t;} +void foo20 () {vuint8m8_t t;} +void foo21 () {vint16mf4_t t;} /* { dg-error {unknown type name 'vint16mf4_t'} } */ +void foo22 () {vuint16mf4_t t;} /* { dg-error {unknown type name 'vuint16mf4_t'} } */ +void foo23 () {vint16mf2_t t;} +void foo24 () {vuint16mf2_t t;} +void foo25 () {vint16m1_t t;} +void foo26 () {vuint16m1_t t;} +void foo27 () {vint16m2_t t;} +void foo28 () {vuint16m2_t t;} +void foo29 () {vint16m4_t t;} +void foo30 () {vuint16m4_t t;} +void foo31 () {vint16m8_t t;} +void foo32 () {vuint16m8_t t;} +void foo33 () {vint32mf2_t t;} /* { dg-error {unknown type name 'vint32mf2_t'} } */ +void foo34 () {vuint32mf2_t t;} /* { dg-error {unknown type name 'vuint32mf2_t'} } */ +void foo35 () {vint32m1_t t;} +void foo36 () {vuint32m1_t t;} +void foo37 () {vint32m2_t t;} +void foo38 () {vuint32m2_t t;} +void foo39 () {vint32m4_t t;} +void foo40 () {vuint32m4_t t;} +void foo41 () {vint32m8_t t;} +void foo42 () {vuint32m8_t t;} +void foo43 () {vint64m1_t t;} /* { dg-error {unknown type name 'vint64m1_t'} } */ +void foo44 () {vuint64m1_t t;} /* { dg-error {unknown type name 'vuint64m1_t'} } */ +void foo45 () {vint64m2_t t;} /* { dg-error {unknown type name 'vint64m2_t'} } */ +void foo46 () {vuint64m2_t t;} /* { dg-error {unknown type name 'vuint64m2_t'} } */ +void foo47 () {vint64m4_t t;} /* { dg-error {unknown type name 'vint64m4_t'} } */ +void foo48 () {vuint64m4_t t;} /* { dg-error {unknown type name 'vuint64m4_t'} } */ +void foo49 () {vint64m8_t t;} /* { dg-error {unknown type name 'vint64m8_t'} } */ +void foo50 () {vuint64m8_t t;} /* { dg-error {unknown type name 'vuint64m8_t'} } */ +void foo57 () {vfloat32mf2_t t;} /* { dg-error {unknown type name 'vfloat32mf2_t'} } */ +void foo58 () {vfloat32m1_t t;} +void foo59 () {vfloat32m2_t t;} +void foo60 () {vfloat32m4_t t;} +void foo61 () {vfloat32m8_t t;} +void foo62 () {vfloat64m1_t t;} /* { dg-error {unknown type name 'vfloat64m1_t'} } */ +void foo63 () {vfloat64m2_t t;} /* { dg-error {unknown type name 'vfloat64m2_t'} } */ +void foo64 () {vfloat64m4_t t;} /* { dg-error {unknown type name 'vfloat64m4_t'} } */ +void foo65 () {vfloat64m8_t t;} /* { dg-error {unknown type name 'vfloat64m8_t'} } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vread_csr.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vread_csr.c new file mode 100644 index 0000000..9151349f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vread_csr.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O3" } */ +/* { dg-skip-if "test intrinsic using rvv" { *-*-* } { "*" } { "-march=rv*v*zfh*" } } */ + +#include <riscv_vector.h> + +unsigned long vread_csr_vstart(void) { + return vread_csr(RVV_VSTART); +} + +unsigned long vread_csr_vxsat(void) { + return vread_csr(RVV_VXSAT); +} + +unsigned long vread_csr_vxrm(void) { + return vread_csr(RVV_VXRM); +} + +unsigned long vread_csr_vcsr(void) { + return vread_csr(RVV_VCSR); +} + +/* { dg-final { scan-assembler-times {csrr\s+(?:ra|[sgtf]p|t[0-6]|s[0-9]|s10|s11|a[0-7]),\s*vstart} 1 } } */ +/* { dg-final { scan-assembler-times {csrr\s+(?:ra|[sgtf]p|t[0-6]|s[0-9]|s10|s11|a[0-7]),\s*vxsat} 1 } } */ +/* { dg-final { scan-assembler-times {csrr\s+(?:ra|[sgtf]p|t[0-6]|s[0-9]|s10|s11|a[0-7]),\s*vxrm} 1 } } */ +/* { dg-final { scan-assembler-times {csrr\s+(?:ra|[sgtf]p|t[0-6]|s[0-9]|s10|s11|a[0-7]),\s*vcsr} 1 } } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vwrite_csr.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vwrite_csr.c new file mode 100644 index 0000000..a50eba7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vwrite_csr.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O3" } */ +/* { dg-skip-if "test intrinsic using rvv" { *-*-* } { "*" } { "-march=rv*v*zfh*" } } */ + +#include <riscv_vector.h> + +void vwrite_csr_vstart(unsigned long value) { + vwrite_csr(RVV_VSTART, value); +} + +void vwrite_csr_vxsat(unsigned long value) { + vwrite_csr(RVV_VXSAT, value); +} + +void vwrite_csr_vxrm(unsigned long value) { + vwrite_csr(RVV_VXRM, value); +} + +void vwrite_csr_vcsr(unsigned long value) { + vwrite_csr(RVV_VCSR, value); +} + +/* { dg-final { scan-assembler-times {csrw\s+vstart,\s*(?:ra|[sgtf]p|t[0-6]|s[0-9]|s10|s11|a[0-7])} 1 } } */ +/* { dg-final { scan-assembler-times {csrw\s+vxsat,\s*(?:ra|[sgtf]p|t[0-6]|s[0-9]|s10|s11|a[0-7])} 1 } } */ +/* { dg-final { scan-assembler-times {csrw\s+vxrm,\s*(?:ra|[sgtf]p|t[0-6]|s[0-9]|s10|s11|a[0-7])} 1 } } */ +/* { dg-final { scan-assembler-times {csrw\s+vcsr,\s*(?:ra|[sgtf]p|t[0-6]|s[0-9]|s10|s11|a[0-7])} 1 } } */
\ No newline at end of file diff --git a/gcc/testsuite/gfortran.dg/gomp/assume-1.f90 b/gcc/testsuite/gfortran.dg/gomp/assume-1.f90 new file mode 100644 index 0000000..8bd5c72 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/assume-1.f90 @@ -0,0 +1,24 @@ +subroutine foo (i, a) + implicit none + integer, value :: i + integer :: a(:) + integer :: j + + j = 7 + !$omp assume no_openmp, absent (target, teams) holds (i < 32) holds (i < 32_2) + !$omp end assume + + !$omp assume no_openmp_routines, contains (simd) + block + !$omp simd + do j = 1, i + a(i) = j + end do + end block + + !$omp assume no_parallelism, contains (error) + if (i >= 32) then + !$omp error at (execution) message ("Should not happen") + end if + !$omp end assume +end diff --git a/gcc/testsuite/gfortran.dg/gomp/assume-2.f90 b/gcc/testsuite/gfortran.dg/gomp/assume-2.f90 new file mode 100644 index 0000000..ca3e04d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/assume-2.f90 @@ -0,0 +1,27 @@ +subroutine foo (i, a) + implicit none + integer, value :: i + integer :: a(:) + integer :: j + + j = 7 + !$omp assume no_openmp, absent (target, teams,target) holds (i < 32) holds (i < 32_2) ! { dg-error "'TARGET' directive mentioned multiple times in ABSENT clause in !.OMP ASSUME directive" } +! !$omp end assume - silence: 'Unexpected !$OMP END ASSUME statement' + + !$omp assume no_openmp_routines, contains (simd) contains ( simd ) ! { dg-error "'SIMD' directive mentioned multiple times in CONTAINS clause in !.OMP ASSUME directive" } + block + !$omp simd + do j = 1, i + a(i) = j + end do + end block + + !$omp assume no_parallelism, contains (error) absent (error) ! { dg-error "'ERROR' directive mentioned both times in ABSENT and CONTAINS clauses in !.OMP ASSUME directive" } + if (i >= 32) then + !$omp error at (execution) message ("Should not happen") + end if +! !$omp end assume - silence: 'Unexpected !$OMP END ASSUME statement' + + !$omp assume holds (1.0) ! { dg-error "HOLDS expression at .1. must be a logical expression" } + !$omp end assume +end diff --git a/gcc/testsuite/gfortran.dg/gomp/assume-3.f90 b/gcc/testsuite/gfortran.dg/gomp/assume-3.f90 new file mode 100644 index 0000000..e5deace --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/assume-3.f90 @@ -0,0 +1,46 @@ +! { dg-do compile } +! { dg-options "-fopenmp -O2 -fdump-tree-optimized -fdump-tree-original" } + +! { dg-final { scan-tree-dump-times ".ASSUME \\(x == 42\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times ".ASSUME \\(x <= 41\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times ".ASSUME \\(y <= 6\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times ".ASSUME \\(y > 5\\);" 1 "original" } } + +! { dg-final { scan-tree-dump-times "return 42;" 3 "optimized" } } +! { dg-final { scan-tree-dump-not "return -1;" "optimized" } } + +integer function foo (x) + implicit none + integer, value :: x + integer :: y + !$omp assume holds (x == 42) + y = x; + !$omp end assume + foo = y +end + +integer function bar (x) + implicit none + integer, value :: x + !$omp assume holds (x < 42) + block + end block + if (x == 42) then + bar = -1 + return + end if + bar = 42 +end + +integer function foobar (y) + implicit none + integer, value :: y + !$omp assume holds(y > 5) holds (y < 7) + block + if (y == 6) then + foobar = 42 + return + end if + end block + foobar = -1 +end diff --git a/gcc/testsuite/gfortran.dg/gomp/assume-4.f90 b/gcc/testsuite/gfortran.dg/gomp/assume-4.f90 new file mode 100644 index 0000000..45857c4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/assume-4.f90 @@ -0,0 +1,50 @@ +! { dg-do compile } +! { dg-options "-fopenmp -O2 -fdump-tree-original -fdump-tree-optimized" } +! { dg-final { scan-tree-dump-times ".ASSUME \\(i_lower_bound \\(\\) < i\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times ".ASSUME \\(TARGET_EXPR <D.\[0-9\]+, D.\[0-9\]+ = j_upper_bound \\(\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_free" 1 "original" } } + +! { dg-final { scan-tree-dump-not "i_lower_bound" "optimized" } } +! { dg-final { scan-tree-dump-not "j_upper_bound" "optimized" } } +! { dg-final { scan-tree-dump-not "__builtin_free" "optimized" } } + +! Note: Currently, the assumption does not help with optimization in either variant. + + +integer function f(i) + implicit none + integer, value :: i + + !$omp assume holds(i > i_lower_bound ()) + block + if (i > 4) then + f = 42 + else + f = -1 + end if + end block +contains + function i_lower_bound () + integer :: i_lower_bound + i_lower_bound = 5 + end function +end + +integer function g(j) + implicit none + integer, value :: j + + !$omp assume holds(j < j_upper_bound ()) + block + if (j < 10) then + g = 42 + else + g = -1 + end if + end block +contains + function j_upper_bound () + integer, allocatable :: j_upper_bound + j_upper_bound = 10 + end function +end diff --git a/gcc/testsuite/gfortran.dg/gomp/assumes-1.f90 b/gcc/testsuite/gfortran.dg/gomp/assumes-1.f90 new file mode 100644 index 0000000..3d468dc --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/assumes-1.f90 @@ -0,0 +1,82 @@ +! All of the following (up to PROGRAM) are okay: +! +subroutine sub + interface + subroutine sub_iterface() + !$omp assumes no_openmp_routines absent(simd) ! OK inferface of an external subroutine/subprogram + end + end interface + !$omp assumes no_openmp_routines absent(simd) ! OK external subroutine/subprogram +contains + subroutine inner_sub + !$omp assumes no_parallelism absent(teams) ! OK internal subroutine/subprogram + end +end + +integer function func () + !$omp assumes no_openmp_routines absent(simd) ! OK external function/subprogram + interface + integer function func_iterface() + !$omp assumes no_openmp_routines absent(simd) ! OK inferface of an external function/subprogram + end + end interface + func = 0 +contains + integer function inner_func() + !$omp assumes no_parallelism absent(teams) ! OK internal function/subprogram + inner_sub2 = 0 + end +end + +module m + integer ::x + !$omp assumes contains(target) holds(x > 0.0) + + interface + subroutine mod_mod_sub_iterface() + !$omp assumes no_openmp_routines absent(simd) ! OK inferface of an external subroutine/subprogram + end + integer function mod_mod_func_iterface() + !$omp assumes no_openmp_routines absent(error) ! OK inferface of an external subroutine/subprogram + end + end interface + +contains + subroutine mod_sub + interface + subroutine mod_sub_iterface() + !$omp assumes no_openmp_routines absent(simd) ! OK inferface of an external subroutine/subprogram + end + end interface + !$omp assumes no_openmp_routines absent(simd) ! OK module subroutine/subprogram + contains + subroutine mod_inner_sub + !$omp assumes no_parallelism absent(teams) ! OK internal subroutine/subprogram + end + end + + integer function mod_func () + !$omp assumes no_openmp_routines absent(simd) ! OK module function/subprogram + interface + integer function mod_func_iterface() + !$omp assumes no_openmp_routines absent(simd) ! OK inferface of an external function/subprogram + end + end interface + mod_func = 0 + contains + integer function mod_inner_func() + !$omp assumes no_parallelism absent(teams) ! OK internal function/subprogram + mod_inner_sub2 = 0 + end + end +end module m + + +! PROGRAM - invalid as: +! main program is a program unit that is not a subprogram +!$omp assumes no_openmp absent(simd) ! { dg-error "must be in the specification part of a subprogram or module" } + block + ! invalid: block + !$omp assumes no_openmp absent(target) ! { dg-error "must be in the specification part of a subprogram or module" } + end block +end diff --git a/gcc/testsuite/gfortran.dg/gomp/assumes-2.f90 b/gcc/testsuite/gfortran.dg/gomp/assumes-2.f90 new file mode 100644 index 0000000..729c973 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/assumes-2.f90 @@ -0,0 +1,19 @@ +module m + integer ::x +! Nonsense but OpenMP-semantically valid: + !$omp assumes contains(target) holds(x > 0.0) + !$omp assumes absent(target) + !$omp assumes holds(0.0) +! { dg-error "HOLDS expression at .1. must be a logical expression" "" { target *-*-* } .-1 } +end module + +module m2 +interface + subroutine foo + !$omp assumes contains(target) contains(teams,target) ! { dg-error "'TARGET' directive mentioned multiple times in CONTAINS clause in !.OMP ASSUMES directive" } + !$omp assumes absent(declare target) ! { dg-error "Invalid 'DECLARE TARGET' directive at .1. in ABSENT clause: declarative, informational and meta directives not permitted" } + !$omp assumes absent(parallel) absent(do,simd,parallel,distribute) ! { dg-error "'PARALLEL' directive mentioned multiple times in ABSENT clause in !.OMP ASSUMES directive" } + !$omp assumes contains(barrier,atomic) absent(cancel,simd,atomic,distribute) ! { dg-error "'SIMD' directive mentioned both times in ABSENT and CONTAINS clauses in !.OMP ASSUMES directive" } + end subroutine foo +end interface +end module m2 diff --git a/gcc/testsuite/gfortran.dg/gomp/openmp-simd-7.f90 b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-7.f90 new file mode 100644 index 0000000..d7010bb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-7.f90 @@ -0,0 +1,23 @@ +! { dg-options "-fno-openmp -fopenmp-simd -fdump-tree-original" } + +subroutine foo (a, b) + integer, contiguous :: a(:), b(:) + integer :: i + !$omp simd reduction (inscan, +:r) + do i = 1, 1024 + r = r + a(i) + !$omp scan inclusive(r) + b(i) = r + end do + !$omp end simd + + !$omp loop + do i = 1, 1024 + a(i) = a(i) + i + end do + !$omp end loop +end + +! { dg-final { scan-tree-dump "#pragma omp simd linear\\(i:1\\) reduction\\(inscan,\\+:r\\)" "original" } } +! { dg-final { scan-tree-dump "#pragma omp scan inclusive\\(r\\)" "original" } } +! { dg-final { scan-tree-dump "#pragma omp loop" "original" } } diff --git a/gcc/testsuite/gnat.dg/lto26.adb b/gcc/testsuite/gnat.dg/lto26.adb new file mode 100644 index 0000000..a27348b --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto26.adb @@ -0,0 +1,13 @@ +-- { dg-do run } +-- { dg-options "-O2 -flto" { target lto } } + +with Ada.Streams; use Ada.Streams; +with Lto26_Pkg1; use Lto26_Pkg1; + +procedure Lto26 is + R : Rec; +begin + for I in 1 .. 10 loop + Set (R, (7, 0, 84, Stream_Element (I), 0, 0, 0), 1); + end loop; +end; diff --git a/gcc/testsuite/gnat.dg/lto26_pkg1.adb b/gcc/testsuite/gnat.dg/lto26_pkg1.adb new file mode 100644 index 0000000..c68b134 --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto26_pkg1.adb @@ -0,0 +1,11 @@ +with Lto26_Pkg2; use Lto26_Pkg2; + +package body Lto26_Pkg1 is + + procedure Set (R : Rec; A : Stream_Element_Array; C :Unsigned_8) is + procedure My_Build is new Build; + begin + My_Build (A, C); + end; + +end Lto26_Pkg1; diff --git a/gcc/testsuite/gnat.dg/lto26_pkg1.ads b/gcc/testsuite/gnat.dg/lto26_pkg1.ads new file mode 100644 index 0000000..5279747 --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto26_pkg1.ads @@ -0,0 +1,11 @@ +with Ada.Finalization; +with Ada.Streams; use Ada.Streams; +with Interfaces; use Interfaces; + +package Lto26_Pkg1 is + + type Rec is new Ada.Finalization.Limited_Controlled with null record; + + procedure Set (R : Rec; A : Stream_Element_Array; C :Unsigned_8); + +end Lto26_Pkg1; diff --git a/gcc/testsuite/gnat.dg/lto26_pkg2.adb b/gcc/testsuite/gnat.dg/lto26_pkg2.adb new file mode 100644 index 0000000..9f89733 --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto26_pkg2.adb @@ -0,0 +1,15 @@ +package body Lto26_Pkg2 is + + procedure Build (A : Stream_Element_Array; C : Unsigned_8) is + Start : Stream_Element_Offset := A'First; + Next : Stream_Element_Offset; + Length : Unsigned_8; + begin + for I in 1 .. C loop + Length := Unsigned_8 (A (A'First)); + Next := Start + Stream_Element_Offset (Length); + Start := Next; + end loop; + end; + +end Lto26_Pkg2; diff --git a/gcc/testsuite/gnat.dg/lto26_pkg2.ads b/gcc/testsuite/gnat.dg/lto26_pkg2.ads new file mode 100644 index 0000000..68741bb8 --- /dev/null +++ b/gcc/testsuite/gnat.dg/lto26_pkg2.ads @@ -0,0 +1,9 @@ +with Ada.Streams; use Ada.Streams; +with Interfaces; use Interfaces; + +package Lto26_Pkg2 is + + generic + procedure Build (A : Stream_Element_Array; C : Unsigned_8); + +end Lto26_Pkg2; diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index 09fa7b6..41f2925 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -1203,8 +1203,40 @@ assign_discriminators (void) { edge e; edge_iterator ei; + gimple_stmt_iterator gsi; gimple *last = last_stmt (bb); location_t locus = last ? gimple_location (last) : UNKNOWN_LOCATION; + location_t curr_locus = UNKNOWN_LOCATION; + int curr_discr = 0; + + /* Traverse the basic block, if two function calls within a basic block + are mapped to the same line, assign a new discriminator because a call + stmt could be a split point of a basic block. */ + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + expanded_location curr_locus_e; + if (curr_locus == UNKNOWN_LOCATION) + { + curr_locus = gimple_location (stmt); + curr_locus_e = expand_location (curr_locus); + } + else if (!same_line_p (curr_locus, &curr_locus_e, gimple_location (stmt))) + { + curr_locus = gimple_location (stmt); + curr_locus_e = expand_location (curr_locus); + curr_discr = 0; + } + else if (curr_discr != 0) + { + location_t loc = gimple_location (stmt); + location_t dloc = location_with_discriminator (loc, curr_discr); + gimple_set_location (stmt, dloc); + } + /* Allocate a new discriminator for CALL stmt. */ + if (gimple_code (stmt) == GIMPLE_CALL) + curr_discr = next_discriminator_for_locus (curr_locus); + } if (locus == UNKNOWN_LOCATION) continue; @@ -6926,8 +6958,6 @@ gimple_duplicate_sese_tail (edge entry, edge exit, /* Anything that is outside of the region, but was dominated by something inside needs to update dominance info. */ iterate_fix_dominators (CDI_DOMINATORS, doms, false); - /* Update the SSA web. */ - update_ssa (TODO_update_ssa); if (free_region_copy) free (region_copy); diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 55807fe..c4f2cea 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1827,7 +1827,10 @@ struct GTY(()) tree_decl_common { TYPE_WARN_IF_NOT_ALIGN. */ unsigned int warn_if_not_align : 6; - /* 14 bits unused. */ + /* In FIELD_DECL, this is DECL_NOT_FLEXARRAY. */ + unsigned int decl_not_flexarray : 1; + + /* 13 bits unused. */ /* UID for points-to sets, stable over copying from inlining. */ unsigned int pt_uid; diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 043e1d5..01d4700 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -171,7 +171,7 @@ remap_ssa_name (tree name, copy_body_data *id) n = id->decl_map->get (name); if (n) { - /* WHen we perform edge redirection as part of CFG copy, IPA-SRA can + /* When we perform edge redirection as part of CFG copy, IPA-SRA can remove an unused LHS from a call statement. Such LHS can however still appear in debug statements, but their value is lost in this function and we do not want to map them. */ diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc index 4eb454a..1f04cb8 100644 --- a/gcc/tree-object-size.cc +++ b/gcc/tree-object-size.cc @@ -604,9 +604,9 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) { tree v = var; - /* For &X->fld, compute object size only if fld isn't the last - field, as struct { int i; char c[1]; } is often used instead - of flexible array member. */ + /* For &X->fld, compute object size if fld isn't a flexible array + member. */ + bool is_flexible_array_mem_ref = false; while (v && v != pt_var) switch (TREE_CODE (v)) { @@ -633,6 +633,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, v = NULL_TREE; break; } + is_flexible_array_mem_ref = array_at_struct_end_p (v); while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) != UNION_TYPE @@ -645,12 +646,9 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) == RECORD_TYPE) { - tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1)); - for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain)) - if (TREE_CODE (fld_chain) == FIELD_DECL) - break; - - if (fld_chain) + /* compute object size only if v is not a + flexible array member. */ + if (!is_flexible_array_mem_ref) { v = NULL_TREE; break; diff --git a/gcc/tree-parloops.cc b/gcc/tree-parloops.cc index e4a148b..e680d97 100644 --- a/gcc/tree-parloops.cc +++ b/gcc/tree-parloops.cc @@ -3131,6 +3131,7 @@ gen_parallel_loop (class loop *loop, to the exit of the loop. */ transform_to_exit_first_loop (loop, reduction_list, nit); } + update_ssa (TODO_update_ssa_no_phi); /* Generate initializations for reductions. */ if (!reduction_list->is_empty ()) @@ -4215,6 +4216,10 @@ pass_parallelize_loops::execute (function *fun) checking_verify_loop_structure (); + /* ??? Intermediate SSA updates with no PHIs might have lost + the virtual operand renaming needed by separate_decls_in_region, + make sure to rename them again. */ + mark_virtual_operands_for_renaming (fun); update_ssa (TODO_update_ssa); if (in_loop_pipeline) rewrite_into_loop_closed_ssa (NULL, 0); diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 2cc2c0e..3748440 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -5718,19 +5718,6 @@ visit_reference_op_store (tree lhs, tree op, gimple *stmt) if (!resultsame) { - /* Only perform the following when being called from PRE - which embeds tail merging. */ - if (default_vn_walk_kind == VN_WALK) - { - assign = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, op); - vn_reference_lookup (assign, vuse, VN_NOWALK, &vnresult, false); - if (vnresult) - { - VN_INFO (vdef)->visited = true; - return set_ssa_val_to (vdef, vnresult->result_vdef); - } - } - if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "No store match\n"); @@ -5755,7 +5742,9 @@ visit_reference_op_store (tree lhs, tree op, gimple *stmt) if (default_vn_walk_kind == VN_WALK) { assign = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, op); - vn_reference_insert (assign, lhs, vuse, vdef); + vn_reference_lookup (assign, vuse, VN_NOWALK, &vnresult, false); + if (!vnresult) + vn_reference_insert (assign, lhs, vuse, vdef); } } else diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc index 219cf5e..57923da 100644 --- a/gcc/tree-streamer-in.cc +++ b/gcc/tree-streamer-in.cc @@ -261,6 +261,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr) else SET_DECL_FIELD_ABI_IGNORED (expr, val); expr->decl_common.off_align = bp_unpack_value (bp, 8); + DECL_NOT_FLEXARRAY (expr) = (unsigned) bp_unpack_value (bp, 1); } else if (VAR_P (expr)) diff --git a/gcc/tree-streamer-out.cc b/gcc/tree-streamer-out.cc index 9b114dc..68a2818 100644 --- a/gcc/tree-streamer-out.cc +++ b/gcc/tree-streamer-out.cc @@ -229,6 +229,7 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr) else bp_pack_value (bp, DECL_FIELD_ABI_IGNORED (expr), 1); bp_pack_value (bp, expr->decl_common.off_align, 8); + bp_pack_value (bp, DECL_NOT_FLEXARRAY (expr), 1); } else if (VAR_P (expr)) diff --git a/gcc/tree.cc b/gcc/tree.cc index f8d24b5..c4ead94 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -12691,14 +12691,30 @@ array_ref_up_bound (tree exp) } /* Returns true if REF is an array reference, component reference, - or memory reference to an array at the end of a structure. - If this is the case, the array may be allocated larger - than its upper bound implies. */ + or memory reference to an array whose actual size might be larger + than its upper bound implies, there are multiple cases: + A. a ref to a flexible array member at the end of a structure; + B. a ref to an array with a different type against the original decl; + for example: + short a[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + (*((char(*)[16])&a[0]))[i+8] + + C. a ref to an array that was passed as a parameter; + for example: + + int test (uint8_t *p, uint32_t t[1][1], int n) { + for (int i = 0; i < 4; i++, p++) + t[i][0] = ...; + + FIXME, the name of this routine need to be changed to be more accurate. */ bool array_at_struct_end_p (tree ref) { - tree atype; + /* the TYPE for this array referece. */ + tree atype = NULL_TREE; + /* the FIELD_DECL for the array field in the containing structure. */ + tree afield_decl = NULL_TREE; if (TREE_CODE (ref) == ARRAY_REF || TREE_CODE (ref) == ARRAY_RANGE_REF) @@ -12708,7 +12724,10 @@ array_at_struct_end_p (tree ref) } else if (TREE_CODE (ref) == COMPONENT_REF && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE) - atype = TREE_TYPE (TREE_OPERAND (ref, 1)); + { + atype = TREE_TYPE (TREE_OPERAND (ref, 1)); + afield_decl = TREE_OPERAND (ref, 1); + } else if (TREE_CODE (ref) == MEM_REF) { tree arg = TREE_OPERAND (ref, 0); @@ -12720,6 +12739,7 @@ array_at_struct_end_p (tree ref) if (tree fld = last_field (argtype)) { atype = TREE_TYPE (fld); + afield_decl = fld; if (TREE_CODE (atype) != ARRAY_TYPE) return false; if (VAR_P (arg) && DECL_SIZE (fld)) @@ -12773,13 +12793,16 @@ array_at_struct_end_p (tree ref) ref = TREE_OPERAND (ref, 0); } - /* The array now is at struct end. Treat flexible arrays as + gcc_assert (!afield_decl + || (afield_decl && TREE_CODE (afield_decl) == FIELD_DECL)); + + /* The array now is at struct end. Treat flexible array member as always subject to extend, even into just padding constrained by an underlying decl. */ if (! TYPE_SIZE (atype) || ! TYPE_DOMAIN (atype) || ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) - return true; + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true; /* If the reference is based on a declared entity, the size of the array is constrained by its given domain. (Do not trust commons PR/69368). */ @@ -12801,9 +12824,9 @@ array_at_struct_end_p (tree ref) if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (atype))) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST) - return true; + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true; if (! get_addr_base_and_unit_offset (ref_to_array, &offset)) - return true; + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true; /* If at least one extra element fits it is a flexarray. */ if (known_le ((wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) @@ -12811,12 +12834,12 @@ array_at_struct_end_p (tree ref) + 2) * wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (atype))), wi::to_offset (DECL_SIZE_UNIT (ref)) - offset)) - return true; + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true; return false; } - return true; + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true; } /* Return a tree representing the offset, in bytes, of the field referenced @@ -3005,6 +3005,12 @@ extern void decl_value_expr_insert (tree, tree); #define DECL_PADDING_P(NODE) \ (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_3) +/* Used in a FIELD_DECL to indicate whether this field is not a flexible + array member. This is only valid for the last array type field of a + structure. */ +#define DECL_NOT_FLEXARRAY(NODE) \ + (FIELD_DECL_CHECK (NODE)->decl_common.decl_not_flexarray) + /* A numeric unique identifier for a LABEL_DECL. The UID allocation is dense, unique within any one function, and may be used to index arrays. If the value is -1, then no UID has been assigned. */ @@ -5547,10 +5553,10 @@ extern tree component_ref_field_offset (tree); returns null. */ enum struct special_array_member { - none, /* Not a special array member. */ - int_0, /* Interior array member with size zero. */ - trail_0, /* Trailing array member with size zero. */ - trail_1 /* Trailing array member with one element. */ + none, /* Not a special array member. */ + int_0, /* Interior array member with size zero. */ + trail_0, /* Trailing array member with size zero. */ + trail_1 /* Trailing array member with one element. */ }; /* Return the size of the member referenced by the COMPONENT_REF, using diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print.cc index 8cbe97b..3a3b4b4 100644 --- a/gcc/value-range-pretty-print.cc +++ b/gcc/value-range-pretty-print.cc @@ -123,7 +123,11 @@ vrange_printer::print_real_value (tree type, const REAL_VALUE_TYPE &r) const char s[100]; real_to_decimal_for_mode (s, &r, sizeof (s), 0, 1, TYPE_MODE (type)); pp_string (pp, s); - if (!DECIMAL_FLOAT_TYPE_P (type)) + if (!DECIMAL_FLOAT_TYPE_P (type) + // real_to_hexadecimal prints infinities and NAN as text. No + // need to print them twice. + && !real_isinf (&r) + && !real_isnan (&r)) { real_to_hexadecimal (s, &r, sizeof (s), 0, 1); pp_printf (pp, " (%s)", s); diff --git a/gcc/value-range.cc b/gcc/value-range.cc index afb26a4..a14f9bc 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -304,13 +304,8 @@ frange::set (tree type, if (real_isnan (&min) || real_isnan (&max)) { gcc_checking_assert (real_identical (&min, &max)); - if (HONOR_NANS (type)) - { - bool sign = real_isneg (&min); - set_nan (type, sign); - } - else - set_undefined (); + bool sign = real_isneg (&min); + set_nan (type, sign); return; } @@ -940,7 +935,7 @@ irange::irange_set (tree min, tree max) m_base[1] = max; m_num_ranges = 1; m_kind = VR_RANGE; - m_nonzero_mask = wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (min))); + m_nonzero_mask = NULL; normalize_kind (); if (flag_checking) @@ -1014,7 +1009,7 @@ irange::irange_set_anti_range (tree min, tree max) } m_kind = VR_RANGE; - m_nonzero_mask = wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (min))); + m_nonzero_mask = NULL; normalize_kind (); if (flag_checking) @@ -1071,7 +1066,7 @@ irange::set (tree min, tree max, value_range_kind kind) m_base[0] = min; m_base[1] = max; m_num_ranges = 1; - m_nonzero_mask = wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (min))); + m_nonzero_mask = NULL; return; } @@ -1121,7 +1116,7 @@ irange::set (tree min, tree max, value_range_kind kind) m_base[0] = min; m_base[1] = max; m_num_ranges = 1; - m_nonzero_mask = wi::shwi (-1, TYPE_PRECISION (TREE_TYPE (min))); + m_nonzero_mask = NULL; normalize_kind (); if (flag_checking) verify_range (); @@ -1140,7 +1135,8 @@ irange::verify_range () } if (m_kind == VR_VARYING) { - gcc_checking_assert (m_nonzero_mask == -1); + gcc_checking_assert (!m_nonzero_mask + || wi::to_wide (m_nonzero_mask) == -1); gcc_checking_assert (m_num_ranges == 1); gcc_checking_assert (varying_compatible_p ()); return; @@ -1414,10 +1410,10 @@ irange::contains_p (tree cst) const gcc_checking_assert (TREE_CODE (cst) == INTEGER_CST); // See if we can exclude CST based on the nonzero bits. - if (m_nonzero_mask != -1) + if (m_nonzero_mask) { wide_int cstw = wi::to_wide (cst); - if (cstw != 0 && wi::bit_and (m_nonzero_mask, cstw) == 0) + if (cstw != 0 && wi::bit_and (wi::to_wide (m_nonzero_mask), cstw) == 0) return false; } @@ -2513,7 +2509,7 @@ irange::irange_contains_p (const irange &r) const // Otherwise, check if this's pair occurs before R's. if (wi::lt_p (wi::to_wide (u), wi::to_wide (rl), sign)) { - // THere's still at leats one pair of R left. + // There's still at least one pair of R left. if (++i >= num_pairs ()) return false; l = m_base[i * 2]; @@ -2781,7 +2777,7 @@ irange::invert () signop sign = TYPE_SIGN (ttype); wide_int type_min = wi::min_value (prec, sign); wide_int type_max = wi::max_value (prec, sign); - m_nonzero_mask = wi::shwi (-1, prec); + m_nonzero_mask = NULL; if (m_num_ranges == m_max_ranges && lower_bound () != type_min && upper_bound () != type_max) @@ -2883,20 +2879,22 @@ bool irange::set_range_from_nonzero_bits () { gcc_checking_assert (!undefined_p ()); - unsigned popcount = wi::popcount (m_nonzero_mask); + if (!m_nonzero_mask) + return false; + unsigned popcount = wi::popcount (wi::to_wide (m_nonzero_mask)); // If we have only one bit set in the mask, we can figure out the // range immediately. if (popcount == 1) { // Make sure we don't pessimize the range. - if (!contains_p (wide_int_to_tree (type (), m_nonzero_mask))) + if (!contains_p (m_nonzero_mask)) return false; bool has_zero = contains_p (build_zero_cst (type ())); - wide_int bits = m_nonzero_mask; - set (type (), bits, bits); - m_nonzero_mask = bits; + tree nz = m_nonzero_mask; + set (nz, nz); + m_nonzero_mask = nz; if (has_zero) { int_range<2> zero; @@ -2913,13 +2911,22 @@ irange::set_nonzero_bits (const wide_int_ref &bits) { gcc_checking_assert (!undefined_p ()); unsigned prec = TYPE_PRECISION (type ()); - gcc_checking_assert (prec == bits.get_precision ()); + + if (bits == -1) + { + m_nonzero_mask = NULL; + normalize_kind (); + if (flag_checking) + verify_range (); + return; + } // Drop VARYINGs with a nonzero mask to a plain range. if (m_kind == VR_VARYING && bits != -1) m_kind = VR_RANGE; - m_nonzero_mask = wide_int::from (bits, prec, TYPE_SIGN (type ())); + wide_int nz = wide_int::from (bits, prec, TYPE_SIGN (type ())); + m_nonzero_mask = wide_int_to_tree (type (), nz); if (set_range_from_nonzero_bits ()) return; @@ -2943,7 +2950,21 @@ irange::get_nonzero_bits () const // the mask precisely up to date at all times. Instead, we default // to -1 and set it when explicitly requested. However, this // function will always return the correct mask. - return m_nonzero_mask & get_nonzero_bits_from_range (); + if (m_nonzero_mask) + return wi::to_wide (m_nonzero_mask) & get_nonzero_bits_from_range (); + else + return get_nonzero_bits_from_range (); +} + +// Convert tree mask to wide_int. Returns -1 for NULL masks. + +inline wide_int +mask_to_wi (tree mask, tree type) +{ + if (mask) + return wi::to_wide (mask); + else + return wi::shwi (-1, TYPE_PRECISION (type)); } // Intersect the nonzero bits in R into THIS and normalize the range. @@ -2954,10 +2975,20 @@ irange::intersect_nonzero_bits (const irange &r) { gcc_checking_assert (!undefined_p () && !r.undefined_p ()); + if (!m_nonzero_mask && !r.m_nonzero_mask) + { + normalize_kind (); + if (flag_checking) + verify_range (); + return false; + } + bool changed = false; - if (m_nonzero_mask != r.m_nonzero_mask) + tree t = type (); + if (mask_to_wi (m_nonzero_mask, t) != mask_to_wi (r.m_nonzero_mask, t)) { - m_nonzero_mask = get_nonzero_bits () & r.get_nonzero_bits (); + wide_int nz = get_nonzero_bits () & r.get_nonzero_bits (); + m_nonzero_mask = wide_int_to_tree (t, nz); if (set_range_from_nonzero_bits ()) return true; changed = true; @@ -2976,10 +3007,20 @@ irange::union_nonzero_bits (const irange &r) { gcc_checking_assert (!undefined_p () && !r.undefined_p ()); + if (!m_nonzero_mask && !r.m_nonzero_mask) + { + normalize_kind (); + if (flag_checking) + verify_range (); + return false; + } + bool changed = false; - if (m_nonzero_mask != r.m_nonzero_mask) + tree t = type (); + if (mask_to_wi (m_nonzero_mask, t) != mask_to_wi (r.m_nonzero_mask, t)) { - m_nonzero_mask = get_nonzero_bits () | r.get_nonzero_bits (); + wide_int nz = get_nonzero_bits () | r.get_nonzero_bits (); + m_nonzero_mask = wide_int_to_tree (t, nz); // No need to call set_range_from_nonzero_bits, because we'll // never narrow the range. Besides, it would cause endless // recursion because of the union_ in @@ -3625,6 +3666,7 @@ range_tests_nan () { frange r0, r1; REAL_VALUE_TYPE q, r; + bool signbit; // Equal ranges but with differing NAN bits are not equal. if (HONOR_NANS (float_type_node)) @@ -3736,6 +3778,26 @@ range_tests_nan () r0.set_nan (float_type_node); r0.clear_nan (); ASSERT_TRUE (r0.undefined_p ()); + + // [10,20] NAN ^ [21,25] NAN = [NAN] + r0 = frange_float ("10", "20"); + r0.update_nan (); + r1 = frange_float ("21", "25"); + r1.update_nan (); + r0.intersect (r1); + ASSERT_TRUE (r0.known_isnan ()); + + // NAN U [5,6] should be [5,6] +-NAN. + r0.set_nan (float_type_node); + r1 = frange_float ("5", "6"); + r1.clear_nan (); + r0.union_ (r1); + real_from_string (&q, "5"); + real_from_string (&r, "6"); + ASSERT_TRUE (real_identical (&q, &r0.lower_bound ())); + ASSERT_TRUE (real_identical (&r, &r0.upper_bound ())); + ASSERT_TRUE (!r0.signbit_p (signbit)); + ASSERT_TRUE (r0.maybe_isnan ()); } static void @@ -3743,7 +3805,6 @@ range_tests_signed_zeros () { tree zero = build_zero_cst (float_type_node); tree neg_zero = fold_build1 (NEGATE_EXPR, float_type_node, zero); - REAL_VALUE_TYPE q, r; frange r0, r1; bool signbit; @@ -3789,18 +3850,6 @@ range_tests_signed_zeros () r0.intersect (r1); ASSERT_TRUE (r0.zero_p ()); - // NAN U [5,6] should be [5,6] NAN. - r0.set_nan (float_type_node); - r1 = frange_float ("5", "6"); - r1.clear_nan (); - r0.union_ (r1); - real_from_string (&q, "5"); - real_from_string (&r, "6"); - ASSERT_TRUE (real_identical (&q, &r0.lower_bound ())); - ASSERT_TRUE (real_identical (&r, &r0.upper_bound ())); - ASSERT_TRUE (!r0.signbit_p (signbit)); - ASSERT_TRUE (r0.maybe_isnan ()); - r0 = frange_float ("+0", "5"); r0.clear_nan (); ASSERT_TRUE (r0.signbit_p (signbit) && !signbit); @@ -3824,7 +3873,10 @@ range_tests_signed_zeros () r1 = frange_float ("0", "0"); r1.update_nan (); r0.intersect (r1); - ASSERT_TRUE (r0.known_isnan ()); + if (HONOR_NANS (float_type_node)) + ASSERT_TRUE (r0.known_isnan ()); + else + ASSERT_TRUE (r0.undefined_p ()); r0.set_nonnegative (float_type_node); ASSERT_TRUE (r0.signbit_p (signbit) && !signbit); @@ -3864,7 +3916,8 @@ range_tests_floats () { frange r0, r1; - range_tests_nan (); + if (HONOR_NANS (float_type_node)) + range_tests_nan (); range_tests_signbit (); if (HONOR_SIGNED_ZEROS (float_type_node)) @@ -3937,14 +3990,6 @@ range_tests_floats () r0.intersect (r1); ASSERT_EQ (r0, frange_float ("15", "20")); - // [10,20] NAN ^ [21,25] NAN = [NAN] - r0 = frange_float ("10", "20"); - r0.update_nan (); - r1 = frange_float ("21", "25"); - r1.update_nan (); - r0.intersect (r1); - ASSERT_TRUE (r0.known_isnan ()); - // [10,20] ^ [21,25] = [] r0 = frange_float ("10", "20"); r0.clear_nan (); diff --git a/gcc/value-range.h b/gcc/value-range.h index d166362..484f911 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -215,7 +215,7 @@ private: bool intersect (const wide_int& lb, const wide_int& ub); unsigned char m_num_ranges; unsigned char m_max_ranges; - wide_int m_nonzero_mask; + tree m_nonzero_mask; tree *m_base; }; @@ -683,11 +683,11 @@ irange::varying_compatible_p () const if (INTEGRAL_TYPE_P (t)) return (wi::to_wide (l) == wi::min_value (prec, sign) && wi::to_wide (u) == wi::max_value (prec, sign) - && m_nonzero_mask == -1); + && (!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == -1)); if (POINTER_TYPE_P (t)) return (wi::to_wide (l) == 0 && wi::to_wide (u) == wi::max_value (prec, sign) - && m_nonzero_mask == -1); + && (!m_nonzero_mask || wi::to_wide (m_nonzero_mask) == -1)); return true; } @@ -754,6 +754,8 @@ gt_ggc_mx (irange *x) gt_ggc_mx (x->m_base[i * 2]); gt_ggc_mx (x->m_base[i * 2 + 1]); } + if (x->m_nonzero_mask) + gt_ggc_mx (x->m_nonzero_mask); } inline void @@ -764,6 +766,8 @@ gt_pch_nx (irange *x) gt_pch_nx (x->m_base[i * 2]); gt_pch_nx (x->m_base[i * 2 + 1]); } + if (x->m_nonzero_mask) + gt_pch_nx (x->m_nonzero_mask); } inline void @@ -774,6 +778,8 @@ gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie) op (&x->m_base[i * 2], NULL, cookie); op (&x->m_base[i * 2 + 1], NULL, cookie); } + if (x->m_nonzero_mask) + op (&x->m_nonzero_mask, NULL, cookie); } template<unsigned N> @@ -868,6 +874,7 @@ irange::set_undefined () { m_kind = VR_UNDEFINED; m_num_ranges = 0; + m_nonzero_mask = NULL; } inline void @@ -875,11 +882,7 @@ irange::set_varying (tree type) { m_kind = VR_VARYING; m_num_ranges = 1; - - if (type == error_mark_node) - m_nonzero_mask = wi::shwi (-1, 1); - else - m_nonzero_mask = wi::shwi (-1, TYPE_PRECISION (type)); + m_nonzero_mask = NULL; if (INTEGRAL_TYPE_P (type)) { @@ -1111,11 +1114,14 @@ inline void frange::update_nan () { gcc_checking_assert (!undefined_p ()); - m_pos_nan = true; - m_neg_nan = true; - normalize_kind (); - if (flag_checking) - verify_range (); + if (HONOR_NANS (m_type)) + { + m_pos_nan = true; + m_neg_nan = true; + normalize_kind (); + if (flag_checking) + verify_range (); + } } // Like above, but set the sign of the NAN. @@ -1124,11 +1130,14 @@ inline void frange::update_nan (bool sign) { gcc_checking_assert (!undefined_p ()); - m_pos_nan = !sign; - m_neg_nan = sign; - normalize_kind (); - if (flag_checking) - verify_range (); + if (HONOR_NANS (m_type)) + { + m_pos_nan = !sign; + m_neg_nan = sign; + normalize_kind (); + if (flag_checking) + verify_range (); + } } // Clear the NAN bit and adjust the range. @@ -1213,12 +1222,17 @@ frange_val_is_max (const REAL_VALUE_TYPE &r, const_tree type) inline void frange::set_nan (tree type) { - m_kind = VR_NAN; - m_type = type; - m_pos_nan = true; - m_neg_nan = true; - if (flag_checking) - verify_range (); + if (HONOR_NANS (type)) + { + m_kind = VR_NAN; + m_type = type; + m_pos_nan = true; + m_neg_nan = true; + if (flag_checking) + verify_range (); + } + else + set_undefined (); } // Build a NAN of type TYPE with SIGN. @@ -1226,12 +1240,17 @@ frange::set_nan (tree type) inline void frange::set_nan (tree type, bool sign) { - m_kind = VR_NAN; - m_type = type; - m_neg_nan = sign; - m_pos_nan = !sign; - if (flag_checking) - verify_range (); + if (HONOR_NANS (type)) + { + m_kind = VR_NAN; + m_type = type; + m_neg_nan = sign; + m_pos_nan = !sign; + if (flag_checking) + verify_range (); + } + else + set_undefined (); } // Return TRUE if range is known to be finite. diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc index e6f5ef4..1ee6da1 100644 --- a/gcc/value-relation.cc +++ b/gcc/value-relation.cc @@ -955,7 +955,7 @@ dom_oracle::set_one_relation (basic_block bb, relation_kind k, tree op1, ptr->dump (dump_file); } // Check into whether we can simply replace the relation rather than - // intersecting it. THis may help with some optimistic iterative + // intersecting it. This may help with some optimistic iterative // updating algorithms. bool new_rel = ptr->intersect (vr); if (dump_file && (dump_flags & TDF_DETAILS)) diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc index 626a918..71fed1e 100644 --- a/gcc/vr-values.cc +++ b/gcc/vr-values.cc @@ -184,21 +184,23 @@ vr_values::range_of_expr (vrange &r, tree expr, gimple *stmt) if (const value_range *vr = get_value_range (expr, stmt)) { + if (!vr->supports_type_p (TREE_TYPE (expr))) + { + // vr_values::extract_range_basic() use of ranger's + // fold_range() can create a situation where we are asked + // for the range of an unsupported legacy type. Since + // get_value_range() above will return varying or undefined + // for such types, avoid copying incompatible range types. + if (vr->undefined_p ()) + r.set_undefined (); + else + r.set_varying (TREE_TYPE (expr)); + return true; + } if (vr->undefined_p () || vr->constant_p ()) r = *vr; else { - if (!vr->supports_type_p (TREE_TYPE (expr))) - { - // vr_values::extract_range_basic() use of ranger's - // fold_range() can create a situation where we are - // asked for the range of an unsupported legacy type. - // Since get_value_range() above will return varying for - // such types, avoid copying incompatible range types. - gcc_checking_assert (vr->varying_p ()); - r.set_varying (TREE_TYPE (expr)); - return true; - } value_range tmp = *vr; tmp.normalize_symbolics (); r = tmp; diff --git a/libdecnumber/ChangeLog b/libdecnumber/ChangeLog index 774c358..71e5c07 100644 --- a/libdecnumber/ChangeLog +++ b/libdecnumber/ChangeLog @@ -1,3 +1,7 @@ +2022-10-07 Martin Liska <mliska@suse.cz> + + * dpd/decimal64.c (decDigitsToDPD): Remove unused variable. + 2022-05-20 Christophe Lyon <christophe.lyon@arm.com> * configure: Regenerate. diff --git a/libdecnumber/dpd/decimal64.c b/libdecnumber/dpd/decimal64.c index 269eaec..f72c573 100644 --- a/libdecnumber/dpd/decimal64.c +++ b/libdecnumber/dpd/decimal64.c @@ -614,7 +614,6 @@ static const uInt multies[]={131073, 26215, 5243, 1049, 210}; #endif void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { Int cut; /* work */ - Int n; /* output bunch counter */ Int digits=dn->digits; /* digit countdown */ uInt dpd; /* densely packed decimal value */ uInt bin; /* binary value 0-999 */ @@ -673,7 +672,7 @@ void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { bin=0; /* [keep compiler quiet] */ #endif - for(n=0; digits>0; n++) { /* each output bunch */ + for(; digits>0;) { /* each output bunch */ #if DECDPUN==3 /* fast path, 3-at-a-time */ bin=*inu; /* 3 digits ready for convert */ digits-=3; /* [may go negative] */ diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 8660fb3..06240c1 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,71 @@ +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + * config/arc/linux-unwind.h (arc_fallback_frame_state): Use + fs->regs.how[X] instead of fs->regs.reg[X].how. + +2022-10-06 Jakub Jelinek <jakub@redhat.com> + + * unwind-dw2.h (REG_UNSAVED, REG_SAVED_OFFSET, REG_SAVED_REG, + REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, REG_SAVED_VAL_EXP, + REG_UNDEFINED): New anonymous enum, moved from inside of + struct frame_state_reg_info. + (struct frame_state_reg_info): Remove reg[].how element and the + anonymous enum there. Add how element. + * unwind-dw2.c: Include stddef.h. + (uw_frame_state_for): Don't clear first + offsetof (_Unwind_FrameState, regs.how[0]) bytes of *fs. + (execute_cfa_program, __frame_state_for, uw_update_context_1, + uw_update_context): Use fs->regs.how[X] instead of fs->regs.reg[X].how + or fs.regs.how[X] instead of fs.regs.reg[X].how. + * config/sh/linux-unwind.h (sh_fallback_frame_state): Likewise. + * config/bfin/linux-unwind.h (bfin_fallback_frame_state): Likewise. + * config/pa/linux-unwind.h (pa32_fallback_frame_state): Likewise. + * config/pa/hpux-unwind.h (UPDATE_FS_FOR_SAR, UPDATE_FS_FOR_GR, + UPDATE_FS_FOR_FR, UPDATE_FS_FOR_PC, pa_fallback_frame_state): + Likewise. + * config/alpha/vms-unwind.h (alpha_vms_fallback_frame_state): + Likewise. + * config/alpha/linux-unwind.h (alpha_fallback_frame_state): Likewise. + * config/arc/linux-unwind.h (arc_fallback_frame_state, + arc_frob_update_context): Likewise. + * config/riscv/linux-unwind.h (riscv_fallback_frame_state): Likewise. + * config/nios2/linux-unwind.h (NIOS2_REG): Likewise. + * config/nds32/linux-unwind.h (NDS32_PUT_FS_REG): Likewise. + * config/s390/tpf-unwind.h (s390_fallback_frame_state): Likewise. + * config/s390/linux-unwind.h (s390_fallback_frame_state): Likewise. + * config/sparc/sol2-unwind.h (sparc64_frob_update_context, + MD_FALLBACK_FRAME_STATE_FOR): Likewise. + * config/sparc/linux-unwind.h (sparc64_fallback_frame_state, + sparc64_frob_update_context, sparc_fallback_frame_state): Likewise. + * config/i386/sol2-unwind.h (x86_64_fallback_frame_state, + x86_fallback_frame_state): Likewise. + * config/i386/w32-unwind.h (i386_w32_fallback_frame_state): Likewise. + * config/i386/linux-unwind.h (x86_64_fallback_frame_state, + x86_fallback_frame_state): Likewise. + * config/i386/freebsd-unwind.h (x86_64_freebsd_fallback_frame_state): + Likewise. + * config/i386/dragonfly-unwind.h + (x86_64_dragonfly_fallback_frame_state): Likewise. + * config/i386/gnu-unwind.h (x86_gnu_fallback_frame_state): Likewise. + * config/csky/linux-unwind.h (csky_fallback_frame_state): Likewise. + * config/aarch64/linux-unwind.h (aarch64_fallback_frame_state): + Likewise. + * config/aarch64/freebsd-unwind.h + (aarch64_freebsd_fallback_frame_state): Likewise. + * config/aarch64/aarch64-unwind.h (aarch64_frob_update_context): + Likewise. + * config/or1k/linux-unwind.h (or1k_fallback_frame_state): Likewise. + * config/mips/linux-unwind.h (mips_fallback_frame_state): Likewise. + * config/loongarch/linux-unwind.h (loongarch_fallback_frame_state): + Likewise. + * config/m68k/linux-unwind.h (m68k_fallback_frame_state): Likewise. + * config/xtensa/linux-unwind.h (xtensa_fallback_frame_state): + Likewise. + * config/rs6000/darwin-fallback.c (set_offset): Likewise. + * config/rs6000/aix-unwind.h (MD_FROB_UPDATE_CONTEXT): Likewise. + * config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Likewise. + * config/rs6000/freebsd-unwind.h (frob_update_context): Likewise. + 2022-10-02 Olivier Hainque <hainque@adacore.com> * config/t-vxworks (LIBGCC2_INCLUDE): Augment comment. Move diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h index e082e95..26db9cb 100644 --- a/libgcc/config/aarch64/aarch64-unwind.h +++ b/libgcc/config/aarch64/aarch64-unwind.h @@ -80,7 +80,7 @@ aarch64_frob_update_context (struct _Unwind_Context *context, { const int reg = DWARF_REGNUM_AARCH64_RA_STATE; int ra_signed; - if (fs->regs.reg[reg].how == REG_UNSAVED) + if (fs->regs.how[reg] == REG_UNSAVED) ra_signed = fs->regs.reg[reg].loc.offset & 0x1; else ra_signed = _Unwind_GetGR (context, reg) & 0x1; diff --git a/libgcc/config/aarch64/freebsd-unwind.h b/libgcc/config/aarch64/freebsd-unwind.h index 8d64680..2f795fb 100644 --- a/libgcc/config/aarch64/freebsd-unwind.h +++ b/libgcc/config/aarch64/freebsd-unwind.h @@ -90,7 +90,7 @@ aarch64_freebsd_fallback_frame_state fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; for (n = 0; n < 32; n++) - fs->regs.reg[n].how = REG_SAVED_OFFSET; + fs->regs.how[n] = REG_SAVED_OFFSET; for (n = 0; n < 30; n++) fs->regs.reg[n].loc.offset = (_Unwind_Ptr) &(sc->XREG(n)) - new_cfa; @@ -98,7 +98,7 @@ aarch64_freebsd_fallback_frame_state fs->regs.reg[30].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(lr)) - new_cfa; fs->regs.reg[31].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(sp)) - new_cfa; - fs->regs.reg[DARC].how = REG_SAVED_OFFSET; + fs->regs.how[DARC] = REG_SAVED_OFFSET; fs->regs.reg[DARC].loc.offset = (_Unwind_Ptr) &(sc->REG_NAME(elr)) - new_cfa; fs->retaddr_column = DARC; diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h index 551b489..bce3f3c 100644 --- a/libgcc/config/aarch64/linux-unwind.h +++ b/libgcc/config/aarch64/linux-unwind.h @@ -89,7 +89,7 @@ aarch64_fallback_frame_state (struct _Unwind_Context *context, for (i = 0; i < AARCH64_DWARF_NUMBER_R; i++) { - fs->regs.reg[AARCH64_DWARF_R0 + i].how = REG_SAVED_OFFSET; + fs->regs.how[AARCH64_DWARF_R0 + i] = REG_SAVED_OFFSET; fs->regs.reg[AARCH64_DWARF_R0 + i].loc.offset = (_Unwind_Ptr) & (sc->regs[i]) - new_cfa; } @@ -115,7 +115,7 @@ aarch64_fallback_frame_state (struct _Unwind_Context *context, { _Unwind_Sword offset; - fs->regs.reg[AARCH64_DWARF_V0 + i].how = REG_SAVED_OFFSET; + fs->regs.how[AARCH64_DWARF_V0 + i] = REG_SAVED_OFFSET; /* sigcontext contains 32 128bit registers for V0 to V31. The kernel will have saved the contents of the @@ -142,12 +142,12 @@ aarch64_fallback_frame_state (struct _Unwind_Context *context, } } - fs->regs.reg[31].how = REG_SAVED_OFFSET; + fs->regs.how[31] = REG_SAVED_OFFSET; fs->regs.reg[31].loc.offset = (_Unwind_Ptr) & (sc->sp) - new_cfa; fs->signal_frame = 1; - fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].how = + fs->regs.how[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__] = REG_SAVED_VAL_OFFSET; fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].loc.offset = (_Unwind_Ptr) (sc->pc) - new_cfa; diff --git a/libgcc/config/alpha/linux-unwind.h b/libgcc/config/alpha/linux-unwind.h index 1f7f95e..1a3a69d 100644 --- a/libgcc/config/alpha/linux-unwind.h +++ b/libgcc/config/alpha/linux-unwind.h @@ -67,17 +67,17 @@ alpha_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (long) context->cfa; for (i = 0; i < 30; ++i) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (long) &sc->sc_regs[i] - new_cfa; } for (i = 0; i < 31; ++i) { - fs->regs.reg[i+32].how = REG_SAVED_OFFSET; + fs->regs.how[i+32] = REG_SAVED_OFFSET; fs->regs.reg[i+32].loc.offset = (long) &sc->sc_fpregs[i] - new_cfa; } - fs->regs.reg[64].how = REG_SAVED_OFFSET; + fs->regs.how[64] = REG_SAVED_OFFSET; fs->regs.reg[64].loc.offset = (long)&sc->sc_pc - new_cfa; fs->retaddr_column = 64; fs->signal_frame = 1; diff --git a/libgcc/config/alpha/vms-unwind.h b/libgcc/config/alpha/vms-unwind.h index 5219d8e..71b59a6 100644 --- a/libgcc/config/alpha/vms-unwind.h +++ b/libgcc/config/alpha/vms-unwind.h @@ -50,7 +50,7 @@ extern int SYS$GL_CALL_HANDL; #define UPDATE_FS_FOR_CFA_GR(FS, GRN, LOC, CFA) \ do { \ -(FS)->regs.reg[GRN].how = REG_SAVED_OFFSET; \ +(FS)->regs.how[GRN] = REG_SAVED_OFFSET; \ (FS)->regs.reg[GRN].loc.offset = (_Unwind_Sword) ((REG) (LOC) - (REG) (CFA)); \ } while (0); @@ -212,10 +212,10 @@ alpha_vms_fallback_frame_state (struct _Unwind_Context *context, if (eh_debug) printf ("FALLBACK: REGISTER frame procedure\n"); - fs->regs.reg[RA_COLUMN].how = REG_SAVED_REG; + fs->regs.how[RA_COLUMN] = REG_SAVED_REG; fs->regs.reg[RA_COLUMN].loc.reg = pv->pdsc$b_save_ra; - fs->regs.reg[29].how = REG_SAVED_REG; + fs->regs.how[29] = REG_SAVED_REG; fs->regs.reg[29].loc.reg = pv->pdsc$b_save_fp; break; diff --git a/libgcc/config/arc/linux-unwind.h b/libgcc/config/arc/linux-unwind.h index be42a31..b3f2dde 100644 --- a/libgcc/config/arc/linux-unwind.h +++ b/libgcc/config/arc/linux-unwind.h @@ -115,14 +115,14 @@ arc_fallback_frame_state (struct _Unwind_Context *context, { if (register_id_for_index[i] == -1) continue; - fs->regs.reg[register_id_for_index[i]].how = REG_SAVED_OFFSET; + fs->regs.how[register_id_for_index[i]] = REG_SAVED_OFFSET; fs->regs.reg[register_id_for_index[i]].loc.offset = ((_Unwind_Ptr) &(regs[i])) - new_cfa; } fs->signal_frame = 1; fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__; - fs->regs.reg[fs->retaddr_column].how = REG_SAVED_VAL_OFFSET; + fs->regs.how[fs->retaddr_column] = REG_SAVED_VAL_OFFSET; fs->regs.reg[fs->retaddr_column].loc.offset = ((_Unwind_Ptr) (regs[ret])) - new_cfa; @@ -140,7 +140,7 @@ arc_frob_update_context (struct _Unwind_Context *context, _Unwind_Word fp_val; asm ("mov %0,fp" : "=r" (fp_val)); - switch (fs->regs.reg[27].how) + switch (fs->regs.how[27]) { case REG_UNSAVED: case REG_UNDEFINED: diff --git a/libgcc/config/bfin/linux-unwind.h b/libgcc/config/bfin/linux-unwind.h index 34ab7da..de7e321 100644 --- a/libgcc/config/bfin/linux-unwind.h +++ b/libgcc/config/bfin/linux-unwind.h @@ -68,93 +68,93 @@ bfin_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_reg = 14; fs->regs.cfa_offset = new_cfa - (long) context->cfa; - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&sc->sc_r0 - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&sc->sc_r1 - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&sc->sc_r2 - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&sc->sc_r3 - new_cfa; - fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.how[4] = REG_SAVED_OFFSET; fs->regs.reg[4].loc.offset = (long)&sc->sc_r4 - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&sc->sc_r5 - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&sc->sc_r6 - new_cfa; - fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.how[7] = REG_SAVED_OFFSET; fs->regs.reg[7].loc.offset = (long)&sc->sc_r7 - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&sc->sc_p0 - new_cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.how[9] = REG_SAVED_OFFSET; fs->regs.reg[9].loc.offset = (long)&sc->sc_p1 - new_cfa; - fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.how[10] = REG_SAVED_OFFSET; fs->regs.reg[10].loc.offset = (long)&sc->sc_p2 - new_cfa; - fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.how[11] = REG_SAVED_OFFSET; fs->regs.reg[11].loc.offset = (long)&sc->sc_p3 - new_cfa; - fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.how[12] = REG_SAVED_OFFSET; fs->regs.reg[12].loc.offset = (long)&sc->sc_p4 - new_cfa; - fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.how[13] = REG_SAVED_OFFSET; fs->regs.reg[13].loc.offset = (long)&sc->sc_p5 - new_cfa; - fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.how[15] = REG_SAVED_OFFSET; fs->regs.reg[15].loc.offset = (long)&sc->sc_fp - new_cfa; - fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.how[16] = REG_SAVED_OFFSET; fs->regs.reg[16].loc.offset = (long)&sc->sc_i0 - new_cfa; - fs->regs.reg[17].how = REG_SAVED_OFFSET; + fs->regs.how[17] = REG_SAVED_OFFSET; fs->regs.reg[17].loc.offset = (long)&sc->sc_i1 - new_cfa; - fs->regs.reg[18].how = REG_SAVED_OFFSET; + fs->regs.how[18] = REG_SAVED_OFFSET; fs->regs.reg[18].loc.offset = (long)&sc->sc_i2 - new_cfa; - fs->regs.reg[19].how = REG_SAVED_OFFSET; + fs->regs.how[19] = REG_SAVED_OFFSET; fs->regs.reg[19].loc.offset = (long)&sc->sc_i3 - new_cfa; - fs->regs.reg[20].how = REG_SAVED_OFFSET; + fs->regs.how[20] = REG_SAVED_OFFSET; fs->regs.reg[20].loc.offset = (long)&sc->sc_b0 - new_cfa; - fs->regs.reg[21].how = REG_SAVED_OFFSET; + fs->regs.how[21] = REG_SAVED_OFFSET; fs->regs.reg[21].loc.offset = (long)&sc->sc_b1 - new_cfa; - fs->regs.reg[22].how = REG_SAVED_OFFSET; + fs->regs.how[22] = REG_SAVED_OFFSET; fs->regs.reg[22].loc.offset = (long)&sc->sc_b2 - new_cfa; - fs->regs.reg[23].how = REG_SAVED_OFFSET; + fs->regs.how[23] = REG_SAVED_OFFSET; fs->regs.reg[23].loc.offset = (long)&sc->sc_b3 - new_cfa; - fs->regs.reg[24].how = REG_SAVED_OFFSET; + fs->regs.how[24] = REG_SAVED_OFFSET; fs->regs.reg[24].loc.offset = (long)&sc->sc_l0 - new_cfa; - fs->regs.reg[25].how = REG_SAVED_OFFSET; + fs->regs.how[25] = REG_SAVED_OFFSET; fs->regs.reg[25].loc.offset = (long)&sc->sc_l1 - new_cfa; - fs->regs.reg[26].how = REG_SAVED_OFFSET; + fs->regs.how[26] = REG_SAVED_OFFSET; fs->regs.reg[26].loc.offset = (long)&sc->sc_l2 - new_cfa; - fs->regs.reg[27].how = REG_SAVED_OFFSET; + fs->regs.how[27] = REG_SAVED_OFFSET; fs->regs.reg[27].loc.offset = (long)&sc->sc_l3 - new_cfa; - fs->regs.reg[28].how = REG_SAVED_OFFSET; + fs->regs.how[28] = REG_SAVED_OFFSET; fs->regs.reg[28].loc.offset = (long)&sc->sc_m0 - new_cfa; - fs->regs.reg[29].how = REG_SAVED_OFFSET; + fs->regs.how[29] = REG_SAVED_OFFSET; fs->regs.reg[29].loc.offset = (long)&sc->sc_m1 - new_cfa; - fs->regs.reg[30].how = REG_SAVED_OFFSET; + fs->regs.how[30] = REG_SAVED_OFFSET; fs->regs.reg[30].loc.offset = (long)&sc->sc_m2 - new_cfa; - fs->regs.reg[31].how = REG_SAVED_OFFSET; + fs->regs.how[31] = REG_SAVED_OFFSET; fs->regs.reg[31].loc.offset = (long)&sc->sc_m3 - new_cfa; /* FIXME: Handle A0, A1, CC. */ - fs->regs.reg[35].how = REG_SAVED_OFFSET; + fs->regs.how[35] = REG_SAVED_OFFSET; fs->regs.reg[35].loc.offset = (long)&sc->sc_rets - new_cfa; - fs->regs.reg[36].how = REG_SAVED_OFFSET; + fs->regs.how[36] = REG_SAVED_OFFSET; fs->regs.reg[36].loc.offset = (long)&sc->sc_pc - new_cfa; - fs->regs.reg[37].how = REG_SAVED_OFFSET; + fs->regs.how[37] = REG_SAVED_OFFSET; fs->regs.reg[37].loc.offset = (long)&sc->sc_retx - new_cfa; - fs->regs.reg[40].how = REG_SAVED_OFFSET; + fs->regs.how[40] = REG_SAVED_OFFSET; fs->regs.reg[40].loc.offset = (long)&sc->sc_astat - new_cfa; - fs->regs.reg[41].how = REG_SAVED_OFFSET; + fs->regs.how[41] = REG_SAVED_OFFSET; fs->regs.reg[41].loc.offset = (long)&sc->sc_seqstat - new_cfa; - fs->regs.reg[44].how = REG_SAVED_OFFSET; + fs->regs.how[44] = REG_SAVED_OFFSET; fs->regs.reg[44].loc.offset = (long)&sc->sc_lt0 - new_cfa; - fs->regs.reg[45].how = REG_SAVED_OFFSET; + fs->regs.how[45] = REG_SAVED_OFFSET; fs->regs.reg[45].loc.offset = (long)&sc->sc_lt1 - new_cfa; - fs->regs.reg[46].how = REG_SAVED_OFFSET; + fs->regs.how[46] = REG_SAVED_OFFSET; fs->regs.reg[46].loc.offset = (long)&sc->sc_lc0 - new_cfa; - fs->regs.reg[47].how = REG_SAVED_OFFSET; + fs->regs.how[47] = REG_SAVED_OFFSET; fs->regs.reg[47].loc.offset = (long)&sc->sc_lc1 - new_cfa; - fs->regs.reg[48].how = REG_SAVED_OFFSET; + fs->regs.how[48] = REG_SAVED_OFFSET; fs->regs.reg[48].loc.offset = (long)&sc->sc_lb0 - new_cfa; - fs->regs.reg[49].how = REG_SAVED_OFFSET; + fs->regs.how[49] = REG_SAVED_OFFSET; fs->regs.reg[49].loc.offset = (long)&sc->sc_lb1 - new_cfa; fs->retaddr_column = 35; diff --git a/libgcc/config/csky/linux-unwind.h b/libgcc/config/csky/linux-unwind.h index a2e4a6d..bdc8f2e 100644 --- a/libgcc/config/csky/linux-unwind.h +++ b/libgcc/config/csky/linux-unwind.h @@ -85,28 +85,28 @@ csky_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_reg = STACK_POINTER_REGNUM; fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (_Unwind_Ptr) & sc_pt_regs (a0) - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (_Unwind_Ptr) & sc_pt_regs (a1) - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (_Unwind_Ptr) & sc_pt_regs (a2) - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (_Unwind_Ptr) & sc_pt_regs (a3) - new_cfa; for (i = 4; i < 14; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (_Unwind_Ptr) & sc_pt_regs (regs[i - 4]) - new_cfa; } for (i = 16; i < 31; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (_Unwind_Ptr) & sc_pt_regs (exregs[i - 16]) - new_cfa; } @@ -114,10 +114,10 @@ csky_fallback_frame_state (struct _Unwind_Context *context, fs->regs.reg[31].loc.offset = (_Unwind_Ptr) & sc_pt_regs_tls (tls) - new_cfa; /* FIXME : hi lo ? */ - fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.how[15] = REG_SAVED_OFFSET; fs->regs.reg[15].loc.offset = (_Unwind_Ptr) & sc_pt_regs_lr - new_cfa; - fs->regs.reg[32].how = REG_SAVED_OFFSET; + fs->regs.how[32] = REG_SAVED_OFFSET; fs->regs.reg[32].loc.offset = (_Unwind_Ptr) & sc_pt_regs (pc) - new_cfa; fs->retaddr_column = 32; fs->signal_frame = 1; diff --git a/libgcc/config/i386/dragonfly-unwind.h b/libgcc/config/i386/dragonfly-unwind.h index de3e230..4cafc5c 100644 --- a/libgcc/config/i386/dragonfly-unwind.h +++ b/libgcc/config/i386/dragonfly-unwind.h @@ -102,37 +102,37 @@ x86_64_dragonfly_fallback_frame_state fs->regs.cfa_offset = new_cfa - (long) context->cfa; /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(rax) - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(rdx) - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(rcx) - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(rbx) - new_cfa; - fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.how[4] = REG_SAVED_OFFSET; fs->regs.reg[4].loc.offset = (long)&sf->REG_NAME(rsi) - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(rdi) - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(rbp) - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(r8) - new_cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.how[9] = REG_SAVED_OFFSET; fs->regs.reg[9].loc.offset = (long)&sf->REG_NAME(r9) - new_cfa; - fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.how[10] = REG_SAVED_OFFSET; fs->regs.reg[10].loc.offset = (long)&sf->REG_NAME(r10) - new_cfa; - fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.how[11] = REG_SAVED_OFFSET; fs->regs.reg[11].loc.offset = (long)&sf->REG_NAME(r11) - new_cfa; - fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.how[12] = REG_SAVED_OFFSET; fs->regs.reg[12].loc.offset = (long)&sf->REG_NAME(r12) - new_cfa; - fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.how[13] = REG_SAVED_OFFSET; fs->regs.reg[13].loc.offset = (long)&sf->REG_NAME(r13) - new_cfa; - fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.how[14] = REG_SAVED_OFFSET; fs->regs.reg[14].loc.offset = (long)&sf->REG_NAME(r14) - new_cfa; - fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.how[15] = REG_SAVED_OFFSET; fs->regs.reg[15].loc.offset = (long)&sf->REG_NAME(r15) - new_cfa; - fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.how[16] = REG_SAVED_OFFSET; fs->regs.reg[16].loc.offset = (long)&sf->REG_NAME(rip) - new_cfa; fs->retaddr_column = 16; fs->signal_frame = 1; @@ -182,21 +182,21 @@ x86_dragonfly_fallback_frame_state fs->regs.cfa_offset = new_cfa - (long) context->cfa; /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(eax) - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(ebx) - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(ecx) - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(edx) - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(esi) - new_cfa; - fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.how[7] = REG_SAVED_OFFSET; fs->regs.reg[7].loc.offset = (long)&sf->REG_NAME(edi) - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(ebp) - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(eip) - new_cfa; fs->retaddr_column = 8; fs->signal_frame = 1; diff --git a/libgcc/config/i386/freebsd-unwind.h b/libgcc/config/i386/freebsd-unwind.h index 777fda8..dcbd8cd 100644 --- a/libgcc/config/i386/freebsd-unwind.h +++ b/libgcc/config/i386/freebsd-unwind.h @@ -110,37 +110,37 @@ x86_64_freebsd_fallback_frame_state fs->regs.cfa_offset = new_cfa - (long) context->cfa; /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(rax) - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(rdx) - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(rcx) - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(rbx) - new_cfa; - fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.how[4] = REG_SAVED_OFFSET; fs->regs.reg[4].loc.offset = (long)&sf->REG_NAME(rsi) - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(rdi) - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(rbp) - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(r8) - new_cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.how[9] = REG_SAVED_OFFSET; fs->regs.reg[9].loc.offset = (long)&sf->REG_NAME(r9) - new_cfa; - fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.how[10] = REG_SAVED_OFFSET; fs->regs.reg[10].loc.offset = (long)&sf->REG_NAME(r10) - new_cfa; - fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.how[11] = REG_SAVED_OFFSET; fs->regs.reg[11].loc.offset = (long)&sf->REG_NAME(r11) - new_cfa; - fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.how[12] = REG_SAVED_OFFSET; fs->regs.reg[12].loc.offset = (long)&sf->REG_NAME(r12) - new_cfa; - fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.how[13] = REG_SAVED_OFFSET; fs->regs.reg[13].loc.offset = (long)&sf->REG_NAME(r13) - new_cfa; - fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.how[14] = REG_SAVED_OFFSET; fs->regs.reg[14].loc.offset = (long)&sf->REG_NAME(r14) - new_cfa; - fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.how[15] = REG_SAVED_OFFSET; fs->regs.reg[15].loc.offset = (long)&sf->REG_NAME(r15) - new_cfa; - fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.how[16] = REG_SAVED_OFFSET; fs->regs.reg[16].loc.offset = (long)&sf->REG_NAME(rip) - new_cfa; fs->retaddr_column = 16; fs->signal_frame = 1; @@ -189,21 +189,21 @@ x86_freebsd_fallback_frame_state fs->regs.cfa_offset = new_cfa - (long) context->cfa; /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&sf->REG_NAME(eax) - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&sf->REG_NAME(ebx) - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&sf->REG_NAME(ecx) - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&sf->REG_NAME(edx) - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&sf->REG_NAME(esi) - new_cfa; - fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.how[7] = REG_SAVED_OFFSET; fs->regs.reg[7].loc.offset = (long)&sf->REG_NAME(edi) - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&sf->REG_NAME(ebp) - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&sf->REG_NAME(eip) - new_cfa; fs->retaddr_column = 8; fs->signal_frame = 1; diff --git a/libgcc/config/i386/gnu-unwind.h b/libgcc/config/i386/gnu-unwind.h index 48fbff8..25eb690 100644 --- a/libgcc/config/i386/gnu-unwind.h +++ b/libgcc/config/i386/gnu-unwind.h @@ -123,14 +123,14 @@ x86_gnu_fallback_frame_state fs->regs.cfa_reg = 4; fs->regs.cfa_offset = usp - (unsigned long) context->cfa; - fs->regs.reg[0].how = REG_SAVED_OFFSET; - fs->regs.reg[1].how = REG_SAVED_OFFSET; - fs->regs.reg[2].how = REG_SAVED_OFFSET; - fs->regs.reg[3].how = REG_SAVED_OFFSET; - fs->regs.reg[5].how = REG_SAVED_OFFSET; - fs->regs.reg[6].how = REG_SAVED_OFFSET; - fs->regs.reg[7].how = REG_SAVED_OFFSET; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; + fs->regs.how[7] = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->retaddr_column = 8; fs->signal_frame = 1; diff --git a/libgcc/config/i386/linux-unwind.h b/libgcc/config/i386/linux-unwind.h index 7a9e4dc..48262b0 100644 --- a/libgcc/config/i386/linux-unwind.h +++ b/libgcc/config/i386/linux-unwind.h @@ -79,37 +79,37 @@ x86_64_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (long) context->cfa; /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&sc->rax - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&sc->rdx - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&sc->rcx - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&sc->rbx - new_cfa; - fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.how[4] = REG_SAVED_OFFSET; fs->regs.reg[4].loc.offset = (long)&sc->rsi - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&sc->rdi - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&sc->rbp - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&sc->r8 - new_cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.how[9] = REG_SAVED_OFFSET; fs->regs.reg[9].loc.offset = (long)&sc->r9 - new_cfa; - fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.how[10] = REG_SAVED_OFFSET; fs->regs.reg[10].loc.offset = (long)&sc->r10 - new_cfa; - fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.how[11] = REG_SAVED_OFFSET; fs->regs.reg[11].loc.offset = (long)&sc->r11 - new_cfa; - fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.how[12] = REG_SAVED_OFFSET; fs->regs.reg[12].loc.offset = (long)&sc->r12 - new_cfa; - fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.how[13] = REG_SAVED_OFFSET; fs->regs.reg[13].loc.offset = (long)&sc->r13 - new_cfa; - fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.how[14] = REG_SAVED_OFFSET; fs->regs.reg[14].loc.offset = (long)&sc->r14 - new_cfa; - fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.how[15] = REG_SAVED_OFFSET; fs->regs.reg[15].loc.offset = (long)&sc->r15 - new_cfa; - fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.how[16] = REG_SAVED_OFFSET; fs->regs.reg[16].loc.offset = (long)&sc->rip - new_cfa; fs->retaddr_column = 16; fs->signal_frame = 1; @@ -159,21 +159,21 @@ x86_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (long) context->cfa; /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&sc->eax - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&sc->ebx - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&sc->ecx - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&sc->edx - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&sc->esi - new_cfa; - fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.how[7] = REG_SAVED_OFFSET; fs->regs.reg[7].loc.offset = (long)&sc->edi - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&sc->ebp - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&sc->eip - new_cfa; fs->retaddr_column = 8; fs->signal_frame = 1; diff --git a/libgcc/config/i386/sol2-unwind.h b/libgcc/config/i386/sol2-unwind.h index 08c9cd5..718dc35 100644 --- a/libgcc/config/i386/sol2-unwind.h +++ b/libgcc/config/i386/sol2-unwind.h @@ -94,37 +94,37 @@ x86_64_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (long) context->cfa; /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&mctx->gregs[REG_RAX] - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&mctx->gregs[REG_RDX] - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&mctx->gregs[REG_RCX] - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&mctx->gregs[REG_RBX] - new_cfa; - fs->regs.reg[4].how = REG_SAVED_OFFSET; + fs->regs.how[4] = REG_SAVED_OFFSET; fs->regs.reg[4].loc.offset = (long)&mctx->gregs[REG_RSI] - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&mctx->gregs[REG_RDI] - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&mctx->gregs[REG_RBP] - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&mctx->gregs[REG_R8] - new_cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.how[9] = REG_SAVED_OFFSET; fs->regs.reg[9].loc.offset = (long)&mctx->gregs[REG_R9] - new_cfa; - fs->regs.reg[10].how = REG_SAVED_OFFSET; + fs->regs.how[10] = REG_SAVED_OFFSET; fs->regs.reg[10].loc.offset = (long)&mctx->gregs[REG_R10] - new_cfa; - fs->regs.reg[11].how = REG_SAVED_OFFSET; + fs->regs.how[11] = REG_SAVED_OFFSET; fs->regs.reg[11].loc.offset = (long)&mctx->gregs[REG_R11] - new_cfa; - fs->regs.reg[12].how = REG_SAVED_OFFSET; + fs->regs.how[12] = REG_SAVED_OFFSET; fs->regs.reg[12].loc.offset = (long)&mctx->gregs[REG_R12] - new_cfa; - fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.how[13] = REG_SAVED_OFFSET; fs->regs.reg[13].loc.offset = (long)&mctx->gregs[REG_R13] - new_cfa; - fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.how[14] = REG_SAVED_OFFSET; fs->regs.reg[14].loc.offset = (long)&mctx->gregs[REG_R14] - new_cfa; - fs->regs.reg[15].how = REG_SAVED_OFFSET; + fs->regs.how[15] = REG_SAVED_OFFSET; fs->regs.reg[15].loc.offset = (long)&mctx->gregs[REG_R15] - new_cfa; - fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.how[16] = REG_SAVED_OFFSET; fs->regs.reg[16].loc.offset = (long)&mctx->gregs[REG_RIP] - new_cfa; fs->retaddr_column = 16; fs->signal_frame = 1; @@ -180,21 +180,21 @@ x86_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (long) context->cfa; /* The SVR4 register numbering macros aren't usable in libgcc. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&mctx->gregs[EAX] - new_cfa; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&mctx->gregs[EBX] - new_cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&mctx->gregs[ECX] - new_cfa; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&mctx->gregs[EDX] - new_cfa; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&mctx->gregs[ESI] - new_cfa; - fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.how[7] = REG_SAVED_OFFSET; fs->regs.reg[7].loc.offset = (long)&mctx->gregs[EDI] - new_cfa; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&mctx->gregs[EBP] - new_cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&mctx->gregs[EIP] - new_cfa; fs->retaddr_column = 8; diff --git a/libgcc/config/i386/w32-unwind.h b/libgcc/config/i386/w32-unwind.h index 7c5980f..096e314 100644 --- a/libgcc/config/i386/w32-unwind.h +++ b/libgcc/config/i386/w32-unwind.h @@ -153,21 +153,21 @@ i386_w32_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa_ - (long) ctx_cfa_; /* Restore registers. */ - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)&proc_ctx_->Eax - new_cfa_; - fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.how[3] = REG_SAVED_OFFSET; fs->regs.reg[3].loc.offset = (long)&proc_ctx_->Ebx - new_cfa_; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long)&proc_ctx_->Ecx - new_cfa_; - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long)&proc_ctx_->Edx - new_cfa_; - fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.how[6] = REG_SAVED_OFFSET; fs->regs.reg[6].loc.offset = (long)&proc_ctx_->Esi - new_cfa_; - fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.how[7] = REG_SAVED_OFFSET; fs->regs.reg[7].loc.offset = (long)&proc_ctx_->Edi - new_cfa_; - fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.how[5] = REG_SAVED_OFFSET; fs->regs.reg[5].loc.offset = (long)&proc_ctx_->Ebp - new_cfa_; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long)&proc_ctx_->Eip - new_cfa_; fs->retaddr_column = 8; fs->signal_frame = 1; @@ -189,12 +189,12 @@ i386_w32_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa_ - (long) ctx_cfa_; /* The saved value of %ecx is at CFA - 4 */ - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = -4; /* and what is stored at the CFA is the return address. */ fs->retaddr_column = 8; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = 0; fs->signal_frame = 1; diff --git a/libgcc/config/loongarch/linux-unwind.h b/libgcc/config/loongarch/linux-unwind.h index 89c168c..f6c782f 100644 --- a/libgcc/config/loongarch/linux-unwind.h +++ b/libgcc/config/loongarch/linux-unwind.h @@ -64,12 +64,12 @@ loongarch_fallback_frame_state (struct _Unwind_Context *context, for (i = 0; i < 32; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (_Unwind_Ptr) & (sc->sc_regs[i]) - new_cfa; } fs->signal_frame = 1; - fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].how + fs->regs.how[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__] = REG_SAVED_VAL_OFFSET; fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].loc.offset = (_Unwind_Ptr) (sc->sc_pc) - new_cfa; diff --git a/libgcc/config/m68k/linux-unwind.h b/libgcc/config/m68k/linux-unwind.h index 1502ad1..ad0da69 100644 --- a/libgcc/config/m68k/linux-unwind.h +++ b/libgcc/config/m68k/linux-unwind.h @@ -68,21 +68,21 @@ m68k_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_reg = 15; fs->regs.cfa_offset = cfa - (long) context->cfa; - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long) &sc->sc_d0 - cfa; - fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.how[1] = REG_SAVED_OFFSET; fs->regs.reg[1].loc.offset = (long) &sc->sc_d1 - cfa; - fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.how[8] = REG_SAVED_OFFSET; fs->regs.reg[8].loc.offset = (long) &sc->sc_a0 - cfa; - fs->regs.reg[9].how = REG_SAVED_OFFSET; + fs->regs.how[9] = REG_SAVED_OFFSET; fs->regs.reg[9].loc.offset = (long) &sc->sc_a1 - cfa; #ifdef __uClinux__ - fs->regs.reg[13].how = REG_SAVED_OFFSET; + fs->regs.how[13] = REG_SAVED_OFFSET; fs->regs.reg[13].loc.offset = (long) &sc->sc_a5 - cfa; #endif - fs->regs.reg[24].how = REG_SAVED_OFFSET; + fs->regs.how[24] = REG_SAVED_OFFSET; fs->regs.reg[24].loc.offset = (long) &sc->sc_pc - cfa; #ifndef __uClinux__ @@ -90,9 +90,9 @@ m68k_fallback_frame_state (struct _Unwind_Context *context, { int *fpregs = (int *) sc->sc_fpregs; - fs->regs.reg[16].how = REG_SAVED_OFFSET; + fs->regs.how[16] = REG_SAVED_OFFSET; fs->regs.reg[16].loc.offset = (long) &fpregs[0] - cfa; - fs->regs.reg[17].how = REG_SAVED_OFFSET; + fs->regs.how[17] = REG_SAVED_OFFSET; fs->regs.reg[17].loc.offset = (long) &fpregs[M68K_FP_SIZE/4] - cfa; } #elif defined __mcffpu__ @@ -124,12 +124,12 @@ m68k_fallback_frame_state (struct _Unwind_Context *context, /* register %d0-%d7/%a0-%a6 */ for (i = 0; i <= 14; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (long) &gregs[i] - cfa; } /* return address */ - fs->regs.reg[24].how = REG_SAVED_OFFSET; + fs->regs.how[24] = REG_SAVED_OFFSET; fs->regs.reg[24].loc.offset = (long) &gregs[16] - cfa; #define uc_fpstate uc_filler[0] @@ -141,7 +141,7 @@ m68k_fallback_frame_state (struct _Unwind_Context *context, /* register %fp0-%fp7 */ for (i = 16; i <= 23; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = fpregs - cfa; fpregs += M68K_FP_SIZE; } diff --git a/libgcc/config/mips/linux-unwind.h b/libgcc/config/mips/linux-unwind.h index e113f52..80e6e77 100644 --- a/libgcc/config/mips/linux-unwind.h +++ b/libgcc/config/mips/linux-unwind.h @@ -103,7 +103,7 @@ mips_fallback_frame_state (struct _Unwind_Context *context, #endif for (i = 0; i < 32; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (_Unwind_Ptr)&(sc->sc_regs[i]) + reg_offset - new_cfa; } @@ -115,7 +115,7 @@ mips_fallback_frame_state (struct _Unwind_Context *context, Note that setting fs->signal_frame would not work. As the comment above MASK_RETURN_ADDR explains, MIPS unwinders must earch for an odd-valued address. */ - fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].how + fs->regs.how[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__] = REG_SAVED_VAL_OFFSET; fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].loc.offset = (_Unwind_Ptr)(sc->sc_pc) + 2 - new_cfa; diff --git a/libgcc/config/nds32/linux-unwind.h b/libgcc/config/nds32/linux-unwind.h index 7a12d3a..cbb2620 100644 --- a/libgcc/config/nds32/linux-unwind.h +++ b/libgcc/config/nds32/linux-unwind.h @@ -92,7 +92,7 @@ nds32_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; #define NDS32_PUT_FS_REG(NUM, NAME) \ - (fs->regs.reg[NUM].how = REG_SAVED_OFFSET, \ + (fs->regs.how[NUM] = REG_SAVED_OFFSET, \ fs->regs.reg[NUM].loc.offset = (_Unwind_Ptr) &(sc_->NAME) - new_cfa) /* Restore all registers value. */ diff --git a/libgcc/config/nios2/linux-unwind.h b/libgcc/config/nios2/linux-unwind.h index 4a8fca4..aa27822 100644 --- a/libgcc/config/nios2/linux-unwind.h +++ b/libgcc/config/nios2/linux-unwind.h @@ -61,7 +61,7 @@ nios2_fallback_frame_state (struct _Unwind_Context *context, return _URC_END_OF_STACK; #define NIOS2_REG(NUM,NAME) \ - (fs->regs.reg[NUM].how = REG_SAVED_OFFSET, \ + (fs->regs.how[NUM] = REG_SAVED_OFFSET, \ fs->regs.reg[NUM].loc.offset = (_Unwind_Ptr)&(regs->NAME) - new_cfa) if (pc[0] == (0x00800004 | (__NR_rt_sigreturn << 6))) diff --git a/libgcc/config/or1k/linux-unwind.h b/libgcc/config/or1k/linux-unwind.h index 3cf9137..71171c5 100644 --- a/libgcc/config/or1k/linux-unwind.h +++ b/libgcc/config/or1k/linux-unwind.h @@ -59,10 +59,10 @@ or1k_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (long) context->cfa; for (i = 2; i < 32; ++i) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (long) &sc->regs.gpr[i] - new_cfa; } - fs->regs.reg[32].how = REG_SAVED_OFFSET; + fs->regs.how[32] = REG_SAVED_OFFSET; fs->regs.reg[32].loc.offset = (long)&sc->regs.pc - new_cfa; fs->retaddr_column = 32; fs->signal_frame = 1; diff --git a/libgcc/config/pa/hpux-unwind.h b/libgcc/config/pa/hpux-unwind.h index f14812a..b30a67e 100644 --- a/libgcc/config/pa/hpux-unwind.h +++ b/libgcc/config/pa/hpux-unwind.h @@ -57,19 +57,19 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #endif #define UPDATE_FS_FOR_SAR(FS, N) \ - (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ + (FS)->regs.how[N] = REG_SAVED_OFFSET; \ (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_cr11) - new_cfa #define UPDATE_FS_FOR_GR(FS, GRN, N) \ - (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ + (FS)->regs.how[N] = REG_SAVED_OFFSET; \ (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_gr##GRN) - new_cfa #define UPDATE_FS_FOR_FR(FS, FRN, N) \ - (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ + (FS)->regs.how[N] = REG_SAVED_OFFSET; \ (FS)->regs.reg[N].loc.offset = (long) &(mc->ss_fr##FRN) - new_cfa; #define UPDATE_FS_FOR_PC(FS, N) \ - (FS)->regs.reg[N].how = REG_SAVED_OFFSET; \ + (FS)->regs.how[N] = REG_SAVED_OFFSET; \ (FS)->regs.reg[N].loc.offset = GetSSRegAddr (mc, ss_pcoq_head) - new_cfa /* Extract bit field from word using HP's numbering (MSB = 0). */ @@ -151,7 +151,7 @@ pa_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = 0; fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = -24; /* Update context to describe the stub frame. */ @@ -171,7 +171,7 @@ pa_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = 0; fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = -8; /* Update context to describe the stub frame. */ diff --git a/libgcc/config/pa/linux-unwind.h b/libgcc/config/pa/linux-unwind.h index 7e424c5..7efab00 100644 --- a/libgcc/config/pa/linux-unwind.h +++ b/libgcc/config/pa/linux-unwind.h @@ -138,22 +138,22 @@ pa32_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (long) context->cfa; for (i = 1; i <= 31; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (long)&sc->sc_gr[i] - new_cfa; } for (i = 4; i <= 31; i++) { /* FP regs have left and right halves */ - fs->regs.reg[2*i+24].how = REG_SAVED_OFFSET; + fs->regs.how[2*i+24] = REG_SAVED_OFFSET; fs->regs.reg[2*i+24].loc.offset = (long)&sc->sc_fr[i] - new_cfa; - fs->regs.reg[2*i+24+1].how = REG_SAVED_OFFSET; + fs->regs.how[2*i+24+1] = REG_SAVED_OFFSET; fs->regs.reg[2*i+24+1].loc.offset = (long)&sc->sc_fr[i] + 4 - new_cfa; } - fs->regs.reg[88].how = REG_SAVED_OFFSET; + fs->regs.how[88] = REG_SAVED_OFFSET; fs->regs.reg[88].loc.offset = (long) &sc->sc_sar - new_cfa; - fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].how + fs->regs.how[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__] = REG_SAVED_OFFSET; fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].loc.offset = (long) &sc->sc_iaoq[0] - new_cfa; diff --git a/libgcc/config/riscv/linux-unwind.h b/libgcc/config/riscv/linux-unwind.h index c86df2f..c44d1a8 100644 --- a/libgcc/config/riscv/linux-unwind.h +++ b/libgcc/config/riscv/linux-unwind.h @@ -73,13 +73,13 @@ riscv_fallback_frame_state (struct _Unwind_Context *context, for (i = 0; i < 32; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (_Unwind_Ptr) &sc->gregs[i] - new_cfa; } fs->signal_frame = 1; fs->retaddr_column = __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__; - fs->regs.reg[fs->retaddr_column].how = REG_SAVED_VAL_OFFSET; + fs->regs.how[fs->retaddr_column] = REG_SAVED_VAL_OFFSET; fs->regs.reg[fs->retaddr_column].loc.offset = (_Unwind_Ptr) sc->gregs[0] - new_cfa; diff --git a/libgcc/config/rs6000/aix-unwind.h b/libgcc/config/rs6000/aix-unwind.h index d7e5f59..9a1efdc 100644 --- a/libgcc/config/rs6000/aix-unwind.h +++ b/libgcc/config/rs6000/aix-unwind.h @@ -40,7 +40,7 @@ #ifdef __64BIT__ #define MD_FROB_UPDATE_CONTEXT(CTX, FS) \ do { \ - if ((FS)->regs.reg[2].how == REG_UNSAVED) \ + if ((FS)->regs.how[2] == REG_UNSAVED) \ { \ unsigned int *insn \ = (unsigned int *) \ @@ -52,7 +52,7 @@ #else #define MD_FROB_UPDATE_CONTEXT(CTX, FS) \ do { \ - if ((FS)->regs.reg[2].how == REG_UNSAVED) \ + if ((FS)->regs.how[2] == REG_UNSAVED) \ { \ unsigned int *insn \ = (unsigned int *) \ @@ -207,7 +207,7 @@ ucontext_for (struct _Unwind_Context *context) #define REGISTER_CFA_OFFSET_FOR(FS,REGNO,ADDR,CFA)\ do { \ -(FS)->regs.reg[REGNO].how = REG_SAVED_OFFSET; \ +(FS)->regs.how[REGNO] = REG_SAVED_OFFSET; \ (FS)->regs.reg[REGNO].loc.offset = (long) (ADDR) - (CFA); \ } while (0) diff --git a/libgcc/config/rs6000/darwin-fallback.c b/libgcc/config/rs6000/darwin-fallback.c index c6bc69c..ad5c195 100644 --- a/libgcc/config/rs6000/darwin-fallback.c +++ b/libgcc/config/rs6000/darwin-fallback.c @@ -368,7 +368,7 @@ handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32], return false; #define set_offset(r, addr) \ - (fs->regs.reg[r].how = REG_SAVED_OFFSET, \ + (fs->regs.how[r] = REG_SAVED_OFFSET, \ fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa) /* Restore even the registers that are not call-saved, since they diff --git a/libgcc/config/rs6000/freebsd-unwind.h b/libgcc/config/rs6000/freebsd-unwind.h index af96135..654e7f6 100644 --- a/libgcc/config/rs6000/freebsd-unwind.h +++ b/libgcc/config/rs6000/freebsd-unwind.h @@ -33,7 +33,7 @@ frob_update_context (struct _Unwind_Context *context, const unsigned int *pc = (const unsigned int *) context->ra; #ifdef __powerpc64__ - if (fs->regs.reg[2].how == REG_UNSAVED) + if (fs->regs.how[2] == REG_UNSAVED) { /* If the current unwind info (FS) does not contain explicit info saving R2, then we have to do a minor amount of code reading to diff --git a/libgcc/config/rs6000/linux-unwind.h b/libgcc/config/rs6000/linux-unwind.h index 6a7c07f..f6ab939 100644 --- a/libgcc/config/rs6000/linux-unwind.h +++ b/libgcc/config/rs6000/linux-unwind.h @@ -215,12 +215,12 @@ ppc_fallback_frame_state (struct _Unwind_Context *context, fs->regs.cfa_offset = new_cfa - (long) context->cfa; #ifdef __powerpc64__ - fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.how[2] = REG_SAVED_OFFSET; fs->regs.reg[2].loc.offset = (long) ®s->gpr[2] - new_cfa; #endif for (i = 14; i < 32; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (long) ®s->gpr[i] - new_cfa; } @@ -230,20 +230,20 @@ ppc_fallback_frame_state (struct _Unwind_Context *context, cr_offset += sizeof (long) - 4; #endif /* In the ELFv1 ABI, CR2 stands in for the whole CR. */ - fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET; + fs->regs.how[R_CR2] = REG_SAVED_OFFSET; fs->regs.reg[R_CR2].loc.offset = cr_offset; #if _CALL_ELF == 2 /* In the ELFv2 ABI, every CR field has a separate CFI entry. */ - fs->regs.reg[R_CR3].how = REG_SAVED_OFFSET; + fs->regs.how[R_CR3] = REG_SAVED_OFFSET; fs->regs.reg[R_CR3].loc.offset = cr_offset; - fs->regs.reg[R_CR4].how = REG_SAVED_OFFSET; + fs->regs.how[R_CR4] = REG_SAVED_OFFSET; fs->regs.reg[R_CR4].loc.offset = cr_offset; #endif - fs->regs.reg[R_LR].how = REG_SAVED_OFFSET; + fs->regs.how[R_LR] = REG_SAVED_OFFSET; fs->regs.reg[R_LR].loc.offset = (long) ®s->link - new_cfa; - fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; + fs->regs.how[ARG_POINTER_REGNUM] = REG_SAVED_OFFSET; fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) ®s->nip - new_cfa; fs->retaddr_column = ARG_POINTER_REGNUM; fs->signal_frame = 1; @@ -251,7 +251,7 @@ ppc_fallback_frame_state (struct _Unwind_Context *context, /* If we have a FPU... */ for (i = 14; i < 32; i++) { - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.how[i + 32] = REG_SAVED_OFFSET; fs->regs.reg[i + 32].loc.offset = (long) ®s->fpr[i] - new_cfa; } @@ -265,12 +265,12 @@ ppc_fallback_frame_state (struct _Unwind_Context *context, { for (i = 20; i < 32; i++) { - fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET; + fs->regs.how[i + R_VR0] = REG_SAVED_OFFSET; fs->regs.reg[i + R_VR0].loc.offset = (long) &vregs->vr[i] - new_cfa; } } - fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET; + fs->regs.how[R_VRSAVE] = REG_SAVED_OFFSET; fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa; /* If we have SPE register high-parts... we check at compile-time to @@ -278,7 +278,7 @@ ppc_fallback_frame_state (struct _Unwind_Context *context, #ifdef __SPE__ for (i = 14; i < 32; i++) { - fs->regs.reg[i + FIRST_SPE_HIGH_REGNO - 4].how = REG_SAVED_OFFSET; + fs->regs.how[i + FIRST_SPE_HIGH_REGNO - 4] = REG_SAVED_OFFSET; fs->regs.reg[i + FIRST_SPE_HIGH_REGNO - 4].loc.offset = (long) ®s->vregs - new_cfa + 4 * i; } @@ -315,7 +315,7 @@ frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATT #endif #ifdef __powerpc64__ - if (fs->regs.reg[2].how == REG_UNSAVED) + if (fs->regs.how[2] == REG_UNSAVED) { /* If the current unwind info (FS) does not contain explicit info saving R2, then we have to do a minor amount of code reading to diff --git a/libgcc/config/s390/linux-unwind.h b/libgcc/config/s390/linux-unwind.h index f3f1337..904bbaa 100644 --- a/libgcc/config/s390/linux-unwind.h +++ b/libgcc/config/s390/linux-unwind.h @@ -106,20 +106,20 @@ s390_fallback_frame_state (struct _Unwind_Context *context, for (i = 0; i < 16; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (long)®s->gprs[i] - new_cfa; } for (i = 0; i < 16; i++) { - fs->regs.reg[16+i].how = REG_SAVED_OFFSET; + fs->regs.how[16+i] = REG_SAVED_OFFSET; fs->regs.reg[16+i].loc.offset = (long)®s->fprs[dwarf_to_fpr_map[i]] - new_cfa; } /* Load return addr from PSW into dummy register 32. */ - fs->regs.reg[32].how = REG_SAVED_OFFSET; + fs->regs.how[32] = REG_SAVED_OFFSET; fs->regs.reg[32].loc.offset = (long)®s->psw_addr - new_cfa; fs->retaddr_column = 32; /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr diff --git a/libgcc/config/s390/tpf-unwind.h b/libgcc/config/s390/tpf-unwind.h index 526bdba..992cffc 100644 --- a/libgcc/config/s390/tpf-unwind.h +++ b/libgcc/config/s390/tpf-unwind.h @@ -88,18 +88,18 @@ s390_fallback_frame_state (struct _Unwind_Context *context, /* All registers remain unchanged ... */ for (i = 0; i < 32; i++) { - fs->regs.reg[i].how = REG_SAVED_REG; + fs->regs.how[i] = REG_SAVED_REG; fs->regs.reg[i].loc.reg = i; } /* ... except for %r14, which is stored at CFA+offset where offset is displacment of ICST_CRET or ICST_SRET from CFA */ if ( __isPATrange(context->ra) ) { - fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.how[14] = REG_SAVED_OFFSET; fs->regs.reg[14].loc.offset = ICST_CRET - STACK_POINTER_OFFSET; fs->retaddr_column = 14; } else { - fs->regs.reg[14].how = REG_SAVED_OFFSET; + fs->regs.how[14] = REG_SAVED_OFFSET; fs->regs.reg[14].loc.offset = ICST_SRET - STACK_POINTER_OFFSET; fs->retaddr_column = 14; @@ -119,13 +119,13 @@ s390_fallback_frame_state (struct _Unwind_Context *context, for (i = 0; i < 16; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = regs + i*8 - new_cfa; } for (i = 0; i < 4; i++) { - fs->regs.reg[16 + i].how = REG_SAVED_OFFSET; + fs->regs.how[16 + i] = REG_SAVED_OFFSET; fs->regs.reg[16 + i].loc.offset = regs + 16*8 + i*8 - new_cfa; } diff --git a/libgcc/config/sh/linux-unwind.h b/libgcc/config/sh/linux-unwind.h index 8cd30f4..8088e3c 100644 --- a/libgcc/config/sh/linux-unwind.h +++ b/libgcc/config/sh/linux-unwind.h @@ -99,24 +99,24 @@ sh_fallback_frame_state (struct _Unwind_Context *context, for (i = 0; i < 15; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (long)&(sc->sc_regs[i]) - new_cfa; } - fs->regs.reg[SH_DWARF_FRAME_PR].how = REG_SAVED_OFFSET; + fs->regs.how[SH_DWARF_FRAME_PR] = REG_SAVED_OFFSET; fs->regs.reg[SH_DWARF_FRAME_PR].loc.offset = (long)&(sc->sc_pr) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_SR].how = REG_SAVED_OFFSET; + fs->regs.how[SH_DWARF_FRAME_SR] = REG_SAVED_OFFSET; fs->regs.reg[SH_DWARF_FRAME_SR].loc.offset = (long)&(sc->sc_sr) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_GBR].how = REG_SAVED_OFFSET; + fs->regs.how[SH_DWARF_FRAME_GBR] = REG_SAVED_OFFSET; fs->regs.reg[SH_DWARF_FRAME_GBR].loc.offset = (long)&(sc->sc_gbr) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_MACH].how = REG_SAVED_OFFSET; + fs->regs.how[SH_DWARF_FRAME_MACH] = REG_SAVED_OFFSET; fs->regs.reg[SH_DWARF_FRAME_MACH].loc.offset = (long)&(sc->sc_mach) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_MACL].how = REG_SAVED_OFFSET; + fs->regs.how[SH_DWARF_FRAME_MACL] = REG_SAVED_OFFSET; fs->regs.reg[SH_DWARF_FRAME_MACL].loc.offset = (long)&(sc->sc_macl) - new_cfa; @@ -124,7 +124,7 @@ sh_fallback_frame_state (struct _Unwind_Context *context, r = SH_DWARF_FRAME_FP0; for (i = 0; i < 16; i++) { - fs->regs.reg[r+i].how = REG_SAVED_OFFSET; + fs->regs.how[r+i] = REG_SAVED_OFFSET; fs->regs.reg[r+i].loc.offset = (long)&(sc->sc_fpregs[i]) - new_cfa; } @@ -132,20 +132,20 @@ sh_fallback_frame_state (struct _Unwind_Context *context, r = SH_DWARF_FRAME_XD0; for (i = 0; i < 8; i++) { - fs->regs.reg[r+i].how = REG_SAVED_OFFSET; + fs->regs.how[r+i] = REG_SAVED_OFFSET; fs->regs.reg[r+i].loc.offset = (long)&(sc->sc_xfpregs[2*i]) - new_cfa; } - fs->regs.reg[SH_DWARF_FRAME_FPUL].how = REG_SAVED_OFFSET; + fs->regs.how[SH_DWARF_FRAME_FPUL] = REG_SAVED_OFFSET; fs->regs.reg[SH_DWARF_FRAME_FPUL].loc.offset = (long)&(sc->sc_fpul) - new_cfa; - fs->regs.reg[SH_DWARF_FRAME_FPSCR].how = REG_SAVED_OFFSET; + fs->regs.how[SH_DWARF_FRAME_FPSCR] = REG_SAVED_OFFSET; fs->regs.reg[SH_DWARF_FRAME_FPSCR].loc.offset = (long)&(sc->sc_fpscr) - new_cfa; #endif - fs->regs.reg[SH_DWARF_FRAME_PC].how = REG_SAVED_OFFSET; + fs->regs.how[SH_DWARF_FRAME_PC] = REG_SAVED_OFFSET; fs->regs.reg[SH_DWARF_FRAME_PC].loc.offset = (long)&(sc->sc_pc) - new_cfa; fs->retaddr_column = SH_DWARF_FRAME_PC; diff --git a/libgcc/config/sparc/linux-unwind.h b/libgcc/config/sparc/linux-unwind.h index 001429e..0095b43 100644 --- a/libgcc/config/sparc/linux-unwind.h +++ b/libgcc/config/sparc/linux-unwind.h @@ -65,13 +65,13 @@ sparc64_fallback_frame_state (struct _Unwind_Context *context, if ((unsigned int) i == __builtin_dwarf_sp_column ()) continue; - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = this_cfa + regs_off + (i * 8) - new_cfa; } for (i = 0; i < 16; i++) { - fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.how[i + 16] = REG_SAVED_OFFSET; fs->regs.reg[i + 16].loc.offset = this_cfa + (i * 8) - new_cfa; } @@ -81,7 +81,7 @@ sparc64_fallback_frame_state (struct _Unwind_Context *context, { if (i > 32 && (i & 0x1)) continue; - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.how[i + 32] = REG_SAVED_OFFSET; fs->regs.reg[i + 32].loc.offset = fpu_save + (i * 4) - new_cfa; } @@ -95,7 +95,7 @@ sparc64_fallback_frame_state (struct _Unwind_Context *context, shifted_ra_location = this_cfa + regs_off + 19 * 8; /* Y register */ *(long *)shifted_ra_location = *(long *)ra_location - 8; fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa; fs->signal_frame = 1; @@ -122,7 +122,7 @@ sparc64_frob_update_context (struct _Unwind_Context *context, context->cfa -= STACK_BIAS; for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__ + 1; ++i) - if (fs->regs.reg[i].how == REG_SAVED_OFFSET) + if (fs->regs.how[i] == REG_SAVED_OFFSET) _Unwind_SetGRPtr (context, i, _Unwind_GetGRPtr (context, i) - STACK_BIAS); } @@ -177,13 +177,13 @@ sparc_fallback_frame_state (struct _Unwind_Context *context, if ((unsigned int) i == __builtin_dwarf_sp_column ()) continue; - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = this_cfa + regs_off + (4 * 4) + (i * 4) - new_cfa; } for (i = 0; i < 16; i++) { - fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.how[i + 16] = REG_SAVED_OFFSET; fs->regs.reg[i + 16].loc.offset = this_cfa + (i * 4) - new_cfa; } @@ -191,7 +191,7 @@ sparc_fallback_frame_state (struct _Unwind_Context *context, { for (i = 0; i < 32; i++) { - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.how[i + 32] = REG_SAVED_OFFSET; fs->regs.reg[i + 32].loc.offset = fpu_save + (i * 4) - new_cfa; } @@ -205,7 +205,7 @@ sparc_fallback_frame_state (struct _Unwind_Context *context, shifted_ra_location = this_cfa + regs_off + 3 * 4; /* Y register */ *(int *)shifted_ra_location = *(int *)ra_location - 8; fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = shifted_ra_location - new_cfa; fs->signal_frame = 1; diff --git a/libgcc/config/sparc/sol2-unwind.h b/libgcc/config/sparc/sol2-unwind.h index 06cc538..4da5a7c 100644 --- a/libgcc/config/sparc/sol2-unwind.h +++ b/libgcc/config/sparc/sol2-unwind.h @@ -96,7 +96,7 @@ sparc64_frob_update_context (struct _Unwind_Context *context, context->cfa -= STACK_BIAS; for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__ + 1; ++i) - if (fs->regs.reg[i].how == REG_SAVED_OFFSET) + if (fs->regs.how[i] == REG_SAVED_OFFSET) _Unwind_SetGRPtr (context, i, _Unwind_GetGRPtr (context, i) - STACK_BIAS); } @@ -221,7 +221,7 @@ MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, continue; /* First the global registers and then the out registers. */ - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (long)&mctx->gregs[REG_Y + i] - new_cfa; } @@ -229,7 +229,7 @@ MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, the register window (in and local registers) was saved. */ for (i = 0; i < 16; i++) { - fs->regs.reg[i + 16].how = REG_SAVED_OFFSET; + fs->regs.how[i + 16] = REG_SAVED_OFFSET; fs->regs.reg[i + 16].loc.offset = i * sizeof(long); } @@ -238,7 +238,7 @@ MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, { for (i = 0; i < 32; i++) { - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.how[i + 32] = REG_SAVED_OFFSET; fs->regs.reg[i + 32].loc.offset = (long)&mctx->fpregs.fpu_fr.fpu_regs[i] - new_cfa; } @@ -250,7 +250,7 @@ MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, if (i > 32 && (i & 1)) continue; - fs->regs.reg[i + 32].how = REG_SAVED_OFFSET; + fs->regs.how[i + 32] = REG_SAVED_OFFSET; fs->regs.reg[i + 32].loc.offset = (long)&mctx->fpregs.fpu_fr.fpu_dregs[i/2] - new_cfa; } @@ -265,7 +265,7 @@ MD_FALLBACK_FRAME_STATE_FOR (struct _Unwind_Context *context, shifted_ra_location = &mctx->gregs[REG_Y]; *(void **)shifted_ra_location = *(void **)ra_location - 8; fs->retaddr_column = 0; - fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.how[0] = REG_SAVED_OFFSET; fs->regs.reg[0].loc.offset = (long)shifted_ra_location - new_cfa; /* SIGFPE for IEEE-754 exceptions is delivered after the faulting insn diff --git a/libgcc/config/xtensa/linux-unwind.h b/libgcc/config/xtensa/linux-unwind.h index fed118e..868624e 100644 --- a/libgcc/config/xtensa/linux-unwind.h +++ b/libgcc/config/xtensa/linux-unwind.h @@ -105,11 +105,11 @@ xtensa_fallback_frame_state (struct _Unwind_Context *context, for (i = 0; i < 16; i++) { - fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.how[i] = REG_SAVED_OFFSET; fs->regs.reg[i].loc.offset = (_Unwind_Ptr) &(sc->sc_a[i]) - new_cfa; } - fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].how = + fs->regs.how[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__] = REG_SAVED_VAL_OFFSET; fs->regs.reg[__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__].loc.offset = (_Unwind_Ptr) (sc->sc_pc) - new_cfa; diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c index a2eb66d..eaceace 100644 --- a/libgcc/unwind-dw2.c +++ b/libgcc/unwind-dw2.c @@ -36,6 +36,7 @@ #include "unwind-dw2-fde.h" #include "gthr.h" #include "unwind-dw2.h" +#include <stddef.h> #ifdef HAVE_SYS_SDT_H #include <sys/sdt.h> @@ -983,7 +984,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.how[reg] = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; } } @@ -992,7 +993,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = insn & 0x3f; reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) - fs->regs.reg[reg].how = REG_UNSAVED; + fs->regs.how[reg] = REG_UNSAVED; } else switch (insn) { @@ -1026,7 +1027,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.how[reg] = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; } break; @@ -1037,21 +1038,21 @@ execute_cfa_program (const unsigned char *insn_ptr, register was saved somewhere. */ reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) - fs->regs.reg[reg].how = REG_UNSAVED; + fs->regs.how[reg] = REG_UNSAVED; break; case DW_CFA_same_value: insn_ptr = read_uleb128 (insn_ptr, ®); reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) - fs->regs.reg[reg].how = REG_UNSAVED; + fs->regs.how[reg] = REG_UNSAVED; break; case DW_CFA_undefined: insn_ptr = read_uleb128 (insn_ptr, ®); reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) - fs->regs.reg[reg].how = REG_UNDEFINED; + fs->regs.how[reg] = REG_UNDEFINED; break; case DW_CFA_nop: @@ -1065,7 +1066,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_REG; + fs->regs.how[reg] = REG_SAVED_REG; fs->regs.reg[reg].loc.reg = (_Unwind_Word)reg2; } } @@ -1128,7 +1129,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_EXP; + fs->regs.how[reg] = REG_SAVED_EXP; fs->regs.reg[reg].loc.exp = insn_ptr; } insn_ptr = read_uleb128 (insn_ptr, &utmp); @@ -1143,7 +1144,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.how[reg] = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; } break; @@ -1171,7 +1172,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET; + fs->regs.how[reg] = REG_SAVED_VAL_OFFSET; fs->regs.reg[reg].loc.offset = offset; } break; @@ -1183,7 +1184,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET; + fs->regs.how[reg] = REG_SAVED_VAL_OFFSET; fs->regs.reg[reg].loc.offset = offset; } break; @@ -1193,7 +1194,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_VAL_EXP; + fs->regs.how[reg] = REG_SAVED_VAL_EXP; fs->regs.reg[reg].loc.exp = insn_ptr; } insn_ptr = read_uleb128 (insn_ptr, &utmp); @@ -1205,14 +1206,14 @@ execute_cfa_program (const unsigned char *insn_ptr, /* This CFA is multiplexed with Sparc. On AArch64 it's used to toggle return address signing status. */ reg = DWARF_REGNUM_AARCH64_RA_STATE; - gcc_assert (fs->regs.reg[reg].how == REG_UNSAVED); + gcc_assert (fs->regs.how[reg] == REG_UNSAVED); fs->regs.reg[reg].loc.offset ^= 1; #else /* ??? Hardcoded for SPARC register window configuration. */ if (__LIBGCC_DWARF_FRAME_REGISTERS__ >= 32) for (reg = 16; reg < 32; ++reg) { - fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.how[reg] = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); } #endif @@ -1232,7 +1233,7 @@ execute_cfa_program (const unsigned char *insn_ptr, reg = DWARF_REG_TO_UNWIND_COLUMN (reg); if (UNWIND_COLUMN_IN_RANGE (reg)) { - fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.how[reg] = REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = -offset; } break; @@ -1255,7 +1256,8 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) const struct dwarf_cie *cie; const unsigned char *aug, *insn, *end; - memset (fs, 0, sizeof (*fs)); + memset (&fs->regs.how[0], 0, + sizeof (*fs) - offsetof (_Unwind_FrameState, regs.how[0])); context->args_size = 0; context->lsda = 0; @@ -1355,7 +1357,7 @@ __frame_state_for (void *pc_target, struct frame_state *state_in) for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++) { - state_in->saved[reg] = fs.regs.reg[reg].how; + state_in->saved[reg] = fs.regs.how[reg]; switch (state_in->saved[reg]) { case REG_SAVED_REG: @@ -1453,7 +1455,7 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) /* Compute the addresses of all registers saved in this frame. */ for (i = 0; i < __LIBGCC_DWARF_FRAME_REGISTERS__ + 1; ++i) - switch (fs->regs.reg[i].how) + switch (fs->regs.how[i]) { case REG_UNSAVED: case REG_UNDEFINED: @@ -1531,7 +1533,7 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) rule is handled like same_value. The only exception is DW_CFA_undefined on retaddr_column which is supposed to mark outermost frame in DWARF 3. */ - if (fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)].how + if (fs->regs.how[DWARF_REG_TO_UNWIND_COLUMN (fs->retaddr_column)] == REG_UNDEFINED) /* uw_frame_state_for uses context->ra == 0 check to find outermost stack frame. */ diff --git a/libgcc/unwind-dw2.h b/libgcc/unwind-dw2.h index 0c478e5..af34e00 100644 --- a/libgcc/unwind-dw2.h +++ b/libgcc/unwind-dw2.h @@ -22,6 +22,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ +enum { + REG_UNSAVED, + REG_SAVED_OFFSET, + REG_SAVED_REG, + REG_SAVED_EXP, + REG_SAVED_VAL_OFFSET, + REG_SAVED_VAL_EXP, + REG_UNDEFINED +}; + /* The result of interpreting the frame unwind info for a frame. This is all symbolic at this point, as none of the values can be resolved until the target pc is located. */ @@ -37,16 +47,8 @@ typedef struct _Unwind_Sword offset; const unsigned char *exp; } loc; - enum { - REG_UNSAVED, - REG_SAVED_OFFSET, - REG_SAVED_REG, - REG_SAVED_EXP, - REG_SAVED_VAL_OFFSET, - REG_SAVED_VAL_EXP, - REG_UNDEFINED - } how; } reg[__LIBGCC_DWARF_FRAME_REGISTERS__+1]; + unsigned char how[__LIBGCC_DWARF_FRAME_REGISTERS__+1]; /* Used to implement DW_CFA_remember_state. */ struct frame_state_reg_info *prev; diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 0377b5c..6779493 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,12 @@ +2022-10-05 Tobias Burnus <tobias@codesourcery.com> + + * libgomp.texi (OpenMP 5.1 Impl. Status): Mark 'assume' as 'Y'. + +2022-10-04 Jakub Jelinek <jakub@redhat.com> + + * libgomp.texi (Support begin/end declare target syntax in C/C++): + Mark as implemented. + 2022-09-30 Tobias Burnus <tobias@codesourcery.com> PR fortran/105318 diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index 03d6913..3efa228 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -287,7 +287,7 @@ The OpenMP 4.5 specification is fully supported. @code{append_args} @tab N @tab @item @code{dispatch} construct @tab N @tab @item device-specific ICV settings with environment variables @tab Y @tab -@item @code{assume} directive @tab P @tab Only C/C++ +@item @code{assume} directive @tab Y @tab @item @code{nothing} directive @tab Y @tab @item @code{error} directive @tab Y @tab @item @code{masked} construct @tab Y @tab diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index c22f9d9..2c0d46b 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,9 @@ +2022-10-07 Nathan Sidwell <nathan@acm.org> + + * cp-demangle.c (d_print_comp_inner): Allow parameter packs + in a lambda signature. + * testsuite/demangle-expected: Add tests. + 2022-09-27 Jakub Jelinek <jakub@redhat.com> PR c++/106652 diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 7ff225e..303bfbf 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -348,7 +348,7 @@ struct d_print_info be bigger than MAX_RECURSION_COUNT. */ int recursion; /* Non-zero if we're printing a lambda argument. A template - parameter reference actually means 'auto'. */ + parameter reference actually means 'auto', a pack expansion means T... */ int is_lambda_arg; /* The current index into any template argument packs we are using for printing, or -1 to print the whole pack. */ @@ -5930,9 +5930,10 @@ d_print_comp_inner (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_PACK_EXPANSION: { - int len; - int i; - struct demangle_component *a = d_find_pack (dpi, d_left (dc)); + struct demangle_component *a = NULL; + + if (!dpi->is_lambda_arg) + a = d_find_pack (dpi, d_left (dc)); if (a == NULL) { /* d_find_pack won't find anything if the only packs involved @@ -5940,17 +5941,20 @@ d_print_comp_inner (struct d_print_info *dpi, int options, case, just print the pattern and "...". */ d_print_subexpr (dpi, options, d_left (dc)); d_append_string (dpi, "..."); - return; } - - len = d_pack_length (a); - dc = d_left (dc); - for (i = 0; i < len; ++i) + else { - dpi->pack_index = i; - d_print_comp (dpi, options, dc); - if (i < len-1) - d_append_string (dpi, ", "); + int len = d_pack_length (a); + int i; + + dc = d_left (dc); + for (i = 0; i < len; ++i) + { + if (i) + d_append_string (dpi, ", "); + dpi->pack_index = i; + d_print_comp (dpi, options, dc); + } } } return; diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 8fad689..90dd4a1 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -1574,3 +1574,10 @@ initializer for module Foo.Bar _ZGIW3FooWP3BarW3Baz initializer for module Foo:Bar.Baz + +_ZZ2L1vENKUlDpT_E_clIJiPiEEEvS0_ +void L1()::{lambda((auto:1)...)#1}::operator()<int, int*>(int, int*) const + +_ZZ2L1vENKUlDpT_E_clIJiPiEEEDaS0_ +auto L1()::{lambda((auto:1)...)#1}::operator()<int, int*>(int, int*) const + diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index be69777..68f9a1d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,105 @@ +2022-10-07 Jonathan Wakely <jwakely@redhat.com> + + * acinclude.m4 (GLIBCXX_ENABLE_HOSTED): Add libstdcxx-hosted + enable arg as an alias for hosted-libstdcxx enable arg. + * configure: Regenerate. + +2022-10-07 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/std_function.h: Include <new> but do not include + <bits/stl_function.h>. + * include/std/functional: Do not include <new>. + +2022-10-07 Jonathan Wakely <jwakely@redhat.com> + + * doc/xml/manual/intro.xml: Add role="bold" attribute to + emphasis elements for issue titles. + * doc/html/manual/bugs.html: Regenerate. + +2022-10-05 Jonathan Wakely <jwakely@redhat.com> + + * include/Makefile.in: Regenerate. + +2022-10-05 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/invoke.h (__invoke_r): Check + __has_builtin(__reference_converts_from_temporary) before using + built-in. + +2022-10-04 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/std/ranges/adaptors/join_with/1.cc: Remove unused + <sstream header. + (test04): Remove constexpr for old std::string ABI and test at + runtime. + +2022-10-04 Jonathan Wakely <jwakely@redhat.com> + + * include/std/type_traits (remove_cv): Use __remove_cv built-in. + (remove_reference): Use __remove_reference built-in. + (remove_cvref): Use __remove_cvref built-in. Remove inheritance + for fallback implementation. + +2022-10-04 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/random.h (__is_seed_seq): Replace with ... + (_If_seed_seq_for): ... this. + * include/ext/random: Adjust to use _If_seed_seq_for. + +2022-10-04 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges (join_with_view::_Iterator::operator*): + Replace use of std::visit with manual visitation. + (join_with_view::_Iterator::operator++): Likewise. + (join_with_view::_Iterator::operator--): Likewise. + (join_with_view::_Iterator::iter_move): Likewise. + (join_with_view::_Iterator::iter_swap): Likewise. + +2022-10-04 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/25_algorithms/stable_sort/mem_check.cc: Do nto run + for freestanding. + +2022-10-04 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/107139 + * include/std/coroutine: Remove all _GLIBCXXHOSTED preprocessor + conditionals. + +2022-10-04 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/107134 + * include/c_global/cstdint [!_GLIBCXX_HOSTED]: Include + <stdint-gcc.h> directly. + +2022-10-04 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/107135 + * include/bits/functexcept.h [!_GLIBCXX_HOSTED] + (__throw_invalid_argument, __throw_out_of_range) + (__throw_out_of_range_fmt, __throw_runtime_error) + (__throw_overflow_error): Define inline. + * include/std/bitset (_M_copy_from_ptr) [!_GLIBCXX_HOSTED]: + Replace __builtin_abort with __throw_invalid_argument. + +2022-10-04 Patrick Palka <ppalka@redhat.com> + + * include/std/ranges: Include <variant> for C++23. + (__detail::__compatible_joinable_ranges): Define. + (__detail::__bidirectional_common): Define. + (join_with_view): Define. + (join_with_view::_Iterator): Define. + (join_with_view::_Sentinel): Define. + (views::__detail::__can_join_with_view): Define. + (views::_JoinWith, views::join_with): Define. + * testsuite/std/ranges/adaptors/join_with/1.cc: New test. + +2022-10-04 Arsen Arsenović <arsen@aarsen.me> + + * include/std/iostream: Use ///< for inline documentation. + * include/std/limits: Likewise. + * include/experimental/internet: Likewise. + 2022-10-03 Jonathan Wakely <jwakely@redhat.com> * doc/xml/manual/status_cxx2020.xml: Update C++20 status. diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 1b404d7..719eab1 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -2962,6 +2962,10 @@ dnl installing only the headers required by [17.4.1.3] and the language dnl support library. More than that will be built (to keep the Makefiles dnl conveniently clean), but not installed. dnl +dnl Also define --disable-libstdcxx-hosted as an alias for +dnl --disable-hosted-libstdcxx but fail if both are given +dnl and their values do not agree. +dnl dnl Sets: dnl is_hosted (yes/no) dnl @@ -2971,7 +2975,8 @@ dnl AC_DEFUN([GLIBCXX_ENABLE_HOSTED], [ AC_ARG_ENABLE([hosted-libstdcxx], AC_HELP_STRING([--disable-hosted-libstdcxx], - [only build freestanding C++ runtime support]),, + [only build freestanding C++ runtime support]), + [enable_hosted_libstdcxx_was_given=yes], [case "$host" in arm*-*-symbianelf*) enable_hosted_libstdcxx=no @@ -2980,6 +2985,21 @@ AC_DEFUN([GLIBCXX_ENABLE_HOSTED], [ enable_hosted_libstdcxx=yes ;; esac]) + + # Because most configure args are --enable-libstdcxx-foo add an alias + # of that form for --enable-hosted-libstdcxx. + AC_ARG_ENABLE([libstdcxx-hosted], + AC_HELP_STRING([--disable-libstdcxx-hosted], + [alias for --disable-hosted-libstdcxx]), + [if test "$enable_hosted_libstdcxx_was_given" = yes; then + if test "$enable_hosted_libstdcxx" != "$enableval"; then + AC_MSG_ERROR([--enable-libstdcxx-hosted=$enableval conflicts with --enable-hosted-libstdcxx=$enable_hosted_libstdcxx]) + fi + else + enable_hosted_libstdcxx=${enableval} + fi + ],) + freestanding_flags= if test "$enable_hosted_libstdcxx" = no; then AC_MSG_NOTICE([Only freestanding libraries will be built]) diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 4f2c12f..7ead77a 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -922,6 +922,7 @@ enable_fast_install with_gnu_ld enable_libtool_lock enable_hosted_libstdcxx +enable_libstdcxx_hosted enable_libstdcxx_verbose enable_libstdcxx_pch with_libstdcxx_lock_policy @@ -1610,6 +1611,8 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --disable-hosted-libstdcxx only build freestanding C++ runtime support + --disable-libstdcxx-hosted + alias for --disable-hosted-libstdcxx --disable-libstdcxx-verbose disable termination messages to standard error --enable-libstdcxx-pch build pre-compiled libstdc++ headers @@ -12200,7 +12203,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12203 "configure" +#line 12206 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12306,7 +12309,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12309 "configure" +#line 12312 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -15635,7 +15638,7 @@ postdeps_CXX=`echo " $postdeps_CXX " | sed 's, -lstdc++ ,,g'` # Check whether --enable-hosted-libstdcxx was given. if test "${enable_hosted_libstdcxx+set}" = set; then : - enableval=$enable_hosted_libstdcxx; + enableval=$enable_hosted_libstdcxx; enable_hosted_libstdcxx_was_given=yes else case "$host" in arm*-*-symbianelf*) @@ -15647,6 +15650,22 @@ else esac fi + + # Because most configure args are --enable-libstdcxx-foo add an alias + # of that form for --enable-hosted-libstdcxx. + # Check whether --enable-libstdcxx-hosted was given. +if test "${enable_libstdcxx_hosted+set}" = set; then : + enableval=$enable_libstdcxx_hosted; if test "$enable_hosted_libstdcxx_was_given" = yes; then + if test "$enable_hosted_libstdcxx" != "$enableval"; then + as_fn_error $? "--enable-libstdcxx-hosted=$enableval conflicts with --enable-hosted-libstdcxx=$enable_hosted_libstdcxx" "$LINENO" 5 + fi + else + enable_hosted_libstdcxx=${enableval} + fi + +fi + + freestanding_flags= if test "$enable_hosted_libstdcxx" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: Only freestanding libraries will be built" >&5 @@ -15990,7 +16009,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; } # Fake what AC_TRY_COMPILE does. cat > conftest.$ac_ext << EOF -#line 15993 "configure" +#line 16012 "configure" int main() { typedef bool atomic_type; @@ -16025,7 +16044,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16028 "configure" +#line 16047 "configure" int main() { typedef short atomic_type; @@ -16060,7 +16079,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16063 "configure" +#line 16082 "configure" int main() { // NB: _Atomic_word not necessarily int. @@ -16096,7 +16115,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16099 "configure" +#line 16118 "configure" int main() { typedef long long atomic_type; @@ -16252,7 +16271,7 @@ $as_echo "mutex" >&6; } # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 16255 "configure" +#line 16274 "configure" int main() { _Decimal32 d1; @@ -16294,7 +16313,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 16297 "configure" +#line 16316 "configure" template<typename T1, typename T2> struct same { typedef T2 type; }; diff --git a/libstdc++-v3/doc/html/manual/bugs.html b/libstdc++-v3/doc/html/manual/bugs.html index 8e0bc1f..58600cd 100644 --- a/libstdc++-v3/doc/html/manual/bugs.html +++ b/libstdc++-v3/doc/html/manual/bugs.html @@ -26,597 +26,597 @@ of style. Note that we usually do not make changes to the code until an issue has reached <a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#DR" target="_top">DR</a> status. </p><div class="variablelist"><dl class="variablelist"><dt><a id="manual.bugs.dr5"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#5" target="_top">5</a>: - <span class="emphasis"><em>string::compare specification questionable</em></span> + <span class="bold"><strong>string::compare specification questionable</strong></span> </span></dt><dd><p>This should be two overloaded functions rather than a single function. </p></dd><dt><a id="manual.bugs.dr17"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#17" target="_top">17</a>: - <span class="emphasis"><em>Bad bool parsing</em></span> + <span class="bold"><strong>Bad bool parsing</strong></span> </span></dt><dd><p>Apparently extracting Boolean values was messed up... </p></dd><dt><a id="manual.bugs.dr19"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#19" target="_top">19</a>: - <span class="emphasis"><em>"Noconv" definition too vague</em></span> + <span class="bold"><strong>"Noconv" definition too vague</strong></span> </span></dt><dd><p>If <code class="code">codecvt::do_in</code> returns <code class="code">noconv</code> there are no changes to the values in <code class="code">[to, to_limit)</code>. </p></dd><dt><a id="manual.bugs.dr22"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#22" target="_top">22</a>: - <span class="emphasis"><em>Member open vs flags</em></span> + <span class="bold"><strong>Member open vs flags</strong></span> </span></dt><dd><p>Re-opening a file stream does <span class="emphasis"><em>not</em></span> clear the state flags. </p></dd><dt><a id="manual.bugs.dr23"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#23" target="_top">23</a>: - <span class="emphasis"><em>Num_get overflow result</em></span> + <span class="bold"><strong>Num_get overflow result</strong></span> </span></dt><dd><p>Implement the proposed resolution. </p></dd><dt><a id="manual.bugs.dr25"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#25" target="_top">25</a>: - <span class="emphasis"><em>String operator<< uses width() value wrong</em></span> + <span class="bold"><strong>String operator<< uses width() value wrong</strong></span> </span></dt><dd><p>Padding issues. </p></dd><dt><a id="manual.bugs.dr48"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#48" target="_top">48</a>: - <span class="emphasis"><em>Use of non-existent exception constructor</em></span> + <span class="bold"><strong>Use of non-existent exception constructor</strong></span> </span></dt><dd><p>An instance of <code class="code">ios_base::failure</code> is constructed instead. </p></dd><dt><a id="manual.bugs.dr49"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#49" target="_top">49</a>: - <span class="emphasis"><em>Underspecification of ios_base::sync_with_stdio</em></span> + <span class="bold"><strong>Underspecification of ios_base::sync_with_stdio</strong></span> </span></dt><dd><p>The return type is the <span class="emphasis"><em>previous</em></span> state of synchronization. </p></dd><dt><a id="manual.bugs.dr50"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#50" target="_top">50</a>: - <span class="emphasis"><em>Copy constructor and assignment operator of ios_base</em></span> + <span class="bold"><strong>Copy constructor and assignment operator of ios_base</strong></span> </span></dt><dd><p>These members functions are declared <code class="code">private</code> and are thus inaccessible. Specifying the correct semantics of "copying stream state" was deemed too complicated. </p></dd><dt><a id="manual.bugs.dr60"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#60" target="_top">60</a>: - <span class="emphasis"><em>What is a formatted input function?</em></span> + <span class="bold"><strong>What is a formatted input function?</strong></span> </span></dt><dd><p>This DR made many widespread changes to <code class="code">basic_istream</code> and <code class="code">basic_ostream</code> all of which have been implemented. </p></dd><dt><a id="manual.bugs.dr63"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#63" target="_top">63</a>: - <span class="emphasis"><em>Exception-handling policy for unformatted output</em></span> + <span class="bold"><strong>Exception-handling policy for unformatted output</strong></span> </span></dt><dd><p>Make the policy consistent with that of formatted input, unformatted input, and formatted output. </p></dd><dt><a id="manual.bugs.dr68"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#68" target="_top">68</a>: - <span class="emphasis"><em>Extractors for char* should store null at end</em></span> + <span class="bold"><strong>Extractors for char* should store null at end</strong></span> </span></dt><dd><p>And they do now. An editing glitch in the last item in the list of [27.6.1.2.3]/7. </p></dd><dt><a id="manual.bugs.dr74"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#74" target="_top">74</a>: - <span class="emphasis"><em>Garbled text for codecvt::do_max_length</em></span> + <span class="bold"><strong>Garbled text for codecvt::do_max_length</strong></span> </span></dt><dd><p>The text of the standard was gibberish. Typos gone rampant. </p></dd><dt><a id="manual.bugs.dr75"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#75" target="_top">75</a>: - <span class="emphasis"><em>Contradiction in codecvt::length's argument types</em></span> + <span class="bold"><strong>Contradiction in codecvt::length's argument types</strong></span> </span></dt><dd><p>Change the first parameter to <code class="code">stateT&</code> and implement the new effects paragraph. </p></dd><dt><a id="manual.bugs.dr83"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#83" target="_top">83</a>: - <span class="emphasis"><em>string::npos vs. string::max_size()</em></span> + <span class="bold"><strong>string::npos vs. string::max_size()</strong></span> </span></dt><dd><p>Safety checks on the size of the string should test against <code class="code">max_size()</code> rather than <code class="code">npos</code>. </p></dd><dt><a id="manual.bugs.dr90"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#90" target="_top">90</a>: - <span class="emphasis"><em>Incorrect description of operator>> for strings</em></span> + <span class="bold"><strong>Incorrect description of operator>> for strings</strong></span> </span></dt><dd><p>The effect contain <code class="code">isspace(c,getloc())</code> which must be replaced by <code class="code">isspace(c,is.getloc())</code>. </p></dd><dt><a id="manual.bugs.dr91"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#91" target="_top">91</a>: - <span class="emphasis"><em>Description of operator>> and getline() for string<> - might cause endless loop</em></span> + <span class="bold"><strong>Description of operator>> and getline() for string<> + might cause endless loop</strong></span> </span></dt><dd><p>They behave as a formatted input function and as an unformatted input function, respectively (except that <code class="code">getline</code> is not required to set <code class="code">gcount</code>). </p></dd><dt><a id="manual.bugs.dr103"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#103" target="_top">103</a>: - <span class="emphasis"><em>set::iterator is required to be modifiable, but this allows - modification of keys.</em></span> + <span class="bold"><strong>set::iterator is required to be modifiable, but this allows + modification of keys.</strong></span> </span></dt><dd><p>For associative containers where the value type is the same as the key type, both <code class="code">iterator</code> and <code class="code">const_iterator </code> are constant iterators. </p></dd><dt><a id="manual.bugs.dr109"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#109" target="_top">109</a>: - <span class="emphasis"><em>Missing binders for non-const sequence elements</em></span> + <span class="bold"><strong>Missing binders for non-const sequence elements</strong></span> </span></dt><dd><p>The <code class="code">binder1st</code> and <code class="code">binder2nd</code> didn't have an <code class="code">operator()</code> taking a non-const parameter. </p></dd><dt><a id="manual.bugs.dr110"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#110" target="_top">110</a>: - <span class="emphasis"><em>istreambuf_iterator::equal not const</em></span> + <span class="bold"><strong>istreambuf_iterator::equal not const</strong></span> </span></dt><dd><p>This was not a const member function. Note that the DR says to replace the function with a const one; we have instead provided an overloaded version with identical contents. </p></dd><dt><a id="manual.bugs.dr117"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#117" target="_top">117</a>: - <span class="emphasis"><em>basic_ostream uses nonexistent num_put member functions</em></span> + <span class="bold"><strong>basic_ostream uses nonexistent num_put member functions</strong></span> </span></dt><dd><p><code class="code">num_put::put()</code> was overloaded on the wrong types. </p></dd><dt><a id="manual.bugs.dr118"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#118" target="_top">118</a>: - <span class="emphasis"><em>basic_istream uses nonexistent num_get member functions</em></span> + <span class="bold"><strong>basic_istream uses nonexistent num_get member functions</strong></span> </span></dt><dd><p>Same as 117, but for <code class="code">num_get::get()</code>. </p></dd><dt><a id="manual.bugs.dr129"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#129" target="_top">129</a>: - <span class="emphasis"><em>Need error indication from seekp() and seekg()</em></span> + <span class="bold"><strong>Need error indication from seekp() and seekg()</strong></span> </span></dt><dd><p>These functions set <code class="code">failbit</code> on error now. </p></dd><dt><a id="manual.bugs.dr130"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#130" target="_top">130</a>: - <span class="emphasis"><em>Return type of container::erase(iterator) differs for associative containers</em></span> + <span class="bold"><strong>Return type of container::erase(iterator) differs for associative containers</strong></span> </span></dt><dd><p>Make member <code class="code">erase</code> return iterator for <code class="code">set</code>, <code class="code">multiset</code>, <code class="code">map</code>, <code class="code">multimap</code>. </p></dd><dt><a id="manual.bugs.dr136"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#136" target="_top">136</a>: - <span class="emphasis"><em>seekp, seekg setting wrong streams?</em></span> + <span class="bold"><strong>seekp, seekg setting wrong streams?</strong></span> </span></dt><dd><p><code class="code">seekp</code> should only set the output stream, and <code class="code">seekg</code> should only set the input stream. </p></dd><dt><a id="manual.bugs.dr167"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#167" target="_top">167</a>: - <span class="emphasis"><em>Improper use of traits_type::length()</em></span> + <span class="bold"><strong>Improper use of traits_type::length()</strong></span> </span></dt><dd><p><code class="code">op<<</code> with a <code class="code">const char*</code> was calculating an incorrect number of characters to write. </p></dd><dt><a id="manual.bugs.dr169"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#169" target="_top">169</a>: - <span class="emphasis"><em>Bad efficiency of overflow() mandated</em></span> + <span class="bold"><strong>Bad efficiency of overflow() mandated</strong></span> </span></dt><dd><p>Grow efficiently the internal array object. </p></dd><dt><a id="manual.bugs.dr171"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#171" target="_top">171</a>: - <span class="emphasis"><em>Strange seekpos() semantics due to joint position</em></span> + <span class="bold"><strong>Strange seekpos() semantics due to joint position</strong></span> </span></dt><dd><p>Quite complex to summarize... </p></dd><dt><a id="manual.bugs.dr181"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#181" target="_top">181</a>: - <span class="emphasis"><em>make_pair() unintended behavior</em></span> + <span class="bold"><strong>make_pair() unintended behavior</strong></span> </span></dt><dd><p>This function used to take its arguments as reference-to-const, now it copies them (pass by value). </p></dd><dt><a id="manual.bugs.dr195"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#195" target="_top">195</a>: - <span class="emphasis"><em>Should basic_istream::sentry's constructor ever set eofbit?</em></span> + <span class="bold"><strong>Should basic_istream::sentry's constructor ever set eofbit?</strong></span> </span></dt><dd><p>Yes, it can, specifically if EOF is reached while skipping whitespace. </p></dd><dt><a id="manual.bugs.dr206"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#206" target="_top">206</a>: - <span class="emphasis"><em><code class="code">operator new(size_t, nothrow)</code> may become - unlinked to ordinary <code class="code">operator new</code> if ordinary - version replaced - </em></span> + <span class="bold"><strong><code class="code">operator new(size_t, nothrow)</code> may become + unlinked to ordinary <code class="code">operator new</code> if ordinary + version replaced + </strong></span> </span></dt><dd><p>The <code class="code">nothrow</code> forms of new and delete were changed to call the throwing forms, handling any exception by catching it and returning a null pointer. </p></dd><dt><a id="manual.bugs.dr211"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#211" target="_top">211</a>: - <span class="emphasis"><em>operator>>(istream&, string&) doesn't set failbit</em></span> + <span class="bold"><strong>operator>>(istream&, string&) doesn't set failbit</strong></span> </span></dt><dd><p>If nothing is extracted into the string, <code class="code">op>></code> now sets <code class="code">failbit</code> (which can cause an exception, etc., etc.). </p></dd><dt><a id="manual.bugs.dr214"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#214" target="_top">214</a>: - <span class="emphasis"><em>set::find() missing const overload</em></span> + <span class="bold"><strong>set::find() missing const overload</strong></span> </span></dt><dd><p>Both <code class="code">set</code> and <code class="code">multiset</code> were missing overloaded find, lower_bound, upper_bound, and equal_range functions for const instances. </p></dd><dt><a id="manual.bugs.dr231"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#231" target="_top">231</a>: - <span class="emphasis"><em>Precision in iostream?</em></span> + <span class="bold"><strong>Precision in iostream?</strong></span> </span></dt><dd><p>For conversion from a floating-point type, <code class="code">str.precision()</code> is specified in the conversion specification. </p></dd><dt><a id="manual.bugs.dr233"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233" target="_top">233</a>: - <span class="emphasis"><em>Insertion hints in associative containers</em></span> + <span class="bold"><strong>Insertion hints in associative containers</strong></span> </span></dt><dd><p>Implement N1780, first check before then check after, insert as close to hint as possible. </p></dd><dt><a id="manual.bugs.dr235"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#235" target="_top">235</a>: - <span class="emphasis"><em>No specification of default ctor for reverse_iterator</em></span> + <span class="bold"><strong>No specification of default ctor for reverse_iterator</strong></span> </span></dt><dd><p>The declaration of <code class="code">reverse_iterator</code> lists a default constructor. However, no specification is given what this constructor should do. </p></dd><dt><a id="manual.bugs.dr241"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#241" target="_top">241</a>: - <span class="emphasis"><em>Does unique_copy() require CopyConstructible and Assignable?</em></span> + <span class="bold"><strong>Does unique_copy() require CopyConstructible and Assignable?</strong></span> </span></dt><dd><p>Add a helper for forward_iterator/output_iterator, fix the existing one for input_iterator/output_iterator to not rely on Assignability. </p></dd><dt><a id="manual.bugs.dr243"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#243" target="_top">243</a>: - <span class="emphasis"><em>get and getline when sentry reports failure</em></span> + <span class="bold"><strong>get and getline when sentry reports failure</strong></span> </span></dt><dd><p>Store a null character only if the character array has a non-zero size. </p></dd><dt><a id="manual.bugs.dr251"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#251" target="_top">251</a>: - <span class="emphasis"><em>basic_stringbuf missing allocator_type</em></span> + <span class="bold"><strong>basic_stringbuf missing allocator_type</strong></span> </span></dt><dd><p>This nested typedef was originally not specified. </p></dd><dt><a id="manual.bugs.dr253"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#253" target="_top">253</a>: - <span class="emphasis"><em>valarray helper functions are almost entirely useless</em></span> + <span class="bold"><strong>valarray helper functions are almost entirely useless</strong></span> </span></dt><dd><p>Make the copy constructor and copy-assignment operator declarations public in gslice_array, indirect_array, mask_array, slice_array; provide definitions. </p></dd><dt><a id="manual.bugs.dr265"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#265" target="_top">265</a>: - <span class="emphasis"><em>std::pair::pair() effects overly restrictive</em></span> + <span class="bold"><strong>std::pair::pair() effects overly restrictive</strong></span> </span></dt><dd><p>The default ctor would build its members from copies of temporaries; now it simply uses their respective default ctors. </p></dd><dt><a id="manual.bugs.dr266"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#266" target="_top">266</a>: - <span class="emphasis"><em>bad_exception::~bad_exception() missing Effects clause</em></span> + <span class="bold"><strong>bad_exception::~bad_exception() missing Effects clause</strong></span> </span></dt><dd><p>The <code class="code">bad_</code>* classes no longer have destructors (they are trivial), since no description of them was ever given. </p></dd><dt><a id="manual.bugs.dr271"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#271" target="_top">271</a>: - <span class="emphasis"><em>basic_iostream missing typedefs</em></span> + <span class="bold"><strong>basic_iostream missing typedefs</strong></span> </span></dt><dd><p>The typedefs it inherits from its base classes can't be used, since (for example) <code class="code">basic_iostream<T>::traits_type</code> is ambiguous. </p></dd><dt><a id="manual.bugs.dr275"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#275" target="_top">275</a>: - <span class="emphasis"><em>Wrong type in num_get::get() overloads</em></span> + <span class="bold"><strong>Wrong type in num_get::get() overloads</strong></span> </span></dt><dd><p>Similar to 118. </p></dd><dt><a id="manual.bugs.dr280"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#280" target="_top">280</a>: - <span class="emphasis"><em>Comparison of reverse_iterator to const reverse_iterator</em></span> + <span class="bold"><strong>Comparison of reverse_iterator to const reverse_iterator</strong></span> </span></dt><dd><p>Add global functions with two template parameters. (NB: not added for now a templated assignment operator) </p></dd><dt><a id="manual.bugs.dr292"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#292" target="_top">292</a>: - <span class="emphasis"><em>Effects of a.copyfmt (a)</em></span> + <span class="bold"><strong>Effects of a.copyfmt (a)</strong></span> </span></dt><dd><p>If <code class="code">(this == &rhs)</code> do nothing. </p></dd><dt><a id="manual.bugs.dr300"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#300" target="_top">300</a>: - <span class="emphasis"><em>List::merge() specification incomplete</em></span> + <span class="bold"><strong>List::merge() specification incomplete</strong></span> </span></dt><dd><p>If <code class="code">(this == &x)</code> do nothing. </p></dd><dt><a id="manual.bugs.dr303"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#303" target="_top">303</a>: - <span class="emphasis"><em>Bitset input operator underspecified</em></span> + <span class="bold"><strong>Bitset input operator underspecified</strong></span> </span></dt><dd><p>Basically, compare the input character to <code class="code">is.widen(0)</code> and <code class="code">is.widen(1)</code>. </p></dd><dt><a id="manual.bugs.dr305"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#305" target="_top">305</a>: - <span class="emphasis"><em>Default behavior of codecvt<wchar_t, char, - mbstate_t>::length()</em></span> + <span class="bold"><strong>Default behavior of codecvt<wchar_t, char, + mbstate_t>::length()</strong></span> </span></dt><dd><p>Do not specify what <code class="code">codecvt<wchar_t, char, mbstate_t>::do_length</code> must return. </p></dd><dt><a id="manual.bugs.dr328"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#328" target="_top">328</a>: - <span class="emphasis"><em>Bad sprintf format modifier in - money_put<>::do_put()</em></span> + <span class="bold"><strong>Bad sprintf format modifier in + money_put<>::do_put()</strong></span> </span></dt><dd><p>Change the format string to "%.0Lf". </p></dd><dt><a id="manual.bugs.dr365"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#365" target="_top">365</a>: - <span class="emphasis"><em>Lack of const-qualification in clause 27</em></span> + <span class="bold"><strong>Lack of const-qualification in clause 27</strong></span> </span></dt><dd><p>Add const overloads of <code class="code">is_open</code>. </p></dd><dt><a id="manual.bugs.dr387"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#387" target="_top">387</a>: - <span class="emphasis"><em>std::complex over-encapsulated</em></span> + <span class="bold"><strong>std::complex over-encapsulated</strong></span> </span></dt><dd><p>Add the <code class="code">real(T)</code> and <code class="code">imag(T)</code> members; in C++11 mode, also adjust the existing <code class="code">real()</code> and <code class="code">imag()</code> members and free functions. </p></dd><dt><a id="manual.bugs.dr389"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#389" target="_top">389</a>: - <span class="emphasis"><em>Const overload of valarray::operator[] returns - by value</em></span> + <span class="bold"><strong>Const overload of valarray::operator[] returns + by value</strong></span> </span></dt><dd><p>Change it to return a <code class="code">const T&</code>. </p></dd><dt><a id="manual.bugs.dr396"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#396" target="_top">396</a>: - <span class="emphasis"><em>what are characters zero and one</em></span> + <span class="bold"><strong>what are characters zero and one</strong></span> </span></dt><dd><p>Implement the proposed resolution. </p></dd><dt><a id="manual.bugs.dr402"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#402" target="_top">402</a>: - <span class="emphasis"><em>Wrong new expression in [some_]allocator::construct</em></span> + <span class="bold"><strong>Wrong new expression in [some_]allocator::construct</strong></span> </span></dt><dd><p>Replace "new" with "::new". </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-closed.html#408" target="_top">408</a>: - <span class="emphasis"><em> + <span class="bold"><strong> Is vector<reverse_iterator<char*> > forbidden? - </em></span> + </strong></span> </span></dt><dd><p>Tweak the debug-mode checks in _Safe_iterator. </p></dd><dt><a id="manual.bugs.dr409"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#409" target="_top">409</a>: - <span class="emphasis"><em>Closing an fstream should clear the error state</em></span> + <span class="bold"><strong>Closing an fstream should clear the error state</strong></span> </span></dt><dd><p>Have <code class="code">open</code> clear the error flags. </p></dd><dt><a id="manual.bugs.dr415"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#415" target="_top">415</a>: - <span class="emphasis"><em>Behavior of std::ws</em></span> + <span class="bold"><strong>Behavior of std::ws</strong></span> </span></dt><dd><p>Change it to be an unformatted input function (i.e. construct a sentry and catch exceptions). </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-closed.html#431" target="_top">431</a>: - <span class="emphasis"><em>Swapping containers with unequal allocators</em></span> + <span class="bold"><strong>Swapping containers with unequal allocators</strong></span> </span></dt><dd><p>Implement Option 3, as per N1599. </p></dd><dt><a id="manual.bugs.dr432"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#432" target="_top">432</a>: - <span class="emphasis"><em>stringbuf::overflow() makes only one write position - available</em></span> + <span class="bold"><strong>stringbuf::overflow() makes only one write position + available</strong></span> </span></dt><dd><p>Implement the resolution, beyond DR 169. </p></dd><dt><a id="manual.bugs.dr434"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#434" target="_top">434</a>: - <span class="emphasis"><em>bitset::to_string() hard to use</em></span> + <span class="bold"><strong>bitset::to_string() hard to use</strong></span> </span></dt><dd><p>Add three overloads, taking fewer template arguments. </p></dd><dt><a id="manual.bugs.dr438"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#438" target="_top">438</a>: - <span class="emphasis"><em>Ambiguity in the "do the right thing" clause</em></span> + <span class="bold"><strong>Ambiguity in the "do the right thing" clause</strong></span> </span></dt><dd><p>Implement the resolution, basically cast less. </p></dd><dt><a id="manual.bugs.dr445"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#445" target="_top">445</a>: - <span class="emphasis"><em>iterator_traits::reference unspecified for some iterator categories</em></span> + <span class="bold"><strong>iterator_traits::reference unspecified for some iterator categories</strong></span> </span></dt><dd><p>Change <code class="code">istreambuf_iterator::reference</code> in C++11 mode. </p></dd><dt><a id="manual.bugs.dr453"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#453" target="_top">453</a>: - <span class="emphasis"><em>basic_stringbuf::seekoff need not always fail for an empty stream</em></span> + <span class="bold"><strong>basic_stringbuf::seekoff need not always fail for an empty stream</strong></span> </span></dt><dd><p>Don't fail if the next pointer is null and newoff is zero. </p></dd><dt><a id="manual.bugs.dr455"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#455" target="_top">455</a>: - <span class="emphasis"><em>cerr::tie() and wcerr::tie() are overspecified</em></span> + <span class="bold"><strong>cerr::tie() and wcerr::tie() are overspecified</strong></span> </span></dt><dd><p>Initialize cerr tied to cout and wcerr tied to wcout. </p></dd><dt><a id="manual.bugs.dr464"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464" target="_top">464</a>: - <span class="emphasis"><em>Suggestion for new member functions in standard containers</em></span> + <span class="bold"><strong>Suggestion for new member functions in standard containers</strong></span> </span></dt><dd><p>Add <code class="code">data()</code> to <code class="code">std::vector</code> and <code class="code">at(const key_type&)</code> to <code class="code">std::map</code>. </p></dd><dt><a id="manual.bugs.dr467"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#467" target="_top">467</a>: - <span class="emphasis"><em>char_traits::lt(), compare(), and memcmp()</em></span> + <span class="bold"><strong>char_traits::lt(), compare(), and memcmp()</strong></span> </span></dt><dd><p>Change <code class="code">lt</code>. </p></dd><dt><a id="manual.bugs.dr508"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#508" target="_top">508</a>: - <span class="emphasis"><em>Bad parameters for ranlux64_base_01</em></span> + <span class="bold"><strong>Bad parameters for ranlux64_base_01</strong></span> </span></dt><dd><p>Fix the parameters. </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-closed.html#512" target="_top">512</a>: - <span class="emphasis"><em>Seeding subtract_with_carry_01 from a single unsigned long</em></span> + <span class="bold"><strong>Seeding subtract_with_carry_01 from a single unsigned long</strong></span> </span></dt><dd><p>Construct a <code class="code">linear_congruential</code> engine and seed with it. </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-closed.html#526" target="_top">526</a>: - <span class="emphasis"><em>Is it undefined if a function in the standard changes in - parameters?</em></span> + <span class="bold"><strong>Is it undefined if a function in the standard changes in + parameters?</strong></span> </span></dt><dd><p>Use &value. </p></dd><dt><a id="manual.bugs.dr538"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#538" target="_top">538</a>: - <span class="emphasis"><em>241 again: Does unique_copy() require CopyConstructible - and Assignable?</em></span> + <span class="bold"><strong>241 again: Does unique_copy() require CopyConstructible + and Assignable?</strong></span> </span></dt><dd><p>In case of input_iterator/output_iterator rely on Assignability of input_iterator' value_type. </p></dd><dt><a id="manual.bugs.dr539"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#539" target="_top">539</a>: - <span class="emphasis"><em>partial_sum and adjacent_difference should mention - requirements</em></span> + <span class="bold"><strong>partial_sum and adjacent_difference should mention + requirements</strong></span> </span></dt><dd><p>We were almost doing the right thing, just use std::move in adjacent_difference. </p></dd><dt><a id="manual.bugs.dr541"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#541" target="_top">541</a>: - <span class="emphasis"><em>shared_ptr template assignment and void</em></span> + <span class="bold"><strong>shared_ptr template assignment and void</strong></span> </span></dt><dd><p>Add an auto_ptr<void> specialization. </p></dd><dt><a id="manual.bugs.dr543"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#543" target="_top">543</a>: - <span class="emphasis"><em>valarray slice default constructor</em></span> + <span class="bold"><strong>valarray slice default constructor</strong></span> </span></dt><dd><p>Follow the straightforward proposed resolution. </p></dd><dt><a id="manual.bugs.dr550"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#550" target="_top">550</a>: - <span class="emphasis"><em>What should the return type of pow(float,int) be?</em></span> + <span class="bold"><strong>What should the return type of pow(float,int) be?</strong></span> </span></dt><dd><p>In C++11 mode, remove the pow(float,int), etc., signatures. </p></dd><dt><a id="manual.bugs.dr581"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#581" target="_top">581</a>: - <span class="emphasis"><em><code class="code">flush()</code> not unformatted function</em></span> + <span class="bold"><strong><code class="code">flush()</code> not unformatted function</strong></span> </span></dt><dd><p>Change it to be a unformatted output function (i.e. construct a sentry and catch exceptions). </p></dd><dt><a id="manual.bugs.dr586"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#586" target="_top">586</a>: - <span class="emphasis"><em>string inserter not a formatted function</em></span> + <span class="bold"><strong>string inserter not a formatted function</strong></span> </span></dt><dd><p>Change it to be a formatted output function (i.e. catch exceptions). </p></dd><dt><a id="manual.bugs.dr596"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#596" target="_top">596</a>: - <span class="emphasis"><em>27.8.1.3 Table 112 omits "a+" and "a+b" modes</em></span> + <span class="bold"><strong>27.8.1.3 Table 112 omits "a+" and "a+b" modes</strong></span> </span></dt><dd><p>Add the missing modes to fopen_mode. </p></dd><dt><a id="manual.bugs.dr630"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#630" target="_top">630</a>: - <span class="emphasis"><em>arrays of valarray</em></span> + <span class="bold"><strong>arrays of valarray</strong></span> </span></dt><dd><p>Implement the simple resolution. </p></dd><dt><a id="manual.bugs.dr660"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#660" target="_top">660</a>: - <span class="emphasis"><em>Missing bitwise operations</em></span> + <span class="bold"><strong>Missing bitwise operations</strong></span> </span></dt><dd><p>Add the missing operations. </p></dd><dt><a id="manual.bugs.dr691"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#691" target="_top">691</a>: - <span class="emphasis"><em>const_local_iterator cbegin, cend missing from TR1</em></span> + <span class="bold"><strong>const_local_iterator cbegin, cend missing from TR1</strong></span> </span></dt><dd><p>In C++11 mode add cbegin(size_type) and cend(size_type) to the unordered containers. </p></dd><dt><a id="manual.bugs.dr693"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#693" target="_top">693</a>: - <span class="emphasis"><em>std::bitset::all() missing</em></span> + <span class="bold"><strong>std::bitset::all() missing</strong></span> </span></dt><dd><p>Add it, consistently with the discussion. </p></dd><dt><a id="manual.bugs.dr695"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#695" target="_top">695</a>: - <span class="emphasis"><em>ctype<char>::classic_table() not accessible</em></span> + <span class="bold"><strong>ctype<char>::classic_table() not accessible</strong></span> </span></dt><dd><p>Make the member functions table and classic_table public. </p></dd><dt><a id="manual.bugs.dr696"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#696" target="_top">696</a>: - <span class="emphasis"><em>istream::operator>>(int&) broken</em></span> + <span class="bold"><strong>istream::operator>>(int&) broken</strong></span> </span></dt><dd><p>Implement the straightforward resolution. </p></dd><dt><a id="manual.bugs.dr761"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#761" target="_top">761</a>: - <span class="emphasis"><em>unordered_map needs an at() member function</em></span> + <span class="bold"><strong>unordered_map needs an at() member function</strong></span> </span></dt><dd><p>In C++11 mode, add at() and at() const. </p></dd><dt><a id="manual.bugs.dr775"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#775" target="_top">775</a>: - <span class="emphasis"><em>Tuple indexing should be unsigned?</em></span> + <span class="bold"><strong>Tuple indexing should be unsigned?</strong></span> </span></dt><dd><p>Implement the int -> size_t replacements. </p></dd><dt><a id="manual.bugs.dr776"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776" target="_top">776</a>: - <span class="emphasis"><em>Undescribed assign function of std::array</em></span> + <span class="bold"><strong>Undescribed assign function of std::array</strong></span> </span></dt><dd><p>In C++11 mode, remove assign, add fill. </p></dd><dt><a id="manual.bugs.dr781"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#781" target="_top">781</a>: - <span class="emphasis"><em>std::complex should add missing C99 functions</em></span> + <span class="bold"><strong>std::complex should add missing C99 functions</strong></span> </span></dt><dd><p>In C++11 mode, add std::proj. </p></dd><dt><a id="manual.bugs.dr809"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809" target="_top">809</a>: - <span class="emphasis"><em>std::swap should be overloaded for array types</em></span> + <span class="bold"><strong>std::swap should be overloaded for array types</strong></span> </span></dt><dd><p>Add the overload. </p></dd><dt><a id="manual.bugs.dr853"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#853" target="_top">853</a>: - <span class="emphasis"><em>to_string needs updating with zero and one</em></span> + <span class="bold"><strong>to_string needs updating with zero and one</strong></span> </span></dt><dd><p>Update / add the signatures. </p></dd><dt><a id="manual.bugs.dr865"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#865" target="_top">865</a>: - <span class="emphasis"><em>More algorithms that throw away information</em></span> + <span class="bold"><strong>More algorithms that throw away information</strong></span> </span></dt><dd><p>The traditional HP / SGI return type and value is blessed by the resolution of the DR. </p></dd><dt><a id="manual.bugs.dr1203"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#1203" target="_top">1203</a>: - <span class="emphasis"><em>More useful rvalue stream insertion</em></span> + <span class="bold"><strong>More useful rvalue stream insertion</strong></span> </span></dt><dd><p>Return the stream as its original type, not the base class. </p></dd><dt><a id="manual.bugs.dr1339"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#1339" target="_top">1339</a>: - <span class="emphasis"><em>uninitialized_fill_n should return the end of its range</em></span> + <span class="bold"><strong>uninitialized_fill_n should return the end of its range</strong></span> </span></dt><dd><p>Return the end of the filled range. </p></dd><dt><a id="manual.bugs.dr2021"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2021" target="_top">2021</a>: - <span class="emphasis"><em>Further incorrect uses of <code class="code">result_of</code></em></span> + <span class="bold"><strong>Further incorrect uses of <code class="code">result_of</code></strong></span> </span></dt><dd><p>Correctly decay types in signature of <code class="code">std::async</code>. </p></dd><dt><a id="manual.bugs.dr2049"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2049" target="_top">2049</a>: - <span class="emphasis"><em><code class="code">is_destructible</code> underspecified</em></span> + <span class="bold"><strong><code class="code">is_destructible</code> underspecified</strong></span> </span></dt><dd><p>Handle non-object types. </p></dd><dt><a id="manual.bugs.dr2056"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2056" target="_top">2056</a>: - <span class="emphasis"><em>future_errc enums start with value 0 (invalid value for broken_promise)</em></span> + <span class="bold"><strong>future_errc enums start with value 0 (invalid value for broken_promise)</strong></span> </span></dt><dd><p>Reorder enumerators. </p></dd><dt><a id="manual.bugs.dr2059"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2059" target="_top">2059</a>: - <span class="emphasis"><em>C++0x ambiguity problem with map::erase</em></span> + <span class="bold"><strong>C++0x ambiguity problem with map::erase</strong></span> </span></dt><dd><p>Add additional overloads. </p></dd><dt><a id="manual.bugs.dr2062"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2062" target="_top">2062</a>: - <span class="emphasis"><em>2062. Effect contradictions w/o no-throw guarantee of <code class="code">std::function</code> swaps</em></span> + <span class="bold"><strong>2062. Effect contradictions w/o no-throw guarantee of <code class="code">std::function</code> swaps</strong></span> </span></dt><dd><p>Add <code class="code">noexcept</code> to swap functions. </p></dd><dt><a id="manual.bugs.dr2063"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2063" target="_top">2063</a>: - <span class="emphasis"><em>Contradictory requirements for string move assignment</em></span> + <span class="bold"><strong>Contradictory requirements for string move assignment</strong></span> </span></dt><dd><p>Respect propagation trait for move assignment. </p></dd><dt><a id="manual.bugs.dr2064"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2064" target="_top">2064</a>: - <span class="emphasis"><em>More noexcept issues in basic_string</em></span> + <span class="bold"><strong>More noexcept issues in basic_string</strong></span> </span></dt><dd><p>Add noexcept to the comparison operators. </p></dd><dt><a id="manual.bugs.dr2067"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2067" target="_top">2067</a>: - <span class="emphasis"><em>packaged_task should have deleted copy c'tor with const parameter</em></span> + <span class="bold"><strong>packaged_task should have deleted copy c'tor with const parameter</strong></span> </span></dt><dd><p>Fix signatures. </p></dd><dt><a id="manual.bugs.dr2101"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2101" target="_top">2101</a>: - <span class="emphasis"><em>Some transformation types can produce impossible types</em></span> + <span class="bold"><strong>Some transformation types can produce impossible types</strong></span> </span></dt><dd><p>Use the referenceable type concept. </p></dd><dt><a id="manual.bugs.dr2106"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2106" target="_top">2106</a>: - <span class="emphasis"><em>move_iterator wrapping iterators returning prvalues</em></span> + <span class="bold"><strong>move_iterator wrapping iterators returning prvalues</strong></span> </span></dt><dd><p>Change the <code class="code">reference</code> type. </p></dd><dt><a id="manual.bugs.dr2108"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2108" target="_top">2108</a>: - <span class="emphasis"><em>No way to identify allocator types that always compare equal</em></span> + <span class="bold"><strong>No way to identify allocator types that always compare equal</strong></span> </span></dt><dd><p>Define and use <code class="code">is_always_equal</code> even for C++11. </p></dd><dt><a id="manual.bugs.dr2118"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2118" target="_top">2118</a>: - <span class="emphasis"><em><code class="code">unique_ptr</code> for array does not support cv qualification conversion of actual argument</em></span> + <span class="bold"><strong><code class="code">unique_ptr</code> for array does not support cv qualification conversion of actual argument</strong></span> </span></dt><dd><p>Adjust constraints to allow safe conversions. </p></dd><dt><a id="manual.bugs.dr2127"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2127" target="_top">2127</a>: - <span class="emphasis"><em>Move-construction with <code class="code">raw_storage_iterator</code></em></span> + <span class="bold"><strong>Move-construction with <code class="code">raw_storage_iterator</code></strong></span> </span></dt><dd><p>Add assignment operator taking an rvalue. </p></dd><dt><a id="manual.bugs.dr2132"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2132" target="_top">2132</a>: - <span class="emphasis"><em><code class="code">std::function</code> ambiguity</em></span> + <span class="bold"><strong><code class="code">std::function</code> ambiguity</strong></span> </span></dt><dd><p>Constrain the constructor to only accept callable types. </p></dd><dt><a id="manual.bugs.dr2141"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2141" target="_top">2141</a>: - <span class="emphasis"><em><code class="code">common_type</code> trait produces reference types</em></span> + <span class="bold"><strong><code class="code">common_type</code> trait produces reference types</strong></span> </span></dt><dd><p>Use <code class="code">decay</code> for the result type. </p></dd><dt><a id="manual.bugs.dr2144"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2144" target="_top">2144</a>: - <span class="emphasis"><em>Missing <code class="code">noexcept</code> specification in <code class="code">type_index</code></em></span> + <span class="bold"><strong>Missing <code class="code">noexcept</code> specification in <code class="code">type_index</code></strong></span> </span></dt><dd><p>Add <code class="code">noexcept</code> </p></dd><dt><a id="manual.bugs.dr2145"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2145" target="_top">2145</a>: - <span class="emphasis"><em><code class="code">error_category</code> default constructor</em></span> + <span class="bold"><strong><code class="code">error_category</code> default constructor</strong></span> </span></dt><dd><p>Declare a public constexpr constructor. </p></dd><dt><a id="manual.bugs.dr2162"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2162" target="_top">2162</a>: - <span class="emphasis"><em><code class="code">allocator_traits::max_size</code> missing <code class="code">noexcept</code></em></span> + <span class="bold"><strong><code class="code">allocator_traits::max_size</code> missing <code class="code">noexcept</code></strong></span> </span></dt><dd><p>Add <code class="code">noexcept</code>. </p></dd><dt><a id="manual.bugs.dr2187"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2187" target="_top">2187</a>: - <span class="emphasis"><em><code class="code">vector<bool></code> is missing <code class="code">emplace</code> and <code class="code">emplace_back</code> member functions</em></span> + <span class="bold"><strong><code class="code">vector<bool></code> is missing <code class="code">emplace</code> and <code class="code">emplace_back</code> member functions</strong></span> </span></dt><dd><p>Add <code class="code">emplace</code> and <code class="code">emplace_back</code> member functions. </p></dd><dt><a id="manual.bugs.dr2192"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2192" target="_top">2192</a>: - <span class="emphasis"><em>Validity and return type of <code class="code">std::abs(0u)</code> is unclear</em></span> + <span class="bold"><strong>Validity and return type of <code class="code">std::abs(0u)</code> is unclear</strong></span> </span></dt><dd><p>Move all declarations to a common header and remove the generic <code class="code">abs</code> which accepted unsigned arguments. </p></dd><dt><a id="manual.bugs.dr2196"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2196" target="_top">2196</a>: - <span class="emphasis"><em>Specification of <code class="code">is_*[copy/move]_[constructible/assignable]</code> unclear for non-referencable types</em></span> + <span class="bold"><strong>Specification of <code class="code">is_*[copy/move]_[constructible/assignable]</code> unclear for non-referencable types</strong></span> </span></dt><dd><p>Use the referenceable type concept. </p></dd><dt><a id="manual.bugs.dr2212"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2212" target="_top">2212</a>: - <span class="emphasis"><em><code class="code">tuple_size</code> for <code class="code">const pair</code> request <code class="code"><tuple></code> header</em></span> + <span class="bold"><strong><code class="code">tuple_size</code> for <code class="code">const pair</code> request <code class="code"><tuple></code> header</strong></span> </span></dt><dd><p>The <code class="code">tuple_size</code> and <code class="code">tuple_element</code> partial specializations are defined in <code class="code"><utility></code> which is included by <code class="code"><array></code>. </p></dd><dt><a id="manual.bugs.dr2296"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2296" target="_top">2296</a>: - <span class="emphasis"><em><code class="code">std::addressof</code> should be constexpr</em></span> + <span class="bold"><strong><code class="code">std::addressof</code> should be constexpr</strong></span> </span></dt><dd><p>Use <code class="code">__builtin_addressof</code> and add <code class="code">constexpr</code> to <code class="code">addressof</code> for C++17 and later. </p></dd><dt><a id="manual.bugs.dr2306"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2306" target="_top">2306</a>: - <span class="emphasis"><em><code class="code">match_results::reference</code> should be <code class="code">value_type&</code>, not <code class="code">const value_type&</code></em></span> + <span class="bold"><strong><code class="code">match_results::reference</code> should be <code class="code">value_type&</code>, not <code class="code">const value_type&</code></strong></span> </span></dt><dd><p>Change typedef. </p></dd><dt><a id="manual.bugs.dr2313"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2313" target="_top">2313</a>: - <span class="emphasis"><em><code class="code">tuple_size</code> should always derive from <code class="code">integral_constant<size_t, N></code></em></span> + <span class="bold"><strong><code class="code">tuple_size</code> should always derive from <code class="code">integral_constant<size_t, N></code></strong></span> </span></dt><dd><p>Update definitions of the partial specializations for const and volatile types. </p></dd><dt><a id="manual.bugs.dr2328"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2328" target="_top">2328</a>: - <span class="emphasis"><em>Rvalue stream extraction should use perfect forwarding</em></span> + <span class="bold"><strong>Rvalue stream extraction should use perfect forwarding</strong></span> </span></dt><dd><p>Use perfect forwarding for right operand. </p></dd><dt><a id="manual.bugs.dr2329"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2329" target="_top">2329</a>: - <span class="emphasis"><em><code class="code">regex_match()/regex_search()</code> with <code class="code">match_results</code> should forbid temporary strings</em></span> + <span class="bold"><strong><code class="code">regex_match()/regex_search()</code> with <code class="code">match_results</code> should forbid temporary strings</strong></span> </span></dt><dd><p>Add deleted overloads for rvalue strings. </p></dd><dt><a id="manual.bugs.dr2332"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2332" target="_top">2332</a>: - <span class="emphasis"><em><code class="code">regex_iterator/regex_token_iterator</code> should forbid temporary regexes</em></span> + <span class="bold"><strong><code class="code">regex_iterator/regex_token_iterator</code> should forbid temporary regexes</strong></span> </span></dt><dd><p>Add deleted constructors. </p></dd><dt><a id="manual.bugs.dr2354"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2354" target="_top">2332</a>: - <span class="emphasis"><em>Unnecessary copying when inserting into maps with braced-init syntax</em></span> + <span class="bold"><strong>Unnecessary copying when inserting into maps with braced-init syntax</strong></span> </span></dt><dd><p>Add overloads of <code class="code">insert</code> taking <code class="code">value_type&&</code> rvalues. </p></dd><dt><a id="manual.bugs.dr2399"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2399" target="_top">2399</a>: - <span class="emphasis"><em><code class="code">shared_ptr</code>'s constructor from <code class="code">unique_ptr</code> should be constrained</em></span> + <span class="bold"><strong><code class="code">shared_ptr</code>'s constructor from <code class="code">unique_ptr</code> should be constrained</strong></span> </span></dt><dd><p>Constrain the constructor to require convertibility. </p></dd><dt><a id="manual.bugs.dr2400"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2400" target="_top">2400</a>: - <span class="emphasis"><em><code class="code">shared_ptr</code>'s <code class="code">get_deleter()</code> should use <code class="code">addressof()</code></em></span> + <span class="bold"><strong><code class="code">shared_ptr</code>'s <code class="code">get_deleter()</code> should use <code class="code">addressof()</code></strong></span> </span></dt><dd><p>Use <code class="code">addressof</code>. </p></dd><dt><a id="manual.bugs.dr2401"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2401" target="_top">2401</a>: - <span class="emphasis"><em><code class="code">std::function</code> needs more <code class="code">noexcept</code></em></span> + <span class="bold"><strong><code class="code">std::function</code> needs more <code class="code">noexcept</code></strong></span> </span></dt><dd><p>Add <code class="code">noexcept</code> to the assignment and comparisons. </p></dd><dt><a id="manual.bugs.dr2407"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2407" target="_top">2407</a>: - <span class="emphasis"><em><code class="code">packaged_task(allocator_arg_t, const Allocator&, F&&)</code> + <span class="bold"><strong><code class="code">packaged_task(allocator_arg_t, const Allocator&, F&&)</code> should neither be constrained nor <code class="code">explicit</code> - </em></span> + </strong></span> </span></dt><dd><p>Remove <code class="code">explicit</code> from the constructor. </p></dd><dt><a id="manual.bugs.dr2408"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2408" target="_top">2408</a>: - <span class="emphasis"><em>SFINAE-friendly + <span class="bold"><strong>SFINAE-friendly <code class="code">common_type</code>/<code class="code">iterator_traits</code> is missing in C++14 - </em></span> + </strong></span> </span></dt><dd><p>Make <code class="code">iterator_traits</code> empty if any of the types is not present in the iterator. Make <code class="code">common_type<></code> empty. </p></dd><dt><a id="manual.bugs.dr2415"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2415" target="_top">2415</a>: - <span class="emphasis"><em>Inconsistency between <code class="code">unique_ptr</code> and <code class="code">shared_ptr</code></em></span> + <span class="bold"><strong>Inconsistency between <code class="code">unique_ptr</code> and <code class="code">shared_ptr</code></strong></span> </span></dt><dd><p>Create empty an <code class="code">shared_ptr</code> from an empty <code class="code">unique_ptr</code>. </p></dd><dt><a id="manual.bugs.dr2418"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2418" target="_top">2418</a>: - <span class="emphasis"><em><code class="code">apply</code> does not work with member pointers</em></span> + <span class="bold"><strong><code class="code">apply</code> does not work with member pointers</strong></span> </span></dt><dd><p>Use <code class="code">mem_fn</code> for member pointers. </p></dd><dt><a id="manual.bugs.dr2440"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2440" target="_top">2440</a>: - <span class="emphasis"><em><code class="code">seed_seq::size()</code> should be <code class="code">noexcept</code></em></span> + <span class="bold"><strong><code class="code">seed_seq::size()</code> should be <code class="code">noexcept</code></strong></span> </span></dt><dd><p>Add <code class="code">noexcept</code>. </p></dd><dt><a id="manual.bugs.dr2441"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2441" target="_top">2441</a>: - <span class="emphasis"><em>Exact-width atomic typedefs should be provided</em></span> + <span class="bold"><strong>Exact-width atomic typedefs should be provided</strong></span> </span></dt><dd><p>Define the typedefs. </p></dd><dt><a id="manual.bugs.dr2442"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2442" target="_top">2442</a>: - <span class="emphasis"><em><code class="code">call_once()</code> shouldn't <code class="code">DECAY_COPY()</code></em></span> + <span class="bold"><strong><code class="code">call_once()</code> shouldn't <code class="code">DECAY_COPY()</code></strong></span> </span></dt><dd><p>Remove indirection through call wrapper that made copies of arguments and forward arguments straight to <code class="code">std::invoke</code>. </p></dd><dt><a id="manual.bugs.dr2454"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2454" target="_top">2454</a>: - <span class="emphasis"><em>Add <code class="code">raw_storage_iterator::base()</code> member - </em></span> + <span class="bold"><strong>Add <code class="code">raw_storage_iterator::base()</code> member + </strong></span> </span></dt><dd><p>Add the <code class="code">base()</code> member function. </p></dd><dt><a id="manual.bugs.dr2455"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2455" target="_top">2455</a>: - <span class="emphasis"><em>Allocator default construction should be allowed to throw - </em></span> + <span class="bold"><strong>Allocator default construction should be allowed to throw + </strong></span> </span></dt><dd><p>Make <code class="code">noexcept</code> specifications conditional. </p></dd><dt><a id="manual.bugs.dr2458"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2458" target="_top">2458</a>: - <span class="emphasis"><em>N3778 and new library deallocation signatures - </em></span> + <span class="bold"><strong>N3778 and new library deallocation signatures + </strong></span> </span></dt><dd><p>Remove unused overloads. </p></dd><dt><a id="manual.bugs.dr2459"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2459" target="_top">2459</a>: - <span class="emphasis"><em><code class="code">std::polar</code> should require a non-negative rho - </em></span> + <span class="bold"><strong><code class="code">std::polar</code> should require a non-negative rho + </strong></span> </span></dt><dd><p>Add debug mode assertion. </p></dd><dt><a id="manual.bugs.dr2465"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2465" target="_top">2465</a>: - <span class="emphasis"><em>SFINAE-friendly <code class="code">common_type</code> is nearly impossible + <span class="bold"><strong>SFINAE-friendly <code class="code">common_type</code> is nearly impossible to specialize correctly and regresses key functionality - </em></span> + </strong></span> </span></dt><dd><p>Detect whether <code class="code">decay_t</code> changes either type and use the decayed types if so. </p></dd><dt><a id="manual.bugs.dr2466"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2466" target="_top">2466</a>: - <span class="emphasis"><em><code class="code">allocator_traits::max_size()</code> default behavior is incorrect - </em></span> + <span class="bold"><strong><code class="code">allocator_traits::max_size()</code> default behavior is incorrect + </strong></span> </span></dt><dd><p>Divide by the object type. </p></dd><dt><a id="manual.bugs.dr2484"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2484" target="_top">2484</a>: - <span class="emphasis"><em><code class="code">rethrow_if_nested()</code> is doubly unimplementable - </em></span> + <span class="bold"><strong><code class="code">rethrow_if_nested()</code> is doubly unimplementable + </strong></span> </span></dt><dd><p>Avoid using <code class="code">dynamic_cast</code> when it would be ill-formed. </p></dd><dt><a id="manual.bugs.dr2487"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2487" target="_top">2487</a>: - <span class="emphasis"><em><code class="code">bind()</code> should be <code class="code">const</code>-overloaded - not cv-overloaded - </em></span> + <span class="bold"><strong><code class="code">bind()</code> should be <code class="code">const</code>-overloaded + not <span class="emphasis"><em>cv</em></span>-overloaded + </strong></span> </span></dt><dd><p>Deprecate volatile-qualified <code class="code">operator()</code> for C++17, make it ill-formed for C++20. </p></dd><dt><a id="manual.bugs.dr2499"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2499" target="_top">2499</a>: - <span class="emphasis"><em><code class="code">operator>>(basic_istream&, CharT*)</code> makes it hard to avoid buffer overflows - </em></span> + <span class="bold"><strong><code class="code">operator>>(basic_istream&, CharT*)</code> makes it hard to avoid buffer overflows + </strong></span> </span></dt><dd><p>Replace <code class="code">operator>>(basic_istream&, CharT*)</code> and other overloads writing through pointers. </p></dd><dt><a id="manual.bugs.dr2537"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2537" target="_top">2537</a>: - <span class="emphasis"><em>Constructors for <code class="code">priority_queue</code> taking allocators + <span class="bold"><strong>Constructors for <code class="code">priority_queue</code> taking allocators should call <code class="code">make_heap</code> - </em></span> + </strong></span> </span></dt><dd><p>Call <code class="code">make_heap</code>. </p></dd><dt><a id="manual.bugs.dr2566"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2566" target="_top">2566</a>: - <span class="emphasis"><em>Requirements on the first template parameter of container adaptors - </em></span> + <span class="bold"><strong>Requirements on the first template parameter of container adaptors + </strong></span> </span></dt><dd><p>Add static assertions to enforce the requirement. </p></dd><dt><a id="manual.bugs.dr2583"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2583" target="_top">2583</a>: - <span class="emphasis"><em>There is no way to supply an allocator for <code class="code">basic_string(str, pos)</code> - </em></span> + <span class="bold"><strong>There is no way to supply an allocator for <code class="code">basic_string(str, pos)</code> + </strong></span> </span></dt><dd><p>Add new constructor. </p></dd><dt><a id="manual.bugs.dr2586"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2586" target="_top">2586</a>: - <span class="emphasis"><em>Wrong value category used in <code class="code">scoped_allocator_adaptor::construct()</code> - </em></span> + <span class="bold"><strong>Wrong value category used in <code class="code">scoped_allocator_adaptor::construct()</code> + </strong></span> </span></dt><dd><p>Change internal helper for uses-allocator construction to always check using const lvalue allocators. </p></dd><dt><a id="manual.bugs.dr2684"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2684" target="_top">2684</a>: - <span class="emphasis"><em><code class="code">priority_queue</code> lacking comparator typedef - </em></span> + <span class="bold"><strong><code class="code">priority_queue</code> lacking comparator typedef + </strong></span> </span></dt><dd><p>Define the <code class="code">value_compare</code> typedef. </p></dd><dt><a id="manual.bugs.dr2735"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2735" target="_top">2735</a>: - <span class="emphasis"><em><code class="code">std::abs(short)</code>, + <span class="bold"><strong><code class="code">std::abs(short)</code>, <code class="code">std::abs(signed char)</code> and others should return <code class="code">int</code> instead of <code class="code">double</code> in order to be compatible with C++98 and C - </em></span> + </strong></span> </span></dt><dd><p>Resolved by the changes for <a class="link" href="bugs.html#manual.bugs.dr2192">2192</a>. </p></dd><dt><a id="manual.bugs.dr2770"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2770" target="_top">2770</a>: - <span class="emphasis"><em><code class="code">tuple_size<const T></code> specialization is not + <span class="bold"><strong><code class="code">tuple_size<const T></code> specialization is not SFINAE compatible and breaks decomposition declarations - </em></span> + </strong></span> </span></dt><dd><p>Safely detect <code class="code">tuple_size<T>::value</code> and only use it if valid. </p></dd><dt><a id="manual.bugs.dr2781"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2781" target="_top">2781</a>: - <span class="emphasis"><em>Contradictory requirements for <code class="code">std::function</code> + <span class="bold"><strong>Contradictory requirements for <code class="code">std::function</code> and <code class="code">std::reference_wrapper</code> - </em></span> + </strong></span> </span></dt><dd><p>Remove special handling for <code class="code">reference_wrapper</code> arguments and store them directly as the target object. </p></dd><dt><a id="manual.bugs.dr2802"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2802" target="_top">2802</a>: - <span class="emphasis"><em>Add noexcept to several <code class="code">shared_ptr</code> related + <span class="bold"><strong>Add noexcept to several <code class="code">shared_ptr</code> related functions - </em></span> + </strong></span> </span></dt><dd><p>Add noexcept. </p></dd><dt><a id="manual.bugs.dr2873"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2873" target="_top">2873</a>: - <span class="emphasis"><em><code class="code">shared_ptr</code> constructor requirements for a deleter - </em></span> + <span class="bold"><strong><code class="code">shared_ptr</code> constructor requirements for a deleter + </strong></span> </span></dt><dd><p>Use rvalues for deleters. </p></dd><dt><a id="manual.bugs.dr2921"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2921" target="_top">2921</a>: - <span class="emphasis"><em><code class="code">packaged_task</code> and type-erased allocators - </em></span> + <span class="bold"><strong><code class="code">packaged_task</code> and type-erased allocators + </strong></span> </span></dt><dd><p>For C++17 mode, remove the constructors taking an allocator argument. </p></dd><dt><a id="manual.bugs.dr2942"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2942" target="_top">2942</a>: - <span class="emphasis"><em>LWG 2873's resolution missed + <span class="bold"><strong>LWG 2873's resolution missed <code class="code">weak_ptr::owner_before</code> - </em></span> + </strong></span> </span></dt><dd><p>Add noexcept. </p></dd><dt><a id="manual.bugs.dr2996"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2996" target="_top">2996</a>: - <span class="emphasis"><em>Missing rvalue overloads for + <span class="bold"><strong>Missing rvalue overloads for <code class="code">shared_ptr</code> operations - </em></span> + </strong></span> </span></dt><dd><p>Add additional constructor and cast overloads. </p></dd><dt><a id="manual.bugs.dr2993"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2993" target="_top">2993</a>: - <span class="emphasis"><em><code class="code">reference_wrapper<T></code> conversion from <code class="code">T&&</code> - </em></span> + <span class="bold"><strong><code class="code">reference_wrapper<T></code> conversion from <code class="code">T&&</code> + </strong></span> </span></dt><dd><p>Replaced the constructors with a constrained template, to prevent participation in overload resolution when not valid. </p></dd><dt><a id="manual.bugs.dr3074"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#3074" target="_top">3074</a>: - <span class="emphasis"><em>Non-member functions for <code class="code">valarray</code> should only deduce from the <code class="code">valarray</code> - </em></span> + <span class="bold"><strong>Non-member functions for <code class="code">valarray</code> should only deduce from the <code class="code">valarray</code> + </strong></span> </span></dt><dd><p>Change scalar operands to be non-deduced context, so that they will allow conversions from other types to the value_type. </p></dd><dt><a id="manual.bugs.dr3076"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#3076" target="_top">3076</a>: - <span class="emphasis"><em><code class="code">basic_string</code> CTAD ambiguity - </em></span> + <span class="bold"><strong><code class="code">basic_string</code> CTAD ambiguity + </strong></span> </span></dt><dd><p>Change constructors to constrained templates. </p></dd><dt><a id="manual.bugs.dr3096"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#3096" target="_top">3096</a>: - <span class="emphasis"><em><code class="code">path::lexically_relative</code> is confused by trailing slashes - </em></span> + <span class="bold"><strong><code class="code">path::lexically_relative</code> is confused by trailing slashes + </strong></span> </span></dt><dd><p>Implement the fix for trailing slashes. </p></dd></dl></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="license.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="status.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="setup.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">License </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 2. Setup</td></tr></table></div></body></html>
\ No newline at end of file diff --git a/libstdc++-v3/doc/xml/manual/intro.xml b/libstdc++-v3/doc/xml/manual/intro.xml index e3a03cf..dee01c8 100644 --- a/libstdc++-v3/doc/xml/manual/intro.xml +++ b/libstdc++-v3/doc/xml/manual/intro.xml @@ -241,56 +241,56 @@ requirements of the license of GCC. <variablelist> <varlistentry xml:id="manual.bugs.dr5"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#5">5</link>: - <emphasis>string::compare specification questionable</emphasis> + <emphasis role="bold">string::compare specification questionable</emphasis> </term> <listitem><para>This should be two overloaded functions rather than a single function. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr17"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#17">17</link>: - <emphasis>Bad bool parsing</emphasis> + <emphasis role="bold">Bad bool parsing</emphasis> </term> <listitem><para>Apparently extracting Boolean values was messed up... </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr19"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#19">19</link>: - <emphasis>"Noconv" definition too vague</emphasis> + <emphasis role="bold">"Noconv" definition too vague</emphasis> </term> <listitem><para>If <code>codecvt::do_in</code> returns <code>noconv</code> there are no changes to the values in <code>[to, to_limit)</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr22"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#22">22</link>: - <emphasis>Member open vs flags</emphasis> + <emphasis role="bold">Member open vs flags</emphasis> </term> <listitem><para>Re-opening a file stream does <emphasis>not</emphasis> clear the state flags. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr23"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#23">23</link>: - <emphasis>Num_get overflow result</emphasis> + <emphasis role="bold">Num_get overflow result</emphasis> </term> <listitem><para>Implement the proposed resolution. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr25"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#25">25</link>: - <emphasis>String operator<< uses width() value wrong</emphasis> + <emphasis role="bold">String operator<< uses width() value wrong</emphasis> </term> <listitem><para>Padding issues. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr48"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#48">48</link>: - <emphasis>Use of non-existent exception constructor</emphasis> + <emphasis role="bold">Use of non-existent exception constructor</emphasis> </term> <listitem><para>An instance of <code>ios_base::failure</code> is constructed instead. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr49"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#49">49</link>: - <emphasis>Underspecification of ios_base::sync_with_stdio</emphasis> + <emphasis role="bold">Underspecification of ios_base::sync_with_stdio</emphasis> </term> <listitem><para>The return type is the <emphasis>previous</emphasis> state of synchronization. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr50"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#50">50</link>: - <emphasis>Copy constructor and assignment operator of ios_base</emphasis> + <emphasis role="bold">Copy constructor and assignment operator of ios_base</emphasis> </term> <listitem><para>These members functions are declared <code>private</code> and are thus inaccessible. Specifying the correct semantics of @@ -298,55 +298,55 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr60"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#60">60</link>: - <emphasis>What is a formatted input function?</emphasis> + <emphasis role="bold">What is a formatted input function?</emphasis> </term> <listitem><para>This DR made many widespread changes to <code>basic_istream</code> and <code>basic_ostream</code> all of which have been implemented. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr63"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#63">63</link>: - <emphasis>Exception-handling policy for unformatted output</emphasis> + <emphasis role="bold">Exception-handling policy for unformatted output</emphasis> </term> <listitem><para>Make the policy consistent with that of formatted input, unformatted input, and formatted output. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr68"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#68">68</link>: - <emphasis>Extractors for char* should store null at end</emphasis> + <emphasis role="bold">Extractors for char* should store null at end</emphasis> </term> <listitem><para>And they do now. An editing glitch in the last item in the list of [27.6.1.2.3]/7. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr74"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#74">74</link>: - <emphasis>Garbled text for codecvt::do_max_length</emphasis> + <emphasis role="bold">Garbled text for codecvt::do_max_length</emphasis> </term> <listitem><para>The text of the standard was gibberish. Typos gone rampant. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr75"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#75">75</link>: - <emphasis>Contradiction in codecvt::length's argument types</emphasis> + <emphasis role="bold">Contradiction in codecvt::length's argument types</emphasis> </term> <listitem><para>Change the first parameter to <code>stateT&</code> and implement the new effects paragraph. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr83"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#83">83</link>: - <emphasis>string::npos vs. string::max_size()</emphasis> + <emphasis role="bold">string::npos vs. string::max_size()</emphasis> </term> <listitem><para>Safety checks on the size of the string should test against <code>max_size()</code> rather than <code>npos</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr90"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#90">90</link>: - <emphasis>Incorrect description of operator>> for strings</emphasis> + <emphasis role="bold">Incorrect description of operator>> for strings</emphasis> </term> <listitem><para>The effect contain <code>isspace(c,getloc())</code> which must be replaced by <code>isspace(c,is.getloc())</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr91"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#91">91</link>: - <emphasis>Description of operator>> and getline() for string<> + <emphasis role="bold">Description of operator>> and getline() for string<> might cause endless loop</emphasis> </term> <listitem><para>They behave as a formatted input function and as an unformatted @@ -355,7 +355,7 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr103"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#103">103</link>: - <emphasis>set::iterator is required to be modifiable, but this allows + <emphasis role="bold">set::iterator is required to be modifiable, but this allows modification of keys.</emphasis> </term> <listitem><para>For associative containers where the value type is the same as @@ -364,14 +364,14 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr109"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#109">109</link>: - <emphasis>Missing binders for non-const sequence elements</emphasis> + <emphasis role="bold">Missing binders for non-const sequence elements</emphasis> </term> <listitem><para>The <code>binder1st</code> and <code>binder2nd</code> didn't have an <code>operator()</code> taking a non-const parameter. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr110"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#110">110</link>: - <emphasis>istreambuf_iterator::equal not const</emphasis> + <emphasis role="bold">istreambuf_iterator::equal not const</emphasis> </term> <listitem><para>This was not a const member function. Note that the DR says to replace the function with a const one; we have instead provided an @@ -379,80 +379,73 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr117"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#117">117</link>: - <emphasis>basic_ostream uses nonexistent num_put member functions</emphasis> + <emphasis role="bold">basic_ostream uses nonexistent num_put member functions</emphasis> </term> <listitem><para><code>num_put::put()</code> was overloaded on the wrong types. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr118"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#118">118</link>: - <emphasis>basic_istream uses nonexistent num_get member functions</emphasis> + <emphasis role="bold">basic_istream uses nonexistent num_get member functions</emphasis> </term> <listitem><para>Same as 117, but for <code>num_get::get()</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr129"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#129">129</link>: - <emphasis>Need error indication from seekp() and seekg()</emphasis> + <emphasis role="bold">Need error indication from seekp() and seekg()</emphasis> </term> <listitem><para>These functions set <code>failbit</code> on error now. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr130"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#130">130</link>: - <emphasis>Return type of container::erase(iterator) differs for associative containers</emphasis> + <emphasis role="bold">Return type of container::erase(iterator) differs for associative containers</emphasis> </term> <listitem><para>Make member <code>erase</code> return iterator for <code>set</code>, <code>multiset</code>, <code>map</code>, <code>multimap</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr136"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#136">136</link>: - <emphasis>seekp, seekg setting wrong streams?</emphasis> + <emphasis role="bold">seekp, seekg setting wrong streams?</emphasis> </term> <listitem><para><code>seekp</code> should only set the output stream, and <code>seekg</code> should only set the input stream. </para></listitem></varlistentry> -<!--<varlistentry><term><ulink url="&DR;#159">159</ulink>: - <emphasis>Strange use of underflow()</emphasis> - </term> - <listitem><para>In fstream.tcc, the basic_filebuf<>::showmanyc() function - should probably not be calling <code>underflow()</code>. - </para></listitem></varlistentry> --> - <varlistentry xml:id="manual.bugs.dr167"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#167">167</link>: - <emphasis>Improper use of traits_type::length()</emphasis> + <emphasis role="bold">Improper use of traits_type::length()</emphasis> </term> <listitem><para><code>op<<</code> with a <code>const char*</code> was calculating an incorrect number of characters to write. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr169"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#169">169</link>: - <emphasis>Bad efficiency of overflow() mandated</emphasis> + <emphasis role="bold">Bad efficiency of overflow() mandated</emphasis> </term> <listitem><para>Grow efficiently the internal array object. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr171"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#171">171</link>: - <emphasis>Strange seekpos() semantics due to joint position</emphasis> + <emphasis role="bold">Strange seekpos() semantics due to joint position</emphasis> </term> <listitem><para>Quite complex to summarize... </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr181"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#181">181</link>: - <emphasis>make_pair() unintended behavior</emphasis> + <emphasis role="bold">make_pair() unintended behavior</emphasis> </term> <listitem><para>This function used to take its arguments as reference-to-const, now it copies them (pass by value). </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr195"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#195">195</link>: - <emphasis>Should basic_istream::sentry's constructor ever set eofbit?</emphasis> + <emphasis role="bold">Should basic_istream::sentry's constructor ever set eofbit?</emphasis> </term> <listitem><para>Yes, it can, specifically if EOF is reached while skipping whitespace. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr206"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#206">206</link>: - <emphasis><code>operator new(size_t, nothrow)</code> may become - unlinked to ordinary <code>operator new</code> if ordinary - version replaced - </emphasis> + <emphasis role="bold"><code>operator new(size_t, nothrow)</code> may become + unlinked to ordinary <code>operator new</code> if ordinary + version replaced + </emphasis> </term> <listitem><para>The <code>nothrow</code> forms of new and delete were changed to call the throwing forms, handling any exception by @@ -460,14 +453,14 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr211"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#211">211</link>: - <emphasis>operator>>(istream&, string&) doesn't set failbit</emphasis> + <emphasis role="bold">operator>>(istream&, string&) doesn't set failbit</emphasis> </term> <listitem><para>If nothing is extracted into the string, <code>op>></code> now sets <code>failbit</code> (which can cause an exception, etc., etc.). </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr214"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#214">214</link>: - <emphasis>set::find() missing const overload</emphasis> + <emphasis role="bold">set::find() missing const overload</emphasis> </term> <listitem><para>Both <code>set</code> and <code>multiset</code> were missing overloaded find, lower_bound, upper_bound, and equal_range functions @@ -475,47 +468,47 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr231"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#231">231</link>: - <emphasis>Precision in iostream?</emphasis> + <emphasis role="bold">Precision in iostream?</emphasis> </term> <listitem><para>For conversion from a floating-point type, <code>str.precision()</code> is specified in the conversion specification. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr233"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#233">233</link>: - <emphasis>Insertion hints in associative containers</emphasis> + <emphasis role="bold">Insertion hints in associative containers</emphasis> </term> <listitem><para>Implement N1780, first check before then check after, insert as close to hint as possible. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr235"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#235">235</link>: - <emphasis>No specification of default ctor for reverse_iterator</emphasis> + <emphasis role="bold">No specification of default ctor for reverse_iterator</emphasis> </term> <listitem><para>The declaration of <code>reverse_iterator</code> lists a default constructor. However, no specification is given what this constructor should do. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr241"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#241">241</link>: - <emphasis>Does unique_copy() require CopyConstructible and Assignable?</emphasis> + <emphasis role="bold">Does unique_copy() require CopyConstructible and Assignable?</emphasis> </term> <listitem><para>Add a helper for forward_iterator/output_iterator, fix the existing one for input_iterator/output_iterator to not rely on Assignability. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr243"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#243">243</link>: - <emphasis>get and getline when sentry reports failure</emphasis> + <emphasis role="bold">get and getline when sentry reports failure</emphasis> </term> <listitem><para>Store a null character only if the character array has a non-zero size. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr251"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#251">251</link>: - <emphasis>basic_stringbuf missing allocator_type</emphasis> + <emphasis role="bold">basic_stringbuf missing allocator_type</emphasis> </term> <listitem><para>This nested typedef was originally not specified. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr253"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#253">253</link>: - <emphasis>valarray helper functions are almost entirely useless</emphasis> + <emphasis role="bold">valarray helper functions are almost entirely useless</emphasis> </term> <listitem><para>Make the copy constructor and copy-assignment operator declarations public in gslice_array, indirect_array, mask_array, slice_array; provide @@ -523,60 +516,60 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr265"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#265">265</link>: - <emphasis>std::pair::pair() effects overly restrictive</emphasis> + <emphasis role="bold">std::pair::pair() effects overly restrictive</emphasis> </term> <listitem><para>The default ctor would build its members from copies of temporaries; now it simply uses their respective default ctors. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr266"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#266">266</link>: - <emphasis>bad_exception::~bad_exception() missing Effects clause</emphasis> + <emphasis role="bold">bad_exception::~bad_exception() missing Effects clause</emphasis> </term> <listitem><para>The <code>bad_</code>* classes no longer have destructors (they are trivial), since no description of them was ever given. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr271"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#271">271</link>: - <emphasis>basic_iostream missing typedefs</emphasis> + <emphasis role="bold">basic_iostream missing typedefs</emphasis> </term> <listitem><para>The typedefs it inherits from its base classes can't be used, since (for example) <code>basic_iostream<T>::traits_type</code> is ambiguous. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr275"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#275">275</link>: - <emphasis>Wrong type in num_get::get() overloads</emphasis> + <emphasis role="bold">Wrong type in num_get::get() overloads</emphasis> </term> <listitem><para>Similar to 118. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr280"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#280">280</link>: - <emphasis>Comparison of reverse_iterator to const reverse_iterator</emphasis> + <emphasis role="bold">Comparison of reverse_iterator to const reverse_iterator</emphasis> </term> <listitem><para>Add global functions with two template parameters. (NB: not added for now a templated assignment operator) </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr292"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#292">292</link>: - <emphasis>Effects of a.copyfmt (a)</emphasis> + <emphasis role="bold">Effects of a.copyfmt (a)</emphasis> </term> <listitem><para>If <code>(this == &rhs)</code> do nothing. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr300"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#300">300</link>: - <emphasis>List::merge() specification incomplete</emphasis> + <emphasis role="bold">List::merge() specification incomplete</emphasis> </term> <listitem><para>If <code>(this == &x)</code> do nothing. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr303"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#303">303</link>: - <emphasis>Bitset input operator underspecified</emphasis> + <emphasis role="bold">Bitset input operator underspecified</emphasis> </term> <listitem><para>Basically, compare the input character to <code>is.widen(0)</code> and <code>is.widen(1)</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr305"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#305">305</link>: - <emphasis>Default behavior of codecvt<wchar_t, char, + <emphasis role="bold">Default behavior of codecvt<wchar_t, char, mbstate_t>::length()</emphasis> </term> <listitem><para>Do not specify what <code>codecvt<wchar_t, char, @@ -584,20 +577,20 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr328"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#328">328</link>: - <emphasis>Bad sprintf format modifier in + <emphasis role="bold">Bad sprintf format modifier in money_put<>::do_put()</emphasis> </term> <listitem><para>Change the format string to "%.0Lf". </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr365"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#365">365</link>: - <emphasis>Lack of const-qualification in clause 27</emphasis> + <emphasis role="bold">Lack of const-qualification in clause 27</emphasis> </term> <listitem><para>Add const overloads of <code>is_open</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr387"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#387">387</link>: - <emphasis>std::complex over-encapsulated</emphasis> + <emphasis role="bold">std::complex over-encapsulated</emphasis> </term> <listitem><para>Add the <code>real(T)</code> and <code>imag(T)</code> members; in C++11 mode, also adjust the existing @@ -606,26 +599,26 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr389"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#389">389</link>: - <emphasis>Const overload of valarray::operator[] returns + <emphasis role="bold">Const overload of valarray::operator[] returns by value</emphasis> </term> <listitem><para>Change it to return a <code>const T&</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr396"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#396">396</link>: - <emphasis>what are characters zero and one</emphasis> + <emphasis role="bold">what are characters zero and one</emphasis> </term> <listitem><para>Implement the proposed resolution. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr402"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#402">402</link>: - <emphasis>Wrong new expression in [some_]allocator::construct</emphasis> + <emphasis role="bold">Wrong new expression in [some_]allocator::construct</emphasis> </term> <listitem><para>Replace "new" with "::new". </para></listitem></varlistentry> <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-closed.html#408">408</link>: - <emphasis> + <emphasis role="bold"> Is vector<reverse_iterator<char*> > forbidden? </emphasis> </term> @@ -633,95 +626,95 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr409"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#409">409</link>: - <emphasis>Closing an fstream should clear the error state</emphasis> + <emphasis role="bold">Closing an fstream should clear the error state</emphasis> </term> <listitem><para>Have <code>open</code> clear the error flags. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr415"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#415">415</link>: - <emphasis>Behavior of std::ws</emphasis> + <emphasis role="bold">Behavior of std::ws</emphasis> </term> <listitem><para>Change it to be an unformatted input function (i.e. construct a sentry and catch exceptions). </para></listitem></varlistentry> <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-closed.html#431">431</link>: - <emphasis>Swapping containers with unequal allocators</emphasis> + <emphasis role="bold">Swapping containers with unequal allocators</emphasis> </term> <listitem><para>Implement Option 3, as per N1599. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr432"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#432">432</link>: - <emphasis>stringbuf::overflow() makes only one write position + <emphasis role="bold">stringbuf::overflow() makes only one write position available</emphasis> </term> <listitem><para>Implement the resolution, beyond DR 169. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr434"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#434">434</link>: - <emphasis>bitset::to_string() hard to use</emphasis> + <emphasis role="bold">bitset::to_string() hard to use</emphasis> </term> <listitem><para>Add three overloads, taking fewer template arguments. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr438"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#438">438</link>: - <emphasis>Ambiguity in the "do the right thing" clause</emphasis> + <emphasis role="bold">Ambiguity in the "do the right thing" clause</emphasis> </term> <listitem><para>Implement the resolution, basically cast less. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr445"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#445">445</link>: - <emphasis>iterator_traits::reference unspecified for some iterator categories</emphasis> + <emphasis role="bold">iterator_traits::reference unspecified for some iterator categories</emphasis> </term> <listitem><para>Change <code>istreambuf_iterator::reference</code> in C++11 mode. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr453"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#453">453</link>: - <emphasis>basic_stringbuf::seekoff need not always fail for an empty stream</emphasis> + <emphasis role="bold">basic_stringbuf::seekoff need not always fail for an empty stream</emphasis> </term> <listitem><para>Don't fail if the next pointer is null and newoff is zero. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr455"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#455">455</link>: - <emphasis>cerr::tie() and wcerr::tie() are overspecified</emphasis> + <emphasis role="bold">cerr::tie() and wcerr::tie() are overspecified</emphasis> </term> <listitem><para>Initialize cerr tied to cout and wcerr tied to wcout. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr464"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#464">464</link>: - <emphasis>Suggestion for new member functions in standard containers</emphasis> + <emphasis role="bold">Suggestion for new member functions in standard containers</emphasis> </term> <listitem><para>Add <code>data()</code> to <code>std::vector</code> and <code>at(const key_type&)</code> to <code>std::map</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr467"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#467">467</link>: - <emphasis>char_traits::lt(), compare(), and memcmp()</emphasis> + <emphasis role="bold">char_traits::lt(), compare(), and memcmp()</emphasis> </term> <listitem><para>Change <code>lt</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr508"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#508">508</link>: - <emphasis>Bad parameters for ranlux64_base_01</emphasis> + <emphasis role="bold">Bad parameters for ranlux64_base_01</emphasis> </term> <listitem><para>Fix the parameters. </para></listitem></varlistentry> <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-closed.html#512">512</link>: - <emphasis>Seeding subtract_with_carry_01 from a single unsigned long</emphasis> + <emphasis role="bold">Seeding subtract_with_carry_01 from a single unsigned long</emphasis> </term> <listitem><para>Construct a <code>linear_congruential</code> engine and seed with it. </para></listitem></varlistentry> <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-closed.html#526">526</link>: - <emphasis>Is it undefined if a function in the standard changes in + <emphasis role="bold">Is it undefined if a function in the standard changes in parameters?</emphasis> </term> <listitem><para>Use &value. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr538"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#538">538</link>: - <emphasis>241 again: Does unique_copy() require CopyConstructible + <emphasis role="bold">241 again: Does unique_copy() require CopyConstructible and Assignable?</emphasis> </term> <listitem><para>In case of input_iterator/output_iterator rely on Assignability of @@ -729,7 +722,7 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr539"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#539">539</link>: - <emphasis>partial_sum and adjacent_difference should mention + <emphasis role="bold">partial_sum and adjacent_difference should mention requirements</emphasis> </term> <listitem><para>We were almost doing the right thing, just use std::move @@ -737,262 +730,262 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr541"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#541">541</link>: - <emphasis>shared_ptr template assignment and void</emphasis> + <emphasis role="bold">shared_ptr template assignment and void</emphasis> </term> <listitem><para>Add an auto_ptr<void> specialization. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr543"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#543">543</link>: - <emphasis>valarray slice default constructor</emphasis> + <emphasis role="bold">valarray slice default constructor</emphasis> </term> <listitem><para>Follow the straightforward proposed resolution. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr550"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#550">550</link>: - <emphasis>What should the return type of pow(float,int) be?</emphasis> + <emphasis role="bold">What should the return type of pow(float,int) be?</emphasis> </term> <listitem><para>In C++11 mode, remove the pow(float,int), etc., signatures. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr581"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#581">581</link>: - <emphasis><code>flush()</code> not unformatted function</emphasis> + <emphasis role="bold"><code>flush()</code> not unformatted function</emphasis> </term> <listitem><para>Change it to be a unformatted output function (i.e. construct a sentry and catch exceptions). </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr586"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#586">586</link>: - <emphasis>string inserter not a formatted function</emphasis> + <emphasis role="bold">string inserter not a formatted function</emphasis> </term> <listitem><para>Change it to be a formatted output function (i.e. catch exceptions). </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr596"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#596">596</link>: - <emphasis>27.8.1.3 Table 112 omits "a+" and "a+b" modes</emphasis> + <emphasis role="bold">27.8.1.3 Table 112 omits "a+" and "a+b" modes</emphasis> </term> <listitem><para>Add the missing modes to fopen_mode. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr630"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#630">630</link>: - <emphasis>arrays of valarray</emphasis> + <emphasis role="bold">arrays of valarray</emphasis> </term> <listitem><para>Implement the simple resolution. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr660"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#660">660</link>: - <emphasis>Missing bitwise operations</emphasis> + <emphasis role="bold">Missing bitwise operations</emphasis> </term> <listitem><para>Add the missing operations. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr691"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#691">691</link>: - <emphasis>const_local_iterator cbegin, cend missing from TR1</emphasis> + <emphasis role="bold">const_local_iterator cbegin, cend missing from TR1</emphasis> </term> <listitem><para>In C++11 mode add cbegin(size_type) and cend(size_type) to the unordered containers. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr693"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#693">693</link>: - <emphasis>std::bitset::all() missing</emphasis> + <emphasis role="bold">std::bitset::all() missing</emphasis> </term> <listitem><para>Add it, consistently with the discussion. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr695"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#695">695</link>: - <emphasis>ctype<char>::classic_table() not accessible</emphasis> + <emphasis role="bold">ctype<char>::classic_table() not accessible</emphasis> </term> <listitem><para>Make the member functions table and classic_table public. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr696"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#696">696</link>: - <emphasis>istream::operator>>(int&) broken</emphasis> + <emphasis role="bold">istream::operator>>(int&) broken</emphasis> </term> <listitem><para>Implement the straightforward resolution. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr761"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#761">761</link>: - <emphasis>unordered_map needs an at() member function</emphasis> + <emphasis role="bold">unordered_map needs an at() member function</emphasis> </term> <listitem><para>In C++11 mode, add at() and at() const. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr775"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#775">775</link>: - <emphasis>Tuple indexing should be unsigned?</emphasis> + <emphasis role="bold">Tuple indexing should be unsigned?</emphasis> </term> <listitem><para>Implement the int -> size_t replacements. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr776"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#776">776</link>: - <emphasis>Undescribed assign function of std::array</emphasis> + <emphasis role="bold">Undescribed assign function of std::array</emphasis> </term> <listitem><para>In C++11 mode, remove assign, add fill. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr781"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#781">781</link>: - <emphasis>std::complex should add missing C99 functions</emphasis> + <emphasis role="bold">std::complex should add missing C99 functions</emphasis> </term> <listitem><para>In C++11 mode, add std::proj. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr809"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#809">809</link>: - <emphasis>std::swap should be overloaded for array types</emphasis> + <emphasis role="bold">std::swap should be overloaded for array types</emphasis> </term> <listitem><para>Add the overload. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr853"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#853">853</link>: - <emphasis>to_string needs updating with zero and one</emphasis> + <emphasis role="bold">to_string needs updating with zero and one</emphasis> </term> <listitem><para>Update / add the signatures. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr865"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#865">865</link>: - <emphasis>More algorithms that throw away information</emphasis> + <emphasis role="bold">More algorithms that throw away information</emphasis> </term> <listitem><para>The traditional HP / SGI return type and value is blessed by the resolution of the DR. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr1203"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#1203">1203</link>: - <emphasis>More useful rvalue stream insertion</emphasis> + <emphasis role="bold">More useful rvalue stream insertion</emphasis> </term> <listitem><para>Return the stream as its original type, not the base class. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr1339"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#1339">1339</link>: - <emphasis>uninitialized_fill_n should return the end of its range</emphasis> + <emphasis role="bold">uninitialized_fill_n should return the end of its range</emphasis> </term> <listitem><para>Return the end of the filled range. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2021"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2021">2021</link>: - <emphasis>Further incorrect uses of <code>result_of</code></emphasis> + <emphasis role="bold">Further incorrect uses of <code>result_of</code></emphasis> </term> <listitem><para>Correctly decay types in signature of <code>std::async</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2049"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2049">2049</link>: - <emphasis><code>is_destructible</code> underspecified</emphasis> + <emphasis role="bold"><code>is_destructible</code> underspecified</emphasis> </term> <listitem><para>Handle non-object types. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2056"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2056">2056</link>: - <emphasis>future_errc enums start with value 0 (invalid value for broken_promise)</emphasis> + <emphasis role="bold">future_errc enums start with value 0 (invalid value for broken_promise)</emphasis> </term> <listitem><para>Reorder enumerators. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2059"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2059">2059</link>: - <emphasis>C++0x ambiguity problem with map::erase</emphasis> + <emphasis role="bold">C++0x ambiguity problem with map::erase</emphasis> </term> <listitem><para>Add additional overloads. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2062"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2062">2062</link>: - <emphasis>2062. Effect contradictions w/o no-throw guarantee of <code>std::function</code> swaps</emphasis> + <emphasis role="bold">2062. Effect contradictions w/o no-throw guarantee of <code>std::function</code> swaps</emphasis> </term> <listitem><para>Add <code>noexcept</code> to swap functions. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2063"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2063">2063</link>: - <emphasis>Contradictory requirements for string move assignment</emphasis> + <emphasis role="bold">Contradictory requirements for string move assignment</emphasis> </term> <listitem><para>Respect propagation trait for move assignment. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2064"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2064">2064</link>: - <emphasis>More noexcept issues in basic_string</emphasis> + <emphasis role="bold">More noexcept issues in basic_string</emphasis> </term> <listitem><para>Add noexcept to the comparison operators. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2067"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2067">2067</link>: - <emphasis>packaged_task should have deleted copy c'tor with const parameter</emphasis> + <emphasis role="bold">packaged_task should have deleted copy c'tor with const parameter</emphasis> </term> <listitem><para>Fix signatures. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2101"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2101">2101</link>: - <emphasis>Some transformation types can produce impossible types</emphasis> + <emphasis role="bold">Some transformation types can produce impossible types</emphasis> </term> <listitem><para>Use the referenceable type concept. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2106"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2106">2106</link>: - <emphasis>move_iterator wrapping iterators returning prvalues</emphasis> + <emphasis role="bold">move_iterator wrapping iterators returning prvalues</emphasis> </term> <listitem><para>Change the <code>reference</code> type. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2108"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2108">2108</link>: - <emphasis>No way to identify allocator types that always compare equal</emphasis> + <emphasis role="bold">No way to identify allocator types that always compare equal</emphasis> </term> <listitem><para>Define and use <code>is_always_equal</code> even for C++11. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2118"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2118">2118</link>: - <emphasis><code>unique_ptr</code> for array does not support cv qualification conversion of actual argument</emphasis> + <emphasis role="bold"><code>unique_ptr</code> for array does not support cv qualification conversion of actual argument</emphasis> </term> <listitem><para>Adjust constraints to allow safe conversions. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2127"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2127">2127</link>: - <emphasis>Move-construction with <code>raw_storage_iterator</code></emphasis> + <emphasis role="bold">Move-construction with <code>raw_storage_iterator</code></emphasis> </term> <listitem><para>Add assignment operator taking an rvalue. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2132"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2132">2132</link>: - <emphasis><code>std::function</code> ambiguity</emphasis> + <emphasis role="bold"><code>std::function</code> ambiguity</emphasis> </term> <listitem><para>Constrain the constructor to only accept callable types. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2141"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2141">2141</link>: - <emphasis><code>common_type</code> trait produces reference types</emphasis> + <emphasis role="bold"><code>common_type</code> trait produces reference types</emphasis> </term> <listitem><para>Use <code>decay</code> for the result type. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2144"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2144">2144</link>: - <emphasis>Missing <code>noexcept</code> specification in <code>type_index</code></emphasis> + <emphasis role="bold">Missing <code>noexcept</code> specification in <code>type_index</code></emphasis> </term> <listitem><para>Add <code>noexcept</code> </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2145"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2145">2145</link>: - <emphasis><code>error_category</code> default constructor</emphasis> + <emphasis role="bold"><code>error_category</code> default constructor</emphasis> </term> <listitem><para>Declare a public constexpr constructor. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2162"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2162">2162</link>: - <emphasis><code>allocator_traits::max_size</code> missing <code>noexcept</code></emphasis> + <emphasis role="bold"><code>allocator_traits::max_size</code> missing <code>noexcept</code></emphasis> </term> <listitem><para>Add <code>noexcept</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2187"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2187">2187</link>: - <emphasis><code>vector<bool></code> is missing <code>emplace</code> and <code>emplace_back</code> member functions</emphasis> + <emphasis role="bold"><code>vector<bool></code> is missing <code>emplace</code> and <code>emplace_back</code> member functions</emphasis> </term> <listitem><para>Add <code>emplace</code> and <code>emplace_back</code> member functions. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2192"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2192">2192</link>: - <emphasis>Validity and return type of <code>std::abs(0u)</code> is unclear</emphasis> + <emphasis role="bold">Validity and return type of <code>std::abs(0u)</code> is unclear</emphasis> </term> <listitem><para>Move all declarations to a common header and remove the generic <code>abs</code> which accepted unsigned arguments. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2196"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2196">2196</link>: - <emphasis>Specification of <code>is_*[copy/move]_[constructible/assignable]</code> unclear for non-referencable types</emphasis> + <emphasis role="bold">Specification of <code>is_*[copy/move]_[constructible/assignable]</code> unclear for non-referencable types</emphasis> </term> <listitem><para>Use the referenceable type concept. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2212"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2212">2212</link>: - <emphasis><code>tuple_size</code> for <code>const pair</code> request <code><tuple></code> header</emphasis> + <emphasis role="bold"><code>tuple_size</code> for <code>const pair</code> request <code><tuple></code> header</emphasis> </term> <listitem><para>The <code>tuple_size</code> and <code>tuple_element</code> partial specializations are defined in <code><utility></code> which @@ -1000,79 +993,79 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2296"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2296">2296</link>: - <emphasis><code>std::addressof</code> should be constexpr</emphasis> + <emphasis role="bold"><code>std::addressof</code> should be constexpr</emphasis> </term> <listitem><para>Use <code>__builtin_addressof</code> and add <code>constexpr</code> to <code>addressof</code> for C++17 and later. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2306"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2306">2306</link>: - <emphasis><code>match_results::reference</code> should be <code>value_type&</code>, not <code>const value_type&</code></emphasis> + <emphasis role="bold"><code>match_results::reference</code> should be <code>value_type&</code>, not <code>const value_type&</code></emphasis> </term> <listitem><para>Change typedef. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2313"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2313">2313</link>: - <emphasis><code>tuple_size</code> should always derive from <code>integral_constant<size_t, N></code></emphasis> + <emphasis role="bold"><code>tuple_size</code> should always derive from <code>integral_constant<size_t, N></code></emphasis> </term> <listitem><para>Update definitions of the partial specializations for const and volatile types. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2328"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2328">2328</link>: - <emphasis>Rvalue stream extraction should use perfect forwarding</emphasis> + <emphasis role="bold">Rvalue stream extraction should use perfect forwarding</emphasis> </term> <listitem><para>Use perfect forwarding for right operand. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2329"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2329">2329</link>: - <emphasis><code>regex_match()/regex_search()</code> with <code>match_results</code> should forbid temporary strings</emphasis> + <emphasis role="bold"><code>regex_match()/regex_search()</code> with <code>match_results</code> should forbid temporary strings</emphasis> </term> <listitem><para>Add deleted overloads for rvalue strings. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2332"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2332">2332</link>: - <emphasis><code>regex_iterator/regex_token_iterator</code> should forbid temporary regexes</emphasis> + <emphasis role="bold"><code>regex_iterator/regex_token_iterator</code> should forbid temporary regexes</emphasis> </term> <listitem><para>Add deleted constructors. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2354"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2354">2332</link>: - <emphasis>Unnecessary copying when inserting into maps with braced-init syntax</emphasis> + <emphasis role="bold">Unnecessary copying when inserting into maps with braced-init syntax</emphasis> </term> <listitem><para>Add overloads of <code>insert</code> taking <code>value_type&&</code> rvalues. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2399"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2399">2399</link>: - <emphasis><code>shared_ptr</code>'s constructor from <code>unique_ptr</code> should be constrained</emphasis> + <emphasis role="bold"><code>shared_ptr</code>'s constructor from <code>unique_ptr</code> should be constrained</emphasis> </term> <listitem><para>Constrain the constructor to require convertibility. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2400"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2400">2400</link>: - <emphasis><code>shared_ptr</code>'s <code>get_deleter()</code> should use <code>addressof()</code></emphasis> + <emphasis role="bold"><code>shared_ptr</code>'s <code>get_deleter()</code> should use <code>addressof()</code></emphasis> </term> <listitem><para>Use <code>addressof</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2401"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2401">2401</link>: - <emphasis><code>std::function</code> needs more <code>noexcept</code></emphasis> + <emphasis role="bold"><code>std::function</code> needs more <code>noexcept</code></emphasis> </term> <listitem><para>Add <code>noexcept</code> to the assignment and comparisons. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2407"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2407">2407</link>: - <emphasis><code>packaged_task(allocator_arg_t, const Allocator&, F&&)</code> + <emphasis role="bold"><code>packaged_task(allocator_arg_t, const Allocator&, F&&)</code> should neither be constrained nor <code>explicit</code> - </emphasis> + </emphasis> </term> <listitem><para>Remove <code>explicit</code> from the constructor. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2408"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2408">2408</link>: - <emphasis>SFINAE-friendly + <emphasis role="bold">SFINAE-friendly <code>common_type</code>/<code>iterator_traits</code> is missing in C++14 - </emphasis> + </emphasis> </term> <listitem><para>Make <code>iterator_traits</code> empty if any of the types is not present in the iterator. @@ -1080,237 +1073,237 @@ requirements of the license of GCC. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2415"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2415">2415</link>: - <emphasis>Inconsistency between <code>unique_ptr</code> and <code>shared_ptr</code></emphasis> + <emphasis role="bold">Inconsistency between <code>unique_ptr</code> and <code>shared_ptr</code></emphasis> </term> <listitem><para>Create empty an <code>shared_ptr</code> from an empty <code>unique_ptr</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2418"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2418">2418</link>: - <emphasis><code>apply</code> does not work with member pointers</emphasis> + <emphasis role="bold"><code>apply</code> does not work with member pointers</emphasis> </term> <listitem><para>Use <code>mem_fn</code> for member pointers. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2440"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2440">2440</link>: - <emphasis><code>seed_seq::size()</code> should be <code>noexcept</code></emphasis> + <emphasis role="bold"><code>seed_seq::size()</code> should be <code>noexcept</code></emphasis> </term> <listitem><para>Add <code>noexcept</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2441"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2441">2441</link>: - <emphasis>Exact-width atomic typedefs should be provided</emphasis> + <emphasis role="bold">Exact-width atomic typedefs should be provided</emphasis> </term> <listitem><para>Define the typedefs. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2442"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2442">2442</link>: - <emphasis><code>call_once()</code> shouldn't <code>DECAY_COPY()</code></emphasis> + <emphasis role="bold"><code>call_once()</code> shouldn't <code>DECAY_COPY()</code></emphasis> </term> <listitem><para>Remove indirection through call wrapper that made copies of arguments and forward arguments straight to <code>std::invoke</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2454"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2454">2454</link>: - <emphasis>Add <code>raw_storage_iterator::base()</code> member - </emphasis> + <emphasis role="bold">Add <code>raw_storage_iterator::base()</code> member + </emphasis> </term> <listitem><para>Add the <code>base()</code> member function. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2455"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2455">2455</link>: - <emphasis>Allocator default construction should be allowed to throw - </emphasis> + <emphasis role="bold">Allocator default construction should be allowed to throw + </emphasis> </term> <listitem><para>Make <code>noexcept</code> specifications conditional. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2458"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2458">2458</link>: - <emphasis>N3778 and new library deallocation signatures - </emphasis> + <emphasis role="bold">N3778 and new library deallocation signatures + </emphasis> </term> <listitem><para>Remove unused overloads. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2459"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2459">2459</link>: - <emphasis><code>std::polar</code> should require a non-negative rho - </emphasis> + <emphasis role="bold"><code>std::polar</code> should require a non-negative rho + </emphasis> </term> <listitem><para>Add debug mode assertion. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2465"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2465">2465</link>: - <emphasis>SFINAE-friendly <code>common_type</code> is nearly impossible + <emphasis role="bold">SFINAE-friendly <code>common_type</code> is nearly impossible to specialize correctly and regresses key functionality - </emphasis> + </emphasis> </term> <listitem><para>Detect whether <code>decay_t</code> changes either type and use the decayed types if so. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2466"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2466">2466</link>: - <emphasis><code>allocator_traits::max_size()</code> default behavior is incorrect - </emphasis> + <emphasis role="bold"><code>allocator_traits::max_size()</code> default behavior is incorrect + </emphasis> </term> <listitem><para>Divide by the object type. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2484"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2484">2484</link>: - <emphasis><code>rethrow_if_nested()</code> is doubly unimplementable - </emphasis> + <emphasis role="bold"><code>rethrow_if_nested()</code> is doubly unimplementable + </emphasis> </term> <listitem><para>Avoid using <code>dynamic_cast</code> when it would be ill-formed. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2487"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2487">2487</link>: - <emphasis><code>bind()</code> should be <code>const</code>-overloaded - not cv-overloaded - </emphasis> + <emphasis role="bold"><code>bind()</code> should be <code>const</code>-overloaded + not <emphasis>cv</emphasis>-overloaded + </emphasis> </term> <listitem><para>Deprecate volatile-qualified <code>operator()</code> for C++17, make it ill-formed for C++20. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2499"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2499">2499</link>: - <emphasis><code>operator>>(basic_istream&, CharT*)</code> makes it hard to avoid buffer overflows - </emphasis> + <emphasis role="bold"><code>operator>>(basic_istream&, CharT*)</code> makes it hard to avoid buffer overflows + </emphasis> </term> <listitem><para>Replace <code>operator>>(basic_istream&, CharT*)</code> and other overloads writing through pointers. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2537"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2537">2537</link>: - <emphasis>Constructors for <code>priority_queue</code> taking allocators + <emphasis role="bold">Constructors for <code>priority_queue</code> taking allocators should call <code>make_heap</code> - </emphasis> + </emphasis> </term> <listitem><para>Call <code>make_heap</code>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2566"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2566">2566</link>: - <emphasis>Requirements on the first template parameter of container adaptors - </emphasis> + <emphasis role="bold">Requirements on the first template parameter of container adaptors + </emphasis> </term> <listitem><para>Add static assertions to enforce the requirement. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2583"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2583">2583</link>: - <emphasis>There is no way to supply an allocator for <code>basic_string(str, pos)</code> - </emphasis> + <emphasis role="bold">There is no way to supply an allocator for <code>basic_string(str, pos)</code> + </emphasis> </term> <listitem><para>Add new constructor. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2586"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2586">2586</link>: - <emphasis>Wrong value category used in <code>scoped_allocator_adaptor::construct()</code> - </emphasis> + <emphasis role="bold">Wrong value category used in <code>scoped_allocator_adaptor::construct()</code> + </emphasis> </term> <listitem><para>Change internal helper for uses-allocator construction to always check using const lvalue allocators. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2684"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2684">2684</link>: - <emphasis><code>priority_queue</code> lacking comparator typedef - </emphasis> + <emphasis role="bold"><code>priority_queue</code> lacking comparator typedef + </emphasis> </term> <listitem><para>Define the <code>value_compare</code> typedef. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2735"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2735">2735</link>: - <emphasis><code>std::abs(short)</code>, + <emphasis role="bold"><code>std::abs(short)</code>, <code>std::abs(signed char)</code> and others should return <code>int</code> instead of <code>double</code> in order to be compatible with C++98 and C - </emphasis> + </emphasis> </term> <listitem><para>Resolved by the changes for <link linkend="manual.bugs.dr2192">2192</link>. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2770"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2770">2770</link>: - <emphasis><code>tuple_size<const T></code> specialization is not + <emphasis role="bold"><code>tuple_size<const T></code> specialization is not SFINAE compatible and breaks decomposition declarations - </emphasis> + </emphasis> </term> <listitem><para>Safely detect <code>tuple_size<T>::value</code> and only use it if valid. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2781"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2781">2781</link>: - <emphasis>Contradictory requirements for <code>std::function</code> + <emphasis role="bold">Contradictory requirements for <code>std::function</code> and <code>std::reference_wrapper</code> - </emphasis> + </emphasis> </term> <listitem><para>Remove special handling for <code>reference_wrapper</code> arguments and store them directly as the target object. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2802"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2802">2802</link>: - <emphasis>Add noexcept to several <code>shared_ptr</code> related + <emphasis role="bold">Add noexcept to several <code>shared_ptr</code> related functions - </emphasis> + </emphasis> </term> <listitem><para>Add noexcept. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2873"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2873">2873</link>: - <emphasis><code>shared_ptr</code> constructor requirements for a deleter - </emphasis> + <emphasis role="bold"><code>shared_ptr</code> constructor requirements for a deleter + </emphasis> </term> <listitem><para>Use rvalues for deleters. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2921"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2921">2921</link>: - <emphasis><code>packaged_task</code> and type-erased allocators - </emphasis> + <emphasis role="bold"><code>packaged_task</code> and type-erased allocators + </emphasis> </term> <listitem><para>For C++17 mode, remove the constructors taking an allocator argument. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2942"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2942">2942</link>: - <emphasis>LWG 2873's resolution missed + <emphasis role="bold">LWG 2873's resolution missed <code>weak_ptr::owner_before</code> - </emphasis> + </emphasis> </term> <listitem><para>Add noexcept. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2996"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2996">2996</link>: - <emphasis>Missing rvalue overloads for + <emphasis role="bold">Missing rvalue overloads for <code>shared_ptr</code> operations - </emphasis> + </emphasis> </term> <listitem><para>Add additional constructor and cast overloads. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr2993"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2993">2993</link>: - <emphasis><code>reference_wrapper<T></code> conversion from <code>T&&</code> - </emphasis> + <emphasis role="bold"><code>reference_wrapper<T></code> conversion from <code>T&&</code> + </emphasis> </term> <listitem><para>Replaced the constructors with a constrained template, to prevent participation in overload resolution when not valid. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr3074"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#3074">3074</link>: - <emphasis>Non-member functions for <code>valarray</code> should only deduce from the <code>valarray</code> - </emphasis> + <emphasis role="bold">Non-member functions for <code>valarray</code> should only deduce from the <code>valarray</code> + </emphasis> </term> <listitem><para>Change scalar operands to be non-deduced context, so that they will allow conversions from other types to the value_type. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr3076"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#3076">3076</link>: - <emphasis><code>basic_string</code> CTAD ambiguity - </emphasis> + <emphasis role="bold"><code>basic_string</code> CTAD ambiguity + </emphasis> </term> <listitem><para>Change constructors to constrained templates. </para></listitem></varlistentry> <varlistentry xml:id="manual.bugs.dr3096"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#3096">3096</link>: - <emphasis><code>path::lexically_relative</code> is confused by trailing slashes - </emphasis> + <emphasis role="bold"><code>path::lexically_relative</code> is confused by trailing slashes + </emphasis> </term> <listitem><para>Implement the fix for trailing slashes. </para></listitem></varlistentry> diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 26d2f6a..9d60755 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -380,13 +380,6 @@ WARN_CXXFLAGS = \ # -I/-D flags to pass when compiling. AM_CPPFLAGS = $(GLIBCXX_INCLUDES) $(CPPFLAGS) -# Regarding *_freestanding: -# For including files in freestanding, create a new _freestanding variable, and -# split *_headers across an ``if GLIBCXX_HOSTED'', then update install-headers -# to account for the new directory/set being added. -# If such a variable exists, simply add to either *_headers or *_freestanding, -# as appropriate. - # Standard C++ includes. std_srcdir = ${glibcxx_srcdir}/include/std std_builddir = . @@ -395,20 +388,25 @@ std_freestanding = \ ${std_srcdir}/array \ ${std_srcdir}/atomic \ ${std_srcdir}/bit \ + ${std_srcdir}/bitset \ ${std_srcdir}/concepts \ ${std_srcdir}/coroutine \ + ${std_srcdir}/expected \ ${std_srcdir}/functional \ ${std_srcdir}/iterator \ ${std_srcdir}/limits \ ${std_srcdir}/memory \ ${std_srcdir}/numbers \ + ${std_srcdir}/numeric \ ${std_srcdir}/optional \ ${std_srcdir}/ranges \ ${std_srcdir}/ratio \ + ${std_srcdir}/scoped_allocator \ ${std_srcdir}/source_location \ ${std_srcdir}/span \ ${std_srcdir}/tuple \ ${std_srcdir}/type_traits \ + ${std_srcdir}/typeindex \ ${std_srcdir}/utility \ ${std_srcdir}/variant \ ${std_srcdir}/version @@ -418,7 +416,6 @@ std_freestanding = \ @GLIBCXX_HOSTED_TRUE@ ${std_freestanding} \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/any \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/barrier \ -@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/bitset \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/charconv \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/chrono \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/codecvt \ @@ -426,7 +423,6 @@ std_freestanding = \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/condition_variable \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/deque \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/execution \ -@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/expected \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/filesystem \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/forward_list \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/fstream \ @@ -442,12 +438,10 @@ std_freestanding = \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/map \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/memory_resource \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/mutex \ -@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/numeric \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/ostream \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/queue \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/random \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/regex \ -@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/scoped_allocator \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/semaphore \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/set \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/shared_mutex \ @@ -463,7 +457,6 @@ std_freestanding = \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/string_view \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/system_error \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/thread \ -@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/typeindex \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/unordered_map \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/unordered_set \ @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/valarray \ @@ -478,6 +471,7 @@ bits_freestanding = \ ${bits_srcdir}/alloc_traits.h \ ${bits_srcdir}/atomic_base.h \ ${bits_srcdir}/c++0x_warning.h \ + ${bits_srcdir}/boost_concept_check.h \ ${bits_srcdir}/concept_check.h \ ${bits_srcdir}/cpp_type_traits.h \ ${bits_srcdir}/enable_special_members.h \ @@ -506,6 +500,7 @@ bits_freestanding = \ ${bits_srcdir}/stl_iterator.h \ ${bits_srcdir}/stl_iterator_base_funcs.h \ ${bits_srcdir}/stl_iterator_base_types.h \ + ${bits_srcdir}/stl_numeric.h \ ${bits_srcdir}/stl_heap.h \ ${bits_srcdir}/stl_pair.h \ ${bits_srcdir}/stl_raw_storage_iter.h \ @@ -528,7 +523,6 @@ bits_freestanding = \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_ios.tcc \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_string.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/basic_string.tcc \ -@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/boost_concept_check.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/char_traits.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/charconv.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/chrono.h \ @@ -601,7 +595,6 @@ bits_freestanding = \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/stl_map.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/stl_multimap.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/stl_multiset.h \ -@GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/stl_numeric.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/stl_queue.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/stl_relops.h \ @GLIBCXX_HOSTED_TRUE@ ${bits_srcdir}/stl_set.h \ @@ -974,49 +967,53 @@ pb_headers7 = \ ext_srcdir = ${glibcxx_srcdir}/include/ext ext_builddir = ./ext -ext_headers = \ - ${ext_srcdir}/algorithm \ +ext_freestanding = \ ${ext_srcdir}/aligned_buffer.h \ ${ext_srcdir}/alloc_traits.h \ ${ext_srcdir}/atomicity.h \ - ${ext_srcdir}/bitmap_allocator.h \ ${ext_srcdir}/cast.h \ - ${ext_srcdir}/cmath \ - ${ext_srcdir}/codecvt_specializations.h \ ${ext_srcdir}/concurrence.h \ - ${ext_srcdir}/debug_allocator.h \ - ${ext_srcdir}/enc_filebuf.h \ - ${ext_srcdir}/extptr_allocator.h \ - ${ext_srcdir}/functional \ - ${ext_srcdir}/iterator \ - ${ext_srcdir}/malloc_allocator.h \ - ${ext_srcdir}/memory \ - ${ext_srcdir}/mt_allocator.h \ - ${ext_srcdir}/new_allocator.h \ - ${ext_srcdir}/numeric \ ${ext_srcdir}/numeric_traits.h \ - ${ext_srcdir}/pod_char_traits.h \ + ${ext_srcdir}/iterator \ ${ext_srcdir}/pointer.h \ - ${ext_srcdir}/pool_allocator.h \ - ${ext_srcdir}/random \ - ${ext_srcdir}/random.tcc \ - ${ext_srcdir}/rb_tree \ - ${ext_srcdir}/rc_string_base.h \ - ${ext_srcdir}/rope \ - ${ext_srcdir}/ropeimpl.h \ - ${ext_srcdir}/slist \ - ${ext_srcdir}/sso_string_base.h \ - ${ext_srcdir}/stdio_filebuf.h \ - ${ext_srcdir}/stdio_sync_filebuf.h \ - ${ext_srcdir}/string_conversions.h \ - ${ext_srcdir}/throw_allocator.h \ - ${ext_srcdir}/typelist.h \ ${ext_srcdir}/type_traits.h \ - ${ext_srcdir}/vstring_fwd.h \ - ${ext_srcdir}/vstring.h \ - ${ext_srcdir}/vstring.tcc \ - ${ext_srcdir}/vstring_util.h \ - ${ext_compat_headers} + ${ext_srcdir}/typelist.h + +@GLIBCXX_HOSTED_FALSE@ext_headers = ${ext_freestanding} +@GLIBCXX_HOSTED_TRUE@ext_headers = \ +@GLIBCXX_HOSTED_TRUE@ ${ext_freestanding} \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/algorithm \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/bitmap_allocator.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/cmath \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/codecvt_specializations.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/debug_allocator.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/enc_filebuf.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/extptr_allocator.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/functional \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/malloc_allocator.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/memory \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/mt_allocator.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/new_allocator.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/numeric \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/pod_char_traits.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/pool_allocator.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/random \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/random.tcc \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/rb_tree \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/rc_string_base.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/rope \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/ropeimpl.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/slist \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/sso_string_base.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/stdio_filebuf.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/stdio_sync_filebuf.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/string_conversions.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/throw_allocator.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/vstring_fwd.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/vstring.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/vstring.tcc \ +@GLIBCXX_HOSTED_TRUE@ ${ext_srcdir}/vstring_util.h \ +@GLIBCXX_HOSTED_TRUE@ ${ext_compat_headers} ext_compat_headers = \ ${backward_srcdir}/hash_set \ @@ -1945,9 +1942,6 @@ install-headers: $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${backward_builddir} for file in ${backward_headers}; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${backward_builddir}; done - $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${ext_builddir} - for file in ${ext_headers}; do \ - $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${ext_builddir}; done $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${std_builddir} for file in ${std_headers}; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${std_builddir}; done @@ -1962,6 +1956,9 @@ install-headers: $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir} for file in ${c_base_headers}; do \ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${c_base_builddir}; done + $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${ext_builddir} + for file in ${ext_headers}; do \ + $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${ext_builddir}; done @GLIBCXX_HOSTED_TRUE@ for dir in ${pb_subdirs}; do \ @GLIBCXX_HOSTED_TRUE@ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/$${dir} ; done @GLIBCXX_HOSTED_TRUE@ for file in ${pb_headers1}; do \ diff --git a/libstdc++-v3/include/bits/functexcept.h b/libstdc++-v3/include/bits/functexcept.h index a78a17b..7fad4b1 100644 --- a/libstdc++-v3/include/bits/functexcept.h +++ b/libstdc++-v3/include/bits/functexcept.h @@ -43,6 +43,7 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#if _GLIBCXX_HOSTED // Helper for exception objects in <except> void __throw_bad_exception(void) __attribute__((__noreturn__)); @@ -112,6 +113,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void __throw_bad_function_call() __attribute__((__noreturn__)); +#else // ! HOSTED + + __attribute__((__noreturn__)) inline void + __throw_invalid_argument(const char*) + { std::__terminate(); } + + __attribute__((__noreturn__)) inline void + __throw_out_of_range(const char*) + { std::__terminate(); } + + __attribute__((__noreturn__)) inline void + __throw_out_of_range_fmt(const char*, ...) + { std::__terminate(); } + + __attribute__((__noreturn__)) inline void + __throw_runtime_error(const char*) + { std::__terminate(); } + + __attribute__((__noreturn__)) inline void + __throw_overflow_error(const char*) + { std::__terminate(); } + +#endif // HOSTED + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/invoke.h b/libstdc++-v3/include/bits/invoke.h index 8724a76..8fa8cf8 100644 --- a/libstdc++-v3/include/bits/invoke.h +++ b/libstdc++-v3/include/bits/invoke.h @@ -130,8 +130,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { using __result = __invoke_result<_Callable, _Args...>; using __type = typename __result::type; +#if __has_builtin(__reference_converts_from_temporary) static_assert(!__reference_converts_from_temporary(_Res, __type), "INVOKE<R> must not create a dangling reference"); +#endif using __tag = typename __result::__invoke_type; return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), std::forward<_Args>(__args)...); diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 3e6eb9d..28b37a9 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -198,16 +198,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Engine& _M_g; }; + // Detect whether a template argument _Sseq is a valid seed sequence for + // a random number engine _Engine with result type _Res. + // Used to constrain _Engine::_Engine(_Sseq&) and _Engine::seed(_Sseq&) + // as required by [rand.eng.general]. + template<typename _Sseq> using __seed_seq_generate_t = decltype( std::declval<_Sseq&>().generate(std::declval<uint_least32_t*>(), std::declval<uint_least32_t*>())); - // Detect whether _Sseq is a valid seed sequence for - // a random number engine _Engine with result type _Res. template<typename _Sseq, typename _Engine, typename _Res, typename _GenerateCheck = __seed_seq_generate_t<_Sseq>> - using __is_seed_seq = __and_< + using _If_seed_seq_for = _Require< __not_<is_same<__remove_cvref_t<_Sseq>, _Engine>>, is_unsigned<typename _Sseq::result_type>, __not_<is_convertible<_Sseq, _Res>> @@ -263,8 +266,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "template argument substituting __m out of bounds"); template<typename _Sseq> - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, linear_congruential_engine, _UIntType>::value>::type; + using _If_seed_seq + = __detail::_If_seed_seq_for<_Sseq, linear_congruential_engine, + _UIntType>; public: /** The type of the generated random value. */ @@ -502,8 +506,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "template argument substituting __f out of bound"); template<typename _Sseq> - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, mersenne_twister_engine, _UIntType>::value>::type; + using _If_seed_seq + = __detail::_If_seed_seq_for<_Sseq, mersenne_twister_engine, + _UIntType>; public: /** The type of the generated random value. */ @@ -702,8 +707,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "template argument substituting __w out of bounds"); template<typename _Sseq> - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, subtract_with_carry_engine, _UIntType>::value>::type; + using _If_seed_seq + = __detail::_If_seed_seq_for<_Sseq, subtract_with_carry_engine, + _UIntType>; public: /** The type of the generated random value. */ @@ -894,8 +900,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename _RandomNumberEngine::result_type result_type; template<typename _Sseq> - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, discard_block_engine, result_type>::value>::type; + using _If_seed_seq + = __detail::_If_seed_seq_for<_Sseq, discard_block_engine, + result_type>; // parameter values static constexpr size_t block_size = __p; @@ -1113,8 +1120,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "template argument substituting __w out of bounds"); template<typename _Sseq> - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, independent_bits_engine, _UIntType>::value>::type; + using _If_seed_seq + = __detail::_If_seed_seq_for<_Sseq, independent_bits_engine, + _UIntType>; public: /** The type of the generated random value. */ @@ -1336,8 +1344,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename _RandomNumberEngine::result_type result_type; template<typename _Sseq> - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, shuffle_order_engine, result_type>::value>::type; + using _If_seed_seq + = __detail::_If_seed_seq_for<_Sseq, shuffle_order_engine, + result_type>; static constexpr size_t table_size = __k; diff --git a/libstdc++-v3/include/bits/std_function.h b/libstdc++-v3/include/bits/std_function.h index f5423a3..8ab32a6 100644 --- a/libstdc++-v3/include/bits/std_function.h +++ b/libstdc++-v3/include/bits/std_function.h @@ -36,11 +36,11 @@ # include <bits/c++0x_warning.h> #else -#include <typeinfo> -#include <bits/stl_function.h> -#include <bits/invoke.h> -#include <bits/refwrap.h> -#include <bits/functexcept.h> +#include <new> // placement new +#include <typeinfo> // typeid +#include <bits/invoke.h> // __invoke_r +#include <bits/refwrap.h> // ref wrapper, _Maybe_unary_or_binary_function +#include <bits/functexcept.h> // __throw_bad_function_call namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/include/c_global/cstdint b/libstdc++-v3/include/c_global/cstdint index 4490d06..4b9df45 100644 --- a/libstdc++-v3/include/c_global/cstdint +++ b/libstdc++-v3/include/c_global/cstdint @@ -37,7 +37,11 @@ #include <bits/c++config.h> -#if _GLIBCXX_HAVE_STDINT_H +#if ! _GLIBCXX_HOSTED && __has_include(<stdint-gcc.h>) +// For --disable-hosted-libstdcxx we want GCC's own stdint-gcc.h header +// even when -ffreestanding isn't used. +# include <stdint-gcc.h> +#elif __has_include(<stdint.h>) # include <stdint.h> #endif @@ -80,9 +84,60 @@ namespace std using ::uintmax_t; using ::uintptr_t; #else // !_GLIBCXX_USE_C99_STDINT_TR1 - // Define the minimum needed for <ratio>, <chrono> etc. + using intmax_t = __INTMAX_TYPE__; using uintmax_t = __UINTMAX_TYPE__; + +#ifdef __INT8_TYPE__ + using int8_t = __INT8_TYPE__; +#endif +#ifdef __INT16_TYPE__ + using int16_t = __INT16_TYPE__; +#endif +#ifdef __INT32_TYPE__ + using int32_t = __INT32_TYPE__; +#endif +#ifdef __INT64_TYPE__ + using int64_t = __INT64_TYPE__; +#endif + + using int_least8_t = __INT_LEAST8_TYPE__; + using int_least16_t = __INT_LEAST16_TYPE__; + using int_least32_t = __INT_LEAST32_TYPE__; + using int_least64_t = __INT_LEAST64_TYPE__; + using int_fast8_t = __INT_FAST8_TYPE__; + using int_fast16_t = __INT_FAST16_TYPE__; + using int_fast32_t = __INT_FAST32_TYPE__; + using int_fast64_t = __INT_FAST64_TYPE__; + +#ifdef __INTPTR_TYPE__ + using intptr_t = __INTPTR_TYPE__; +#endif + +#ifdef __UINT8_TYPE__ + using uint8_t = __UINT8_TYPE__; +#endif +#ifdef __UINT16_TYPE__ + using uint16_t = __UINT16_TYPE__; +#endif +#ifdef __UINT32_TYPE__ + using uint32_t = __UINT32_TYPE__; +#endif +#ifdef __UINT64_TYPE__ + using uint64_t = __UINT64_TYPE__; +#endif + using uint_least8_t = __UINT_LEAST8_TYPE__; + using uint_least16_t = __UINT_LEAST16_TYPE__; + using uint_least32_t = __UINT_LEAST32_TYPE__; + using uint_least64_t = __UINT_LEAST64_TYPE__; + using uint_fast8_t = __UINT_FAST8_TYPE__; + using uint_fast16_t = __UINT_FAST16_TYPE__; + using uint_fast32_t = __UINT_FAST32_TYPE__; + using uint_fast64_t = __UINT_FAST64_TYPE__; +#ifdef __UINTPTR_TYPE__ + using uintptr_t = __UINTPTR_TYPE__; +#endif + #endif // _GLIBCXX_USE_C99_STDINT_TR1 } // namespace std diff --git a/libstdc++-v3/include/ext/random b/libstdc++-v3/include/ext/random index 4cc0e25..406b12b 100644 --- a/libstdc++-v3/include/ext/random +++ b/libstdc++-v3/include/ext/random @@ -89,9 +89,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Sseq> using _If_seed_seq - = typename std::enable_if<std::__detail::__is_seed_seq< - _Sseq, simd_fast_mersenne_twister_engine, result_type>::value - >::type; + = std::__detail::_If_seed_seq_for<_Sseq, + simd_fast_mersenne_twister_engine, + result_type>; public: static constexpr size_t state_size = _M_nstate * (16 diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset index afabeb4..1f3f68f 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -1514,13 +1514,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER else if (_Traits::eq(__c, __one)) _Unchecked_set(__i - 1); else - { -#if _GLIBCXX_HOSTED - __throw_invalid_argument(__N("bitset::_M_copy_from_ptr")); -#else - __builtin_abort(); -#endif - } + __throw_invalid_argument(__N("bitset::_M_copy_from_ptr")); } } diff --git a/libstdc++-v3/include/std/coroutine b/libstdc++-v3/include/std/coroutine index f4189c7..ebaf11d 100644 --- a/libstdc++-v3/include/std/coroutine +++ b/libstdc++-v3/include/std/coroutine @@ -39,7 +39,7 @@ # include <compare> #endif -#if !defined __cpp_lib_three_way_comparison && _GLIBCXX_HOSTED +#if !defined __cpp_lib_three_way_comparison # include <bits/stl_function.h> // for std::less #endif @@ -165,11 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr bool operator<(coroutine_handle<> __a, coroutine_handle<> __b) noexcept { -#if _GLIBCXX_HOSTED return less<void*>()(__a.address(), __b.address()); -#else - return (__UINTPTR_TYPE__)__a.address() < (__UINTPTR_TYPE__)__b.address(); -#endif } constexpr bool @@ -343,7 +339,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // namespace __n4861 -#if _GLIBCXX_HOSTED template<typename _Tp> struct hash; template<typename _Promise> @@ -355,10 +350,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return reinterpret_cast<size_t>(__h.address()); } }; -#endif #else -#error "the coroutine header requires -fcoroutines" +#error "the <coroutine> header requires -fcoroutines" #endif _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index adf9cb1..d22acaa 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -46,11 +46,10 @@ #pragma GCC system_header #include <bits/c++config.h> -#include <bits/stl_function.h> +#include <bits/stl_function.h> // std::equal_to, std::unary_function etc. #if __cplusplus >= 201103L -#include <new> #include <tuple> #include <type_traits> #include <bits/functional_hash.h> @@ -67,8 +66,8 @@ # endif # include <bits/stl_algo.h> // std::search #endif -#if __cplusplus > 201703L -# include <bits/ranges_cmp.h> +#if __cplusplus >= 202002L +# include <bits/ranges_cmp.h> // std::identity, ranges::equal_to etc. # include <compare> #endif #if __cplusplus > 202002L && _GLIBCXX_HOSTED diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index c2eacde..1f82112 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -44,6 +44,9 @@ #include <optional> #include <span> #include <tuple> +#if __cplusplus > 202002L +#include <variant> +#endif #include <bits/ranges_util.h> #include <bits/refwrap.h> @@ -6873,6 +6876,486 @@ namespace views::__adaptor inline constexpr _ChunkBy chunk_by; } + + namespace __detail + { + template<typename _Range, typename _Pattern> + concept __compatible_joinable_ranges + = common_with<range_value_t<_Range>, range_value_t<_Pattern>> + && common_reference_with<range_reference_t<_Range>, + range_reference_t<_Pattern>> + && common_reference_with<range_rvalue_reference_t<_Range>, + range_rvalue_reference_t<_Pattern>>; + + template<typename _Range> + concept __bidirectional_common = bidirectional_range<_Range> && common_range<_Range>; + } + + template<input_range _Vp, forward_range _Pattern> + requires view<_Vp> && view<_Pattern> + && input_range<range_reference_t<_Vp>> + && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, _Pattern> + class join_with_view : public view_interface<join_with_view<_Vp, _Pattern>> + { + using _InnerRange = range_reference_t<_Vp>; + + _Vp _M_base = _Vp(); + __detail::__non_propagating_cache<remove_cv_t<_InnerRange>> _M_inner; + _Pattern _M_pattern = _Pattern(); + + template<bool _Const> using _Base = __detail::__maybe_const_t<_Const, _Vp>; + template<bool _Const> using _InnerBase = range_reference_t<_Base<_Const>>; + template<bool _Const> using _PatternBase = __detail::__maybe_const_t<_Const, _Pattern>; + + template<bool _Const> using _OuterIter = iterator_t<_Base<_Const>>; + template<bool _Const> using _InnerIter = iterator_t<_InnerBase<_Const>>; + template<bool _Const> using _PatternIter = iterator_t<_PatternBase<_Const>>; + + template<bool _Const> + static constexpr bool _S_ref_is_glvalue = is_reference_v<_InnerBase<_Const>>; + + template<bool _Const> + struct __iter_cat + { }; + + template<bool _Const> + requires _S_ref_is_glvalue<_Const> + && forward_range<_Base<_Const>> + && forward_range<_InnerBase<_Const>> + struct __iter_cat<_Const> + { + private: + static auto + _S_iter_cat() + { + using _OuterIter = join_with_view::_OuterIter<_Const>; + using _InnerIter = join_with_view::_InnerIter<_Const>; + using _PatternIter = join_with_view::_PatternIter<_Const>; + using _OuterCat = typename iterator_traits<_OuterIter>::iterator_category; + using _InnerCat = typename iterator_traits<_InnerIter>::iterator_category; + using _PatternCat = typename iterator_traits<_PatternIter>::iterator_category; + if constexpr (!is_lvalue_reference_v<common_reference_t<iter_reference_t<_InnerIter>, + iter_reference_t<_PatternIter>>>) + return input_iterator_tag{}; + else if constexpr (derived_from<_OuterCat, bidirectional_iterator_tag> + && derived_from<_InnerCat, bidirectional_iterator_tag> + && derived_from<_PatternCat, bidirectional_iterator_tag> + && common_range<_InnerBase<_Const>> + && common_range<_PatternBase<_Const>>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_OuterCat, forward_iterator_tag> + && derived_from<_InnerCat, forward_iterator_tag> + && derived_from<_PatternCat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template<bool> struct _Iterator; + template<bool> struct _Sentinel; + + public: + join_with_view() requires (default_initializable<_Vp> + && default_initializable<_Pattern>) + = default; + + constexpr + join_with_view(_Vp __base, _Pattern __pattern) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) + { } + + template<input_range _Range> + requires constructible_from<_Vp, views::all_t<_Range>> + && constructible_from<_Pattern, single_view<range_value_t<_InnerRange>>> + constexpr + join_with_view(_Range&& __r, range_value_t<_InnerRange> __e) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(views::single(std::move(__e))) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + constexpr bool __use_const = is_reference_v<_InnerRange> + && __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; + return _Iterator<__use_const>{*this, ranges::begin(_M_base)}; + } + + constexpr auto + begin() const + requires input_range<const _Vp> + && forward_range<const _Pattern> + && is_reference_v<range_reference_t<const _Vp>> + { return _Iterator<true>{*this, ranges::begin(_M_base)}; } + + constexpr auto + end() + { + constexpr bool __use_const + = __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; + if constexpr (is_reference_v<_InnerRange> + && forward_range<_Vp> && common_range<_Vp> + && forward_range<_InnerRange> && common_range<_InnerRange>) + return _Iterator<__use_const>{*this, ranges::end(_M_base)}; + else + return _Sentinel<__use_const>{*this}; + } + + constexpr auto + end() const + requires input_range<const _Vp> + && forward_range<const _Pattern> + && is_reference_v<range_reference_t<const _Vp>> + { + using _InnerConstRange = range_reference_t<const _Vp>; + if constexpr (forward_range<const _Vp> + && forward_range<_InnerConstRange> + && common_range<const _Vp> + && common_range<_InnerConstRange>) + return _Iterator<true>{*this, ranges::end(_M_base)}; + else + return _Sentinel<true>{*this}; + } + }; + + template<typename _Range, typename _Pattern> + join_with_view(_Range&&, _Pattern&&) + -> join_with_view<views::all_t<_Range>, views::all_t<_Pattern>>; + + template<input_range _Range> + join_with_view(_Range&&, range_value_t<range_reference_t<_Range>>) + -> join_with_view<views::all_t<_Range>, + single_view<range_value_t<range_reference_t<_Range>>>>; + + template<input_range _Vp, forward_range _Pattern> + requires view<_Vp> && view<_Pattern> + && input_range<range_reference_t<_Vp>> + && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, _Pattern> + template<bool _Const> + class join_with_view<_Vp, _Pattern>::_Iterator : public __iter_cat<_Const> + { + using _Parent = __detail::__maybe_const_t<_Const, join_with_view>; + using _Base = join_with_view::_Base<_Const>; + using _InnerBase = join_with_view::_InnerBase<_Const>; + using _PatternBase = join_with_view::_PatternBase<_Const>; + + using _OuterIter = join_with_view::_OuterIter<_Const>; + using _InnerIter = join_with_view::_InnerIter<_Const>; + using _PatternIter = join_with_view::_PatternIter<_Const>; + + static constexpr bool _S_ref_is_glvalue = join_with_view::_S_ref_is_glvalue<_Const>; + + _Parent* _M_parent = nullptr; + _OuterIter _M_outer_it = _OuterIter(); + variant<_PatternIter, _InnerIter> _M_inner_it; + + constexpr + _Iterator(_Parent& __parent, iterator_t<_Base> __outer) + : _M_parent(std::__addressof(__parent)), _M_outer_it(std::move(__outer)) + { + if (_M_outer_it != ranges::end(_M_parent->_M_base)) + { + auto&& __inner = _M_update_inner(_M_outer_it); + _M_inner_it.template emplace<1>(ranges::begin(__inner)); + _M_satisfy(); + } + } + + constexpr auto&& + _M_update_inner(const _OuterIter& __x) + { + if constexpr (_S_ref_is_glvalue) + return *__x; + else + return _M_parent->_M_inner._M_emplace_deref(__x); + } + + constexpr auto&& + _M_get_inner(const _OuterIter& __x) + { + if constexpr (_S_ref_is_glvalue) + return *__x; + else + return *_M_parent->_M_inner; + } + + constexpr void + _M_satisfy() + { + while (true) + { + if (_M_inner_it.index() == 0) + { + if (std::get<0>(_M_inner_it) != ranges::end(_M_parent->_M_pattern)) + break; + + auto&& __inner = _M_update_inner(_M_outer_it); + _M_inner_it.template emplace<1>(ranges::begin(__inner)); + } + else + { + auto&& __inner = _M_get_inner(_M_outer_it); + if (std::get<1>(_M_inner_it) != ranges::end(__inner)) + break; + + if (++_M_outer_it == ranges::end(_M_parent->_M_base)) + { + if constexpr (_S_ref_is_glvalue) + _M_inner_it.template emplace<0>(); + break; + } + + _M_inner_it.template emplace<0>(ranges::begin(_M_parent->_M_pattern)); + } + } + } + + static auto + _S_iter_concept() + { + if constexpr (_S_ref_is_glvalue + && bidirectional_range<_Base> + && __detail::__bidirectional_common<_InnerBase> + && __detail::__bidirectional_common<_PatternBase>) + return bidirectional_iterator_tag{}; + else if constexpr (_S_ref_is_glvalue + && forward_range<_Base> + && forward_range<_InnerBase>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend join_with_view; + + public: + using iterator_concept = decltype(_S_iter_concept()); + // iterator_category defined in join_with_view::__iter_cat + using value_type = common_type_t<iter_value_t<_InnerIter>, + iter_value_t<_PatternIter>>; + using difference_type = common_type_t<iter_difference_t<_OuterIter>, + iter_difference_t<_InnerIter>, + iter_difference_t<_PatternIter>>; + + _Iterator() requires default_initializable<_OuterIter> = default; + + constexpr + _Iterator(_Iterator<!_Const> __i) + requires _Const + && convertible_to<iterator_t<_Vp>, _OuterIter> + && convertible_to<iterator_t<_InnerRange>, _InnerIter> + && convertible_to<iterator_t<_Pattern>, _PatternIter> + : _M_parent(__i._M_parent), + _M_outer_it(std::move(__i._M_outer_it)) + { + if (__i._M_inner_it.index() == 0) + _M_inner_it.template emplace<0>(std::get<0>(std::move(__i._M_inner_it))); + else + _M_inner_it.template emplace<1>(std::get<1>(std::move(__i._M_inner_it))); + } + + constexpr common_reference_t<iter_reference_t<_InnerIter>, + iter_reference_t<_PatternIter>> + operator*() const + { + if (_M_inner_it.index() == 0) + return *std::get<0>(_M_inner_it); + else + return *std::get<1>(_M_inner_it); + } + + constexpr _Iterator& + operator++() + { + if (_M_inner_it.index() == 0) + ++std::get<0>(_M_inner_it); + else + ++std::get<1>(_M_inner_it); + _M_satisfy(); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) + requires _S_ref_is_glvalue + && forward_iterator<_OuterIter> && forward_iterator<_InnerIter> + { + _Iterator __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires _S_ref_is_glvalue + && bidirectional_range<_Base> + && __detail::__bidirectional_common<_InnerBase> + && __detail::__bidirectional_common<_PatternBase> + { + if (_M_outer_it == ranges::end(_M_parent->_M_base)) + { + auto&& __inner = *--_M_outer_it; + _M_inner_it.template emplace<1>(ranges::end(__inner)); + } + + while (true) + { + if (_M_inner_it.index() == 0) + { + auto& __it = std::get<0>(_M_inner_it); + if (__it == ranges::begin(_M_parent->_M_pattern)) + { + auto&& __inner = *--_M_outer_it; + _M_inner_it.template emplace<1>(ranges::end(__inner)); + } + else + break; + } + else + { + auto& __it = std::get<1>(_M_inner_it); + auto&& __inner = *_M_outer_it; + if (__it == ranges::begin(__inner)) + _M_inner_it.template emplace<0>(ranges::end(_M_parent->_M_pattern)); + else + break; + } + } + + if (_M_inner_it.index() == 0) + --std::get<0>(_M_inner_it); + else + --std::get<1>(_M_inner_it); + return *this; + } + + constexpr _Iterator + operator--(int) + requires _S_ref_is_glvalue && bidirectional_range<_Base> + && __detail::__bidirectional_common<_InnerBase> + && __detail::__bidirectional_common<_PatternBase> + { + _Iterator __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires _S_ref_is_glvalue + && equality_comparable<_OuterIter> && equality_comparable<_InnerIter> + { return __x._M_outer_it == __y._M_outer_it && __x._M_inner_it ==__y._M_inner_it; } + + friend constexpr common_reference_t<iter_rvalue_reference_t<_InnerIter>, + iter_rvalue_reference_t<_PatternIter>> + iter_move(const _Iterator& __x) + { + if (__x._M_inner_it.index() == 0) + return ranges::iter_move(std::get<0>(__x._M_inner_it)); + else + return ranges::iter_move(std::get<1>(__x._M_inner_it)); + } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + requires indirectly_swappable<_InnerIter, _PatternIter> + { + if (__x._M_inner_it.index() == 0) + { + if (__y._M_inner_it.index() == 0) + ranges::iter_swap(std::get<0>(__x._M_inner_it), std::get<0>(__y._M_inner_it)); + else + ranges::iter_swap(std::get<0>(__x._M_inner_it), std::get<1>(__y._M_inner_it)); + } + else + { + if (__y._M_inner_it.index() == 0) + ranges::iter_swap(std::get<1>(__x._M_inner_it), std::get<0>(__y._M_inner_it)); + else + ranges::iter_swap(std::get<1>(__x._M_inner_it), std::get<1>(__y._M_inner_it)); + } + } + }; + + template<input_range _Vp, forward_range _Pattern> + requires view<_Vp> && view<_Pattern> + && input_range<range_reference_t<_Vp>> + && __detail::__compatible_joinable_ranges<range_reference_t<_Vp>, _Pattern> + template<bool _Const> + class join_with_view<_Vp, _Pattern>::_Sentinel + { + using _Parent = __detail::__maybe_const_t<_Const, join_with_view>; + using _Base = join_with_view::_Base<_Const>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + constexpr explicit + _Sentinel(_Parent& __parent) + : _M_end(ranges::end(__parent._M_base)) + { } + + friend join_with_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel<!_Const> __s) + requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>> + : _M_end(std::move(__s._M_end)) + { } + + template<bool _OtherConst> + requires sentinel_for<sentinel_t<_Base>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_outer_it == __y._M_end; } + }; + + namespace views + { + namespace __detail + { + template<typename _Range, typename _Pattern> + concept __can_join_with_view + = requires { join_with_view(std::declval<_Range>(), std::declval<_Pattern>()); }; + } // namespace __detail + + struct _JoinWith : __adaptor::_RangeAdaptor<_JoinWith> + { + template<viewable_range _Range, typename _Pattern> + requires __detail::__can_join_with_view<_Range, _Pattern> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Pattern&& __f) const + { + return join_with_view(std::forward<_Range>(__r), std::forward<_Pattern>(__f)); + } + + using _RangeAdaptor<_JoinWith>::operator(); + static constexpr int _S_arity = 2; + template<typename _Pattern> + static constexpr bool _S_has_simple_extra_args + = _LazySplit::_S_has_simple_extra_args<_Pattern>; + }; + + inline constexpr _JoinWith join_with; + } // namespace views #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index a015fd9..b74565e 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -1507,6 +1507,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef _Tp type; }; /// remove_cv +#if __has_builtin(__remove_cv) + template<typename _Tp> + struct remove_cv + { using type = __remove_cv(_Tp); }; +#else template<typename _Tp> struct remove_cv { using type = _Tp; }; @@ -1522,6 +1527,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct remove_cv<const volatile _Tp> { using type = _Tp; }; +#endif /// add_const template<typename _Tp> @@ -1570,17 +1576,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Reference transformations. /// remove_reference +#if __has_builtin(__remove_reference) template<typename _Tp> struct remove_reference - { typedef _Tp type; }; + { using type = __remove_reference(_Tp); }; +#else + template<typename _Tp> + struct remove_reference + { using type = _Tp; }; template<typename _Tp> struct remove_reference<_Tp&> - { typedef _Tp type; }; + { using type = _Tp; }; template<typename _Tp> struct remove_reference<_Tp&&> - { typedef _Tp type; }; + { using type = _Tp; }; +#endif /// add_lvalue_reference template<typename _Tp> @@ -3358,20 +3370,23 @@ template<typename _Ret, typename _Fn, typename... _Args> */ #define __cpp_lib_remove_cvref 201711L +#if __has_builtin(__remove_cvref) template<typename _Tp> struct remove_cvref - : remove_cv<_Tp> - { }; + { using type = __remove_cvref(_Tp); }; +#else + template<typename _Tp> + struct remove_cvref + { using type = typename remove_cv<_Tp>::type; }; template<typename _Tp> struct remove_cvref<_Tp&> - : remove_cv<_Tp> - { }; + { using type = typename remove_cv<_Tp>::type; }; template<typename _Tp> struct remove_cvref<_Tp&&> - : remove_cv<_Tp> - { }; + { using type = typename remove_cv<_Tp>::type; }; +#endif template<typename _Tp> using remove_cvref_t = typename remove_cvref<_Tp>::type; diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_sort/mem_check.cc b/libstdc++-v3/testsuite/25_algorithms/stable_sort/mem_check.cc index d1f7690..9dde4fb 100644 --- a/libstdc++-v3/testsuite/25_algorithms/stable_sort/mem_check.cc +++ b/libstdc++-v3/testsuite/25_algorithms/stable_sort/mem_check.cc @@ -15,6 +15,8 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +// { dg-require-effective-target hosted } + // 25.3.1.2 [lib.stable.sort] #include <algorithm> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/join_with/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/join_with/1.cc new file mode 100644 index 0000000..8b9c6c4 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/join_with/1.cc @@ -0,0 +1,103 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include <ranges> +#include <algorithm> +#include <string> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +namespace ranges = std::ranges; +namespace views = std::views; +using namespace std::literals; + +constexpr bool +test01() +{ + std::string_view rs[] = {"hello", "world"}; + auto v = rs | views::join_with(' '); + VERIFY( ranges::equal(v | views::split(' '), rs, ranges::equal) ); + auto i = v.begin(), j = v.begin(); + VERIFY( i == j ); + ++i; + i++; + VERIFY( i != j ); + VERIFY( *i == 'l' ); + --i; + i--; + VERIFY( *i == 'h' ); + return true; +} + +constexpr bool +test02() +{ + std::string_view rs[] = {"the", "quick", "brown", "fox"}; + auto v = rs + | views::transform([](auto x) { return x; }) + | views::filter([](auto) { return true; }); + VERIFY( ranges::equal(v | views::join_with(views::empty<char>), "thequickbrownfox"sv) ); + VERIFY( ranges::equal(v | views::join_with('-'), "the-quick-brown-fox"sv) ); + VERIFY( ranges::equal(v | views::join_with("--"sv), "the--quick--brown--fox"sv) ); + VERIFY( ranges::empty(views::empty<int[3]> | views::join_with(0))); + VERIFY( ranges::equal(views::single(std::array{42}) | views::join_with(0), (int[]){42})); + return true; +} + +constexpr bool +test03() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_bidirectional_range; + + using ty1 = ranges::join_with_view<views::all_t<test_input_range<test_input_range<int>>>, + views::all_t<test_forward_range<int>>>; + static_assert(ranges::input_range<ty1>); + static_assert(!ranges::forward_range<ty1>); + static_assert(!ranges::common_range<ty1>); + + using ty2 = ranges::join_with_view<views::all_t<test_forward_range<test_forward_range<int>>>, + views::all_t<test_forward_range<int>>>; + static_assert(ranges::forward_range<ty2>); + static_assert(!ranges::bidirectional_range<ty2>); + static_assert(!ranges::common_range<ty2>); + + using ty3 = ranges::join_with_view<views::all_t<std::array<std::string_view, 3>>, + std::string_view>; + static_assert(ranges::bidirectional_range<ty3>); + static_assert(!ranges::random_access_range<ty3>); + static_assert(ranges::common_range<ty3>); + + return true; +} + +#if _GLIBCXX_USE_CXX11_ABI +constexpr +#endif +bool +test04() +{ + std::string rs[] = {"a", "", "b", "", "c"}; + auto v = rs | views::join_with(' '); + VERIFY( ranges::equal(v, "a b c"sv) ); + auto i = v.begin(); + auto j = ranges::next(i, 3); + ranges::iter_swap(i, j); + *j = ranges::iter_move(i); + VERIFY( ranges::equal(v, "b b c"sv) ); + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +#if _GLIBCXX_USE_CXX11_ABI + static_assert(test04()); +#else + VERIFY(test04()); +#endif +} |